Skip to content

Commit 3b0daff

Browse files
authored
[LLD][COFF] Use EC load config for ARM64X relocations of load config directory (llvm#121337)
This change ensures the load config in the hybrid image view is handled correctly. It introduces a new Arm64XRelocVal class to abstract relocation values, allowing them to be relative to a symbol. This class will also be useful for managing ARM64X relocation offsets in the future.
1 parent 55b5875 commit 3b0daff

File tree

4 files changed

+58
-14
lines changed

4 files changed

+58
-14
lines changed

lld/COFF/Chunks.cpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,10 @@ uint32_t ImportThunkChunkARM64EC::extendRanges() {
11661166
return sizeof(arm64Thunk) - sizeof(uint32_t);
11671167
}
11681168

1169+
uint64_t Arm64XRelocVal::get() const {
1170+
return (sym ? sym->getRVA() : 0) + value;
1171+
}
1172+
11691173
size_t Arm64XDynamicRelocEntry::getSize() const {
11701174
switch (type) {
11711175
case IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE:
@@ -1186,13 +1190,13 @@ void Arm64XDynamicRelocEntry::writeTo(uint8_t *buf) const {
11861190
*out |= ((bit_width(size) - 1) << 14); // Encode the size.
11871191
switch (size) {
11881192
case 2:
1189-
out[1] = value;
1193+
out[1] = value.get();
11901194
break;
11911195
case 4:
1192-
*reinterpret_cast<ulittle32_t *>(out + 1) = value;
1196+
*reinterpret_cast<ulittle32_t *>(out + 1) = value.get();
11931197
break;
11941198
case 8:
1195-
*reinterpret_cast<ulittle64_t *>(out + 1) = value;
1199+
*reinterpret_cast<ulittle64_t *>(out + 1) = value.get();
11961200
break;
11971201
default:
11981202
llvm_unreachable("invalid size");

lld/COFF/Chunks.h

+15-3
Original file line numberDiff line numberDiff line change
@@ -835,18 +835,30 @@ class ECExportThunkChunk : public NonSectionCodeChunk {
835835
Defined *target;
836836
};
837837

838+
// ARM64X relocation value, potentially relative to a symbol.
839+
class Arm64XRelocVal {
840+
public:
841+
Arm64XRelocVal(uint64_t value = 0) : value(value) {}
842+
Arm64XRelocVal(Defined *sym, int32_t offset = 0) : sym(sym), value(offset) {}
843+
uint64_t get() const;
844+
845+
private:
846+
Defined *sym = nullptr;
847+
uint64_t value;
848+
};
849+
838850
// ARM64X entry for dynamic relocations.
839851
class Arm64XDynamicRelocEntry {
840852
public:
841853
Arm64XDynamicRelocEntry(llvm::COFF::Arm64XFixupType type, uint8_t size,
842-
uint32_t offset, uint64_t value)
854+
uint32_t offset, Arm64XRelocVal value)
843855
: offset(offset), value(value), type(type), size(size) {}
844856

845857
size_t getSize() const;
846858
void writeTo(uint8_t *buf) const;
847859

848860
uint32_t offset;
849-
uint64_t value;
861+
Arm64XRelocVal value;
850862

851863
private:
852864
llvm::COFF::Arm64XFixupType type;
@@ -862,7 +874,7 @@ class DynamicRelocsChunk : public NonSectionChunk {
862874
void finalize();
863875

864876
void add(llvm::COFF::Arm64XFixupType type, uint8_t size, uint32_t offset,
865-
uint64_t value) {
877+
Arm64XRelocVal value) {
866878
arm64xRelocs.emplace_back(type, size, offset, value);
867879
}
868880

lld/COFF/Writer.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -2584,18 +2584,17 @@ void Writer::createDynamicRelocs() {
25842584
coffHeaderOffset + offsetof(coff_file_header, Machine),
25852585
AMD64);
25862586

2587-
// Clear the load config directory.
2588-
// FIXME: Use the hybrid load config value instead.
2587+
// Set the hybrid load config to the EC load config.
25892588
ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
25902589
dataDirOffset64 +
25912590
LOAD_CONFIG_TABLE * sizeof(data_directory) +
25922591
offsetof(data_directory, RelativeVirtualAddress),
2593-
0);
2592+
ctx.hybridSymtab->loadConfigSym);
25942593
ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
25952594
dataDirOffset64 +
25962595
LOAD_CONFIG_TABLE * sizeof(data_directory) +
25972596
offsetof(data_directory, Size),
2598-
0);
2597+
ctx.hybridSymtab->loadConfigSize);
25992598
}
26002599

26012600
PartialSection *Writer::createPartialSection(StringRef name,

lld/test/COFF/arm64x-loadconfig.s

+33-4
Original file line numberDiff line numberDiff line change
@@ -99,20 +99,49 @@
9999
// LOADCFG-NEXT: RVA: 0x150
100100
// LOADCFG-NEXT: Type: VALUE
101101
// LOADCFG-NEXT: Size: 0x4
102-
// LOADCFG-NEXT: Value: 0x0
102+
// LOADCFG-NEXT: Value: 0x1140
103103
// LOADCFG-NEXT: ]
104104
// LOADCFG-NEXT: Entry [
105105
// LOADCFG-NEXT: RVA: 0x154
106106
// LOADCFG-NEXT: Type: VALUE
107107
// LOADCFG-NEXT: Size: 0x4
108-
// LOADCFG-NEXT: Value: 0x0
108+
// LOADCFG-NEXT: Value: 0x140
109109
// LOADCFG-NEXT: ]
110110
// LOADCFG-NEXT: ]
111111
// LOADCFG-NEXT: ]
112112
// LOADCFG-NEXT: HybridObject {
113-
// LOADCFG-NEXT: Format: COFF-x86-64
114-
// LOADCFG-NEXT: Arch: x86_64
113+
// LOADCFG-NEXT: Format: COFF-ARM64EC
114+
// LOADCFG-NEXT: Arch: aarch64
115115
// LOADCFG-NEXT: AddressSize: 64bit
116+
// LOADCFG-NEXT: LoadConfig [
117+
// LOADCFG-NEXT: Size: 0x140
118+
// LOADCFG: CHPEMetadata [
119+
// LOADCFG-NEXT: Version: 0x2
120+
// LOADCFG: ]
121+
// LOADCFG-NEXT: DynamicRelocations [
122+
// LOADCFG-NEXT: Version: 0x1
123+
// LOADCFG-NEXT: Arm64X [
124+
// LOADCFG-NEXT: Entry [
125+
// LOADCFG-NEXT: RVA: 0x7C
126+
// LOADCFG-NEXT: Type: VALUE
127+
// LOADCFG-NEXT: Size: 0x2
128+
// LOADCFG-NEXT: Value: 0x8664
129+
// LOADCFG-NEXT: ]
130+
// LOADCFG-NEXT: Entry [
131+
// LOADCFG-NEXT: RVA: 0x150
132+
// LOADCFG-NEXT: Type: VALUE
133+
// LOADCFG-NEXT: Size: 0x4
134+
// LOADCFG-NEXT: Value: 0x1140
135+
// LOADCFG-NEXT: ]
136+
// LOADCFG-NEXT: Entry [
137+
// LOADCFG-NEXT: RVA: 0x154
138+
// LOADCFG-NEXT: Type: VALUE
139+
// LOADCFG-NEXT: Size: 0x4
140+
// LOADCFG-NEXT: Value: 0x140
141+
// LOADCFG-NEXT: ]
142+
// LOADCFG-NEXT: ]
143+
// LOADCFG-NEXT: ]
144+
// LOADCFG-NEXT: }
116145

117146
// RUN: llvm-readobj --coff-basereloc out-hyb.dll | FileCheck --check-prefix=BASERELOC %s
118147
// BASERELOC: BaseReloc [

0 commit comments

Comments
 (0)