Skip to content

Commit a17a245

Browse files
authored
[LLD][COFF] Add Support for auxiliary IAT copy (#108610)
In addition to the auxiliary IAT, ARM64EC modules also contain a copy of it. At runtime, the auxiliary IAT is filled with the addresses of actual ARM64EC functions when possible. If patching is detected, the OS may use the IAT copy to revert the auxiliary IAT, ensuring that the call checker is used for calls to imported functions.
1 parent 07e0b8a commit a17a245

File tree

8 files changed

+47
-5
lines changed

8 files changed

+47
-5
lines changed

lld/COFF/DLL.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,13 +730,19 @@ void IdataContents::create(COFFLinkerContext &ctx) {
730730
auto chunk = make<AuxImportChunk>(s->file);
731731
auxIat.push_back(chunk);
732732
s->file->impECSym->setLocation(chunk);
733+
734+
chunk = make<AuxImportChunk>(s->file);
735+
auxIatCopy.push_back(chunk);
736+
s->file->auxImpCopySym->setLocation(chunk);
733737
}
734738
}
735739
// Terminate with null values.
736740
lookups.push_back(make<NullChunk>(ctx.config.wordsize));
737741
addresses.push_back(make<NullChunk>(ctx.config.wordsize));
738-
if (ctx.config.machine == ARM64EC)
742+
if (ctx.config.machine == ARM64EC) {
739743
auxIat.push_back(make<NullChunk>(ctx.config.wordsize));
744+
auxIatCopy.push_back(make<NullChunk>(ctx.config.wordsize));
745+
}
740746

741747
for (int i = 0, e = syms.size(); i < e; ++i)
742748
syms[i]->setLocation(addresses[base + i]);

lld/COFF/DLL.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class IdataContents {
3232
std::vector<Chunk *> hints;
3333
std::vector<Chunk *> dllNames;
3434
std::vector<Chunk *> auxIat;
35+
std::vector<Chunk *> auxIatCopy;
3536
};
3637

3738
// Windows-specific.

lld/COFF/Driver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2448,6 +2448,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
24482448
ctx.symtab.addAbsolute("__arm64x_redirection_metadata", 0);
24492449
ctx.symtab.addAbsolute("__arm64x_redirection_metadata_count", 0);
24502450
ctx.symtab.addAbsolute("__hybrid_auxiliary_iat", 0);
2451+
ctx.symtab.addAbsolute("__hybrid_auxiliary_iat_copy", 0);
24512452
ctx.symtab.addAbsolute("__hybrid_code_map", 0);
24522453
ctx.symtab.addAbsolute("__hybrid_code_map_count", 0);
24532454
ctx.symtab.addAbsolute("__x64_code_ranges_to_entry_points", 0);

lld/COFF/InputFiles.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,12 @@ void ImportFile::parse() {
10911091
}
10921092
if (!impECSym)
10931093
return;
1094+
1095+
StringRef auxImpCopyName = saver().save("__auximpcopy_" + name);
1096+
auxImpCopySym =
1097+
ctx.symtab.addImportData(auxImpCopyName, this, auxCopyLocation);
1098+
if (!auxImpCopySym)
1099+
return;
10941100
}
10951101
// If this was a duplicate, we logged an error but may continue;
10961102
// in this case, impSym is nullptr.

