Skip to content

Commit 07b5962

Browse files
committed
[BOLT][AArch64] Basic support for Linux kernel
Make parts specific to X86 also work on AArch64
1 parent 91af15b commit 07b5962

File tree

4 files changed

+91
-28
lines changed

4 files changed

+91
-28
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,9 @@ class BinaryContext {
612612
/// Addresses reserved for kernel on x86_64 start at this location.
613613
static constexpr uint64_t KernelStartX86_64 = 0xFFFF'FFFF'8000'0000;
614614

615+
/// https://www.kernel.org/doc/html/v6.12/arch/arm64/memory.html
616+
static constexpr uint64_t KernelStartAArch64 = 0xFFF0'0000'0000'0000;
617+
615618
/// Map address to a constant island owner (constant data in code section)
616619
std::map<uint64_t, BinaryFunction *> AddressToConstantIslandMap;
617620

bolt/lib/Core/JumpTable.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void bolt::JumpTable::updateOriginal() {
8585
uint64_t EntryOffset = BaseOffset;
8686
for (MCSymbol *Entry : Entries) {
8787
const uint64_t RelType =
88-
Type == JTT_NORMAL ? ELF::R_X86_64_64 : ELF::R_X86_64_PC32;
88+
Type == JTT_NORMAL ? Relocation::getAbs64() : Relocation::getPC32();
8989
const uint64_t RelAddend =
9090
Type == JTT_NORMAL ? 0 : EntryOffset - BaseOffset;
9191
// Replace existing relocation with the new one to allow any modifications

bolt/lib/Rewrite/LinuxKernelRewriter.cpp

Lines changed: 75 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@ class LinuxKernelRewriter final : public MetadataRewriter {
196196

197197
/// Section containing the Linux exception table.
198198
ErrorOr<BinarySection &> ExceptionsSection = std::errc::bad_address;
199-
static constexpr size_t EXCEPTION_TABLE_ENTRY_SIZE = 12;
200199

201200
/// Functions with exception handling code.
202201
DenseSet<BinaryFunction *> FunctionsWithExceptions;
@@ -225,6 +224,17 @@ class LinuxKernelRewriter final : public MetadataRewriter {
225224
ErrorOr<BinarySection &> PCIFixupSection = std::errc::bad_address;
226225
static constexpr size_t PCI_FIXUP_ENTRY_SIZE = 16;
227226

227+
size_t getExceptionTableEntrySize() {
228+
switch (BC.TheTriple->getArch()) {
229+
case llvm::Triple::x86_64:
230+
return 12;
231+
case llvm::Triple::aarch64:
232+
return 8;
233+
default:
234+
llvm_unreachable("Unsupported architecture");
235+
}
236+
}
237+
228238
/// Process linux kernel special sections and their relocations.
229239
void processLKSections();
230240

@@ -474,8 +484,8 @@ void LinuxKernelRewriter::processInstructionFixups() {
474484
continue;
475485

476486
Fixup.Section.addRelocation(Fixup.Offset, &Fixup.Label,
477-
Fixup.IsPCRelative ? ELF::R_X86_64_PC32
478-
: ELF::R_X86_64_64,
487+
Fixup.IsPCRelative ? Relocation::getPC32()
488+
: Relocation::getAbs64(),
479489
/*Addend*/ 0);
480490
}
481491
}
@@ -998,7 +1008,7 @@ Error LinuxKernelRewriter::rewriteStaticCalls() {
9981008
StaticCallSection->getAddress() +
9991009
(Entry.ID - 1) * STATIC_CALL_ENTRY_SIZE;
10001010
StaticCallSection->addRelocation(EntryOffset, Entry.Label,
1001-
ELF::R_X86_64_PC32, /*Addend*/ 0);
1011+
Relocation::getPC32(), /*Addend*/ 0);
10021012
}
10031013

10041014
return Error::success();
@@ -1023,7 +1033,8 @@ Error LinuxKernelRewriter::readExceptionTable() {
10231033
if (!ExceptionsSection)
10241034
return Error::success();
10251035

1026-
if (ExceptionsSection->getSize() % EXCEPTION_TABLE_ENTRY_SIZE)
1036+
size_t EntrySize = getExceptionTableEntrySize();
1037+
if (ExceptionsSection->getSize() % EntrySize)
10271038
return createStringError(errc::executable_format_error,
10281039
"exception table size error");
10291040

@@ -1038,7 +1049,19 @@ Error LinuxKernelRewriter::readExceptionTable() {
10381049
SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor);
10391050
const uint64_t FixupAddress =
10401051
SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor);
1041-
const uint64_t Data = DE.getU32(Cursor);
1052+
1053+
auto ReadData = [this, &DE, &Cursor]() {
1054+
switch (BC.TheTriple->getArch()) {
1055+
case llvm::Triple::x86_64:
1056+
return DE.getU32(Cursor);
1057+
case llvm::Triple::aarch64:
1058+
return 0U;
1059+
default:
1060+
llvm_unreachable("Unsupported architecture");
1061+
}
1062+
};
1063+
1064+
const uint64_t Data = ReadData();
10421065

10431066
// Consume the status of the cursor.
10441067
if (!Cursor)
@@ -1100,8 +1123,7 @@ Error LinuxKernelRewriter::readExceptionTable() {
11001123
}
11011124
}
11021125

1103-
BC.outs() << "BOLT-INFO: parsed "
1104-
<< ExceptionsSection->getSize() / EXCEPTION_TABLE_ENTRY_SIZE
1126+
BC.outs() << "BOLT-INFO: parsed " << ExceptionsSection->getSize() / EntrySize
11051127
<< " exception table entries\n";
11061128

11071129
return Error::success();
@@ -1305,7 +1327,8 @@ Error LinuxKernelRewriter::rewriteBugTable() {
13051327
MCSymbol *Label =
13061328
BC.MIB->getOrCreateInstLabel(Inst, "__BUG_", BC.Ctx.get());
13071329
const uint64_t EntryOffset = (ID - 1) * BUG_TABLE_ENTRY_SIZE;
1308-
BugTableSection->addRelocation(EntryOffset, Label, ELF::R_X86_64_PC32,
1330+
BugTableSection->addRelocation(EntryOffset, Label,
1331+
Relocation::getPC32(),
13091332
/*Addend*/ 0);
13101333
}
13111334
}
@@ -1315,7 +1338,8 @@ Error LinuxKernelRewriter::rewriteBugTable() {
13151338
for (const uint32_t ID : FunctionBugList[&BF]) {
13161339
if (!EmittedIDs.count(ID)) {
13171340
const uint64_t EntryOffset = (ID - 1) * BUG_TABLE_ENTRY_SIZE;
1318-
BugTableSection->addRelocation(EntryOffset, nullptr, ELF::R_X86_64_PC32,
1341+
BugTableSection->addRelocation(EntryOffset, nullptr,
1342+
Relocation::getPC32(),
13191343
/*Addend*/ 0);
13201344
}
13211345
}
@@ -1589,6 +1613,41 @@ Error LinuxKernelRewriter::readPCIFixupTable() {
15891613
return Error::success();
15901614
}
15911615

1616+
static bool checkStaticKeysJumpInstSize(const BinaryContext &BC, size_t Size) {
1617+
switch (BC.TheTriple->getArch()) {
1618+
case llvm::Triple::x86_64:
1619+
return Size == 2 || Size == 5;
1620+
case llvm::Triple::aarch64:
1621+
return Size == 4;
1622+
default:
1623+
llvm_unreachable("Unsupported architecture");
1624+
}
1625+
}
1626+
1627+
static bool checkStaticKeysJumpInstSize(const BinaryContext &BC, size_t Size,
1628+
uint64_t &NumShort, uint64_t &NumLong) {
1629+
switch (BC.TheTriple->getArch()) {
1630+
case llvm::Triple::x86_64:
1631+
if (Size == 2) {
1632+
++NumShort;
1633+
return true;
1634+
}
1635+
if (Size == 5) {
1636+
++NumLong;
1637+
return true;
1638+
}
1639+
return false;
1640+
case llvm::Triple::aarch64:
1641+
if (Size == 4) {
1642+
++NumLong;
1643+
return true;
1644+
}
1645+
return false;
1646+
default:
1647+
llvm_unreachable("Unsupported architecture");
1648+
}
1649+
}
1650+
15921651
/// Runtime code modification used by static keys is the most ubiquitous
15931652
/// self-modifying feature of the Linux kernel. The idea is to eliminate the
15941653
/// condition check and associated conditional jump on a hot path if that
@@ -1719,7 +1778,7 @@ Error LinuxKernelRewriter::readStaticKeysJumpTable() {
17191778
JumpAddress);
17201779

17211780
const uint64_t Size = BC.computeInstructionSize(*Inst);
1722-
if (Size != 2 && Size != 5) {
1781+
if (!checkStaticKeysJumpInstSize(BC, Size)) {
17231782
return createStringError(
17241783
errc::executable_format_error,
17251784
"unexpected static keys jump size at address 0x%" PRIx64,
@@ -1805,11 +1864,7 @@ Error LinuxKernelRewriter::rewriteStaticKeysJumpTable() {
18051864
const bool IsBranch = Info.Likely ^ Info.InitValue;
18061865

18071866
uint32_t Size = *BC.MIB->getSize(Inst);
1808-
if (Size == 2)
1809-
++NumShort;
1810-
else if (Size == 5)
1811-
++NumLong;
1812-
else
1867+
if (!checkStaticKeysJumpInstSize(BC, Size, NumShort, NumLong))
18131868
llvm_unreachable("Wrong size for static keys jump instruction.");
18141869

18151870
MCInst NewInst;
@@ -1839,10 +1894,10 @@ Error LinuxKernelRewriter::rewriteStaticKeysJumpTable() {
18391894
StaticKeysJumpSection->getAddress() +
18401895
(EntryID - 1) * 16;
18411896
StaticKeysJumpSection->addRelocation(EntryOffset, Label,
1842-
ELF::R_X86_64_PC32,
1897+
Relocation::getPC32(),
18431898
/*Addend*/ 0);
1844-
StaticKeysJumpSection->addRelocation(EntryOffset + 4, Target,
1845-
ELF::R_X86_64_PC32, /*Addend*/ 0);
1899+
StaticKeysJumpSection->addRelocation(
1900+
EntryOffset + 4, Target, Relocation::getPC32(), /*Addend*/ 0);
18461901
}
18471902
}
18481903
}
@@ -1915,11 +1970,7 @@ Error LinuxKernelRewriter::updateStaticKeysJumpTablePostEmit() {
19151970
}
19161971
assert(BC.MIB->isBranch(Inst) && "Branch instruction expected.");
19171972

1918-
if (Size == 2)
1919-
++NumShort;
1920-
else if (Size == 5)
1921-
++NumLong;
1922-
else
1973+
if (!checkStaticKeysJumpInstSize(BC, Size, NumShort, NumLong))
19231974
llvm_unreachable("Unexpected size for static keys jump instruction.");
19241975

19251976
// Check if we need to convert jump instruction into a nop.

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -529,9 +529,18 @@ Error RewriteInstance::discoverStorage() {
529529
BC->SegmentMapInfo[Phdr.p_vaddr] = SegmentInfo{
530530
Phdr.p_vaddr, Phdr.p_memsz, Phdr.p_offset,
531531
Phdr.p_filesz, Phdr.p_align, ((Phdr.p_flags & ELF::PF_X) != 0)};
532-
if (BC->TheTriple->getArch() == llvm::Triple::x86_64 &&
533-
Phdr.p_vaddr >= BinaryContext::KernelStartX86_64)
534-
BC->IsLinuxKernel = true;
532+
533+
switch (BC->TheTriple->getArch()) {
534+
case llvm::Triple::x86_64:
535+
if (Phdr.p_vaddr >= BinaryContext::KernelStartX86_64)
536+
BC->IsLinuxKernel = true;
537+
break;
538+
case llvm::Triple::aarch64:
539+
if (Phdr.p_vaddr >= BinaryContext::KernelStartAArch64)
540+
BC->IsLinuxKernel = true;
541+
break;
542+
}
543+
535544
break;
536545
case ELF::PT_INTERP:
537546
BC->HasInterpHeader = true;

0 commit comments

Comments
 (0)