Skip to content

Commit 868c409

Browse files
committed
Reapply "[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.
1 parent fefb685 commit 868c409

File tree

2 files changed

+145
-10
lines changed

2 files changed

+145
-10
lines changed

lld/COFF/Writer.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,10 +1986,17 @@ static void maybeAddAddressTakenFunction(SymbolRVASet &addressTakenSyms,
19861986
// Common is always data, so it is ignored.
19871987
break;
19881988
case Symbol::DefinedAbsoluteKind:
1989-
case Symbol::DefinedSyntheticKind:
19901989
// Absolute is never code, synthetic generally isn't and usually isn't
19911990
// determinable.
19921991
break;
1992+
case Symbol::DefinedSyntheticKind:
1993+
// For EC export thunks, mark both the thunk itself and its target.
1994+
if (auto expChunk = dyn_cast_or_null<ECExportThunkChunk>(
1995+
cast<Defined>(s)->getChunk())) {
1996+
addSymbolToRVASet(addressTakenSyms, cast<Defined>(s));
1997+
addSymbolToRVASet(addressTakenSyms, expChunk->target);
1998+
}
1999+
break;
19932000
case Symbol::LazyArchiveKind:
19942001
case Symbol::LazyObjectKind:
19952002
case Symbol::LazyDLLSymbolKind:
@@ -2054,9 +2061,11 @@ void Writer::createGuardCFTables() {
20542061
// with /guard:cf.
20552062
for (ObjFile *file : ctx.objFileInstances) {
20562063
if (file->hasGuardCF()) {
2057-
Symbol *flagSym = ctx.symtab.findUnderscore("__guard_flags");
2058-
cast<DefinedAbsolute>(flagSym)->setVA(
2059-
uint32_t(GuardFlags::CF_INSTRUMENTED));
2064+
ctx.forEachSymtab([&](SymbolTable &symtab) {
2065+
Symbol *flagSym = symtab.findUnderscore("__guard_flags");
2066+
cast<DefinedAbsolute>(flagSym)->setVA(
2067+
uint32_t(GuardFlags::CF_INSTRUMENTED));
2068+
});
20602069
break;
20612070
}
20622071
}
@@ -2138,8 +2147,10 @@ void Writer::createGuardCFTables() {
21382147
guardFlags |= uint32_t(GuardFlags::CF_LONGJUMP_TABLE_PRESENT);
21392148
if (config->guardCF & GuardCFLevel::EHCont)
21402149
guardFlags |= uint32_t(GuardFlags::EH_CONTINUATION_TABLE_PRESENT);
2141-
Symbol *flagSym = ctx.symtab.findUnderscore("__guard_flags");
2142-
cast<DefinedAbsolute>(flagSym)->setVA(guardFlags);
2150+
ctx.forEachSymtab([guardFlags](SymbolTable &symtab) {
2151+
Symbol *flagSym = symtab.findUnderscore("__guard_flags");
2152+
cast<DefinedAbsolute>(flagSym)->setVA(guardFlags);
2153+
});
21432154
}
21442155

21452156
// Take a list of input sections containing symbol table indices and add those
@@ -2210,10 +2221,12 @@ void Writer::maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym,
22102221
tableChunk = make<RVATableChunk>(std::move(tableSymbols));
22112222
rdataSec->addChunk(tableChunk);
22122223

2213-
Symbol *t = ctx.symtab.findUnderscore(tableSym);
2214-
Symbol *c = ctx.symtab.findUnderscore(countSym);
2215-
replaceSymbol<DefinedSynthetic>(t, t->getName(), tableChunk);
2216-
cast<DefinedAbsolute>(c)->setVA(tableChunk->getSize() / (hasFlag ? 5 : 4));
2224+
ctx.forEachSymtab([&](SymbolTable &symtab) {
2225+
Symbol *t = symtab.findUnderscore(tableSym);
2226+
Symbol *c = symtab.findUnderscore(countSym);
2227+
replaceSymbol<DefinedSynthetic>(t, t->getName(), tableChunk);
2228+
cast<DefinedAbsolute>(c)->setVA(tableChunk->getSize() / (hasFlag ? 5 : 4));
2229+
});
22172230
}
22182231

22192232
// Create CHPE metadata chunks.

lld/test/COFF/arm64x-guardcf.s

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// REQUIRES: aarch64, x86
2+
// RUN: split-file %s %t.dir && cd %t.dir
3+
4+
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows func-gfids.s -o func-gfids-arm64.obj
5+
// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows func-gfids.s -o func-gfids-arm64ec.obj
6+
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows func-exp.s -o func-exp-arm64.obj
7+
// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows func-exp.s -o func-exp-arm64ec.obj
8+
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows dllmain.s -o dllmain-arm64.obj
9+
// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows dllmain.s -o dllmain-arm64ec.obj
10+
// RUN: llvm-mc -filetype=obj -triple=x86_64-windows func-amd64.s -o func-amd64.obj
11+
// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
12+
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj
13+
14+
15+
// Check that CF guard tables contain both native and EC symbols and are referenced from both load configs.
16+
17+
// RUN: lld-link -dll -noentry -machine:arm64x func-gfids-arm64.obj func-gfids-arm64ec.obj func-amd64.obj -guard:cf -out:out.dll \
18+
// RUN: loadconfig-arm64ec.obj loadconfig-arm64.obj
19+
// RUN: llvm-readobj --coff-load-config out.dll | FileCheck --check-prefix=LOADCFG %s
20+
21+
// LOADCFG: LoadConfig [
22+
// LOADCFG: GuardCFFunctionCount: 3
23+
// LOADCFG-NEXT: GuardFlags [ (0x10500)
24+
// LOADCFG-NEXT: CF_FUNCTION_TABLE_PRESENT (0x400)
25+
// LOADCFG-NEXT: CF_INSTRUMENTED (0x100)
26+
// LOADCFG-NEXT: CF_LONGJUMP_TABLE_PRESENT (0x10000)
27+
// LOADCFG-NEXT: ]
28+
// LOADCFG: ]
29+
// LOADCFG: GuardFidTable [
30+
// LOADCFG-NEXT: 0x180001000
31+
// LOADCFG-NEXT: 0x180002000
32+
// LOADCFG-NEXT: 0x180003000
33+
// LOADCFG-NEXT: ]
34+
// LOADCFG: HybridObject {
35+
// LOADCFG: LoadConfig [
36+
// LOADCFG: GuardCFFunctionCount: 3
37+
// LOADCFG-NEXT: GuardFlags [ (0x10500)
38+
// LOADCFG-NEXT: CF_FUNCTION_TABLE_PRESENT (0x400)
39+
// LOADCFG-NEXT: CF_INSTRUMENTED (0x100)
40+
// LOADCFG-NEXT: CF_LONGJUMP_TABLE_PRESENT (0x10000)
41+
// LOADCFG-NEXT: ]
42+
// LOADCFG: ]
43+
// LOADCFG: GuardFidTable [
44+
// LOADCFG-NEXT: 0x180001000
45+
// LOADCFG-NEXT: 0x180002000
46+
// LOADCFG-NEXT: 0x180003000
47+
// LOADCFG-NEXT: ]
48+
// LOADCFG: ]
49+
50+
51+
// Check that exports from both views are present in CF guard tables.
52+
53+
// RUN: lld-link -dll -noentry -machine:arm64x func-exp-arm64.obj func-exp-arm64ec.obj -guard:cf -out:out-exp.dll \
54+
// RUN: loadconfig-arm64ec.obj loadconfig-arm64.obj
55+
// RUN: llvm-readobj --coff-load-config out-exp.dll | FileCheck --check-prefix=LOADCFG %s
56+
57+
58+
// Check that entry points from both views are present in CF guard tables.
59+
60+
// RUN: lld-link -dll -machine:arm64x dllmain-arm64.obj dllmain-arm64ec.obj -guard:cf -out:out-entry.dll \
61+
// RUN: loadconfig-arm64ec.obj loadconfig-arm64.obj
62+
// RUN: llvm-readobj --coff-load-config out-entry.dll | FileCheck --check-prefix=LOADCFG %s
63+
64+
65+
// Check that both load configs are marked as instrumented if any input object was built with /guard:cf.
66+
67+
// RUN: lld-link -dll -noentry -machine:arm64x func-gfids-arm64ec.obj -out:out-nocfg.dll \
68+
// RUN: loadconfig-arm64ec.obj loadconfig-arm64.obj
69+
70+
// RUN: llvm-readobj --coff-load-config out-nocfg.dll | FileCheck --check-prefix=LOADCFG-INST %s
71+
72+
// LOADCFG-INST: LoadConfig [
73+
// LOADCFG-INST: GuardFlags [ (0x100)
74+
// LOADCFG-INST-NEXT: CF_INSTRUMENTED (0x100)
75+
// LOADCFG-INST-NEXT: ]
76+
// LOADCFG-INST: ]
77+
// LOADCFG-INST: HybridObject {
78+
// LOADCFG-INST: LoadConfig [
79+
// LOADCFG-INST: GuardFlags [ (0x100)
80+
// LOADCFG-INST-NEXT: CF_INSTRUMENTED (0x100)
81+
// LOADCFG-INST-NEXT: ]
82+
// LOADCFG-INST: ]
83+
// LOADCFG-INST: ]
84+
85+
#--- func-gfids.s
86+
.def @feat.00; .scl 3; .type 0; .endef
87+
.globl @feat.00
88+
@feat.00 = 0x800
89+
90+
.globl func
91+
func:
92+
ret
93+
94+
.section .gfids$y,"dr"
95+
.symidx func
96+
97+
#--- func-amd64.s
98+
.def @feat.00; .scl 3; .type 0; .endef
99+
.globl @feat.00
100+
@feat.00 = 0x800
101+
102+
.globl func_amd64
103+
func_amd64:
104+
ret
105+
106+
.section .gfids$y,"dr"
107+
.symidx func_amd64
108+
109+
#--- func-exp.s
110+
.def func; .scl 2; .type 32; .endef
111+
.globl func
112+
func:
113+
ret
114+
115+
.section .drectve
116+
.ascii "-export:func"
117+
118+
#--- dllmain.s
119+
.def _DllMainCRTStartup; .scl 2; .type 32; .endef
120+
.globl _DllMainCRTStartup
121+
_DllMainCRTStartup:
122+
ret

0 commit comments

Comments
 (0)