Skip to content

Commit

Permalink
[lld] Sort code section chunks by range types on EC targets.
Browse files Browse the repository at this point in the history
Instead of having the code all mixed together, it's separated in each section by sorting chunks.
  • Loading branch information
cjacek committed Oct 18, 2023
1 parent 9322a0c commit a4b91a6
Show file tree
Hide file tree
Showing 5 changed files with 349 additions and 2 deletions.
34 changes: 32 additions & 2 deletions lld/COFF/Chunks.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@
namespace lld::coff {

using llvm::COFF::ImportDirectoryTableEntry;
using llvm::object::COFFSymbolRef;
using llvm::object::SectionRef;
using llvm::object::chpe_range_type;
using llvm::object::coff_relocation;
using llvm::object::coff_section;
using llvm::object::COFFSymbolRef;
using llvm::object::SectionRef;

class Baserel;
class Defined;
Expand Down Expand Up @@ -114,6 +115,9 @@ class Chunk {
// synthesized by the linker.
bool isHotPatchable() const;

MachineTypes getMachine() const;
chpe_range_type getArm64ECRangeType() const;

protected:
Chunk(Kind k = OtherKind) : chunkKind(k), hasData(true), p2Align(0) {}

Expand Down Expand Up @@ -164,6 +168,8 @@ class NonSectionChunk : public Chunk {
// Collect all locations that contain absolute addresses for base relocations.
virtual void getBaserels(std::vector<Baserel> *res) {}

virtual MachineTypes getMachine() const { return IMAGE_FILE_MACHINE_UNKNOWN; }

// Returns a human-readable name of this chunk. Chunks are unnamed chunks of
// bytes, so this is used only for logging or debugging.
virtual StringRef getDebugName() const { return ""; }
Expand Down Expand Up @@ -420,6 +426,24 @@ inline StringRef Chunk::getDebugName() const {
return static_cast<const NonSectionChunk *>(this)->getDebugName();
}

inline MachineTypes Chunk::getMachine() const {
if (isa<SectionChunk>(this))
return static_cast<const SectionChunk *>(this)->getMachine();
else
return static_cast<const NonSectionChunk *>(this)->getMachine();
}

inline chpe_range_type Chunk::getArm64ECRangeType() const {
switch (getMachine()) {
case AMD64:
return chpe_range_type::Amd64;
case ARM64EC:
return chpe_range_type::Arm64EC;
default:
return chpe_range_type::Arm64;
}
}

// This class is used to implement an lld-specific feature (not implemented in
// MSVC) that minimizes the output size by finding string literals sharing tail
// parts and merging them.
Expand Down Expand Up @@ -506,6 +530,7 @@ class ImportThunkChunkX64 : public ImportThunkChunk {
explicit ImportThunkChunkX64(COFFLinkerContext &ctx, Defined *s);
size_t getSize() const override { return sizeof(importThunkX86); }
void writeTo(uint8_t *buf) const override;
MachineTypes getMachine() const override { return AMD64; }
};

class ImportThunkChunkX86 : public ImportThunkChunk {
Expand All @@ -515,6 +540,7 @@ class ImportThunkChunkX86 : public ImportThunkChunk {
size_t getSize() const override { return sizeof(importThunkX86); }
void getBaserels(std::vector<Baserel> *res) override;
void writeTo(uint8_t *buf) const override;
MachineTypes getMachine() const override { return I386; }
};

class ImportThunkChunkARM : public ImportThunkChunk {
Expand All @@ -526,6 +552,7 @@ class ImportThunkChunkARM : public ImportThunkChunk {
size_t getSize() const override { return sizeof(importThunkARM); }
void getBaserels(std::vector<Baserel> *res) override;
void writeTo(uint8_t *buf) const override;
MachineTypes getMachine() const override { return ARMNT; }
};

class ImportThunkChunkARM64 : public ImportThunkChunk {
Expand All @@ -536,6 +563,7 @@ class ImportThunkChunkARM64 : public ImportThunkChunk {
}
size_t getSize() const override { return sizeof(importThunkARM64); }
void writeTo(uint8_t *buf) const override;
MachineTypes getMachine() const override { return ARM64; }
};

class RangeExtensionThunkARM : public NonSectionChunk {
Expand All @@ -546,6 +574,7 @@ class RangeExtensionThunkARM : public NonSectionChunk {
}
size_t getSize() const override;
void writeTo(uint8_t *buf) const override;
MachineTypes getMachine() const override { return ARMNT; }

Defined *target;

Expand All @@ -561,6 +590,7 @@ class RangeExtensionThunkARM64 : public NonSectionChunk {
}
size_t getSize() const override;
void writeTo(uint8_t *buf) const override;
MachineTypes getMachine() const override { return ARM64; }

Defined *target;

Expand Down
8 changes: 8 additions & 0 deletions lld/COFF/DLL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ class ThunkChunkX64 : public NonSectionChunk {
ThunkChunkX64(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {}

size_t getSize() const override { return sizeof(thunkX64); }
MachineTypes getMachine() const override { return AMD64; }

void writeTo(uint8_t *buf) const override {
memcpy(buf, thunkX64, sizeof(thunkX64));
Expand All @@ -334,6 +335,7 @@ class TailMergeChunkX64 : public NonSectionChunk {
TailMergeChunkX64(Chunk *d, Defined *h) : desc(d), helper(h) {}

size_t getSize() const override { return sizeof(tailMergeX64); }
MachineTypes getMachine() const override { return AMD64; }

void writeTo(uint8_t *buf) const override {
memcpy(buf, tailMergeX64, sizeof(tailMergeX64));
Expand Down Expand Up @@ -386,6 +388,7 @@ class ThunkChunkX86 : public NonSectionChunk {
: imp(i), tailMerge(tm), ctx(ctx) {}

size_t getSize() const override { return sizeof(thunkX86); }
MachineTypes getMachine() const override { return I386; }

void writeTo(uint8_t *buf) const override {
memcpy(buf, thunkX86, sizeof(thunkX86));
Expand All @@ -410,6 +413,7 @@ class TailMergeChunkX86 : public NonSectionChunk {
: desc(d), helper(h), ctx(ctx) {}

size_t getSize() const override { return sizeof(tailMergeX86); }
MachineTypes getMachine() const override { return I386; }

void writeTo(uint8_t *buf) const override {
memcpy(buf, tailMergeX86, sizeof(tailMergeX86));
Expand All @@ -436,6 +440,7 @@ class ThunkChunkARM : public NonSectionChunk {
}

size_t getSize() const override { return sizeof(thunkARM); }
MachineTypes getMachine() const override { return ARMNT; }

void writeTo(uint8_t *buf) const override {
memcpy(buf, thunkARM, sizeof(thunkARM));
Expand All @@ -462,6 +467,7 @@ class TailMergeChunkARM : public NonSectionChunk {
}

size_t getSize() const override { return sizeof(tailMergeARM); }
MachineTypes getMachine() const override { return ARMNT; }

void writeTo(uint8_t *buf) const override {
memcpy(buf, tailMergeARM, sizeof(tailMergeARM));
Expand All @@ -487,6 +493,7 @@ class ThunkChunkARM64 : public NonSectionChunk {
}

size_t getSize() const override { return sizeof(thunkARM64); }
MachineTypes getMachine() const override { return ARM64; }

void writeTo(uint8_t *buf) const override {
memcpy(buf, thunkARM64, sizeof(thunkARM64));
Expand All @@ -506,6 +513,7 @@ class TailMergeChunkARM64 : public NonSectionChunk {
}

size_t getSize() const override { return sizeof(tailMergeARM64); }
MachineTypes getMachine() const override { return ARM64; }

void writeTo(uint8_t *buf) const override {
memcpy(buf, tailMergeARM64, sizeof(tailMergeARM64));
Expand Down
17 changes: 17 additions & 0 deletions lld/COFF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ class Writer {
void locateImportTables();
void createExportTable();
void mergeSections();
void sortECChunks();
void removeUnusedSections();
void assignAddresses();
bool isInRange(uint16_t relType, uint64_t s, uint64_t p, int margin);
Expand Down Expand Up @@ -676,6 +677,7 @@ void Writer::run() {
createMiscChunks();
createExportTable();
mergeSections();
sortECChunks();
removeUnusedSections();
finalizeAddresses();
removeEmptySections();
Expand Down Expand Up @@ -1377,6 +1379,21 @@ void Writer::mergeSections() {
}
}

// EC targets may have chunks of various architectures mixed together at this
// point. Group code chunks of the same architecture together by sorting chunks
// by their EC range type.
void Writer::sortECChunks() {
if (!isArm64EC(ctx.config.machine))
return;

for (OutputSection *sec : ctx.outputSections) {
if (sec->isCodeSection())
llvm::stable_sort(sec->chunks, [=](const Chunk *a, const Chunk *b) {
return a->getArm64ECRangeType() < b->getArm64ECRangeType();
});
}
}

// Visits all sections to assign incremental, non-overlapping RVAs and
// file offsets.
void Writer::assignAddresses() {
Expand Down
97 changes: 97 additions & 0 deletions lld/test/COFF/Inputs/loadconfig-arm64ec.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
.section .rdata,"dr"
.globl _load_config_used
.p2align 3, 0
_load_config_used:
.word 0x140
.fill 0x54, 1, 0
.xword __security_cookie
.fill 0x10, 1, 0
.xword __guard_check_icall_fptr
.xword __guard_dispatch_icall_fptr
.xword __guard_fids_table
.xword __guard_fids_count
.xword __guard_flags
.xword 0
.xword __guard_iat_table
.xword __guard_iat_count
.xword __guard_longjmp_table
.xword __guard_longjmp_count
.xword 0
.xword __chpe_metadata
.fill 0x78, 1, 0

__guard_check_icall_fptr:
.xword 0
__guard_dispatch_icall_fptr:
.xword 0
__os_arm64x_dispatch_call_no_redirect:
.xword 0
__os_arm64x_dispatch_ret:
.xword 0
__os_arm64x_check_call:
.xword 0
__os_arm64x_check_icall:
.xword 0
__os_arm64x_get_x64_information:
.xword 0
__os_arm64x_set_x64_information:
.xword 0
__os_arm64x_check_icall_cfg:
.xword 0
__os_arm64x_dispatch_fptr:
.xword 0
__os_arm64x_helper0:
.xword 0
__os_arm64x_helper1:
.xword 0
__os_arm64x_helper2:
.xword 0
__os_arm64x_helper3:
.xword 0
__os_arm64x_helper4:
.xword 0
__os_arm64x_helper5:
.xword 0
__os_arm64x_helper6:
.xword 0
__os_arm64x_helper7:
.xword 0
__os_arm64x_helper8:
.xword 0

.data
.globl __chpe_metadata
.p2align 3, 0
__chpe_metadata:
.word 1
.rva code_map
.word code_map_count
.word 0 // __x64_code_ranges_to_entry_points
.word 0 //__arm64x_redirection_metadata
.rva __os_arm64x_dispatch_call_no_redirect
.rva __os_arm64x_dispatch_ret
.rva __os_arm64x_check_call
.rva __os_arm64x_check_icall
.rva __os_arm64x_check_icall_cfg
.word 0 // __arm64x_native_entrypoint
.word 0 // __hybrid_auxiliary_iat
.word 0 // __x64_code_ranges_to_entry_points_count
.word 0 // __arm64x_redirection_metadata_count
.rva __os_arm64x_get_x64_information
.rva __os_arm64x_set_x64_information
.word 0 // __arm64x_extra_rfe_table
.word 0 // __arm64x_extra_rfe_table_size
.rva __os_arm64x_dispatch_fptr
.word 0 // __hybrid_auxiliary_iat_copy
.rva __os_arm64x_helper0
.rva __os_arm64x_helper1
.rva __os_arm64x_helper2
.rva __os_arm64x_helper3
.rva __os_arm64x_helper4
.rva __os_arm64x_helper5
.rva __os_arm64x_helper6
.rva __os_arm64x_helper7
.rva __os_arm64x_helper8

__security_cookie:
.xword 0
Loading

0 comments on commit a4b91a6

Please sign in to comment.