Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lld/COFF/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,10 @@ struct Configuration {
bool dynamicBase = true;
bool allowBind = true;
bool cetCompat = false;
bool cetCompatStrict = false;
bool cetCompatIpValidationRelaxed = false;
bool cetCompatDynamicApisInProcOnly = false;
bool hotpatchCompat = false;
bool nxCompat = true;
bool allowIsolation = true;
bool terminalServerAware = true;
Expand Down
14 changes: 14 additions & 0 deletions lld/COFF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2145,6 +2145,14 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
config->integrityCheck =
args.hasFlag(OPT_integritycheck, OPT_integritycheck_no, false);
config->cetCompat = args.hasFlag(OPT_cetcompat, OPT_cetcompat_no, false);
config->cetCompatStrict =
args.hasFlag(OPT_cetcompatstrict, OPT_cetcompatstrict_no, false);
config->cetCompatIpValidationRelaxed = args.hasFlag(
OPT_cetipvalidationrelaxed, OPT_cetipvalidationrelaxed_no, false);
config->cetCompatDynamicApisInProcOnly = args.hasFlag(
OPT_cetdynamicapisinproc, OPT_cetdynamicapisinproc_no, false);
config->hotpatchCompat =
args.hasFlag(OPT_hotpatchcompatible, OPT_hotpatchcompatible_no, false);
config->nxCompat = args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true);
for (auto *arg : args.filtered(OPT_swaprun))
parseSwaprun(arg->getValue());
Expand Down Expand Up @@ -2298,6 +2306,12 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
for (auto *arg : args.filtered(OPT_functionpadmin, OPT_functionpadmin_opt))
parseFunctionPadMin(arg);

// MS link.exe compatibility, at least 6 bytes of function padding is
// required if hotpatchable
if (config->hotpatchCompat && config->functionPadMin < 6)
Err(ctx)
<< "/hotpatchcompatible: requires at least 6 bytes of /functionpadmin";

// Handle /dependentloadflag
for (auto *arg :
args.filtered(OPT_dependentloadflag, OPT_dependentloadflag_opt))
Expand Down
8 changes: 8 additions & 0 deletions lld/COFF/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -196,13 +196,21 @@ defm appcontainer : B<"appcontainer",
"Image can run outside an app container (default)">;
defm cetcompat : B<"cetcompat", "Mark executable image as compatible with Control-flow Enforcement Technology (CET) Shadow Stack",
"Don't mark executable image as compatible with Control-flow Enforcement Technology (CET) Shadow Stack (default)">;
defm cetcompatstrict : B<"cetcompatstrict", "Mark executable image as compatible with Control-flow Enforcement Technology (CET) Shadow Stack in strict mode",
"Don't mark executable image as compatible with Control-flow Enforcement Technology (CET) Shadow Stack in strict mode (default)">;
defm cetdynamicapisinproc : B<"cetdynamicapisinproc", "Mark executable image as compatible with Control-flow Enforcement Technology (CET) Shadow Stack in such a way that dynamic APIs allowed in process",
"Don't mark executable image as compatible with Control-flow Enforcement Technology (CET) Shadow Stack with dynamic APIs allowed in process (default)">;
defm cetipvalidationrelaxed : B<"cetipvalidationrelaxed", "Mark executable image as compatible with Control-flow Enforcement Technology (CET) Shadow Stack with relaxed context IP validation",
"Don't mark executable image as compatible with Control-flow Enforcement Technology (CET) Shadow Stack with relaxed context IP validation (default)">;
defm dynamicbase : B<"dynamicbase", "Enable ASLR (default unless /fixed)",
"Disable ASLR (default when /fixed)">;
defm fixed : B<"fixed", "Disable base relocations",
"Enable base relocations (default)">;
defm highentropyva : B<"highentropyva",
"Enable 64-bit ASLR (default on 64-bit)",
"Disable 64-bit ASLR">;
defm hotpatchcompatible : B<"hotpatchcompatible", "Mark executable image as compatible with hotpatch",
"Don't mark executable image as compatible with hotpatch (default)">;
defm incremental : B<"incremental",
"Keep original import library if contents are unchanged",
"Overwrite import library even if contents are unchanged">;
Expand Down
28 changes: 23 additions & 5 deletions lld/COFF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1216,7 +1216,9 @@ void Writer::createMiscChunks() {
// Create Debug Information Chunks
debugInfoSec = config->mingw ? buildidSec : rdataSec;
if (config->buildIDHash != BuildIDHash::None || config->debug ||
config->repro || config->cetCompat) {
config->repro || config->cetCompat || config->cetCompatStrict ||
config->cetCompatIpValidationRelaxed ||
config->cetCompatDynamicApisInProcOnly || config->hotpatchCompat) {
debugDirectory =
make<DebugDirectoryChunk>(ctx, debugRecords, config->repro);
debugDirectory->setAlignment(4);
Expand All @@ -1237,10 +1239,26 @@ void Writer::createMiscChunks() {
});
}

