Skip to content

Commit cbbb545

Browse files
authored
[lld] Sort code section chunks by range types on Arm64EC targets. (#69099)
1 parent 9322a0c commit cbbb545

File tree

5 files changed

+349
-2
lines changed

5 files changed

+349
-2
lines changed

lld/COFF/Chunks.h

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@
2424
namespace lld::coff {
2525

2626
using llvm::COFF::ImportDirectoryTableEntry;
27-
using llvm::object::COFFSymbolRef;
28-
using llvm::object::SectionRef;
27+
using llvm::object::chpe_range_type;
2928
using llvm::object::coff_relocation;
3029
using llvm::object::coff_section;
30+
using llvm::object::COFFSymbolRef;
31+
using llvm::object::SectionRef;
3132

3233
class Baserel;
3334
class Defined;
@@ -114,6 +115,9 @@ class Chunk {
114115
// synthesized by the linker.
115116
bool isHotPatchable() const;
116117

118+
MachineTypes getMachine() const;
119+
chpe_range_type getArm64ECRangeType() const;
120+
117121
protected:
118122
Chunk(Kind k = OtherKind) : chunkKind(k), hasData(true), p2Align(0) {}
119123

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

171+
virtual MachineTypes getMachine() const { return IMAGE_FILE_MACHINE_UNKNOWN; }
172+
167173
// Returns a human-readable name of this chunk. Chunks are unnamed chunks of
168174
// bytes, so this is used only for logging or debugging.
169175
virtual StringRef getDebugName() const { return ""; }
@@ -420,6 +426,24 @@ inline StringRef Chunk::getDebugName() const {
420426
return static_cast<const NonSectionChunk *>(this)->getDebugName();
421427
}
422428

429+
inline MachineTypes Chunk::getMachine() const {
430+
if (isa<SectionChunk>(this))
431+
return static_cast<const SectionChunk *>(this)->getMachine();
432+
else
433+
return static_cast<const NonSectionChunk *>(this)->getMachine();
434+
}
435+
436+
inline chpe_range_type Chunk::getArm64ECRangeType() const {
437+
switch (getMachine()) {
438+
case AMD64:
439+
return chpe_range_type::Amd64;
440+
case ARM64EC:
441+
return chpe_range_type::Arm64EC;
442+
default:
443+
return chpe_range_type::Arm64;
444+
}
445+
}
446+
423447
// This class is used to implement an lld-specific feature (not implemented in
424448
// MSVC) that minimizes the output size by finding string literals sharing tail
425449
// parts and merging them.
@@ -506,6 +530,7 @@ class ImportThunkChunkX64 : public ImportThunkChunk {
506530
explicit ImportThunkChunkX64(COFFLinkerContext &ctx, Defined *s);
507531
size_t getSize() const override { return sizeof(importThunkX86); }
508532
void writeTo(uint8_t *buf) const override;
533+
MachineTypes getMachine() const override { return AMD64; }
509534
};
510535

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

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

531558
class ImportThunkChunkARM64 : public ImportThunkChunk {
@@ -536,6 +563,7 @@ class ImportThunkChunkARM64 : public ImportThunkChunk {
536563
}
537564
size_t getSize() const override { return sizeof(importThunkARM64); }
538565
void writeTo(uint8_t *buf) const override;
566+
MachineTypes getMachine() const override { return ARM64; }
539567
};
540568

541569
class RangeExtensionThunkARM : public NonSectionChunk {
@@ -546,6 +574,7 @@ class RangeExtensionThunkARM : public NonSectionChunk {
546574
}
547575
size_t getSize() const override;
548576
void writeTo(uint8_t *buf) const override;
577+
MachineTypes getMachine() const override { return ARMNT; }
549578

550579
Defined *target;
551580

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

565595
Defined *target;
566596

lld/COFF/DLL.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ class ThunkChunkX64 : public NonSectionChunk {
318318
ThunkChunkX64(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {}
319319

320320
size_t getSize() const override { return sizeof(thunkX64); }
321+
MachineTypes getMachine() const override { return AMD64; }
321322

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

336337
size_t getSize() const override { return sizeof(tailMergeX64); }
338+
MachineTypes getMachine() const override { return AMD64; }
337339

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

388390
size_t getSize() const override { return sizeof(thunkX86); }
391+
MachineTypes getMachine() const override { return I386; }
389392

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

412415
size_t getSize() const override { return sizeof(tailMergeX86); }
416+
MachineTypes getMachine() const override { return I386; }
413417

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

438442
size_t getSize() const override { return sizeof(thunkARM); }
443+
MachineTypes getMachine() const override { return ARMNT; }
439444

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

464469
size_t getSize() const override { return sizeof(tailMergeARM); }
470+
MachineTypes getMachine() const override { return ARMNT; }
465471

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

489495
size_t getSize() const override { return sizeof(thunkARM64); }
496+
MachineTypes getMachine() const override { return ARM64; }
490497

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

508515
size_t getSize() const override { return sizeof(tailMergeARM64); }
516+
MachineTypes getMachine() const override { return ARM64; }
509517

510518
void writeTo(uint8_t *buf) const override {
511519
memcpy(buf, tailMergeARM64, sizeof(tailMergeARM64));

lld/COFF/Writer.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ class Writer {
212212
void locateImportTables();
213213
void createExportTable();
214214
void mergeSections();
215+
void sortECChunks();
215216
void removeUnusedSections();
216217
void assignAddresses();
217218
bool isInRange(uint16_t relType, uint64_t s, uint64_t p, int margin);
@@ -676,6 +677,7 @@ void Writer::run() {
676677
createMiscChunks();
677678
createExportTable();
678679
mergeSections();
680+
sortECChunks();
679681
removeUnusedSections();
680682
finalizeAddresses();
681683
removeEmptySections();
@@ -1377,6 +1379,21 @@ void Writer::mergeSections() {
13771379
}
13781380
}
13791381

1382+
// EC targets may have chunks of various architectures mixed together at this
1383+
// point. Group code chunks of the same architecture together by sorting chunks
1384+
// by their EC range type.
1385+
void Writer::sortECChunks() {
1386+
if (!isArm64EC(ctx.config.machine))
1387+
return;
1388+
1389+
for (OutputSection *sec : ctx.outputSections) {
1390+
if (sec->isCodeSection())
1391+
llvm::stable_sort(sec->chunks, [=](const Chunk *a, const Chunk *b) {
1392+
return a->getArm64ECRangeType() < b->getArm64ECRangeType();
1393+
});
1394+
}
1395+
}
1396+
13801397
// Visits all sections to assign incremental, non-overlapping RVAs and
13811398
// file offsets.
13821399
void Writer::assignAddresses() {
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
.section .rdata,"dr"
2+
.globl _load_config_used
3+
.p2align 3, 0
4+
_load_config_used:
5+
.word 0x140
6+
.fill 0x54, 1, 0
7+
.xword __security_cookie
8+
.fill 0x10, 1, 0
9+
.xword __guard_check_icall_fptr
10+
.xword __guard_dispatch_icall_fptr
11+
.xword __guard_fids_table
12+
.xword __guard_fids_count
13+
.xword __guard_flags
14+
.xword 0
15+
.xword __guard_iat_table
16+
.xword __guard_iat_count
17+
.xword __guard_longjmp_table
18+
.xword __guard_longjmp_count
19+
.xword 0
20+
.xword __chpe_metadata
21+
.fill 0x78, 1, 0
22+
23+
__guard_check_icall_fptr:
24+
.xword 0
25+
__guard_dispatch_icall_fptr:
26+
.xword 0
27+
__os_arm64x_dispatch_call_no_redirect:
28+
.xword 0
29+
__os_arm64x_dispatch_ret:
30+
.xword 0
31+
__os_arm64x_check_call:
32+
.xword 0
33+
__os_arm64x_check_icall:
34+
.xword 0
35+
__os_arm64x_get_x64_information:
36+
.xword 0
37+
__os_arm64x_set_x64_information:
38+
.xword 0
39+
__os_arm64x_check_icall_cfg:
40+
.xword 0
41+
__os_arm64x_dispatch_fptr:
42+
.xword 0
43+
__os_arm64x_helper0:
44+
.xword 0
45+
__os_arm64x_helper1:
46+
.xword 0
47+
__os_arm64x_helper2:
48+
.xword 0
49+
__os_arm64x_helper3:
50+
.xword 0
51+
__os_arm64x_helper4:
52+
.xword 0
53+
__os_arm64x_helper5:
54+
.xword 0
55+
__os_arm64x_helper6:
56+
.xword 0
57+
__os_arm64x_helper7:
58+
.xword 0
59+
__os_arm64x_helper8:
60+
.xword 0
61+
62+
.data
63+
.globl __chpe_metadata
64+
.p2align 3, 0
65+
__chpe_metadata:
66+
.word 1
67+
.rva code_map
68+
.word code_map_count
69+
.word 0 // __x64_code_ranges_to_entry_points
70+
.word 0 //__arm64x_redirection_metadata
71+
.rva __os_arm64x_dispatch_call_no_redirect
72+
.rva __os_arm64x_dispatch_ret
73+
.rva __os_arm64x_check_call
74+
.rva __os_arm64x_check_icall
75+
.rva __os_arm64x_check_icall_cfg
76+
.word 0 // __arm64x_native_entrypoint
77+
.word 0 // __hybrid_auxiliary_iat
78+
.word 0 // __x64_code_ranges_to_entry_points_count
79+
.word 0 // __arm64x_redirection_metadata_count
80+
.rva __os_arm64x_get_x64_information
81+
.rva __os_arm64x_set_x64_information
82+
.word 0 // __arm64x_extra_rfe_table
83+
.word 0 // __arm64x_extra_rfe_table_size
84+
.rva __os_arm64x_dispatch_fptr
85+
.word 0 // __hybrid_auxiliary_iat_copy
86+
.rva __os_arm64x_helper0
87+
.rva __os_arm64x_helper1
88+
.rva __os_arm64x_helper2
89+
.rva __os_arm64x_helper3
90+
.rva __os_arm64x_helper4
91+
.rva __os_arm64x_helper5
92+
.rva __os_arm64x_helper6
93+
.rva __os_arm64x_helper7
94+
.rva __os_arm64x_helper8
95+
96+
__security_cookie:
97+
.xword 0

0 commit comments

Comments
 (0)