-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[LLD][COFF] Add more variety of CET and hotpatch flags #150761
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-platform-windows @llvm/pr-subscribers-lld-coff Author: None (kkent030315) ChangesThose are all MS link.exe compatible flags. CET (Control-flow Enforcement Technology) family
Misc
Full diff: https://github.com/llvm/llvm-project/pull/150761.diff 11 Files Affected:
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 91b6e632fa7ed..95491c51bb7cd 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -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;
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 83040b534be9c..8cdadb2068ccd 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2145,6 +2145,13 @@ 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());
diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index 2a82fb5cd8845..da2e4706fa606 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -196,6 +196,14 @@ 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 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 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 hotpatchcompatible : B<"hotpatchcompatible", "Mark executable image as compatible with hotpatch",
+ "Don't mark executable image as compatible with hotpatch (default)">;
defm dynamicbase : B<"dynamicbase", "Enable ASLR (default unless /fixed)",
"Disable ASLR (default when /fixed)">;
defm fixed : B<"fixed", "Disable base relocations",
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 076561807af47..5c72cca522feb 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -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);
@@ -1237,10 +1239,30 @@ void Writer::createMiscChunks() {
});
}
+ 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>(
- IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT));
+ ex_characteristics_flags));
}
// Align and add each chunk referenced by the debug data directory.
diff --git a/lld/test/COFF/options.test b/lld/test/COFF/options.test
index 0dd889042869a..d131169eada61 100644
--- a/lld/test/COFF/options.test
+++ b/lld/test/COFF/options.test
@@ -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 %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
diff --git a/llvm/include/llvm/BinaryFormat/COFF.h b/llvm/include/llvm/BinaryFormat/COFF.h
index f3b5d5e3f23c6..e06fc39b5de23 100644
--- a/llvm/include/llvm/BinaryFormat/COFF.h
+++ b/llvm/include/llvm/BinaryFormat/COFF.h
@@ -694,7 +694,22 @@ enum DLLCharacteristics : unsigned {
enum ExtendedDLLCharacteristics : unsigned {
/// Image is CET compatible
- IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT = 0x0001
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT = 0x0001,
+ /// Image is CET compatible in strict mode
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE = 0x0002,
+ /// Image is CET compatible in such a way that context IP validation is relaxed
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE = 0x0004,
+ /// Image is CET compatible in such a way that the use of
+ /// dynamic APIs is restricted to processes only
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY = 0x0008,
+ /// Reserved for future use. Not used by MSVC link.exe
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_1 = 0x0010,
+ /// Reserved for future use. Not used by MSVC link.exe
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_2 = 0x0020,
+ /// Image is CFI compatible.
+ IMAGE_DLL_CHARACTERISTICS_EX_FORWARD_CFI_COMPAT = 0x0040,
+ /// Image is hotpatch compatible.
+ IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE = 0x0080,
};
enum DebugType : unsigned {
diff --git a/llvm/test/tools/llvm-readobj/COFF/cetcompatstrict.test b/llvm/test/tools/llvm-readobj/COFF/cetcompatstrict.test
new file mode 100644
index 0000000000000..9807bfe5686ee
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/cetcompatstrict.test
@@ -0,0 +1,16 @@
+# To regenerate has-cetstrict.exe
+# $ echo int main() { return 0; } > has-cetstrict.c
+# $ cl has-cetstrict.c /link /cetcompatstrict
+RUN: llvm-readobj --coff-debug-directory %p/Inputs/has-cetstrict.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: }
+
diff --git a/llvm/test/tools/llvm-readobj/COFF/cetdynamicapisinproc.test b/llvm/test/tools/llvm-readobj/COFF/cetdynamicapisinproc.test
new file mode 100644
index 0000000000000..18b3ec70177cb
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/cetdynamicapisinproc.test
@@ -0,0 +1,16 @@
+# To regenerate has-cetdynamicapisinproc.exe
+# $ echo int main() { return 0; } > has-cetdynamicapisinproc.c
+# $ cl has-cetdynamicapisinproc.c /link /cetdynamicapisinproc
+RUN: llvm-readobj --coff-debug-directory %p/Inputs/has-cetdynamicapisinproc.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: }
+
diff --git a/llvm/test/tools/llvm-readobj/COFF/cetipvalidationrelaxed.test b/llvm/test/tools/llvm-readobj/COFF/cetipvalidationrelaxed.test
new file mode 100644
index 0000000000000..25cf1db3464f7
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/cetipvalidationrelaxed.test
@@ -0,0 +1,16 @@
+# To regenerate has-cetipvalidationrelaxed.exe
+# $ echo int main() { return 0; } > has-cetipvalidationrelaxed.c
+# $ cl has-cetipvalidationrelaxed.c /link /cetipvalidationrelaxed
+RUN: llvm-readobj --coff-debug-directory %p/Inputs/has-cetipvalidationrelaxed.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: }
+
diff --git a/llvm/test/tools/llvm-readobj/COFF/hotpatchcompatible.test b/llvm/test/tools/llvm-readobj/COFF/hotpatchcompatible.test
new file mode 100644
index 0000000000000..87208d24f9fee
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/hotpatchcompatible.test
@@ -0,0 +1,16 @@
+# To regenerate has-hotpatchcompatible.exe
+# $ echo int main() { return 0; } > has-hotpatchcompatible.c
+# $ cl has-hotpatchcompatible.c /link /hotpatchcompatible
+RUN: llvm-readobj --coff-debug-directory %p/Inputs/has-hotpatchcompatible.exe | FileCheck %s
+
+CHECK: DebugEntry {
+CHECK: Characteristics: 0x0
+CHECK: Type: ExtendedDLLCharacteristics (0x14)
+CHECK: ExtendedCharacteristics [ (0x80)
+CHECK: IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE (0x80)
+CHECK: ]
+CHECK: RawData (
+CHECK: 0000: 80000000 |....|
+CHECK: )
+CHECK: }
+
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index dce8e60bda1ef..2f158e1bbe781 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -414,7 +414,14 @@ const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = {
static const EnumEntry<COFF::ExtendedDLLCharacteristics>
PEExtendedDLLCharacteristics[] = {
- LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_1 ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_2 ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_FORWARD_CFI_COMPAT ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE ),
};
static const EnumEntry<COFF::SectionCharacteristics>
|
@llvm/pr-subscribers-lld Author: None (kkent030315) ChangesThose are all MS link.exe compatible flags. CET (Control-flow Enforcement Technology) family
Misc
Full diff: https://github.com/llvm/llvm-project/pull/150761.diff 11 Files Affected:
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 91b6e632fa7ed..95491c51bb7cd 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -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;
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 83040b534be9c..8cdadb2068ccd 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2145,6 +2145,13 @@ 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());
diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index 2a82fb5cd8845..da2e4706fa606 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -196,6 +196,14 @@ 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 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 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 hotpatchcompatible : B<"hotpatchcompatible", "Mark executable image as compatible with hotpatch",
+ "Don't mark executable image as compatible with hotpatch (default)">;
defm dynamicbase : B<"dynamicbase", "Enable ASLR (default unless /fixed)",
"Disable ASLR (default when /fixed)">;
defm fixed : B<"fixed", "Disable base relocations",
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 076561807af47..5c72cca522feb 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -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);
@@ -1237,10 +1239,30 @@ void Writer::createMiscChunks() {
});
}
+ 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>(
- IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT));
+ ex_characteristics_flags));
}
// Align and add each chunk referenced by the debug data directory.
diff --git a/lld/test/COFF/options.test b/lld/test/COFF/options.test
index 0dd889042869a..d131169eada61 100644
--- a/lld/test/COFF/options.test
+++ b/lld/test/COFF/options.test
@@ -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 %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
diff --git a/llvm/include/llvm/BinaryFormat/COFF.h b/llvm/include/llvm/BinaryFormat/COFF.h
index f3b5d5e3f23c6..e06fc39b5de23 100644
--- a/llvm/include/llvm/BinaryFormat/COFF.h
+++ b/llvm/include/llvm/BinaryFormat/COFF.h
@@ -694,7 +694,22 @@ enum DLLCharacteristics : unsigned {
enum ExtendedDLLCharacteristics : unsigned {
/// Image is CET compatible
- IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT = 0x0001
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT = 0x0001,
+ /// Image is CET compatible in strict mode
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE = 0x0002,
+ /// Image is CET compatible in such a way that context IP validation is relaxed
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE = 0x0004,
+ /// Image is CET compatible in such a way that the use of
+ /// dynamic APIs is restricted to processes only
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY = 0x0008,
+ /// Reserved for future use. Not used by MSVC link.exe
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_1 = 0x0010,
+ /// Reserved for future use. Not used by MSVC link.exe
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_2 = 0x0020,
+ /// Image is CFI compatible.
+ IMAGE_DLL_CHARACTERISTICS_EX_FORWARD_CFI_COMPAT = 0x0040,
+ /// Image is hotpatch compatible.
+ IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE = 0x0080,
};
enum DebugType : unsigned {
diff --git a/llvm/test/tools/llvm-readobj/COFF/cetcompatstrict.test b/llvm/test/tools/llvm-readobj/COFF/cetcompatstrict.test
new file mode 100644
index 0000000000000..9807bfe5686ee
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/cetcompatstrict.test
@@ -0,0 +1,16 @@
+# To regenerate has-cetstrict.exe
+# $ echo int main() { return 0; } > has-cetstrict.c
+# $ cl has-cetstrict.c /link /cetcompatstrict
+RUN: llvm-readobj --coff-debug-directory %p/Inputs/has-cetstrict.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: }
+
diff --git a/llvm/test/tools/llvm-readobj/COFF/cetdynamicapisinproc.test b/llvm/test/tools/llvm-readobj/COFF/cetdynamicapisinproc.test
new file mode 100644
index 0000000000000..18b3ec70177cb
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/cetdynamicapisinproc.test
@@ -0,0 +1,16 @@
+# To regenerate has-cetdynamicapisinproc.exe
+# $ echo int main() { return 0; } > has-cetdynamicapisinproc.c
+# $ cl has-cetdynamicapisinproc.c /link /cetdynamicapisinproc
+RUN: llvm-readobj --coff-debug-directory %p/Inputs/has-cetdynamicapisinproc.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: }
+
diff --git a/llvm/test/tools/llvm-readobj/COFF/cetipvalidationrelaxed.test b/llvm/test/tools/llvm-readobj/COFF/cetipvalidationrelaxed.test
new file mode 100644
index 0000000000000..25cf1db3464f7
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/cetipvalidationrelaxed.test
@@ -0,0 +1,16 @@
+# To regenerate has-cetipvalidationrelaxed.exe
+# $ echo int main() { return 0; } > has-cetipvalidationrelaxed.c
+# $ cl has-cetipvalidationrelaxed.c /link /cetipvalidationrelaxed
+RUN: llvm-readobj --coff-debug-directory %p/Inputs/has-cetipvalidationrelaxed.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: }
+
diff --git a/llvm/test/tools/llvm-readobj/COFF/hotpatchcompatible.test b/llvm/test/tools/llvm-readobj/COFF/hotpatchcompatible.test
new file mode 100644
index 0000000000000..87208d24f9fee
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/hotpatchcompatible.test
@@ -0,0 +1,16 @@
+# To regenerate has-hotpatchcompatible.exe
+# $ echo int main() { return 0; } > has-hotpatchcompatible.c
+# $ cl has-hotpatchcompatible.c /link /hotpatchcompatible
+RUN: llvm-readobj --coff-debug-directory %p/Inputs/has-hotpatchcompatible.exe | FileCheck %s
+
+CHECK: DebugEntry {
+CHECK: Characteristics: 0x0
+CHECK: Type: ExtendedDLLCharacteristics (0x14)
+CHECK: ExtendedCharacteristics [ (0x80)
+CHECK: IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE (0x80)
+CHECK: ]
+CHECK: RawData (
+CHECK: 0000: 80000000 |....|
+CHECK: )
+CHECK: }
+
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index dce8e60bda1ef..2f158e1bbe781 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -414,7 +414,14 @@ const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = {
static const EnumEntry<COFF::ExtendedDLLCharacteristics>
PEExtendedDLLCharacteristics[] = {
- LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_1 ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_2 ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_FORWARD_CFI_COMPAT ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE ),
};
static const EnumEntry<COFF::SectionCharacteristics>
|
@llvm/pr-subscribers-llvm-binary-utilities Author: None (kkent030315) ChangesThose are all MS link.exe compatible flags. CET (Control-flow Enforcement Technology) family
Misc
Full diff: https://github.com/llvm/llvm-project/pull/150761.diff 11 Files Affected:
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 91b6e632fa7ed..95491c51bb7cd 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -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;
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 83040b534be9c..8cdadb2068ccd 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2145,6 +2145,13 @@ 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());
diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index 2a82fb5cd8845..da2e4706fa606 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -196,6 +196,14 @@ 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 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 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 hotpatchcompatible : B<"hotpatchcompatible", "Mark executable image as compatible with hotpatch",
+ "Don't mark executable image as compatible with hotpatch (default)">;
defm dynamicbase : B<"dynamicbase", "Enable ASLR (default unless /fixed)",
"Disable ASLR (default when /fixed)">;
defm fixed : B<"fixed", "Disable base relocations",
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 076561807af47..5c72cca522feb 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -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);
@@ -1237,10 +1239,30 @@ void Writer::createMiscChunks() {
});
}
+ 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>(
- IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT));
+ ex_characteristics_flags));
}
// Align and add each chunk referenced by the debug data directory.
diff --git a/lld/test/COFF/options.test b/lld/test/COFF/options.test
index 0dd889042869a..d131169eada61 100644
--- a/lld/test/COFF/options.test
+++ b/lld/test/COFF/options.test
@@ -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 %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
diff --git a/llvm/include/llvm/BinaryFormat/COFF.h b/llvm/include/llvm/BinaryFormat/COFF.h
index f3b5d5e3f23c6..e06fc39b5de23 100644
--- a/llvm/include/llvm/BinaryFormat/COFF.h
+++ b/llvm/include/llvm/BinaryFormat/COFF.h
@@ -694,7 +694,22 @@ enum DLLCharacteristics : unsigned {
enum ExtendedDLLCharacteristics : unsigned {
/// Image is CET compatible
- IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT = 0x0001
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT = 0x0001,
+ /// Image is CET compatible in strict mode
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE = 0x0002,
+ /// Image is CET compatible in such a way that context IP validation is relaxed
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE = 0x0004,
+ /// Image is CET compatible in such a way that the use of
+ /// dynamic APIs is restricted to processes only
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY = 0x0008,
+ /// Reserved for future use. Not used by MSVC link.exe
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_1 = 0x0010,
+ /// Reserved for future use. Not used by MSVC link.exe
+ IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_2 = 0x0020,
+ /// Image is CFI compatible.
+ IMAGE_DLL_CHARACTERISTICS_EX_FORWARD_CFI_COMPAT = 0x0040,
+ /// Image is hotpatch compatible.
+ IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE = 0x0080,
};
enum DebugType : unsigned {
diff --git a/llvm/test/tools/llvm-readobj/COFF/cetcompatstrict.test b/llvm/test/tools/llvm-readobj/COFF/cetcompatstrict.test
new file mode 100644
index 0000000000000..9807bfe5686ee
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/cetcompatstrict.test
@@ -0,0 +1,16 @@
+# To regenerate has-cetstrict.exe
+# $ echo int main() { return 0; } > has-cetstrict.c
+# $ cl has-cetstrict.c /link /cetcompatstrict
+RUN: llvm-readobj --coff-debug-directory %p/Inputs/has-cetstrict.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: }
+
diff --git a/llvm/test/tools/llvm-readobj/COFF/cetdynamicapisinproc.test b/llvm/test/tools/llvm-readobj/COFF/cetdynamicapisinproc.test
new file mode 100644
index 0000000000000..18b3ec70177cb
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/cetdynamicapisinproc.test
@@ -0,0 +1,16 @@
+# To regenerate has-cetdynamicapisinproc.exe
+# $ echo int main() { return 0; } > has-cetdynamicapisinproc.c
+# $ cl has-cetdynamicapisinproc.c /link /cetdynamicapisinproc
+RUN: llvm-readobj --coff-debug-directory %p/Inputs/has-cetdynamicapisinproc.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: }
+
diff --git a/llvm/test/tools/llvm-readobj/COFF/cetipvalidationrelaxed.test b/llvm/test/tools/llvm-readobj/COFF/cetipvalidationrelaxed.test
new file mode 100644
index 0000000000000..25cf1db3464f7
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/cetipvalidationrelaxed.test
@@ -0,0 +1,16 @@
+# To regenerate has-cetipvalidationrelaxed.exe
+# $ echo int main() { return 0; } > has-cetipvalidationrelaxed.c
+# $ cl has-cetipvalidationrelaxed.c /link /cetipvalidationrelaxed
+RUN: llvm-readobj --coff-debug-directory %p/Inputs/has-cetipvalidationrelaxed.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: }
+
diff --git a/llvm/test/tools/llvm-readobj/COFF/hotpatchcompatible.test b/llvm/test/tools/llvm-readobj/COFF/hotpatchcompatible.test
new file mode 100644
index 0000000000000..87208d24f9fee
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/hotpatchcompatible.test
@@ -0,0 +1,16 @@
+# To regenerate has-hotpatchcompatible.exe
+# $ echo int main() { return 0; } > has-hotpatchcompatible.c
+# $ cl has-hotpatchcompatible.c /link /hotpatchcompatible
+RUN: llvm-readobj --coff-debug-directory %p/Inputs/has-hotpatchcompatible.exe | FileCheck %s
+
+CHECK: DebugEntry {
+CHECK: Characteristics: 0x0
+CHECK: Type: ExtendedDLLCharacteristics (0x14)
+CHECK: ExtendedCharacteristics [ (0x80)
+CHECK: IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE (0x80)
+CHECK: ]
+CHECK: RawData (
+CHECK: 0000: 80000000 |....|
+CHECK: )
+CHECK: }
+
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index dce8e60bda1ef..2f158e1bbe781 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -414,7 +414,14 @@ const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = {
static const EnumEntry<COFF::ExtendedDLLCharacteristics>
PEExtendedDLLCharacteristics[] = {
- LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_1 ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_2 ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_FORWARD_CFI_COMPAT ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE ),
};
static const EnumEntry<COFF::SectionCharacteristics>
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
For the linting problem in |
I agree. Feel free to add the clang format on/off comments around that block. |
72842c2
to
3c52ce8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To emphasize the layering, I think this would be good to split into two separate PRs, one for adding support for the new flags in llvm-readobj
, and one for making LLD produce them.
Isolated COFF dumper part from llvm#150761. - Decreased the size of existing `has-cet.exe`. - Added `IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE` - Added `IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE` - Added `IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY` - Added `IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_1` - Added `IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_2` - Added `IMAGE_DLL_CHARACTERISTICS_EX_FORWARD_CFI_COMPAT` - Added `IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE`
Split out the COFF dumper from issue llvm#150761. - Decreased the size of existing `has-cet.exe`. - Added `IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE` - Added `IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE` - Added `IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY` - Added `IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_1` - Added `IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_2` - Added `IMAGE_DLL_CHARACTERISTICS_EX_FORWARD_CFI_COMPAT` - Added `IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE`
Ok, #150967 is now merged and parted changs reverted in this PR. Ready for final review :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM now, thanks!
While I am not familiar with these options, I have the impression a lot more is required to support these CET and hotpatching features in the linker, not just emitting the right flags in the binary. I have the feeling we can't just blindly emit these flags if the feature is not there, can we? I'd be fine to support the |
Let me clarify that all of these options (including the Here is the snippet of the Another look here:
The flags being added in this PR is to control |
Just to make sure that my statements stands correct, I have attached a zip consists of 4 PE64 file compiled/linked with different MSVC linker flags. (
You can manually generate them:
Then you can bindiff (if you're Windows user, there's
|
Some good read is here:
Actually, those flags are to control some "mitigation policy", as some described in the article:
So all that said -- this is all about a flag to tell the OS how CET binaries should be treatened, so there should not be anything that should linker do. Nice catch though. Thanks @aganea for raising the concern :) Footnotes |
Those are all MS link.exe compatible flags.
CET (Control-flow Enforcement Technology) family
/cetcompat[:no]
/cetcompatstrict[:no]
flag in LLD/COFF/cetipvalidationrelaxed[:no]
flag in LLD/COFF/cetdynamicapisinproc[:no]
flag in LLD/COFFMisc
/hotpatchcompatible[:no]
flag in LLD/COFF/functionpadmin:#
) as per link.exe