if (config->cetCompat) {
debugRecords.emplace_back(COFF::IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS,
make<ExtendedDllCharacteristicsChunk>(
IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT));
uint16_t ex_characteristics_flags = 0;
if (config->cetCompat)
ex_characteristics_flags |= IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT;
if (config->cetCompatStrict)
ex_characteristics_flags |=
IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE;
if (config->cetCompatIpValidationRelaxed)
ex_characteristics_flags |=
IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE;
if (config->cetCompatDynamicApisInProcOnly)
ex_characteristics_flags |=
IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY;
if (config->hotpatchCompat)
ex_characteristics_flags |=
IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE;

if (ex_characteristics_flags) {
debugRecords.emplace_back(
COFF::IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS,
make<ExtendedDllCharacteristicsChunk>(ex_characteristics_flags));
}

// Align and add each chunk referenced by the debug data directory.
Expand Down
15 changes: 15 additions & 0 deletions lld/test/COFF/cetcompatstrict.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
RUN: yaml2obj %p/Inputs/ret42.yaml -o %t.obj
RUN: lld-link /out:%t.exe /entry:main /cetcompatstrict %t.obj
RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck %s

CHECK: DebugEntry {
CHECK: Characteristics: 0x0
CHECK: Type: ExtendedDLLCharacteristics (0x14)
CHECK: ExtendedCharacteristics [ (0x2)
CHECK: IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE (0x2)
CHECK: ]
CHECK: RawData (
CHECK: 0000: 02000000 |....|
CHECK: )
CHECK: }

15 changes: 15 additions & 0 deletions lld/test/COFF/cetdynamicapisinproc.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
RUN: yaml2obj %p/Inputs/ret42.yaml -o %t.obj
RUN: lld-link /out:%t.exe /entry:main /cetdynamicapisinproc %t.obj
RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck %s

CHECK: DebugEntry {
CHECK: Characteristics: 0x0
CHECK: Type: ExtendedDLLCharacteristics (0x14)
CHECK: ExtendedCharacteristics [ (0x8)
CHECK: IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY (0x8)
CHECK: ]
CHECK: RawData (
CHECK: 0000: 08000000 |....|
CHECK: )
CHECK: }

15 changes: 15 additions & 0 deletions lld/test/COFF/cetipvalidationrelaxed.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
RUN: yaml2obj %p/Inputs/ret42.yaml -o %t.obj
RUN: lld-link /out:%t.exe /entry:main /cetipvalidationrelaxed %t.obj
RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck %s

CHECK: DebugEntry {
CHECK: Characteristics: 0x0
CHECK: Type: ExtendedDLLCharacteristics (0x14)
CHECK: ExtendedCharacteristics [ (0x4)
CHECK: IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE (0x4)
CHECK: ]
CHECK: RawData (
CHECK: 0000: 04000000 |....|
CHECK: )
CHECK: }

33 changes: 33 additions & 0 deletions lld/test/COFF/hotpatchcompatible.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
RUN: yaml2obj %p/Inputs/ret42.yaml -o %t.obj
RUN: lld-link /out:%t.exe /entry:main /hotpatchcompatible /functionpadmin:6 %t.obj
RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=CHECK1 %s

CHECK1: DebugEntry {
CHECK1: Characteristics: 0x0
CHECK1: Type: ExtendedDLLCharacteristics (0x14)
CHECK1: ExtendedCharacteristics [ (0x80)
CHECK1: IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE (0x80)
CHECK1: ]
CHECK1: RawData (
CHECK1: 0000: 80000000 |....|
CHECK1: )
CHECK1: }

// ---- more than 6 bytes is accepted
RUN: lld-link /out:%t.exe /entry:main /hotpatchcompatible /functionpadmin:10 %t.obj
RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=CHECK2 %s

CHECK2: DebugEntry {
CHECK2: Characteristics: 0x0
CHECK2: Type: ExtendedDLLCharacteristics (0x14)
CHECK2: ExtendedCharacteristics [ (0x80)
CHECK2: IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE (0x80)
CHECK2: ]
CHECK2: RawData (
CHECK2: 0000: 80000000 |....|
CHECK2: )
CHECK2: }

// ---- hotpach compatible image requires at least 6 bytes function padding
RUN: not lld-link /out:%t.exe /entry:main /hotpatchcompatible /functionpadmin:5 %t.obj
CHECK3: lld-link: error: /hotpatchcompatible: requires at least 6 bytes of /functionpadmin
40 changes: 40 additions & 0 deletions lld/test/COFF/options.test
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,46 @@ CETCOMPAT: IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT
# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=NONCETCOMPAT %s
NONCETCOMPAT-NOT: IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT

# RUN: lld-link /out:%t.exe /entry:main /cetcompatstrict %t.obj
# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=CETCOMPATSTRICT %s
CETCOMPATSTRICT: IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE

# RUN: lld-link /out:%t.exe /entry:main %t.obj
# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=NONCETCOMPATSTRICT %s
# RUN: lld-link /out:%t.exe /entry:main /cetcompatstrict:no %t.obj
# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=NONCETCOMPATSTRICT %s
NONCETCOMPATSTRICT-NOT: IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE

# RUN: lld-link /out:%t.exe /entry:main /cetipvalidationrelaxed %t.obj
# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=CETCOMPATSTIPVALIDATIONRELAXED %s
CETCOMPATSTIPVALIDATIONRELAXED: IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE

# RUN: lld-link /out:%t.exe /entry:main %t.obj
# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=NONCETCOMPATSTIPVALIDATIONRELAXED %s
# RUN: lld-link /out:%t.exe /entry:main /cetipvalidationrelaxed:no %t.obj
# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=NONCETCOMPATSTIPVALIDATIONRELAXED %s
NONCETCOMPATSTIPVALIDATIONRELAXED-NOT: IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE

# RUN: lld-link /out:%t.exe /entry:main /cetdynamicapisinproc %t.obj
# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=CETDYNAMICAPISINPROC %s
CETDYNAMICAPISINPROC: IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY

# RUN: lld-link /out:%t.exe /entry:main %t.obj
# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=NONCETDYNAMICAPISINPROC %s
# RUN: lld-link /out:%t.exe /entry:main /cetdynamicapisinproc:no %t.obj
# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=NONCETDYNAMICAPISINPROC %s
NONCETDYNAMICAPISINPROC-NOT: IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY

# RUN: lld-link /out:%t.exe /entry:main /hotpatchcompatible /functionpadmin:6 %t.obj
# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=HOTPATCHCOMPATIBLE %s
HOTPATCHCOMPATIBLE: IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE

# RUN: lld-link /out:%t.exe /entry:main %t.obj
# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=NONHOTPATCHCOMPATIBLE %s
# RUN: lld-link /out:%t.exe /entry:main /hotpatchcompatible:no %t.obj
# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck -check-prefix=NONHOTPATCHCOMPATIBLE %s
NONHOTPATCHCOMPATIBLE-NOT: IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE

# RUN: lld-link /out:%t.exe /entry:main /swaprun:CD %t.obj
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=SWAPCD %s
# RUN: lld-link /out:%t.exe /entry:main /swaprun:cd,net %t.obj
Expand Down