diff options
author | George Rimar <grimar@accesssoftek.com> | 2016-03-03 07:49:35 +0000 |
---|---|---|
committer | George Rimar <grimar@accesssoftek.com> | 2016-03-03 07:49:35 +0000 |
commit | 4cfe572932ddb35dc91d4c241e41205543479b17 (patch) | |
tree | d0e5894145383d376c05a9cf97ac95f16f97e97b | |
parent | a64c8233b87eb26e9677faf5afe43e72a0ca1079 (diff) | |
download | bcm5719-llvm-4cfe572932ddb35dc91d4c241e41205543479b17.tar.gz bcm5719-llvm-4cfe572932ddb35dc91d4c241e41205543479b17.zip |
[ELF] - add support for relocations against local symbols when producing relocatable output.
There was a known limitation for -r option:
relocations against local symbols were not supported.
For example rel[a].eh_frame sections contained relocations against sections
and that was not supported for -r before. Patch fixes that.
Differential review: http://reviews.llvm.org/D17813
llvm-svn: 262590
-rw-r--r-- | lld/ELF/InputFiles.cpp | 4 | ||||
-rw-r--r-- | lld/ELF/InputSection.cpp | 14 | ||||
-rw-r--r-- | lld/ELF/OutputSections.h | 3 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 11 | ||||
-rw-r--r-- | lld/test/ELF/Inputs/relocatable-ehframe.s | 14 | ||||
-rw-r--r-- | lld/test/ELF/relocatable-ehframe.s | 42 |
6 files changed, 81 insertions, 7 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 393c52b874d..95307e993e1 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -266,7 +266,9 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { return MipsReginfo; } - if (Name == ".eh_frame") + // We dont need special handling of .eh_frame sections if relocatable + // output was choosen. Proccess them as usual input sections. + if (!Config->Relocatable && Name == ".eh_frame") return new (EHAlloc.Allocate()) EHInputSection<ELFT>(this, &Sec); if (shouldMerge<ELFT>(Sec)) return new (MAlloc.Allocate()) MergeInputSection<ELFT>(this, &Sec); diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 4bdb45ee07d..61f3c3c583e 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -132,11 +132,15 @@ void InputSection<ELFT>::copyRelocations(uint8_t *Buf, RelType *P = reinterpret_cast<RelType *>(Buf); Buf += sizeof(RelType); - // Relocation for local symbol here means that it is probably - // rel[a].eh_frame section which has references to - // sections in r_info field. Also needs fix for addend. - if (SymIndex < SymTab->sh_info) - fatal("Relocation against local symbols is not supported yet"); + // Relocation against local symbol here means that it is probably + // rel[a].eh_frame section which has references to sections in r_info field. + if (SymIndex < SymTab->sh_info) { + const Elf_Sym *Sym = this->File->getLocalSymbol(SymIndex); + uint32_t Idx = Out<ELFT>::SymTab->Locals[Sym]; + P->r_offset = RelocatedSection->getOffset(Rel.r_offset); + P->setSymbolAndType(Idx, Type, Config->Mips64EL); + continue; + } SymbolBody *Body = this->File->getSymbolBody(SymIndex)->repl(); P->r_offset = RelocatedSection->getOffset(Rel.r_offset); diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 8ded7d7fca7..68103525dca 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -241,6 +241,9 @@ public: unsigned NumLocals = 0; StringTableSection<ELFT> &StrTabSec; + // Local symbol -> ID, filled only when producing relocatable output. + llvm::DenseMap<const Elf_Sym *, uint32_t> Locals; + private: void writeLocalSymbols(uint8_t *&Buf); void writeGlobalSymbols(uint8_t *Buf); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 8b1486c392c..264ffd757f1 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -528,9 +528,13 @@ static void reportUndefined(SymbolTable<ELFT> &Symtab, SymbolBody *Sym) { template <class ELFT> static bool shouldKeepInSymtab(const ObjectFile<ELFT> &File, StringRef SymName, const typename ELFFile<ELFT>::Elf_Sym &Sym) { - if (Sym.getType() == STT_SECTION || Sym.getType() == STT_FILE) + if (Sym.getType() == STT_FILE) return false; + // We keep sections in symtab for relocatable output. + if (Sym.getType() == STT_SECTION) + return Config->Relocatable; + InputSectionBase<ELFT> *Sec = File.getSection(Sym); // If sym references a section in a discarded group, don't keep it. if (Sec == InputSection<ELFT>::Discarded) @@ -569,8 +573,13 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { InputSectionBase<ELFT> *Section = F->getSection(Sym); if (!Section->Live) continue; + // That can happen if creating relocatable output. + if (Sym.getType() == STT_SECTION) + SymName = Section->getSectionName(); } ++Out<ELFT>::SymTab->NumLocals; + if (Config->Relocatable) + Out<ELFT>::SymTab->Locals[&Sym] = Out<ELFT>::SymTab->NumLocals; F->KeptLocalSyms.push_back(std::make_pair( &Sym, Out<ELFT>::SymTab->StrTabSec.addString(SymName))); } diff --git a/lld/test/ELF/Inputs/relocatable-ehframe.s b/lld/test/ELF/Inputs/relocatable-ehframe.s new file mode 100644 index 00000000000..68211e1d9a2 --- /dev/null +++ b/lld/test/ELF/Inputs/relocatable-ehframe.s @@ -0,0 +1,14 @@ +.section foo1,"ax",@progbits
+.cfi_startproc
+ nop
+.cfi_endproc
+
+.section bar1,"ax",@progbits
+.cfi_startproc
+ nop
+.cfi_endproc
+
+.section dah1,"ax",@progbits
+.cfi_startproc
+ nop
+.cfi_endproc
diff --git a/lld/test/ELF/relocatable-ehframe.s b/lld/test/ELF/relocatable-ehframe.s new file mode 100644 index 00000000000..d26939eb7ad --- /dev/null +++ b/lld/test/ELF/relocatable-ehframe.s @@ -0,0 +1,42 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocatable-ehframe.s -o %t2.o +# RUN: ld.lld -r %t1.o %t2.o -o %t +# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s +# RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=CHECKTEXT %s + +# CHECK: Relocations [ +# CHECK-NEXT: Section {{.*}} .rela.eh_frame { +# CHECK-NEXT: 0x20 R_X86_64_PC32 foo 0x0 +# CHECK-NEXT: 0x34 R_X86_64_PC32 bar 0x0 +# CHECK-NEXT: 0x48 R_X86_64_PC32 dah 0x0 +# CHECK-NEXT: 0x78 R_X86_64_PC32 foo1 0x0 +# CHECK-NEXT: 0x8C R_X86_64_PC32 bar1 0x0 +# CHECK-NEXT: 0xA0 R_X86_64_PC32 dah1 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +# CHECKTEXT: Contents of section .strtab: +# CHECKTEXT-NEXT: 0000 00666f6f 00626172 00646168 00666f6f .foo.bar.dah.foo +# CHECKTEXT-NEXT: 0010 31006261 72310064 61683100 5f737461 1.bar1.dah1._sta +# CHECKTEXT-NEXT: 0020 727400 rt. + +.section foo,"ax",@progbits +.cfi_startproc + nop +.cfi_endproc + +.section bar,"ax",@progbits +.cfi_startproc + nop +.cfi_endproc + +.section dah,"ax",@progbits +.cfi_startproc + nop +.cfi_endproc + +.text +.globl _start; +_start: + nop |