lld/COFF/InputFiles.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,12 @@ class ImportFile : public InputFile {
362362
const coff_import_header *hdr;
363363
Chunk *location = nullptr;
364364

365-
// Auxiliary IAT symbol and chunk on ARM64EC.
365+
// Auxiliary IAT symbols and chunks on ARM64EC.
366366
DefinedImportData *impECSym = nullptr;
367367
Chunk *auxLocation = nullptr;
368368
Symbol *auxThunkSym = nullptr;
369+
DefinedImportData *auxImpCopySym = nullptr;
370+
Chunk *auxCopyLocation = nullptr;
369371

370372
// We want to eliminate dllimported symbols if no one actually refers to them.
371373
// These "Live" bits are used to keep track of which import library members

lld/COFF/Writer.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,8 @@ void Writer::addSyntheticIdata() {
916916
add(".idata$7", idata.dllNames);
917917
if (!idata.auxIat.empty())
918918
add(".idata$9", idata.auxIat);
919+
if (!idata.auxIatCopy.empty())
920+
add(".idata$a", idata.auxIatCopy);
919921
}
920922

921923
void Writer::appendECImportTables() {
@@ -2279,6 +2281,11 @@ void Writer::setECSymbols() {
22792281
replaceSymbol<DefinedSynthetic>(iatSym, "__hybrid_auxiliary_iat",
22802282
idata.auxIat.empty() ? nullptr
22812283
: idata.auxIat.front());
2284+
2285+
Symbol *iatCopySym = ctx.symtab.findUnderscore("__hybrid_auxiliary_iat_copy");
2286+
replaceSymbol<DefinedSynthetic>(
2287+
iatCopySym, "__hybrid_auxiliary_iat_copy",
2288+
idata.auxIatCopy.empty() ? nullptr : idata.auxIatCopy.front());
22822289
}
22832290

22842291
// Write section contents to a mmap'ed file.

lld/test/COFF/Inputs/loadconfig-arm64ec.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ __chpe_metadata:
8484
.rva __arm64x_extra_rfe_table
8585
.word __arm64x_extra_rfe_table_size
8686
.rva __os_arm64x_dispatch_fptr
87-
.word 0 // __hybrid_auxiliary_iat_copy
87+
.rva __hybrid_auxiliary_iat_copy
8888
.rva __os_arm64x_helper0
8989
.rva __os_arm64x_helper1
9090
.rva __os_arm64x_helper2

lld/test/COFF/arm64ec-import.test

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ RUN: llvm-readobj --coff-imports out2.dll | FileCheck --check-prefix=IMPORTS %s
2727
RUN: llvm-readobj --coff-imports out3.dll | FileCheck -check-prefix=IMPORTS %s
2828
IMPORTS: Import {
2929
IMPORTS-NEXT: Name: test.dll
30-
IMPORTS-NEXT: ImportLookupTableRVA:
30+
IMPORTS-NEXT: ImportLookupTableRVA: 0x4230
3131
IMPORTS-NEXT: ImportAddressTableRVA: 0x3000
3232
IMPORTS-NEXT: Symbol: data (0)
3333
IMPORTS-NEXT: Symbol: func (0)
@@ -79,12 +79,13 @@ RUN: llvm-readobj --hex-dump=.test out2.dll | FileCheck --check-prefix=TESTSEC %
7979
TESTSEC: 0x180007000 08500000 00300000 10500000 20500000
8080
TESTSEC-NEXT: 0x180007010 08300000 00500000 10300000 20300000
8181
TESTSEC-NEXT: 0x180007020 14100000 28100000 00200000 08100000
82-
TESTSEC-NEXT: 0x180007030 3c100000
82+
TESTSEC-NEXT: 0x180007030 3c100000 a0420000
8383

8484
RUN: llvm-readobj --hex-dump=.test out3.dll | FileCheck -check-prefix=TESTSEC-X64 %s
8585
TESTSEC-X64: 0x180007000 08300000 00300000 10300000 20300000
8686
TESTSEC-X64-NEXT: 0x180007010 08300000 00500000 10300000 20300000
8787
TESTSEC-X64-NEXT: 0x180007020 14100000 28100000 00200000 08100000
88+
TESTSEC-X64-NEXT: 0x180007030 3c100000 a0420000
8889

8990
RUN: llvm-readobj --headers out.dll | FileCheck -check-prefix=HEADERS %s
9091
RUN: llvm-readobj --headers out2.dll | FileCheck -check-prefix=HEADERS %s
@@ -97,10 +98,15 @@ RUN: llvm-readobj --coff-load-config out.dll | FileCheck -check-prefix=LOADCONFI
9798
RUN: llvm-readobj --coff-load-config out2.dll | FileCheck -check-prefix=LOADCONFIG %s
9899
RUN: llvm-readobj --coff-load-config out3.dll | FileCheck -check-prefix=LOADCONFIG %s
99100
LOADCONFIG: AuxiliaryIAT: 0x5000
101+
LOADCONFIG: AuxiliaryIATCopy: 0x4298
100102

101103
RUN: llvm-readobj --hex-dump=.rdata out.dll | FileCheck -check-prefix=RDATA %s
102104
RUN: llvm-readobj --hex-dump=.rdata out2.dll | FileCheck -check-prefix=RDATA %s
103105
RUN: llvm-readobj --hex-dump=.rdata out3.dll | FileCheck -check-prefix=RDATA %s
106+
RDATA: 0x180004290 2e646c6c 00000000 00000000 00000000
107+
RDATA-NEXT: 0x1800042a0 14100080 01000000 28100080 01000000
108+
RDATA-NEXT: 0x1800042b0 00000000 00000000 48100080 01000000
109+
RDATA-NEXT: 0x1800042c0 00000000 00000000 00000000 00000000
104110
RDATA: 0x180005000 00000000 00000000 14100080 01000000
105111
RDATA-NEXT: 0x180005010 28100080 01000000 00000000 00000000
106112
RDATA-NEXT: 0x180005020 48100080 01000000 00000000 00000000
@@ -109,6 +115,18 @@ RUN: llvm-readobj --coff-basereloc out.dll | FileCheck -check-prefix=BASERELOC %
109115
RUN: llvm-readobj --coff-basereloc out2.dll | FileCheck -check-prefix=BASERELOC %s
110116
RUN: llvm-readobj --coff-basereloc out3.dll | FileCheck -check-prefix=BASERELOC %s
111117
BASERELOC: BaseReloc [
118+
Aux IAT copy:
119+
BASERELOC: Address: 0x42A0
120+
BASERELOC-NEXT: }
121+
BASERELOC-NEXT: Entry {
122+
BASERELOC-NEXT: Type: DIR64
123+
BASERELOC-NEXT: Address: 0x42A8
124+
BASERELOC-NEXT: }
125+
BASERELOC-NEXT: Entry {
126+
BASERELOC-NEXT: Type: DIR64
127+
BASERELOC-NEXT: Address: 0x42B8
128+
BASERELOC-NEXT: }
129+
Aux IAT:
112130
BASERELOC-NOT: Address: 0x5000
113131
BASERELOC: Address: 0x5008
114132
BASERELOC-NEXT: }
@@ -139,6 +157,7 @@ arm64ec_data_sym:
139157
.rva func
140158
.rva "#func"
141159
.rva "#t2func"
160+
.rva __auximpcopy_func
142161

143162
#--- icall.s
144163
.text

0 commit comments

Comments
 (0)