Skip to content

[BOLT][Linux] Add support for AArch64 #130480

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

FLZ101
Copy link
Contributor

@FLZ101 FLZ101 commented Mar 9, 2025

Basic support for AArch64.

This PR depends on #130398.

…ersions

* utilize LinuxKernelVersion to simplify parsing of alternative
  instruction entries and exception table entries
* refactor static keys handling to make it work with relocation
  mode and function splitting, and also reduce duplicated code
@llvmbot
Copy link
Member

llvmbot commented Mar 9, 2025

@llvm/pr-subscribers-bolt

Author: Franklin (FLZ101)

Changes

It is not expected to work well yet, fixes will be pushed later.


Patch is 51.60 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/130480.diff

21 Files Affected:

  • (modified) bolt/docs/CommandLineArgumentReference.md (-12)
  • (modified) bolt/include/bolt/Core/BinaryContext.h (+15-1)
  • (modified) bolt/include/bolt/Core/BinaryFunction.h (+11)
  • (modified) bolt/include/bolt/Core/FunctionLayout.h (+4)
  • (modified) bolt/include/bolt/Core/Linker.h (+7)
  • (modified) bolt/include/bolt/Core/MCPlusBuilder.h (+2-1)
  • (modified) bolt/include/bolt/Rewrite/MetadataRewriter.h (+7-1)
  • (modified) bolt/include/bolt/Rewrite/MetadataRewriters.h (+4-4)
  • (modified) bolt/include/bolt/Rewrite/RewriteInstance.h (+2)
  • (modified) bolt/lib/Core/BinaryContext.cpp (+17)
  • (modified) bolt/lib/Core/JumpTable.cpp (+1-1)
  • (modified) bolt/lib/Core/MCPlusBuilder.cpp (+7-2)
  • (modified) bolt/lib/Rewrite/BuildIDRewriter.cpp (+4-4)
  • (modified) bolt/lib/Rewrite/CMakeLists.txt (+1)
  • (modified) bolt/lib/Rewrite/LinuxKernelRewriter.cpp (+228-208)
  • (added) bolt/lib/Rewrite/MetadataRewriter.cpp (+20)
  • (modified) bolt/lib/Rewrite/PseudoProbeRewriter.cpp (+4-4)
  • (modified) bolt/lib/Rewrite/RewriteInstance.cpp (+27-8)
  • (modified) bolt/lib/Rewrite/SDTRewriter.cpp (+4-3)
  • (modified) bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp (+10)
  • (modified) bolt/test/X86/linux-alt-instruction.s (+2-36)
diff --git a/bolt/docs/CommandLineArgumentReference.md b/bolt/docs/CommandLineArgumentReference.md
index f3881c9a640a9..2c880388e3faa 100644
--- a/bolt/docs/CommandLineArgumentReference.md
+++ b/bolt/docs/CommandLineArgumentReference.md
@@ -56,14 +56,6 @@
 
   Allow processing of stripped binaries
 
-- `--alt-inst-feature-size=<uint>`
-
-  Size of feature field in .altinstructions
-
-- `--alt-inst-has-padlen`
-
-  Specify that .altinstructions has padlen field
-
 - `--asm-dump[=<dump folder>]`
 
   Dump function into assembly
@@ -254,10 +246,6 @@
 
   Redirect journaling to a file instead of stdout/stderr
 
-- `--long-jump-labels`
-
-  Always use long jumps/nops for Linux kernel static keys
-
 - `--match-profile-with-function-hash`
 
   Match profile with function hash
diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h
index 8bec1db70e25a..959dd11e4a799 100644
--- a/bolt/include/bolt/Core/BinaryContext.h
+++ b/bolt/include/bolt/Core/BinaryContext.h
@@ -613,6 +613,9 @@ class BinaryContext {
   /// Addresses reserved for kernel on x86_64 start at this location.
   static constexpr uint64_t KernelStartX86_64 = 0xFFFF'FFFF'8000'0000;
 
+  /// Addresses reserved for kernel on aarch64 start at this location.
+  static constexpr uint64_t KernelStartAArch64 = 0xFFFF'0000'0000'0000;
+
   /// Map address to a constant island owner (constant data in code section)
   std::map<uint64_t, BinaryFunction *> AddressToConstantIslandMap;
 
@@ -911,7 +914,11 @@ class BinaryContext {
   /// Return a value of the global \p Symbol or an error if the value
   /// was not set.
   ErrorOr<uint64_t> getSymbolValue(const MCSymbol &Symbol) const {
-    const BinaryData *BD = getBinaryDataByName(Symbol.getName());
+    return getSymbolValue(Symbol.getName());
+  }
+
+  ErrorOr<uint64_t> getSymbolValue(StringRef Name) const {
+    const BinaryData *BD = getBinaryDataByName(Name);
     if (!BD)
       return std::make_error_code(std::errc::bad_address);
     return BD->getAddress();
@@ -1237,6 +1244,13 @@ class BinaryContext {
     return const_cast<BinaryContext *>(this)->getSectionForAddress(Address);
   }
 
+  ErrorOr<BinarySection &> getSectionForOutputAddress(uint64_t Address);
+  ErrorOr<const BinarySection &>
+  getSectionForOutputAddress(uint64_t Address) const {
+    return const_cast<BinaryContext *>(this)->getSectionForOutputAddress(
+        Address);
+  }
+
   /// Return internal section representation for a section in a file.
   BinarySection *getSectionForSectionRef(SectionRef Section) const {
     return SectionRefToBinarySection.lookup(Section);
diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h
index 942840a7621fd..20caebe4b129c 100644
--- a/bolt/include/bolt/Core/BinaryFunction.h
+++ b/bolt/include/bolt/Core/BinaryFunction.h
@@ -1243,6 +1243,17 @@ class BinaryFunction {
     return Islands->FunctionColdConstantIslandLabel;
   }
 
+  const FunctionFragment *
+  getFunctionFragmentForOutputAddress(uint64_t OutputAddress) const {
+    for (const FunctionFragment &FF : Layout.fragments()) {
+      uint64_t Address = FF.getAddress();
+      uint64_t Size = FF.getImageSize();
+      if (Address <= OutputAddress && OutputAddress < Address + Size)
+        return &FF;
+    }
+    return nullptr;
+  }
+
   /// Return true if this is a function representing a PLT entry.
   bool isPLTFunction() const { return PLTSymbol != nullptr; }
 
diff --git a/bolt/include/bolt/Core/FunctionLayout.h b/bolt/include/bolt/Core/FunctionLayout.h
index ee4dd689b8dd6..65b80051862c4 100644
--- a/bolt/include/bolt/Core/FunctionLayout.h
+++ b/bolt/include/bolt/Core/FunctionLayout.h
@@ -117,6 +117,10 @@ class FunctionFragment {
   uint64_t getFileOffset() const { return FileOffset; }
   void setFileOffset(uint64_t Offset) { FileOffset = Offset; }
 
+  uint8_t *getOutputData() const {
+    return reinterpret_cast<uint8_t *>(getImageAddress());
+  }
+
   unsigned size() const { return Size; };
   bool empty() const { return size() == 0; };
   iterator begin();
diff --git a/bolt/include/bolt/Core/Linker.h b/bolt/include/bolt/Core/Linker.h
index 66b3ad18e3c7b..1e0876a0e13d9 100644
--- a/bolt/include/bolt/Core/Linker.h
+++ b/bolt/include/bolt/Core/Linker.h
@@ -46,6 +46,13 @@ class BOLTLinker {
   /// Return the address and size of a symbol or std::nullopt if it cannot be
   /// found.
   virtual std::optional<SymbolInfo> lookupSymbolInfo(StringRef Name) const = 0;
+
+  /// Return the address of a symbol or std::nullopt if it cannot be found.
+  std::optional<uint64_t> lookupSymbol(StringRef Name) const {
+    if (const auto Info = lookupSymbolInfo(Name))
+      return Info->Address;
+    return std::nullopt;
+  }
 };
 
 } // namespace bolt
diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h
index fbb853656fb91..52643ffcd5b78 100644
--- a/bolt/include/bolt/Core/MCPlusBuilder.h
+++ b/bolt/include/bolt/Core/MCPlusBuilder.h
@@ -1211,8 +1211,9 @@ class MCPlusBuilder {
 
   /// Set the label of \p Inst or return the existing label for the instruction.
   /// This label will be emitted right before \p Inst is emitted to MCStreamer.
+  /// If \p Temp is true, then this label does not survive in the symbol table.
   MCSymbol *getOrCreateInstLabel(MCInst &Inst, const Twine &Name,
-                                 MCContext *Ctx) const;
+                                 MCContext *Ctx, bool Temp = true) const;
 
   /// Set the label of \p Inst. This label will be emitted right before \p Inst
   /// is emitted to MCStreamer.
diff --git a/bolt/include/bolt/Rewrite/MetadataRewriter.h b/bolt/include/bolt/Rewrite/MetadataRewriter.h
index 6ff8f0af7a8e6..6988e5de4e6bd 100644
--- a/bolt/include/bolt/Rewrite/MetadataRewriter.h
+++ b/bolt/include/bolt/Rewrite/MetadataRewriter.h
@@ -19,6 +19,8 @@
 namespace llvm {
 namespace bolt {
 
+class RewriteInstance;
+
 /// Base class for handling file sections with metadata. In this context,
 /// metadata encompasses a wide range of data that references code and other
 /// data. Such metadata may or may not have an impact on program execution.
@@ -34,10 +36,14 @@ class MetadataRewriter {
   StringRef Name;
 
 protected:
+  RewriteInstance &RI;
+
   /// Provides access to the binary context.
   BinaryContext &BC;
 
-  MetadataRewriter(StringRef Name, BinaryContext &BC) : Name(Name), BC(BC) {}
+  MetadataRewriter(StringRef Name, RewriteInstance &RI);
+
+  std::optional<uint64_t> lookupSymbol(const StringRef Name);
 
 public:
   virtual ~MetadataRewriter() = default;
diff --git a/bolt/include/bolt/Rewrite/MetadataRewriters.h b/bolt/include/bolt/Rewrite/MetadataRewriters.h
index b71bd6cad2505..76face9888235 100644
--- a/bolt/include/bolt/Rewrite/MetadataRewriters.h
+++ b/bolt/include/bolt/Rewrite/MetadataRewriters.h
@@ -19,13 +19,13 @@ class BinaryContext;
 
 // The list of rewriter build functions.
 
-std::unique_ptr<MetadataRewriter> createLinuxKernelRewriter(BinaryContext &);
+std::unique_ptr<MetadataRewriter> createLinuxKernelRewriter(RewriteInstance &);
 
-std::unique_ptr<MetadataRewriter> createBuildIDRewriter(BinaryContext &);
+std::unique_ptr<MetadataRewriter> createBuildIDRewriter(RewriteInstance &);
 
-std::unique_ptr<MetadataRewriter> createPseudoProbeRewriter(BinaryContext &);
+std::unique_ptr<MetadataRewriter> createPseudoProbeRewriter(RewriteInstance &);
 
-std::unique_ptr<MetadataRewriter> createSDTRewriter(BinaryContext &);
+std::unique_ptr<MetadataRewriter> createSDTRewriter(RewriteInstance &);
 
 } // namespace bolt
 } // namespace llvm
diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h
index 42094cb732107..92a2763e28c4d 100644
--- a/bolt/include/bolt/Rewrite/RewriteInstance.h
+++ b/bolt/include/bolt/Rewrite/RewriteInstance.h
@@ -42,6 +42,8 @@ class ProfileReaderBase;
 /// optimizations) and rewriting. It also has the logic to coordinate such
 /// events.
 class RewriteInstance {
+  friend class MetadataRewriter;
+
 public:
   // This constructor has complex initialization that can fail during
   // construction. Constructors can’t return errors, so clients must test \p Err
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
index f9fc536f3569a..377de5a994a11 100644
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -2110,6 +2110,23 @@ ErrorOr<BinarySection &> BinaryContext::getSectionForAddress(uint64_t Address) {
   return std::make_error_code(std::errc::bad_address);
 }
 
+ErrorOr<BinarySection &>
+BinaryContext::getSectionForOutputAddress(uint64_t Address) {
+  for (auto &Sec : allocatableSections()) {
+    // Skip pseudo sections that serve a purpose of creating a corresponding
+    // entry in section header table
+    if (Sec.getOutputContents().empty())
+      continue;
+
+    uint64_t OutputAddress = Sec.getOutputAddress();
+    uint64_t OutputSize = Sec.getOutputSize();
+    if (OutputAddress && OutputAddress <= Address &&
+        Address < OutputAddress + OutputSize)
+      return Sec;
+  }
+  return std::make_error_code(std::errc::bad_address);
+}
+
 ErrorOr<StringRef>
 BinaryContext::getSectionNameForAddress(uint64_t Address) const {
   if (ErrorOr<const BinarySection &> Section = getSectionForAddress(Address))
diff --git a/bolt/lib/Core/JumpTable.cpp b/bolt/lib/Core/JumpTable.cpp
index 65e1032c579b5..d3ca951d7e453 100644
--- a/bolt/lib/Core/JumpTable.cpp
+++ b/bolt/lib/Core/JumpTable.cpp
@@ -85,7 +85,7 @@ void bolt::JumpTable::updateOriginal() {
   uint64_t EntryOffset = BaseOffset;
   for (MCSymbol *Entry : Entries) {
     const uint64_t RelType =
-        Type == JTT_NORMAL ? ELF::R_X86_64_64 : ELF::R_X86_64_PC32;
+        Type == JTT_NORMAL ? Relocation::getAbs64() : Relocation::getPC32();
     const uint64_t RelAddend =
         Type == JTT_NORMAL ? 0 : EntryOffset - BaseOffset;
     // Replace existing relocation with the new one to allow any modifications
diff --git a/bolt/lib/Core/MCPlusBuilder.cpp b/bolt/lib/Core/MCPlusBuilder.cpp
index 7ff7a2288451c..b0aa40f9eac16 100644
--- a/bolt/lib/Core/MCPlusBuilder.cpp
+++ b/bolt/lib/Core/MCPlusBuilder.cpp
@@ -288,12 +288,17 @@ MCSymbol *MCPlusBuilder::getInstLabel(const MCInst &Inst) const {
 }
 
 MCSymbol *MCPlusBuilder::getOrCreateInstLabel(MCInst &Inst, const Twine &Name,
-                                              MCContext *Ctx) const {
+                                              MCContext *Ctx, bool Temp) const {
   MCSymbol *Label = getInstLabel(Inst);
   if (Label)
     return Label;
 
-  Label = Ctx->createNamedTempSymbol(Name);
+  if (Temp) {
+    Label = Ctx->createNamedTempSymbol(Name);
+  } else {
+    SmallVector<char, 16> Buf;
+    Label = Ctx->createLocalSymbol(Name.toStringRef(Buf));
+  }
   setAnnotationOpValue(Inst, MCAnnotation::kLabel,
                        reinterpret_cast<int64_t>(Label));
   return Label;
diff --git a/bolt/lib/Rewrite/BuildIDRewriter.cpp b/bolt/lib/Rewrite/BuildIDRewriter.cpp
index 83d0c9bfe182a..8a9c32619f6a9 100644
--- a/bolt/lib/Rewrite/BuildIDRewriter.cpp
+++ b/bolt/lib/Rewrite/BuildIDRewriter.cpp
@@ -39,8 +39,8 @@ class BuildIDRewriter final : public MetadataRewriter {
   std::optional<uint64_t> BuildIDSize;
 
 public:
-  BuildIDRewriter(StringRef Name, BinaryContext &BC)
-      : MetadataRewriter(Name, BC) {}
+  BuildIDRewriter(StringRef Name, RewriteInstance &RI)
+      : MetadataRewriter(Name, RI) {}
 
   Error sectionInitializer() override;
 
@@ -108,6 +108,6 @@ Error BuildIDRewriter::postEmitFinalizer() {
 } // namespace
 
 std::unique_ptr<MetadataRewriter>
-llvm::bolt::createBuildIDRewriter(BinaryContext &BC) {
-  return std::make_unique<BuildIDRewriter>("build-id-rewriter", BC);
+llvm::bolt::createBuildIDRewriter(RewriteInstance &RI) {
+  return std::make_unique<BuildIDRewriter>("build-id-rewriter", RI);
 }
diff --git a/bolt/lib/Rewrite/CMakeLists.txt b/bolt/lib/Rewrite/CMakeLists.txt
index c83cf36982167..c403b8fcc33b2 100644
--- a/bolt/lib/Rewrite/CMakeLists.txt
+++ b/bolt/lib/Rewrite/CMakeLists.txt
@@ -20,6 +20,7 @@ add_llvm_library(LLVMBOLTRewrite
   LinuxKernelRewriter.cpp
   MachORewriteInstance.cpp
   MetadataManager.cpp
+  MetadataRewriter.cpp
   BuildIDRewriter.cpp
   PseudoProbeRewriter.cpp
   RewriteInstance.cpp
diff --git a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp
index 5a5e044184d0b..6c02e1784afe9 100644
--- a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp
+++ b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp
@@ -31,16 +31,6 @@ using namespace bolt;
 
 namespace opts {
 
-static cl::opt<bool>
-    AltInstHasPadLen("alt-inst-has-padlen",
-                     cl::desc("specify that .altinstructions has padlen field"),
-                     cl::init(false), cl::Hidden, cl::cat(BoltCategory));
-
-static cl::opt<uint32_t>
-    AltInstFeatureSize("alt-inst-feature-size",
-                       cl::desc("size of feature field in .altinstructions"),
-                       cl::init(2), cl::Hidden, cl::cat(BoltCategory));
-
 static cl::opt<bool>
     DumpAltInstructions("dump-alt-instructions",
                         cl::desc("dump Linux alternative instructions info"),
@@ -79,11 +69,6 @@ static cl::opt<bool>
                    cl::desc("dump Linux kernel static keys jump table"),
                    cl::init(false), cl::Hidden, cl::cat(BoltCategory));
 
-static cl::opt<bool> LongJumpLabels(
-    "long-jump-labels",
-    cl::desc("always use long jumps/nops for Linux kernel static keys"),
-    cl::init(false), cl::Hidden, cl::cat(BoltCategory));
-
 static cl::opt<bool>
     PrintORC("print-orc",
              cl::desc("print ORC unwind information for instructions"),
@@ -94,7 +79,7 @@ static cl::opt<bool>
 /// Linux kernel version
 struct LKVersion {
   LKVersion() {}
-  LKVersion(unsigned Major, unsigned Minor, unsigned Rev)
+  LKVersion(unsigned Major, unsigned Minor, unsigned Rev = 0)
       : Major(Major), Minor(Minor), Rev(Rev) {}
 
   bool operator<(const LKVersion &Other) const {
@@ -229,13 +214,16 @@ class LinuxKernelRewriter final : public MetadataRewriter {
   static constexpr size_t STATIC_KEYS_JUMP_ENTRY_SIZE = 8;
 
   struct JumpInfoEntry {
-    bool Likely;
-    bool InitValue;
+    bool Likely{false};
+    bool InitValue{false};
+    bool Nop{false};
+    MCSymbol *JumpInstLabel{nullptr};
+    BinaryFunction *BF{nullptr};
   };
-  SmallVector<JumpInfoEntry, 16> JumpInfo;
+  std::vector<JumpInfoEntry> JumpInfo;
 
-  /// Static key entries that need nop conversion.
-  DenseSet<uint32_t> NopIDs;
+  // Use long jumps/nops for Linux kernel static keys
+  bool LongJumpLabels{false};
 
   /// Section containing static call table.
   ErrorOr<BinarySection &> StaticCallSection = std::errc::bad_address;
@@ -249,11 +237,6 @@ class LinuxKernelRewriter final : public MetadataRewriter {
   };
   using StaticCallListType = std::vector<StaticCallInfo>;
   StaticCallListType StaticCallEntries;
-
-  /// Section containing the Linux exception table.
-  ErrorOr<BinarySection &> ExceptionsSection = std::errc::bad_address;
-  static constexpr size_t EXCEPTION_TABLE_ENTRY_SIZE = 12;
-
   /// Functions with exception handling code.
   DenseSet<BinaryFunction *> FunctionsWithExceptions;
 
@@ -266,6 +249,15 @@ class LinuxKernelRewriter final : public MetadataRewriter {
   /// .altinstructions section.
   ErrorOr<BinarySection &> AltInstrSection = std::errc::bad_address;
 
+  struct AltInstrEntry {
+    uint64_t Offset{0};
+    uint64_t OrgInstrAddr{0};
+    uint64_t AltInstrAddr{0};
+    uint8_t Instrlen{0};
+    uint8_t Replacementlen{0};
+  };
+  std::vector<AltInstrEntry> AltInstrEntries;
+
   /// Section containing Linux bug table.
   ErrorOr<BinarySection &> BugTableSection = std::errc::bad_address;
 
@@ -314,7 +306,7 @@ class LinuxKernelRewriter final : public MetadataRewriter {
   Error readStaticCalls();
   Error rewriteStaticCalls();
 
-  Error readExceptionTable();
+  Error readExceptionTable(StringRef SectionName);
   Error rewriteExceptionTable();
 
   /// Paravirtual instruction patch sites.
@@ -332,8 +324,6 @@ class LinuxKernelRewriter final : public MetadataRewriter {
   /// Handle alternative instruction info from .altinstructions.
   Error readAltInstructions();
   void processAltInstructionsPostCFG();
-  Error tryReadAltInstructions(uint32_t AltInstFeatureSize,
-                               bool AltInstHasPadLen, bool ParseOnly);
 
   /// Read .pci_fixup
   Error readPCIFixupTable();
@@ -344,8 +334,8 @@ class LinuxKernelRewriter final : public MetadataRewriter {
   Error updateStaticKeysJumpTablePostEmit();
 
 public:
-  LinuxKernelRewriter(BinaryContext &BC)
-      : MetadataRewriter("linux-kernel-rewriter", BC) {}
+  LinuxKernelRewriter(RewriteInstance &RI)
+      : MetadataRewriter("linux-kernel-rewriter", RI) {}
 
   Error preCFGInitializer() override {
     if (Error E = detectLinuxKernelVersion())
@@ -359,7 +349,10 @@ class LinuxKernelRewriter final : public MetadataRewriter {
     if (Error E = readStaticCalls())
       return E;
 
-    if (Error E = readExceptionTable())
+    if (Error E = readExceptionTable("__ex_table"))
+      return E;
+
+    if (Error E = readExceptionTable("__kvm_ex_table"))
       return E;
 
     if (Error E = readParaInstructions())
@@ -446,6 +439,8 @@ Error LinuxKernelRewriter::detectLinuxKernelVersion() {
       LinuxKernelVersion = LKVersion(Major, Minor, Rev);
       BC.outs() << "BOLT-INFO: Linux kernel version is " << Match[1].str()
                 << "\n";
+      if (LinuxKernelVersion < LKVersion(5, 0))
+        return createStringError("Unsupported Linux kernel version");
       return Error::success();
     }
   }
@@ -557,8 +552,8 @@ void LinuxKernelRewriter::processInstructionFixups() {
       continue;
 
     Fixup.Section.addRelocation(Fixup.Offset, &Fixup.Label,
-                                Fixup.IsPCRelative ? ELF::R_X86_64_PC32
-                                                   : ELF::R_X86_64_64,
+                                Fixup.IsPCRelative ? Relocation::getPC32()
+                                                   : Relocation::getAbs64(),
                                 /*Addend*/ 0);
   }
 }
@@ -1074,7 +1069,7 @@ Error LinuxKernelRewriter::rewriteStaticCalls() {
                                  StaticCallSection->getAddress() +
                                  (Entry.ID - 1) * STATIC_CALL_ENTRY_SIZE;
     StaticCallSection->addRelocation(EntryOffset, Entry.Label,
-                                     ELF::R_X86_64_PC32, /*Addend*/ 0);
+                                     Relocation::getPC32(), /*Addend*/ 0);
   }
 
   return Error::success();
@@ -1094,12 +1089,31 @@ Error LinuxKernelRewriter::rewriteStaticCalls() {
 ///
 /// More info at:
 /// https://www.kernel.org/doc/Documentation/x86/exception-tables.txt
-Error LinuxKernelRewriter::readExceptionTable() {
-  ExceptionsSection = BC.getUniqueSectionByName("__ex_table");
+Error LinuxKernelRewriter::readExceptionTable(StringRef SectionName) {
+  ErrorOr<BinarySection &> ExceptionsSection =
+      BC.getUniqueSectionByName(SectionName);
   if (!ExceptionsSection)
     return Error::success();
 
-  if (ExceptionsSection->getSize() % EXCEPTION_TABLE_ENTRY_SIZE)
+  size_t ExceptionTableEntrySize = 0;
+  switch (BC.TheTriple->getArch()) {
+  case llvm::Triple::x86_64:
+    ExceptionTableEntrySize = 12;
+    break;
+
+  case llvm::Triple::aarch64:
+    if (LinuxKernelVersion >= LKVersion(5, 16))
+      ExceptionTableEntrySize = 12;
+    else
+      ExceptionTableEntrySize = 8;
+    break;
+
+  default:
+    llvm_unreachable("Unsupported architecture");
+  }
+  assert(ExceptionTableEntrySize && "exception table entry size is unknown");
+
+  if (ExceptionsSection->getSize() % ExceptionTableEntrySize)
     return createStringError(errc::executable_format_error,
                              "exception table size error");
 
@@ -1111,7 +1125,7 @@ Error LinuxKernelRewriter::readExceptionTable() {
   while (Cursor && Cursor.tell() < ExceptionsSection->getSize()) {
     const uint64_t InstAddress = AE.getPCRelAddress32(Cursor);
     const uint64_t FixupAddress = AE.getPCRelAddress32(Cursor);
-    const uint64_t Data = AE.getU32(Cursor);
+    Cursor.seek(Cursor.tell() + ExceptionTableEntrySize - 8);
 
     // Consume the status of the cursor.
     if (!Cursor)
@@ -1125,8 +1139,7 @@ Error LinuxKernelRewriter::readExceptionTable() {
     if (opts::DumpExceptions) {
       BC.outs() << "Exception Entry...
[truncated]

@FLZ101 FLZ101 force-pushed the feature-bolt-linux-aarch64 branch from c8a2cca to 5fa1a94 Compare March 11, 2025 15:13
Basic support for AArch64
@FLZ101 FLZ101 force-pushed the feature-bolt-linux-aarch64 branch from 5fa1a94 to c1f95bd Compare March 11, 2025 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants