From 1e8254e60bad8f8a2286daedd41dd36660e757f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 10 Feb 2024 00:36:16 +0200 Subject: [PATCH 1/2] [LLD] [COFF] Pick timestamps from the SOURCE_DATE_EPOCH variable The SOURCE_DATE_EPOCH environment variable can be set in order to get reproducible build. When linking PE/COFF modules with LLD, the timestamp field is set to the current time, unless either the /timestamp: or /Brepro option is set. If neither of them is set, check the SOURCE_DATE_EPOCH variable, before resorting to using the actual current date and time. --- lld/COFF/Driver.cpp | 10 +++++++++- lld/test/COFF/timestamp.test | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index e0afb6b18805b..22ee2f133be98 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -1825,7 +1825,15 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { } } else { config->repro = false; - config->timestamp = time(nullptr); + if (std::optional epoch = + Process::GetEnv("SOURCE_DATE_EPOCH")) { + StringRef value(*epoch); + if (value.getAsInteger(0, config->timestamp)) + fatal(Twine("invalid SOURCE_DATE_EPOCH timestamp: ") + value + + ". Expected 32-bit integer"); + } else { + config->timestamp = time(nullptr); + } } // Handle /alternatename diff --git a/lld/test/COFF/timestamp.test b/lld/test/COFF/timestamp.test index fbdc5788a33a5..f94eeee8793f0 100644 --- a/lld/test/COFF/timestamp.test +++ b/lld/test/COFF/timestamp.test @@ -3,9 +3,11 @@ RUN: yaml2obj %p/Inputs/generic.yaml -o %t.obj RUN: lld-link %t.obj /debug /Brepro /entry:main /nodefaultlib /out:%t.1.exe RUN: lld-link %t.obj /debug /Brepro /entry:main /nodefaultlib /out:%t.2.exe RUN: lld-link %t.obj /debug /timestamp:0 /entry:main /nodefaultlib /out:%t.3.exe +RUN: env SOURCE_DATE_EPOCH=0 lld-link %t.obj /debug /entry:main /nodefaultlib /out:%t.4.exe RUN: llvm-readobj --file-headers --coff-debug-directory %t.1.exe | FileCheck %s --check-prefix=HASH RUN: llvm-readobj --file-headers --coff-debug-directory %t.2.exe | FileCheck %s --check-prefix=HASH RUN: llvm-readobj --file-headers --coff-debug-directory %t.3.exe | FileCheck %s --check-prefix=ZERO +RUN: llvm-readobj --file-headers --coff-debug-directory %t.4.exe | FileCheck %s --check-prefix=ZERO HASH: ImageFileHeader { HASH: TimeDateStamp: [[STAMP:.*]] From a0bd398f9162a015103588cc15b17bb4d444bbbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 10 Feb 2024 14:14:07 +0200 Subject: [PATCH 2/2] Test more cases --- lld/test/COFF/timestamp.test | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lld/test/COFF/timestamp.test b/lld/test/COFF/timestamp.test index f94eeee8793f0..c0658d6109811 100644 --- a/lld/test/COFF/timestamp.test +++ b/lld/test/COFF/timestamp.test @@ -4,10 +4,18 @@ RUN: lld-link %t.obj /debug /Brepro /entry:main /nodefaultlib /out:%t.1.exe RUN: lld-link %t.obj /debug /Brepro /entry:main /nodefaultlib /out:%t.2.exe RUN: lld-link %t.obj /debug /timestamp:0 /entry:main /nodefaultlib /out:%t.3.exe RUN: env SOURCE_DATE_EPOCH=0 lld-link %t.obj /debug /entry:main /nodefaultlib /out:%t.4.exe +RUN: lld-link %t.obj /debug /timestamp:4294967295 /entry:main /nodefaultlib /out:%t.5.exe +RUN: env SOURCE_DATE_EPOCH=4294967295 lld-link %t.obj /debug /entry:main /nodefaultlib /out:%t.6.exe +RUN: env SOURCE_DATE_EPOCH=12345 lld-link %t.obj /debug /timestamp:0 /entry:main /nodefaultlib /out:%t.7.exe +RUN: env LLD_IN_TEST=1 not lld-link %t.obj /debug /timestamp:4294967296 /entry:main /nodefaultlib /out:%t.8.exe 2>&1 | FileCheck %s --check-prefix=ERROR +RUN: env SOURCE_DATE_EPOCH=4294967296 env LLD_IN_TEST=1 not lld-link %t.obj /debug /entry:main /nodefaultlib /out:%t.9.exe 2>&1 | FileCheck %s --check-prefix=ERROR2 RUN: llvm-readobj --file-headers --coff-debug-directory %t.1.exe | FileCheck %s --check-prefix=HASH RUN: llvm-readobj --file-headers --coff-debug-directory %t.2.exe | FileCheck %s --check-prefix=HASH RUN: llvm-readobj --file-headers --coff-debug-directory %t.3.exe | FileCheck %s --check-prefix=ZERO RUN: llvm-readobj --file-headers --coff-debug-directory %t.4.exe | FileCheck %s --check-prefix=ZERO +RUN: llvm-readobj --file-headers --coff-debug-directory %t.5.exe | FileCheck %s --check-prefix=MAX +RUN: llvm-readobj --file-headers --coff-debug-directory %t.6.exe | FileCheck %s --check-prefix=MAX +RUN: llvm-readobj --file-headers --coff-debug-directory %t.7.exe | FileCheck %s --check-prefix=ZERO HASH: ImageFileHeader { HASH: TimeDateStamp: [[STAMP:.*]] @@ -18,3 +26,11 @@ ZERO: ImageFileHeader { ZERO: TimeDateStamp: 1970-01-01 00:00:00 (0x0) ZERO: DebugDirectory [ ZERO: TimeDateStamp: 1970-01-01 00:00:00 (0x0) + +MAX: ImageFileHeader { +MAX: TimeDateStamp: 2106-02-07 06:28:15 (0xFFFFFFFF) +MAX: DebugDirectory [ +MAX: TimeDateStamp: 2106-02-07 06:28:15 (0xFFFFFFFF) + +ERROR: error: invalid timestamp: 4294967296. Expected 32-bit integer +ERROR2: error: invalid SOURCE_DATE_EPOCH timestamp: 4294967296. Expected 32-bit integer