[RFC] Reproducible PE timestamps
Stephen Kitt
steve@sk2.org
Sat Jun 6 16:58:00 GMT 2015
Hi,
--no-insert-timestamp was added to ld so that PE binaries can be built
reproducibly (with no timestamp), but it has the unfortunate side-effect of
causing crashes if binaries are bound to non-timestamped DLLs which are later
updated. (See https://sourceware.org/bugzilla/show_bug.cgi?id=16887 for
details.)
It occurred to me that one way of satisfying the various use cases without
breaking anything is to allow the timestamp to be set: that way, builds can
be reproduced, but as long as changes to DLLs cause a change in the
timestamp, then bound executables will be OK too. The following is a first
stab at this; it allows a timestamp to be given as a value to
--insert-timestamp. As far as I'm concerned the patch still needs
error-handling, the optarg processing should probably be extracted as a
separate function, and it needs documentation too. I'm also wondering whether
using "%s" with strptime is acceptable, since that's a GNU extension; would
it be worth pulling in the standard FSF parse-datetime.y?
Regards,
Stephen
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 34e71a8..8558728 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -124,7 +124,7 @@ typedef struct pe_tdata
int dll;
int has_reloc_section;
int dont_strip_reloc;
- bfd_boolean insert_timestamp;
+ time_t insert_timestamp;
bfd_boolean (*in_reloc_p) (bfd *, reloc_howto_type *);
flagword real_flags;
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index c897c64..1f4e785 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -877,7 +877,7 @@ _bfd_XXi_only_swap_filehdr_out (bfd * abfd, void * in, void * out)
/* Only use a real timestamp if the option was chosen. */
if ((pe_data (abfd)->insert_timestamp))
- H_PUT_32 (abfd, time (0), filehdr_out->f_timdat);
+ H_PUT_32 (abfd, pe_data (abfd)->insert_timestamp, filehdr_out->f_timdat);
PUT_FILEHDR_SYMPTR (abfd, filehdr_in->f_symptr,
filehdr_out->f_symptr);
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 60882ce..9310f36 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -83,6 +83,8 @@ fragment <<EOF
#include "pe-dll.h"
#include "safe-ctype.h"
+#include <time.h>
+
/* Permit the emulation parameters to override the default section
alignment by setting OVERRIDE_SECTION_ALIGNMENT. FIXME: This makes
it seem that include/coff/internal.h should not define
@@ -132,7 +134,7 @@ static int support_old_code = 0;
static char * thumb_entry_symbol = NULL;
static lang_assignment_statement_type *image_base_statement = 0;
static unsigned short pe_dll_characteristics = 0;
-static bfd_boolean insert_timestamp = TRUE;
+static time_t insert_timestamp = 0;
static const char *emit_build_id;
#ifdef DLL_SUPPORT
@@ -307,7 +309,7 @@ gld${EMULATION_NAME}_add_options
OPTION_USE_NUL_PREFIXED_IMPORT_TABLES},
{"no-leading-underscore", no_argument, NULL, OPTION_NO_LEADING_UNDERSCORE},
{"leading-underscore", no_argument, NULL, OPTION_LEADING_UNDERSCORE},
- {"insert-timestamp", no_argument, NULL, OPTION_INSERT_TIMESTAMP},
+ {"insert-timestamp", optional_argument, NULL, OPTION_INSERT_TIMESTAMP},
{"no-insert-timestamp", no_argument, NULL, OPTION_NO_INSERT_TIMESTAMP},
#ifdef DLL_SUPPORT
/* getopt allows abbreviations, so we do this to stop it
@@ -769,7 +771,15 @@ gld${EMULATION_NAME}_handle_option (int optc)
pe_leading_underscore = 1;
break;
case OPTION_INSERT_TIMESTAMP:
- insert_timestamp = TRUE;
+ if (optarg)
+ {
+ struct tm tm;
+ memset (&tm, 0, sizeof (struct tm));
+ strptime (optarg, "%s", &tm);
+ insert_timestamp = mktime (&tm);
+ }
+ else
+ insert_timestamp = time (0);
break;
case OPTION_NO_INSERT_TIMESTAMP:
insert_timestamp = FALSE;
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index d6de792..cf289a4 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -85,6 +85,8 @@ fragment <<EOF
#include "pep-dll.h"
#include "safe-ctype.h"
+#include <time.h>
+
/* Permit the emulation parameters to override the default section
alignment by setting OVERRIDE_SECTION_ALIGNMENT. FIXME: This makes
it seem that include/coff/internal.h should not define
@@ -147,7 +149,7 @@ static flagword real_flags = IMAGE_FILE_LARGE_ADDRESS_AWARE;
static int support_old_code = 0;
static lang_assignment_statement_type *image_base_statement = 0;
static unsigned short pe_dll_characteristics = 0;
-static bfd_boolean insert_timestamp = TRUE;
+static time_t insert_timestamp = 0;
static const char *emit_build_id;
#ifdef DLL_SUPPORT
@@ -324,7 +326,7 @@ gld${EMULATION_NAME}_add_options
{"no-bind", no_argument, NULL, OPTION_NO_BIND},
{"wdmdriver", no_argument, NULL, OPTION_WDM_DRIVER},
{"tsaware", no_argument, NULL, OPTION_TERMINAL_SERVER_AWARE},
- {"insert-timestamp", no_argument, NULL, OPTION_INSERT_TIMESTAMP},
+ {"insert-timestamp", optional_argument, NULL, OPTION_INSERT_TIMESTAMP},
{"no-insert-timestamp", no_argument, NULL, OPTION_NO_INSERT_TIMESTAMP},
{"build-id", optional_argument, NULL, OPTION_BUILD_ID},
{NULL, no_argument, NULL, 0}
@@ -725,7 +727,15 @@ gld${EMULATION_NAME}_handle_option (int optc)
pep_leading_underscore = 1;
break;
case OPTION_INSERT_TIMESTAMP:
- insert_timestamp = TRUE;
+ if (optarg)
+ {
+ struct tm tm;
+ memset (&tm, 0, sizeof (struct tm));
+ strptime (optarg, "%s", &tm);
+ insert_timestamp = mktime (&tm);
+ }
+ else
+ insert_timestamp = TRUE;
break;
case OPTION_NO_INSERT_TIMESTAMP:
insert_timestamp = FALSE;
diff --git a/ld/pe-dll.c b/ld/pe-dll.c
index e3e1f1f..4af64de 100644
--- a/ld/pe-dll.c
+++ b/ld/pe-dll.c
@@ -1186,7 +1186,7 @@ fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
memset (edata_d, 0, edata_sz);
if (pe_data (abfd)->insert_timestamp)
- H_PUT_32 (abfd, time (0), edata_d + 4);
+ H_PUT_32 (abfd, pe_data (abfd)->insert_timestamp, edata_d + 4);
if (pe_def_file->version_major != -1)
{
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <https://sourceware.org/pipermail/binutils/attachments/20150606/caced888/attachment.sig>
More information about the Binutils
mailing list