[llvm-objcopy] Fix sh_link
authorAlexander Shaposhnikov <shal1t712@gmail.com>
Fri, 20 Apr 2018 20:46:04 +0000 (20:46 +0000)
committerAlexander Shaposhnikov <shal1t712@gmail.com>
Fri, 20 Apr 2018 20:46:04 +0000 (20:46 +0000)
This diff fixes sh_link for various types of sections
(i.e. for SHT_ARM_EXIDX, SHT_HASH). In particular, this change enables us
to use llvm-objcopy with clang -gsplit-dwarf for the target android-arm.

Test plan: make check-all

Differential revision: https://reviews.llvm.org/D45851

llvm-svn: 330478

llvm/test/tools/llvm-objcopy/armexidx-link.test [new file with mode: 0644]
llvm/test/tools/llvm-objcopy/dynsym-error-remove-strtab.test
llvm/tools/llvm-objcopy/Object.cpp
llvm/tools/llvm-objcopy/Object.h

diff --git a/llvm/test/tools/llvm-objcopy/armexidx-link.test b/llvm/test/tools/llvm-objcopy/armexidx-link.test
new file mode 100644 (file)
index 0000000..ec942a1
--- /dev/null
@@ -0,0 +1,48 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy -remove-section=.text.bar %t %t2
+# RUN: llvm-readobj -sections %t2 | FileCheck %s
+
+# CHECK:          Index: 2
+# CHECK-NEXT:     Name: .ARM.exidx.text.foo (1)
+# CHECK-NEXT:     Type: SHT_ARM_EXIDX (0x70000001)
+# CHECK:          Address: 0x0
+# CHECK-NEXT:     Offset: 0x34
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Link: 1
+# CHECK-NEXT:     Info: 0
+
+--- !ELF
+FileHeader:      
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_ARM
+  Flags:           [ EF_ARM_EABI_VER5 ]
+Sections:        
+  - Name:            .text.bar
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000004
+    Content:         ''
+  - Name:            .text.foo
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000004
+    Content:         ''
+  - Name:            .ARM.exidx.text.foo
+    Type:            SHT_ARM_EXIDX
+    Flags:           [ SHF_ALLOC, SHF_LINK_ORDER ]
+    Link:            .text.foo
+    AddressAlign:    0x0000000000000004
+    Content:         ''
+Symbols:         
+  Local:           
+    - Name:            .text.bar
+      Type:            STT_SECTION
+      Section:         .text.bar
+    - Name:            .text.foo
+      Type:            STT_SECTION
+      Section:         .text.foo
+    - Name:            .ARM.exidx.text.foo
+      Type:            STT_SECTION
+      Section:         .ARM.exidx.text.foo
index ef6ef24..a6df5df 100644 (file)
@@ -1,3 +1,3 @@
 # RUN: not llvm-objcopy -R .dynstr %p/Inputs/dynsym.so %t 2>&1 >/dev/null | FileCheck %s
 
-# CHECK: String table .dynstr cannot be removed because it is referenced by the section .dynsym
+# CHECK: Section .dynstr cannot be removed because it is referenced by the section .dynsym
index e4c268d..c7ce230 100644 (file)
@@ -353,9 +353,9 @@ void DynamicRelocationSection::accept(SectionVisitor &Visitor) const {
   Visitor.visit(*this);
 }
 
-void SectionWithStrTab::removeSectionReferences(const SectionBase *Sec) {
-  if (StrTab == Sec) {
-    error("String table " + StrTab->Name +
+void Section::removeSectionReferences(const SectionBase *Sec) {
+  if (LinkSection == Sec) {
+    error("Section " + LinkSection->Name +
           " cannot be removed because it is "
           "referenced by the section " +
           this->Name);
@@ -367,23 +367,18 @@ void GroupSection::finalize() {
   this->Link = SymTab->Index;
 }
 
-bool SectionWithStrTab::classof(const SectionBase *S) {
-  return isa<DynamicSymbolTableSection>(S) || isa<DynamicSection>(S);
+void Section::initialize(SectionTableRef SecTable) {
+  if (Link != ELF::SHN_UNDEF)
+    LinkSection =
+        SecTable.getSection(Link, "Link field value " + Twine(Link) +
+                                      " in section " + Name + " is invalid");
 }
 
-void SectionWithStrTab::initialize(SectionTableRef SecTable) {
-  auto StrTab =
-      SecTable.getSection(Link, "Link field value " + Twine(Link) +
-                                    " in section " + Name + " is invalid");
-  if (StrTab->Type != SHT_STRTAB) {
-    error("Link field value " + Twine(Link) + " in section " + Name +
-          " is not a string table");
-  }
-  setStrTab(StrTab);
+void Section::finalize() {
+  if (LinkSection)
+    this->Link = LinkSection->Index;
 }
 
-void SectionWithStrTab::finalize() { this->Link = StrTab->Index; }
-
 void GnuDebugLinkSection::init(StringRef File, StringRef Data) {
   FileName = sys::path::filename(File);
   // The format for the .gnu_debuglink starts with the file name and is
index bf8b522..ddc0da1 100644 (file)
@@ -259,11 +259,15 @@ class Section : public SectionBase {
   MAKE_SEC_WRITER_FRIEND
 
   ArrayRef<uint8_t> Contents;
+  SectionBase *LinkSection = nullptr;
 
 public:
   explicit Section(ArrayRef<uint8_t> Data) : Contents(Data) {}
 
   void accept(SectionVisitor &Visitor) const override;
+  void removeSectionReferences(const SectionBase *Sec) override;
+  void initialize(SectionTableRef SecTable) override;
+  void finalize() override;
 };
 
 class OwnedDataSection : public SectionBase {
@@ -456,7 +460,7 @@ public:
   void setFlagWord(ELF::Elf32_Word W) { FlagWord = W; }
   void addMember(SectionBase *Sec) { GroupMembers.push_back(Sec); }
 
-  void initialize(SectionTableRef SecTable) override {};
+  void initialize(SectionTableRef SecTable) override{};
   void accept(SectionVisitor &) const override;
   void finalize() override;
 
@@ -465,31 +469,18 @@ public:
   }
 };
 
-class SectionWithStrTab : public Section {
-  const SectionBase *StrTab = nullptr;
-  void setStrTab(const SectionBase *StringTable) { StrTab = StringTable; }
-
-public:
-  explicit SectionWithStrTab(ArrayRef<uint8_t> Data) : Section(Data) {}
-  void removeSectionReferences(const SectionBase *Sec) override;
-  void initialize(SectionTableRef SecTable) override;
-  void finalize() override;
-  static bool classof(const SectionBase *S);
-};
-
-class DynamicSymbolTableSection : public SectionWithStrTab {
+class DynamicSymbolTableSection : public Section {
 public:
-  explicit DynamicSymbolTableSection(ArrayRef<uint8_t> Data)
-      : SectionWithStrTab(Data) {}
+  explicit DynamicSymbolTableSection(ArrayRef<uint8_t> Data) : Section(Data) {}
 
   static bool classof(const SectionBase *S) {
     return S->Type == ELF::SHT_DYNSYM;
   }
 };
 
-class DynamicSection : public SectionWithStrTab {
+class DynamicSection : public Section {
 public:
-  explicit DynamicSection(ArrayRef<uint8_t> Data) : SectionWithStrTab(Data) {}
+  explicit DynamicSection(ArrayRef<uint8_t> Data) : Section(Data) {}
 
   static bool classof(const SectionBase *S) {
     return S->Type == ELF::SHT_DYNAMIC;