Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 1 addition & 8 deletions lld/COFF/DLL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ void IdataContents::create(COFFLinkerContext &ctx) {
dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry), 4));
}

std::vector<Chunk *> DelayLoadContents::getChunks() {
std::vector<Chunk *> DelayLoadContents::getRDataChunks() {
std::vector<Chunk *> v;
v.insert(v.end(), dirs.begin(), dirs.end());
v.insert(v.end(), names.begin(), names.end());
Expand All @@ -900,13 +900,6 @@ std::vector<Chunk *> DelayLoadContents::getChunks() {
return v;
}

std::vector<Chunk *> DelayLoadContents::getDataChunks() {
std::vector<Chunk *> v;
v.insert(v.end(), moduleHandles.begin(), moduleHandles.end());
v.insert(v.end(), addresses.begin(), addresses.end());
return v;
}

uint64_t DelayLoadContents::getDirSize() {
return dirs.size() * sizeof(delay_import_directory_table_entry);
}
Expand Down
5 changes: 3 additions & 2 deletions lld/COFF/DLL.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ class DelayLoadContents {
void add(DefinedImportData *sym) { imports.push_back(sym); }
bool empty() { return imports.empty(); }
void create();
std::vector<Chunk *> getChunks();
std::vector<Chunk *> getDataChunks();
ArrayRef<Chunk *> getChunks() { return addresses; }
std::vector<Chunk *> getRDataChunks();
ArrayRef<Chunk *> getDataChunks() { return moduleHandles; }
ArrayRef<Chunk *> getCodeChunks() { return thunks; }
ArrayRef<Chunk *> getCodePData() { return pdata; }
ArrayRef<Chunk *> getCodeUnwindInfo() { return unwindinfo; }
Expand Down
1 change: 0 additions & 1 deletion lld/COFF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2015,7 +2015,6 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
// Add default section merging rules after user rules. User rules take
// precedence, but we will emit a warning if there is a conflict.
parseMerge(".idata=.rdata");
parseMerge(".didat=.rdata");
parseMerge(".edata=.rdata");
parseMerge(".xdata=.rdata");
parseMerge(".00cfg=.rdata");
Expand Down
4 changes: 3 additions & 1 deletion lld/COFF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1083,7 +1083,7 @@ void Writer::createSections() {
pdataSec = createSection(".pdata", data | r);
idataSec = createSection(".idata", data | r);
edataSec = createSection(".edata", data | r);
didatSec = createSection(".didat", data | r);
didatSec = createSection(".didat", data | r | w);
Copy link
Contributor Author

@jeremyd2019 jeremyd2019 Apr 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MSVC dloadsup.h sayeth:

           // This delay load helper module does not support merging the delay
           // load section to a read only section because memory management
           // would not guarantee that there is commit available - and thus a
           // low memory failure path where the delay load failure hook could
           // not be safely invoked (the delay load section would still be
           // read only) might be encountered.
           //
           // It is a build time configuration problem to produce such a
           // binary so abort here and now so that the problem can be
           // identified & fixed.

Additionally, making this section read-only by default would make such a binary incompatible with OS versions that have ResolveDelayLoadedAPI and don't support IMAGE_GUARD_PROTECT_DELAYLOAD_IAT - they wouldn't know to make the section read-write before writing to it (I know Wine is such a situation).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should put this under some condition. Something like:

if (delay_load_protected) // Check /didatownsection or guard flags directly?
  didatSec = createSection(".didat", data | r | w);
else
  didatSec = createSection(".didat", data | r);

if (isArm64EC(ctx.config.machine))
a64xrmSec = createSection(".a64xrm", data | r);
rsrcSec = createSection(".rsrc", data | r);
Expand Down Expand Up @@ -1329,6 +1329,8 @@ void Writer::appendImportThunks() {
delayIdata.create();
for (Chunk *c : delayIdata.getChunks())
didatSec->addChunk(c);
for (Chunk *c : delayIdata.getRDataChunks())
rdataSec->addChunk(c);
for (Chunk *c : delayIdata.getDataChunks())
dataSec->addChunk(c);
for (Chunk *c : delayIdata.getCodeChunks())
Expand Down
22 changes: 19 additions & 3 deletions lld/test/COFF/arm64-delayimport.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
# RUN: lld-link /entry:main /subsystem:console /out:%t.exe %t.obj %p/Inputs/library-arm64.lib /alternatename:__delayLoadHelper2=main /delayload:library.dll
# RUN: llvm-objdump --no-print-imm-hex -d %t.exe | FileCheck %s --check-prefix DISASM
# RUN: llvm-readobj --coff-imports %t.exe | FileCheck %s -check-prefix IMPORTS
# RUN: llvm-readobj --section-headers %t.exe | FileCheck %s -check-prefix SECTION

# DISASM: 140001014: d0000011 adrp x17, 0x140003000
# DISASM: 140001018: 91002231 add x17, x17, #8
# DISASM: 140001014: f0000011 adrp x17, 0x140004000
# DISASM: 140001018: 91000231 add x17, x17, #0
# DISASM: 14000101c: 14000001 b 0x140001020 <.text+0x20>
# DISASM: 140001020: a9b37bfd stp x29, x30, [sp, #-208]!
# DISASM: 140001024: 910003fd mov x29, sp
Expand Down Expand Up @@ -41,7 +42,7 @@
# IMPORTS: Name: library.dll
# IMPORTS: Attributes: 0x1
# IMPORTS: ModuleHandle: 0x3000
# IMPORTS: ImportAddressTable: 0x3008
# IMPORTS: ImportAddressTable: 0x4000
# IMPORTS: ImportNameTable: 0x2040
# IMPORTS: BoundDelayImportTable: 0x0
# IMPORTS: UnloadDelayImportTable: 0x0
Expand All @@ -50,6 +51,21 @@
# IMPORTS: Address: 0x140001014
# IMPORTS: }
# IMPORTS: }
# SECTION: Name: .didat (2E 64 69 64 61 74 00 00)
# SECTION-NEXT: VirtualSize: 0x10
# SECTION-NEXT: VirtualAddress: 0x4000
# SECTION-NEXT: RawDataSize: 512
# SECTION-NEXT: PointerToRawData: 0x{{[0-9A-F]+}}
# SECTION-NEXT: PointerToRelocations: 0x0
# SECTION-NEXT: PointerToLineNumbers: 0x0
# SECTION-NEXT: RelocationCount: 0
# SECTION-NEXT: LineNumberCount: 0
# SECTION-NEXT: Characteristics [ (0xC0000040)
# SECTION-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
# SECTION-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
# SECTION-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000)
# SECTION-NEXT: ]
# SECTION-NEXT: }

--- !COFF
header:
Expand Down
50 changes: 25 additions & 25 deletions lld/test/COFF/arm64ec-delayimport.test
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ RUN: lld-link -machine:arm64ec -dll -noentry -out:out.dll loadconfig-arm64ec.obj
RUN: helper-mangled.obj test-arm64ec.lib test2-arm64ec.lib -delayload:test.dll -map

RUN: llvm-readobj --hex-dump=.test out.dll | FileCheck --check-prefix=TESTSEC %s
TESTSEC: 0x18000a000 00600000 88700000 00200000 10100000
TESTSEC-NEXT: 0x18000a010 08600000 90700000 10200000 30100000
TESTSEC-NEXT: 0x18000a020 1c100000 3c100000 00300000
TESTSEC: 0x18000b000 00600000 00900000 00200000 10100000
TESTSEC-NEXT: 0x18000b010 08600000 08900000 10200000 30100000
TESTSEC-NEXT: 0x18000b020 1c100000 3c100000 00300000

RUN: llvm-objdump -d out.dll | FileCheck --check-prefix=DISASM %s
DISASM: 0000000180001000 <.text>:
Expand All @@ -25,16 +25,16 @@ DISASM-NEXT: 18000100c: d65f03c0 ret
DISASM-NEXT: 180001010: b0000030 adrp x16, 0x180006000
DISASM-NEXT: 180001014: f9400210 ldr x16, [x16]
DISASM-NEXT: 180001018: d61f0200 br x16
DISASM-NEXT: 18000101c: d000002b adrp x11, 0x180007000
DISASM-NEXT: 180001020: f940456b ldr x11, [x11, #0x88]
DISASM-NEXT: 18000101c: 9000004b adrp x11, 0x180009000
DISASM-NEXT: 180001020: f940016b ldr x11, [x11]
DISASM-NEXT: 180001024: 9000000a adrp x10, 0x180001000 <.text>
DISASM-NEXT: 180001028: 9101414a add x10, x10, #0x50
DISASM-NEXT: 18000102c: 17fffff5 b 0x180001000 <.text>
DISASM-NEXT: 180001030: b0000030 adrp x16, 0x180006000
DISASM-NEXT: 180001034: f9400610 ldr x16, [x16, #0x8]
DISASM-NEXT: 180001038: d61f0200 br x16
DISASM-NEXT: 18000103c: d000002b adrp x11, 0x180007000
DISASM-NEXT: 180001040: f940496b ldr x11, [x11, #0x90]
DISASM-NEXT: 18000103c: 9000004b adrp x11, 0x180009000
DISASM-NEXT: 180001040: f940056b ldr x11, [x11, #0x8]
DISASM-NEXT: 180001044: 9000000a adrp x10, 0x180001000 <.text>
DISASM-NEXT: 180001048: 9101614a add x10, x10, #0x58
DISASM-NEXT: 18000104c: 17ffffed b 0x180001000 <.text>
Expand All @@ -43,13 +43,13 @@ DISASM-NEXT: 180001054: d65f03c0 ret
DISASM-NEXT: 180001058: 52800060 mov w0, #0x3 // =3
DISASM-NEXT: 18000105c: d65f03c0 ret
DISASM-NEXT: ...
DISASM-NEXT: 180002000: ff 25 82 50 00 00 jmpq *0x5082(%rip) # 0x180007088
DISASM-NEXT: 180002000: ff 25 fa 6f 00 00 jmpq *0x6ffa(%rip) # 0x180009000
DISASM-NEXT: ...
DISASM-NEXT: 18000200e: 00 00 addb %al, (%rax)
DISASM-NEXT: 180002010: ff 25 7a 50 00 00 jmpq *0x507a(%rip) # 0x180007090
DISASM-NEXT: 180002016: 48 8d 05 6b 50 00 00 leaq 0x506b(%rip), %rax # 0x180007088
DISASM-NEXT: 180002010: ff 25 f2 6f 00 00 jmpq *0x6ff2(%rip) # 0x180009008
DISASM-NEXT: 180002016: 48 8d 05 e3 6f 00 00 leaq 0x6fe3(%rip), %rax # 0x180009000
DISASM-NEXT: 18000201d: e9 0c 00 00 00 jmp 0x18000202e <.text+0x102e>
DISASM-NEXT: 180002022: 48 8d 05 67 50 00 00 leaq 0x5067(%rip), %rax # 0x180007090
DISASM-NEXT: 180002022: 48 8d 05 df 6f 00 00 leaq 0x6fdf(%rip), %rax # 0x180009008
DISASM-NEXT: 180002029: e9 00 00 00 00 jmp 0x18000202e <.text+0x102e>
DISASM-NEXT: 18000202e: 51 pushq %rcx
DISASM-NEXT: 18000202f: 52 pushq %rdx
Expand All @@ -61,7 +61,7 @@ DISASM-NEXT: 18000203d: 66 0f 7f 4c 24 10 movdqa %xmm1, 0x10(%rsp)
DISASM-NEXT: 180002043: 66 0f 7f 54 24 20 movdqa %xmm2, 0x20(%rsp)
DISASM-NEXT: 180002049: 66 0f 7f 5c 24 30 movdqa %xmm3, 0x30(%rsp)
DISASM-NEXT: 18000204f: 48 8b d0 movq %rax, %rdx
DISASM-NEXT: 180002052: 48 8d 0d a7 21 00 00 leaq 0x21a7(%rip), %rcx # 0x180004200
DISASM-NEXT: 180002052: 48 8d 0d a7 1f 00 00 leaq 0x1fa7(%rip), %rcx # 0x180004000
DISASM-NEXT: 180002059: e8 aa ef ff ff callq 0x180001008 <.text+0x8>
DISASM-NEXT: 18000205e: 66 0f 6f 04 24 movdqa (%rsp), %xmm0
DISASM-NEXT: 180002063: 66 0f 6f 4c 24 10 movdqa 0x10(%rsp), %xmm1
Expand All @@ -77,15 +77,15 @@ DISASM-NEXT: 18000207f: ff e0 jmpq *%rax
RUN: llvm-readobj --coff-load-config out.dll | FileCheck --check-prefix=LOADCFG %s
LOADCFG: CHPEMetadata [
LOADCFG: AuxiliaryDelayloadIAT: 0x6000
LOADCFG-NEXT: AuxiliaryDelayloadIATCopy: 0x4000
LOADCFG-NEXT: AuxiliaryDelayloadIATCopy: 0x4078

RUN: llvm-readobj --coff-imports out.dll | FileCheck --check-prefix=IMPORTS %s
IMPORTS: DelayImport {
IMPORTS-NEXT: Name: test.dll
IMPORTS-NEXT: Attributes: 0x1
IMPORTS-NEXT: ModuleHandle: 0x7080
IMPORTS-NEXT: ImportAddressTable: 0x7088
IMPORTS-NEXT: ImportNameTable: 0x4240
IMPORTS-NEXT: ImportAddressTable: 0x9000
IMPORTS-NEXT: ImportNameTable: 0x4040
IMPORTS-NEXT: BoundDelayImportTable: 0x0
IMPORTS-NEXT: UnloadDelayImportTable: 0x0
IMPORTS-NEXT: Import {
Expand All @@ -109,29 +109,29 @@ MAP-NEXT: 0001:00000058 func2_exit_thunk 0000000180001058 t
MAP-NEXT: 0001:00001000 func 0000000180002000 test-arm64ec:test.dll
MAP-NEXT: 0001:00001010 func2 0000000180002010 test-arm64ec:test.dll
MAP-NEXT: 0002:00000000 __imp_data 0000000180003000 test2-arm64ec:test2.dll
MAP-NEXT: 0000:00000000 __hybrid_auxiliary_delayload_iat_copy 0000000180004000 <linker-defined>
MAP-NEXT: 0002:00001000 __auximpcopy_func 0000000180004000 test-arm64ec:test.dll
MAP-NEXT: 0002:00001008 __auximpcopy_func2 0000000180004008 test-arm64ec:test.dll
MAP-NEXT: 0000:00000000 __hybrid_auxiliary_delayload_iat_copy 0000000180004078 <linker-defined>
MAP-NEXT: 0002:00001078 __auximpcopy_func 0000000180004078 test-arm64ec:test.dll
MAP-NEXT: 0002:00001080 __auximpcopy_func2 0000000180004080 test-arm64ec:test.dll
MAP: 0002:00003000 __imp_func 0000000180006000 test-arm64ec:test.dll
MAP-NEXT: 0002:00003008 __imp_func2 0000000180006008 test-arm64ec:test.dll
MAP: 0003:00000088 __imp_aux_func 0000000180007088 test-arm64ec:test.dll
MAP-NEXT: 0003:00000090 __imp_aux_func2 0000000180007090 test-arm64ec:test.dll
MAP: 0005:00000000 __imp_aux_func 0000000180009000 test-arm64ec:test.dll
MAP-NEXT: 0005:00000008 __imp_aux_func2 0000000180009008 test-arm64ec:test.dll

RUN: llvm-readobj --hex-dump=.rdata out.dll | FileCheck --check-prefix=RDATA %s
RDATA: 0x180004000 1c100080 01000000 3c100080 01000000
RDATA-NEXT: 0x180004010 00000000 00000000
RDATA: 0x180004070 {{[0-9a-f]{8} [0-9a-f]{8} }}1c100080 01000000
RDATA-NEXT: 0x180004080 3c100080 01000000 00000000 00000000
RDATA: 0x180006000 1c100080 01000000 3c100080 01000000
RDATA-NEXT: 0x180006010 00000000 00000000

RUN: llvm-readobj --coff-basereloc out.dll | FileCheck --check-prefix=RELOC %s
RELOC: BaseReloc [
RELOC-NEXT: Entry {
RELOC-NEXT: Type: DIR64
RELOC-NEXT: Address: 0x4000
RELOC-NEXT: Address: 0x4078
RELOC-NEXT: }
RELOC-NEXT: Entry {
RELOC-NEXT: Type: DIR64
RELOC-NEXT: Address: 0x4008
RELOC-NEXT: Address: 0x4080
RELOC-NEXT: }
RELOC: Address: 0x6000
RELOC-NEXT: }
Expand All @@ -141,7 +141,7 @@ RELOC-NEXT: Address: 0x6008
RELOC-NEXT: }

RUN: llvm-readobj --hex-dump=.pdata out.dll | FileCheck --check-prefix=PDATA %s
PDATA: 0x180008000 2e200000 81200000 18400000
PDATA: 0x180008000 2e200000 81200000 90400000

Verify that a demangled version of __delayLoadHelper2 can be used.

Expand Down
Loading
Loading