Running 'peflags -p /bin/*.exe' with the patch applied suggests that
objcopy/strip recently changed behavior and no longer set timestamps to 0.
Related: https://sourceware.org/bugzilla/show_bug.cgi?id=30702
--
Regards,
Christian
From 68d42574e4b7bbc0659708ce801b6cd25b88dc11 Mon Sep 17 00:00:00 2001
From: Christian Franke <christian.fra...@t-online.de>
Date: Mon, 7 Aug 2023 14:02:12 +0200
Subject: [PATCH] peflags: Add -p, --timestamp option
This allows to set the header timestamp to 0 or some other fixed
value (SOURCE_DATE_EPOCH) to support reproducible builds.
Signed-off-by: Christian Franke <christian.fra...@t-online.de>
---
peflags.c | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/peflags.c b/peflags.c
index d98b121..f4b1812 100644
--- a/peflags.c
+++ b/peflags.c
@@ -131,6 +131,7 @@ enum {
SIZEOF_HEAP_RESERVE,
SIZEOF_HEAP_COMMIT,
SIZEOF_CYGWIN_HEAP,
+ SIZEOF_TIMESTAMP,
NUM_SIZEOF_VALUES /* Keep at the end */
};
@@ -152,7 +153,7 @@ typedef struct {
ULONG offset32;
} sizeof_values_t;
-sizeof_values_t sizeof_vals[5] = {
+static sizeof_values_t sizeof_vals[NUM_SIZEOF_VALUES] = {
{ 0, "stack reserve size" , "bytes", 0, FALSE,
offsetof (IMAGE_NT_HEADERS64, OptionalHeader.SizeOfStackReserve),
offsetof (IMAGE_NT_HEADERS32, OptionalHeader.SizeOfStackReserve),
@@ -172,6 +173,10 @@ sizeof_values_t sizeof_vals[5] = {
{ 0, "initial Cygwin heap size", "MB", 0, TRUE,
offsetof (IMAGE_NT_HEADERS64, OptionalHeader.LoaderFlags),
offsetof (IMAGE_NT_HEADERS32, OptionalHeader.LoaderFlags),
+ },
+ { 0, "file header timestamp", "seconds", 0, TRUE,
+ offsetof (IMAGE_NT_HEADERS64, FileHeader.TimeDateStamp),
+ offsetof (IMAGE_NT_HEADERS32, FileHeader.TimeDateStamp),
}
};
@@ -197,6 +202,7 @@ static struct option long_options[] = {
{"heap-reserve", optional_argument, NULL, 'y'},
{"heap-commit", optional_argument, NULL, 'Y'},
{"cygwin-heap", optional_argument, NULL, 'z'},
+ {"timestamp", optional_argument, NULL, 'p'},
{"filelist", no_argument, NULL, 'T'},
{"verbose", no_argument, NULL, 'v'},
{"help", no_argument, NULL, 'h'},
@@ -204,7 +210,7 @@ static struct option long_options[] = {
{NULL, no_argument, NULL, 0}
};
static const char *short_options
- = "d::e::c::f::n::i::s::b::W::t::w::l::S::x::X::y::Y::z::T:vhV";
+ = "d::e::c::f::n::i::s::b::W::t::w::l::S::x::X::y::Y::z::p::T:vhV";
static void short_usage (FILE *f);
static void help (FILE *f);
@@ -459,13 +465,22 @@ do_mark (const char *pathname)
{
if (sizeof_vals[i].handle != DONT_HANDLE)
{
- printf ("%*s%-24s: %" PRIu64 " (0x%" PRIx64 ") %s\n",
+ char extra[32] = "";
+ if (verbose && i == SIZEOF_TIMESTAMP)
+ {
+ time_t t = (time_t)sizeof_vals[i].value;
+ const struct tm * tp = gmtime (&t);
+ if (tp)
+ strftime (extra, sizeof(extra), " [%Y-%m-%d %H:%M:%S UTC]",
tp);
+ }
+
+ printf ("%*s%-24s: %" PRIu64 " (0x%" PRIx64 ") %s%s\n",
printed_characteristic ? (int) strlen (pathname) + 2
: 0, "",
sizeof_vals[i].name,
(uint64_t) sizeof_vals[i].value,
(uint64_t) sizeof_vals[i].value,
- sizeof_vals[i].unit);
+ sizeof_vals[i].unit, extra);
printed_characteristic = TRUE;
}
}
@@ -786,6 +801,11 @@ parse_args (int argc, char *argv[])
optarg,
SIZEOF_CYGWIN_HEAP);
break;
+ case 'p':
+ handle_num_option (long_options[option_index].name,
+ optarg,
+ SIZEOF_TIMESTAMP);
+ break;
case 'T':
file_list = optarg;
break;
@@ -1118,6 +1138,7 @@ help (FILE *f)
" Useful values are between 4 and 2048. If 0,\n"
" Cygwin uses the default heap size of 384
Megs.\n"
" Has no meaning for non-Cygwin applications.\n"
+" -p, --timestamp [NUM] Timestamp in file header (seconds since
epoch).\n"
" -T, --filelist FILE Indicate that FILE contains a list\n"
" of PE files to process\n"
" -v, --verbose Display diagnostic information\n"
--
2.39.0