[PATCH] D130815: [BOLT] Handle unclaimed PC data relocation related to jump table

Huan Nguyen via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 29 19:38:51 PDT 2022


nhuhuan created this revision.
Herald added a reviewer: rafauler.
Herald added a subscriber: ayermolo.
Herald added a reviewer: Amir.
Herald added a reviewer: maksfb.
Herald added a project: All.
nhuhuan requested review of this revision.
Herald added subscribers: llvm-commits, yota9.
Herald added a project: LLVM.

The limit in current implementation of jump table analysis causes some
jump tables, or parts of a jump table to be mishandled. Optimizing
functions pointing to/pointed by such jump table lead to incorrect
binaries. Therefore, some efforts are needed to handle such unclaimed
relocations.

The main idea is (a) finding the jump table base potentially associated
to the unclaimed relocation, and (b) conservatively ignoring functions
pointing to/pointed by such possible jump table entry.

To avoid skipping many unrelated functions, we only process potential
entries within a range from the jump table base.

Test Plan:

  ninja check-bolt


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130815

Files:
  bolt/lib/Core/BinaryContext.cpp


Index: bolt/lib/Core/BinaryContext.cpp
===================================================================
--- bolt/lib/Core/BinaryContext.cpp
+++ bolt/lib/Core/BinaryContext.cpp
@@ -723,6 +723,7 @@
       AbortedJTs.push_back(JT);
       continue;
     }
+
     for (BinaryFunction *Frag : JT->Parents) {
       for (uint64_t EntryAddress : JT->EntriesAsAddress)
         // if target is builtin_unreachable
@@ -735,9 +736,10 @@
         }
     }
 
-    // In strict mode, erase PC-relative relocation record. Later we check that
-    // all such records are erased and thus have been accounted for.
-    if (opts::StrictMode && JT->Type == JumpTable::JTT_PIC) {
+    // For nonstripped binaries, erase identified PC-relative relocations
+    // Later, account for unclaimed relocations possibly related to jump table
+    // In strict mode, check if all such relocations have been accounted for
+    if (!DataPCRelocations.empty() && JT->Type == JumpTable::JTT_PIC) {
       for (uint64_t Address = JT->getAddress();
            Address < JT->getAddress() + JT->getSize();
            Address += JT->EntrySize) {
@@ -760,6 +762,63 @@
     JumpTables.erase(JumpTables.find(JT->getAddress()));
   }
 
+  // Scan for unclaimed PC-relative relocations related to jump table only
+  // 1. Find the PIC jump table preceding the relocation address
+  // 2. Compute jump table target with respect to jump table base
+  // 3. Perform instruction boundary checks to prune invalid targets
+  // 4. Ignore the function contains the jump table target instruction
+  // 5. Ignore all functions that access to the jump table
+  if (!JumpTables.empty()) {
+    for (uint64_t Reloc : DataPCRelocations) {
+      JumpTable *JT = nullptr;
+      // Reloc does not belong to any jump table
+      if (Reloc < JumpTables.begin()->first)
+        continue;
+      // Reloc is an entry in the last jump table
+      if (JumpTables.rbegin()->first <= Reloc) {
+        if (JumpTables.rbegin()->first + 50 > Reloc)
+          JT = JumpTables.rbegin()->second;
+      }
+      // Reloc is an entry in the jump table preceding Reloc
+      else {
+        auto Iter = JumpTables.upper_bound(Reloc);
+        --Iter;
+        if (Iter->first + 50 > Reloc)
+          JT = Iter->second;
+      }
+
+      if (JT != nullptr && JT->Type == JumpTable::JTT_PIC) {
+        // Compute jump table target
+        const uint64_t EntrySize = getJumpTableEntrySize(JT->Type);
+        uint64_t Address =
+            JT->getAddress() + *getSignedValueAtAddress(Reloc, EntrySize);
+        BinaryFunction *TargetBF = getBinaryFunctionContainingAddress(Address);
+        // Perform instruction boundary check
+        if (TargetBF != nullptr) {
+          // If the potential entry points to a valid function
+          if (TargetBF->getState() == BinaryFunction::State::Disassembled) {
+            if (TargetBF->getInstructionAtOffset(Address -
+                                                 TargetBF->getAddress())) {
+              // Ignore the function containing jump table target
+              TargetBF->setIgnored();
+              // Ignore all functions accessing the jump table
+              for (BinaryFunction *BF : JT->Parents)
+                BF->setIgnored();
+            }
+          }
+          // If the potential entry points to a skipped function
+          else {
+            // Ignore the function containing jump table target
+            TargetBF->setIgnored();
+            // Ignore all functions accessing the jump table
+            for (BinaryFunction *BF : JT->Parents)
+              BF->setIgnored();
+          }
+        }
+      }
+    }
+  }
+
   if (opts::StrictMode && DataPCRelocations.size()) {
     LLVM_DEBUG({
       dbgs() << DataPCRelocations.size()


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D130815.448762.patch
Type: text/x-patch
Size: 3769 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220730/3c7df749/attachment.bin>


More information about the llvm-commits mailing list