Skip to content

[LLD][COFF] Support MinGW constructor and destructor lists on ARM64X #127205

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

Merged
merged 1 commit into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 6 additions & 2 deletions lld/COFF/Chunks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1070,16 +1070,20 @@ void MergeChunk::writeTo(uint8_t *buf) const {
}

// MinGW specific.
size_t AbsolutePointerChunk::getSize() const { return ctx.config.wordsize; }
size_t AbsolutePointerChunk::getSize() const {
return symtab.ctx.config.wordsize;
}

void AbsolutePointerChunk::writeTo(uint8_t *buf) const {
if (ctx.config.is64()) {
if (symtab.ctx.config.is64()) {
write64le(buf, value);
} else {
write32le(buf, value);
}
}

MachineTypes AbsolutePointerChunk::getMachine() const { return symtab.machine; }

void ECExportThunkChunk::writeTo(uint8_t *buf) const {
memcpy(buf, ECExportThunkCode, sizeof(ECExportThunkCode));
write32le(buf + 10, target->getRVA() - rva - 14);
Expand Down
7 changes: 4 additions & 3 deletions lld/COFF/Chunks.h
Original file line number Diff line number Diff line change
Expand Up @@ -910,16 +910,17 @@ class PseudoRelocTableChunk : public NonSectionChunk {
// MinGW specific. A Chunk that contains one pointer-sized absolute value.
class AbsolutePointerChunk : public NonSectionChunk {
public:
AbsolutePointerChunk(COFFLinkerContext &ctx, uint64_t value)
: value(value), ctx(ctx) {
AbsolutePointerChunk(SymbolTable &symtab, uint64_t value)
: value(value), symtab(symtab) {
setAlignment(getSize());
}
size_t getSize() const override;
void writeTo(uint8_t *buf) const override;
MachineTypes getMachine() const override;

private:
uint64_t value;
COFFLinkerContext &ctx;
SymbolTable &symtab;
};

// Return true if this file has the hotpatch flag set to true in the S_COMPILE3
Expand Down
37 changes: 22 additions & 15 deletions lld/COFF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2335,21 +2335,28 @@ void Writer::createRuntimePseudoRelocs() {
// There's a symbol pointing to the start sentinel pointer, __CTOR_LIST__
// and __DTOR_LIST__ respectively.
void Writer::insertCtorDtorSymbols() {
AbsolutePointerChunk *ctorListHead = make<AbsolutePointerChunk>(ctx, -1);
AbsolutePointerChunk *ctorListEnd = make<AbsolutePointerChunk>(ctx, 0);
AbsolutePointerChunk *dtorListHead = make<AbsolutePointerChunk>(ctx, -1);
AbsolutePointerChunk *dtorListEnd = make<AbsolutePointerChunk>(ctx, 0);
ctorsSec->insertChunkAtStart(ctorListHead);
ctorsSec->addChunk(ctorListEnd);
dtorsSec->insertChunkAtStart(dtorListHead);
dtorsSec->addChunk(dtorListEnd);

Symbol *ctorListSym = ctx.symtab.findUnderscore("__CTOR_LIST__");
Symbol *dtorListSym = ctx.symtab.findUnderscore("__DTOR_LIST__");
replaceSymbol<DefinedSynthetic>(ctorListSym, ctorListSym->getName(),
ctorListHead);
replaceSymbol<DefinedSynthetic>(dtorListSym, dtorListSym->getName(),
dtorListHead);
ctx.forEachSymtab([&](SymbolTable &symtab) {
AbsolutePointerChunk *ctorListHead = make<AbsolutePointerChunk>(symtab, -1);
AbsolutePointerChunk *ctorListEnd = make<AbsolutePointerChunk>(symtab, 0);
AbsolutePointerChunk *dtorListHead = make<AbsolutePointerChunk>(symtab, -1);
AbsolutePointerChunk *dtorListEnd = make<AbsolutePointerChunk>(symtab, 0);
ctorsSec->insertChunkAtStart(ctorListHead);
ctorsSec->addChunk(ctorListEnd);
dtorsSec->insertChunkAtStart(dtorListHead);
dtorsSec->addChunk(dtorListEnd);

Symbol *ctorListSym = symtab.findUnderscore("__CTOR_LIST__");
Symbol *dtorListSym = symtab.findUnderscore("__DTOR_LIST__");
replaceSymbol<DefinedSynthetic>(ctorListSym, ctorListSym->getName(),
ctorListHead);
replaceSymbol<DefinedSynthetic>(dtorListSym, dtorListSym->getName(),
dtorListHead);
});

if (ctx.hybridSymtab) {
ctorsSec->splitECChunks();
dtorsSec->splitECChunks();
}
}

// Handles /section options to allow users to overwrite
Expand Down
76 changes: 76 additions & 0 deletions lld/test/COFF/arm64x-ctors-sec.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// REQUIRES: aarch64, x86
// RUN: split-file %s %t.dir && cd %t.dir

// RUN: llvm-mc -filetype=obj -triple=aarch64-windows ctor1-arm64.s -o ctor1-arm64.obj
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows ctor2-arm64.s -o ctor2-arm64.obj
// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows ctor1-arm64ec.s -o ctor1-arm64ec.obj
// RUN: llvm-mc -filetype=obj -triple=x86_64-windows ctor2-amd64.s -o ctor2-amd64.obj
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows test.s -o test-arm64.obj
// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows test.s -o test-arm64ec.obj

// Check that .ctors and .dtors chunks are correctly sorted and that EC and native chunks are split.

// RUN: lld-link -out:out.dll -machine:arm64x -lldmingw -dll -noentry test-arm64.obj test-arm64ec.obj \
// RUN: ctor1-arm64.obj ctor2-arm64.obj ctor1-arm64ec.obj ctor2-amd64.obj
// RUN: llvm-readobj --hex-dump=.rdata --hex-dump=.test out.dll | FileCheck %s

// RUN: lld-link -out:out2.dll -machine:arm64x -lldmingw -dll -noentry test-arm64.obj test-arm64ec.obj \
// RUN: ctor1-arm64ec.obj ctor2-amd64.obj ctor1-arm64.obj ctor2-arm64.obj
// RUN: llvm-readobj --hex-dump=.rdata --hex-dump=.test out2.dll | FileCheck %s

// RUN: lld-link -out:out3.dll -machine:arm64x -lldmingw -dll -noentry test-arm64.obj test-arm64ec.obj \
// RUN: ctor2-arm64.obj ctor1-arm64ec.obj ctor2-amd64.obj ctor1-arm64.obj
// RUN: llvm-readobj --hex-dump=.rdata --hex-dump=.test out3.dll | FileCheck %s

// CHECK: Hex dump of section '.rdata':
// CHECK-NEXT: 0x180001000 ffffffff ffffffff 01000000 00000000
// CHECK-NEXT: 0x180001010 02000000 00000000 03000000 00000000
// CHECK-NEXT: 0x180001020 00000000 00000000 ffffffff ffffffff
// CHECK-NEXT: 0x180001030 11000000 00000000 12000000 00000000
// CHECK-NEXT: 0x180001040 13000000 00000000 00000000 00000000
// CHECK-NEXT: 0x180001050 ffffffff ffffffff 01010000 00000000
// CHECK-NEXT: 0x180001060 02010000 00000000 03010000 00000000
// CHECK-NEXT: 0x180001070 00000000 00000000 ffffffff ffffffff
// CHECK-NEXT: 0x180001080 11010000 00000000 12010000 00000000
// CHECK-NEXT: 0x180001090 13010000 00000000 00000000 00000000
// CHECK-EMPTY:
// CHECK-NEXT: Hex dump of section '.test':
// CHECK-NEXT: 0x180003000 00100000 50100000 28100000 78100000

#--- ctor1-arm64.s
.section .ctors.1,"drw"
.xword 1
.section .ctors.3,"drw"
.xword 3
.section .dtors.1,"drw"
.xword 0x101
.section .dtors.3,"drw"
.xword 0x103

#--- ctor2-arm64.s
.section .ctors.2,"drw"
.xword 2
.section .dtors.2,"drw"
.xword 0x102

#--- ctor1-arm64ec.s
.section .ctors.1,"drw"
.xword 0x11
.section .ctors.3,"drw"
.xword 0x13
.section .dtors.1,"drw"
.xword 0x111
.section .dtors.3,"drw"
.xword 0x113

#--- ctor2-amd64.s
.section .ctors.2,"drw"
.quad 0x12
.section .dtors.2,"drw"
.quad 0x112

#--- test.s
.section .test
.rva __CTOR_LIST__
.rva __DTOR_LIST__