[lld] 14bab65 - [LLD][COFF] Support CF guards on ARM64X (#128440)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 27 12:55:19 PST 2025
Author: Jacek Caban
Date: 2025-02-27T21:55:16+01:00
New Revision: 14bab65cbfb2bf9a410c3ce206a6b7a273441f26
URL: https://github.com/llvm/llvm-project/commit/14bab65cbfb2bf9a410c3ce206a6b7a273441f26
DIFF: https://github.com/llvm/llvm-project/commit/14bab65cbfb2bf9a410c3ce206a6b7a273441f26.diff
LOG: [LLD][COFF] Support CF guards on ARM64X (#128440)
Both native and EC views share table chunks. Ensure relevant symbols are
set in both symbol tables.
Added:
lld/test/COFF/arm64x-guardcf.s
Modified:
lld/COFF/Writer.cpp
Removed:
################################################################################
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 3efbcdb452ebe..0a84bce146483 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -1986,10 +1986,17 @@ static void maybeAddAddressTakenFunction(SymbolRVASet &addressTakenSyms,
// Common is always data, so it is ignored.
break;
case Symbol::DefinedAbsoluteKind:
- case Symbol::DefinedSyntheticKind:
// Absolute is never code, synthetic generally isn't and usually isn't
// determinable.
break;
+ case Symbol::DefinedSyntheticKind:
+ // For EC export thunks, mark both the thunk itself and its target.
+ if (auto expChunk = dyn_cast_or_null<ECExportThunkChunk>(
+ cast<Defined>(s)->getChunk())) {
+ addSymbolToRVASet(addressTakenSyms, cast<Defined>(s));
+ addSymbolToRVASet(addressTakenSyms, expChunk->target);
+ }
+ break;
case Symbol::LazyArchiveKind:
case Symbol::LazyObjectKind:
case Symbol::LazyDLLSymbolKind:
@@ -2054,9 +2061,11 @@ void Writer::createGuardCFTables() {
// with /guard:cf.
for (ObjFile *file : ctx.objFileInstances) {
if (file->hasGuardCF()) {
- Symbol *flagSym = ctx.symtab.findUnderscore("__guard_flags");
- cast<DefinedAbsolute>(flagSym)->setVA(
- uint32_t(GuardFlags::CF_INSTRUMENTED));
+ ctx.forEachSymtab([&](SymbolTable &symtab) {
+ Symbol *flagSym = symtab.findUnderscore("__guard_flags");
+ cast<DefinedAbsolute>(flagSym)->setVA(
+ uint32_t(GuardFlags::CF_INSTRUMENTED));
+ });
break;
}
}
@@ -2138,8 +2147,10 @@ void Writer::createGuardCFTables() {
guardFlags |= uint32_t(GuardFlags::CF_LONGJUMP_TABLE_PRESENT);
if (config->guardCF & GuardCFLevel::EHCont)
guardFlags |= uint32_t(GuardFlags::EH_CONTINUATION_TABLE_PRESENT);
- Symbol *flagSym = ctx.symtab.findUnderscore("__guard_flags");
- cast<DefinedAbsolute>(flagSym)->setVA(guardFlags);
+ ctx.forEachSymtab([guardFlags](SymbolTable &symtab) {
+ Symbol *flagSym = symtab.findUnderscore("__guard_flags");
+ cast<DefinedAbsolute>(flagSym)->setVA(guardFlags);
+ });
}
// Take a list of input sections containing symbol table indices and add those
@@ -2210,10 +2221,12 @@ void Writer::maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym,
tableChunk = make<RVATableChunk>(std::move(tableSymbols));
rdataSec->addChunk(tableChunk);
- Symbol *t = ctx.symtab.findUnderscore(tableSym);
- Symbol *c = ctx.symtab.findUnderscore(countSym);
- replaceSymbol<DefinedSynthetic>(t, t->getName(), tableChunk);
- cast<DefinedAbsolute>(c)->setVA(tableChunk->getSize() / (hasFlag ? 5 : 4));
+ ctx.forEachSymtab([&](SymbolTable &symtab) {
+ Symbol *t = symtab.findUnderscore(tableSym);
+ Symbol *c = symtab.findUnderscore(countSym);
+ replaceSymbol<DefinedSynthetic>(t, t->getName(), tableChunk);
+ cast<DefinedAbsolute>(c)->setVA(tableChunk->getSize() / (hasFlag ? 5 : 4));
+ });
}
// Create CHPE metadata chunks.
diff --git a/lld/test/COFF/arm64x-guardcf.s b/lld/test/COFF/arm64x-guardcf.s
new file mode 100644
index 0000000000000..750bf0b3862c5
--- /dev/null
+++ b/lld/test/COFF/arm64x-guardcf.s
@@ -0,0 +1,122 @@
+// REQUIRES: aarch64, x86
+// RUN: split-file %s %t.dir && cd %t.dir
+
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows func-gfids.s -o func-gfids-arm64.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows func-gfids.s -o func-gfids-arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows func-exp.s -o func-exp-arm64.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows func-exp.s -o func-exp-arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows dllmain.s -o dllmain-arm64.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows dllmain.s -o dllmain-arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=x86_64-windows func-amd64.s -o func-amd64.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj
+
+
+// Check that CF guard tables contain both native and EC symbols and are referenced from both load configs.
+
+// RUN: lld-link -dll -noentry -machine:arm64x func-gfids-arm64.obj func-gfids-arm64ec.obj func-amd64.obj -guard:cf -out:out.dll \
+// RUN: loadconfig-arm64ec.obj loadconfig-arm64.obj
+// RUN: llvm-readobj --coff-load-config out.dll | FileCheck --check-prefix=LOADCFG %s
+
+// LOADCFG: LoadConfig [
+// LOADCFG: GuardCFFunctionCount: 3
+// LOADCFG-NEXT: GuardFlags [ (0x10500)
+// LOADCFG-NEXT: CF_FUNCTION_TABLE_PRESENT (0x400)
+// LOADCFG-NEXT: CF_INSTRUMENTED (0x100)
+// LOADCFG-NEXT: CF_LONGJUMP_TABLE_PRESENT (0x10000)
+// LOADCFG-NEXT: ]
+// LOADCFG: ]
+// LOADCFG: GuardFidTable [
+// LOADCFG-NEXT: 0x180001000
+// LOADCFG-NEXT: 0x180002000
+// LOADCFG-NEXT: 0x180003000
+// LOADCFG-NEXT: ]
+// LOADCFG: HybridObject {
+// LOADCFG: LoadConfig [
+// LOADCFG: GuardCFFunctionCount: 3
+// LOADCFG-NEXT: GuardFlags [ (0x10500)
+// LOADCFG-NEXT: CF_FUNCTION_TABLE_PRESENT (0x400)
+// LOADCFG-NEXT: CF_INSTRUMENTED (0x100)
+// LOADCFG-NEXT: CF_LONGJUMP_TABLE_PRESENT (0x10000)
+// LOADCFG-NEXT: ]
+// LOADCFG: ]
+// LOADCFG: GuardFidTable [
+// LOADCFG-NEXT: 0x180001000
+// LOADCFG-NEXT: 0x180002000
+// LOADCFG-NEXT: 0x180003000
+// LOADCFG-NEXT: ]
+// LOADCFG: ]
+
+
+// Check that exports from both views are present in CF guard tables.
+
+// RUN: lld-link -dll -noentry -machine:arm64x func-exp-arm64.obj func-exp-arm64ec.obj -guard:cf -out:out-exp.dll \
+// RUN: loadconfig-arm64ec.obj loadconfig-arm64.obj
+// RUN: llvm-readobj --coff-load-config out-exp.dll | FileCheck --check-prefix=LOADCFG %s
+
+
+// Check that entry points from both views are present in CF guard tables.
+
+// RUN: lld-link -dll -machine:arm64x dllmain-arm64.obj dllmain-arm64ec.obj -guard:cf -out:out-entry.dll \
+// RUN: loadconfig-arm64ec.obj loadconfig-arm64.obj
+// RUN: llvm-readobj --coff-load-config out-entry.dll | FileCheck --check-prefix=LOADCFG %s
+
+
+// Check that both load configs are marked as instrumented if any input object was built with /guard:cf.
+
+// RUN: lld-link -dll -noentry -machine:arm64x func-gfids-arm64ec.obj -out:out-nocfg.dll \
+// RUN: loadconfig-arm64ec.obj loadconfig-arm64.obj
+
+// RUN: llvm-readobj --coff-load-config out-nocfg.dll | FileCheck --check-prefix=LOADCFG-INST %s
+
+// LOADCFG-INST: LoadConfig [
+// LOADCFG-INST: GuardFlags [ (0x100)
+// LOADCFG-INST-NEXT: CF_INSTRUMENTED (0x100)
+// LOADCFG-INST-NEXT: ]
+// LOADCFG-INST: ]
+// LOADCFG-INST: HybridObject {
+// LOADCFG-INST: LoadConfig [
+// LOADCFG-INST: GuardFlags [ (0x100)
+// LOADCFG-INST-NEXT: CF_INSTRUMENTED (0x100)
+// LOADCFG-INST-NEXT: ]
+// LOADCFG-INST: ]
+// LOADCFG-INST: ]
+
+#--- func-gfids.s
+ .def @feat.00; .scl 3; .type 0; .endef
+ .globl @feat.00
+ at feat.00 = 0x800
+
+ .globl func
+func:
+ ret
+
+ .section .gfids$y,"dr"
+ .symidx func
+
+#--- func-amd64.s
+ .def @feat.00; .scl 3; .type 0; .endef
+ .globl @feat.00
+ at feat.00 = 0x800
+
+ .globl func_amd64
+func_amd64:
+ ret
+
+ .section .gfids$y,"dr"
+ .symidx func_amd64
+
+#--- func-exp.s
+ .def func; .scl 2; .type 32; .endef
+ .globl func
+func:
+ ret
+
+ .section .drectve
+ .ascii "-export:func"
+
+#--- dllmain.s
+ .def _DllMainCRTStartup; .scl 2; .type 32; .endef
+ .globl _DllMainCRTStartup
+_DllMainCRTStartup:
+ ret
More information about the llvm-commits
mailing list