diff options
author | Jacek Caban <jacek@codeweavers.com> | 2025-02-17 20:03:32 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-17 20:03:32 +0100 |
commit | 15944056aa5c1ab2c777dd2e3b4f19b8a1f1403d (patch) | |
tree | 8970613605868f7cd5d992eb9f1e86f2c6a85ad2 | |
parent | 0d2722c20d75b237524dd4ec87a1d3da707ec96e (diff) | |
download | llvm-15944056aa5c1ab2c777dd2e3b4f19b8a1f1403d.zip llvm-15944056aa5c1ab2c777dd2e3b4f19b8a1f1403d.tar.gz llvm-15944056aa5c1ab2c777dd2e3b4f19b8a1f1403d.tar.bz2 |
[LLD][COFF] Split native and EC .CRT chunks on ARM64X (#127203)
-rw-r--r-- | lld/COFF/Writer.cpp | 11 | ||||
-rw-r--r-- | lld/COFF/Writer.h | 3 | ||||
-rw-r--r-- | lld/test/COFF/arm64x-crt-sec.s | 42 |
3 files changed, 56 insertions, 0 deletions
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 678de91..5045580 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -403,6 +403,12 @@ void OutputSection::addContributingPartialSection(PartialSection *sec) { contribSections.push_back(sec); } +void OutputSection::splitECChunks() { + llvm::stable_sort(chunks, [=](const Chunk *a, const Chunk *b) { + return (a->getMachine() != ARM64) < (b->getMachine() != ARM64); + }); +} + // Check whether the target address S is in range from a relocation // of type relType at address P. bool Writer::isInRange(uint16_t relType, uint64_t s, uint64_t p, int margin, @@ -1156,6 +1162,11 @@ void Writer::createSections() { sec->addContributingPartialSection(pSec); } + if (ctx.hybridSymtab) { + if (OutputSection *sec = findSection(".CRT")) + sec->splitECChunks(); + } + // Finally, move some output sections to the end. auto sectionOrder = [&](const OutputSection *s) { // Move DISCARDABLE (or non-memory-mapped) sections to the end of file diff --git a/lld/COFF/Writer.h b/lld/COFF/Writer.h index 9004bb3..7e458b7 100644 --- a/lld/COFF/Writer.h +++ b/lld/COFF/Writer.h @@ -50,6 +50,9 @@ public: void writeHeaderTo(uint8_t *buf, bool isDebug); void addContributingPartialSection(PartialSection *sec); + // Sort chunks to split native and EC sections on hybrid targets. + void splitECChunks(); + // Returns the size of this section in an executable memory image. // This may be smaller than the raw size (the raw size is multiple // of disk sector size, so there may be padding at end), or may be diff --git a/lld/test/COFF/arm64x-crt-sec.s b/lld/test/COFF/arm64x-crt-sec.s new file mode 100644 index 0000000..5be70a1 --- /dev/null +++ b/lld/test/COFF/arm64x-crt-sec.s @@ -0,0 +1,42 @@ +// REQUIRES: aarch64, x86 +// RUN: split-file %s %t.dir && cd %t.dir + +// RUN: llvm-mc -filetype=obj -triple=aarch64-windows crt1-arm64.s -o crt1-arm64.obj +// RUN: llvm-mc -filetype=obj -triple=aarch64-windows crt2-arm64.s -o crt2-arm64.obj +// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows crt1-arm64ec.s -o crt1-arm64ec.obj +// RUN: llvm-mc -filetype=obj -triple=x86_64-windows crt2-amd64.s -o crt2-amd64.obj + +// Check that .CRT chunks are correctly sorted and that EC and native chunks are split. + +// RUN: lld-link -out:out.dll -machine:arm64x -dll -noentry crt1-arm64.obj crt2-arm64.obj crt1-arm64ec.obj crt2-amd64.obj +// RUN: llvm-readobj --hex-dump=.CRT out.dll | FileCheck %s + +// RUN: lld-link -out:out2.dll -machine:arm64x -dll -noentry crt1-arm64.obj crt1-arm64ec.obj crt2-arm64.obj crt2-amd64.obj +// RUN: llvm-readobj --hex-dump=.CRT out2.dll | FileCheck %s + +// RUN: lld-link -out:out3.dll -machine:arm64x -dll -noentry crt2-amd64.obj crt1-arm64ec.obj crt2-arm64.obj crt1-arm64.obj +// RUN: llvm-readobj --hex-dump=.CRT out3.dll | FileCheck %s + +// CHECK: 0x180002000 01000000 00000000 02000000 00000000 +// CHECK-NEXT: 0x180002010 03000000 00000000 11000000 00000000 +// CHECK-NEXT: 0x180002020 12000000 00000000 13000000 00000000 + +#--- crt1-arm64.s + .section .CRT$A,"dr" + .xword 1 + .section .CRT$Z,"dr" + .xword 3 + +#--- crt2-arm64.s + .section .CRT$B,"dr" + .xword 2 + +#--- crt1-arm64ec.s + .section .CRT$A,"dr" + .xword 0x11 + .section .CRT$Z,"dr" + .xword 0x13 + +#--- crt2-amd64.s + .section .CRT$B,"dr" + .quad 0x12 |