Skip to content

Commit 71c2a13

Browse files
authored
[BOLT] support AArch64 JUMP26 createRelocation (llvm#83531)
Add R_AARCH64_JUMP26 implementation for createRelocation, which could significantly reduce the number of failed scan-refs cases if we perform bolt on a selective range of functions.
1 parent aaf5c81 commit 71c2a13

File tree

3 files changed

+54
-0
lines changed

3 files changed

+54
-0
lines changed

bolt/lib/Core/Relocation.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,14 @@ static uint64_t encodeValueAArch64(uint64_t Type, uint64_t Value, uint64_t PC) {
381381
// OP 1001_01 goes in bits 31:26 of BL.
382382
Value = ((Value >> 2) & 0x3ffffff) | 0x94000000ULL;
383383
break;
384+
case ELF::R_AARCH64_JUMP26:
385+
Value -= PC;
386+
assert(isInt<28>(Value) &&
387+
"only PC +/- 128MB is allowed for direct branch");
388+
// Immediate goes in bits 25:0 of B.
389+
// OP 0001_01 goes in bits 31:26 of B.
390+
Value = ((Value >> 2) & 0x3ffffff) | 0x14000000ULL;
391+
break;
384392
}
385393
return Value;
386394
}

bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,9 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
16291629
uint64_t RelType;
16301630
if (Fixup.getKind() == MCFixupKind(AArch64::fixup_aarch64_pcrel_call26))
16311631
RelType = ELF::R_AARCH64_CALL26;
1632+
else if (Fixup.getKind() ==
1633+
MCFixupKind(AArch64::fixup_aarch64_pcrel_branch26))
1634+
RelType = ELF::R_AARCH64_JUMP26;
16321635
else if (FKI.Flags & MCFixupKindInfo::FKF_IsPCRel) {
16331636
switch (FKI.TargetSize) {
16341637
default:

bolt/unittests/Core/BinaryContext.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,49 @@ TEST_P(BinaryContextTester, FlushPendingRelocCALL26) {
104104
EXPECT_FALSE(memcmp(Func2Call, &Vect[12], 4)) << "Wrong forward call value\n";
105105
}
106106

107+
TEST_P(BinaryContextTester, FlushPendingRelocJUMP26) {
108+
if (GetParam() != Triple::aarch64)
109+
GTEST_SKIP();
110+
111+
// This test checks that encodeValueAArch64 used by flushPendingRelocations
112+
// returns correctly encoded values for R_AARCH64_JUMP26 relocation for both
113+
// backward and forward branches.
114+
//
115+
// The offsets layout is:
116+
// 4: func1
117+
// 8: b func1
118+
// 12: b func2
119+
// 16: func2
120+
121+
const uint64_t Size = 20;
122+
char *Data = new char[Size];
123+
BinarySection &BS = BC->registerOrUpdateSection(
124+
".text", ELF::SHT_PROGBITS, ELF::SHF_EXECINSTR | ELF::SHF_ALLOC,
125+
(uint8_t *)Data, Size, 4);
126+
MCSymbol *RelSymbol1 = BC->getOrCreateGlobalSymbol(4, "Func1");
127+
ASSERT_TRUE(RelSymbol1);
128+
BS.addRelocation(8, RelSymbol1, ELF::R_AARCH64_JUMP26, 0, 0, true);
129+
MCSymbol *RelSymbol2 = BC->getOrCreateGlobalSymbol(16, "Func2");
130+
ASSERT_TRUE(RelSymbol2);
131+
BS.addRelocation(12, RelSymbol2, ELF::R_AARCH64_JUMP26, 0, 0, true);
132+
133+
std::error_code EC;
134+
SmallVector<char> Vect(Size);
135+
raw_svector_ostream OS(Vect);
136+
137+
BS.flushPendingRelocations(OS, [&](const MCSymbol *S) {
138+
return S == RelSymbol1 ? 4 : S == RelSymbol2 ? 16 : 0;
139+
});
140+
141+
const uint8_t Func1Call[4] = {255, 255, 255, 23};
142+
const uint8_t Func2Call[4] = {1, 0, 0, 20};
143+
144+
EXPECT_FALSE(memcmp(Func1Call, &Vect[8], 4))
145+
<< "Wrong backward branch value\n";
146+
EXPECT_FALSE(memcmp(Func2Call, &Vect[12], 4))
147+
<< "Wrong forward branch value\n";
148+
}
149+
107150
#endif
108151

109152
TEST_P(BinaryContextTester, BaseAddress) {

0 commit comments

Comments
 (0)