[BOLT] Handle broken .dynsym in stripped binaries
authorHuan Nguyen <nhuhuan@yahoo.com>
Fri, 22 Jul 2022 18:23:38 +0000 (11:23 -0700)
committerAmir Ayupov <aaupov@fb.com>
Fri, 22 Jul 2022 18:24:09 +0000 (11:24 -0700)
Strip tools cause a few symbols in .dynsym to have bad section index.
This update safely keeps such broken symbols intact.

Test Plan:
```
ninja check-bolt
```

Reviewed By: Amir

Differential Revision: https://reviews.llvm.org/D130073

bolt/lib/Rewrite/RewriteInstance.cpp
bolt/test/X86/Inputs/broken_dynsym.yaml [new file with mode: 0644]
bolt/test/X86/broken_dynsym.test [new file with mode: 0644]

index 001ef3b..4e23866 100644 (file)
@@ -4465,6 +4465,14 @@ void RewriteInstance::updateELFSymbolTable(
   std::vector<ELFSymTy> Symbols;
 
   auto getNewSectionIndex = [&](uint32_t OldIndex) {
+    // For dynamic symbol table, the section index could be wrong on the input,
+    // and its value is ignored by the runtime if it's different from
+    // SHN_UNDEF and SHN_ABS.
+    // However, we still need to update dynamic symbol table, so return a
+    // section index, even though the index is broken.
+    if (IsDynSym && OldIndex >= NewSectionIndex.size())
+      return OldIndex;
+
     assert(OldIndex < NewSectionIndex.size() && "section index out of bounds");
     const uint32_t NewIndex = NewSectionIndex[OldIndex];
 
diff --git a/bolt/test/X86/Inputs/broken_dynsym.yaml b/bolt/test/X86/Inputs/broken_dynsym.yaml
new file mode 100644 (file)
index 0000000..84812b6
--- /dev/null
@@ -0,0 +1,33 @@
+!ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data: ELFDATA2LSB
+  Type: ET_EXEC
+  Machine: EM_X86_64
+ProgramHeaders:
+  - Type: PT_LOAD
+    FirstSec: .a
+    LastSec: .a
+    Align:           0x1000
+Sections:
+  - Name: .a
+    Type: SHT_PROGBITS
+    Content: 00
+    AddressAlign:    0x1
+  - Name: .b
+    Type: 0
+    AddressAlign:    0x1
+  - Name: .bss
+    Type: 0
+    AddressAlign:    0x1
+  - Type: SectionHeaderTable
+    Sections:
+      - Name: .dynsym
+      - Name: .dynstr
+      - Name: .a
+      - Name: .b
+      - Name: .bss
+      - Name: .strtab
+      - Name: .shstrtab
+DynamicSymbols:
+  - Section: .bss
diff --git a/bolt/test/X86/broken_dynsym.test b/bolt/test/X86/broken_dynsym.test
new file mode 100644 (file)
index 0000000..c715be8
--- /dev/null
@@ -0,0 +1,8 @@
+# This test checks if BOLT can process stripped binaries, where symbol's section
+# header index is corrupted due to strip tool.
+
+# RUN: yaml2obj %p/Inputs/broken_dynsym.yaml -o %t
+# RUN: llvm-strip -s %t
+# RUN: llvm-bolt %t -o %t.bolt | FileCheck %s
+
+# CHECK-NOT: section index out of bounds