[yaml2obj] - Lookup relocation symbols in dynamic symbol when .dynsym referenced.

This fixes https://bugs.llvm.org/show_bug.cgi?id=40337.

Previously, it was always assumed that relocations referenced symbols in the static symbol table. 
Now, if the Link field references a section called ".dynsym" it will look up these symbols
in the dynamic symbol table.

This patch is heavily based on D59097 by James Henderson

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

llvm-svn: 369645
This commit is contained in:
George Rimar 2019-08-22 12:39:56 +00:00
parent c2ca965c89
commit 91208447d0
4 changed files with 84 additions and 18 deletions

View File

@ -111,10 +111,11 @@ template <class ELFT> class ELFState {
NameToIdxMap SN2I;
NameToIdxMap SymN2I;
NameToIdxMap DynSymN2I;
ELFYAML::Object &Doc;
bool buildSectionIndex();
bool buildSymbolIndex(ArrayRef<ELFYAML::Symbol> Symbols);
bool buildSymbolIndexes();
void initELFHeader(Elf_Ehdr &Header);
void initProgramHeaders(std::vector<Elf_Phdr> &PHeaders);
bool initImplicitHeader(ELFState<ELFT> &State, ContiguousBlobAccumulator &CBA,
@ -717,11 +718,12 @@ bool ELFState<ELFT>::writeSectionContent(
auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
const NameToIdxMap &SymMap = Section.Link == ".dynsym" ? DynSymN2I : SymN2I;
for (const auto &Rel : Section.Relocations) {
unsigned SymIdx = 0;
// If a relocation references a symbol, try to look one up in the symbol
// table. If it is not there, treat the value as a symbol index.
if (Rel.Symbol && !SymN2I.lookup(*Rel.Symbol, SymIdx) &&
if (Rel.Symbol && !SymMap.lookup(*Rel.Symbol, SymIdx) &&
!to_integer(*Rel.Symbol, SymIdx)) {
WithColor::error() << "Unknown symbol referenced: '" << *Rel.Symbol
<< "' at YAML section '" << Section.Name << "'.\n";
@ -987,11 +989,10 @@ template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
return true;
}
template <class ELFT>
bool ELFState<ELFT>::buildSymbolIndex(ArrayRef<ELFYAML::Symbol> Symbols) {
static bool buildSymbolsMap(ArrayRef<ELFYAML::Symbol> V, NameToIdxMap &Map) {
bool GlobalSymbolSeen = false;
std::size_t I = 0;
for (const auto &Sym : Symbols) {
for (const ELFYAML::Symbol &Sym : V) {
++I;
StringRef Name = Sym.Name;
@ -1003,7 +1004,7 @@ bool ELFState<ELFT>::buildSymbolIndex(ArrayRef<ELFYAML::Symbol> Symbols) {
if (Sym.Binding.value != ELF::STB_LOCAL)
GlobalSymbolSeen = true;
if (!Name.empty() && !SymN2I.addName(Name, I)) {
if (!Name.empty() && !Map.addName(Name, I)) {
WithColor::error() << "Repeated symbol name: '" << Name << "'.\n";
return false;
}
@ -1011,6 +1012,11 @@ bool ELFState<ELFT>::buildSymbolIndex(ArrayRef<ELFYAML::Symbol> Symbols) {
return true;
}
template <class ELFT> bool ELFState<ELFT>::buildSymbolIndexes() {
return buildSymbolsMap(Doc.Symbols, SymN2I) &&
buildSymbolsMap(Doc.DynamicSymbols, DynSymN2I);
}
template <class ELFT> void ELFState<ELFT>::finalizeStrings() {
// Add the regular symbol names to .strtab section.
for (const ELFYAML::Symbol &Sym : Doc.Symbols)
@ -1049,10 +1055,7 @@ int ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc) {
// sections that might want to use them.
State.finalizeStrings();
if (!State.buildSectionIndex())
return 1;
if (!State.buildSymbolIndex(Doc.Symbols))
if (!State.buildSectionIndex() || !State.buildSymbolIndexes())
return 1;
Elf_Ehdr Header;

View File

@ -139,9 +139,7 @@ Sections:
EntSize: 0x18
Relocations:
- Offset: 0x10
## FIXME: This should be a lookup in the corresponding symbol table, not necessarily the static symbol table.
## See https://bugs.llvm.org/show_bug.cgi?id=40337.
Symbol: _Z3fooc
Symbol: _Z3fooi
Type: R_X86_64_PC32
Addend: 0x4
- Name: .dynamic

View File

@ -0,0 +1,65 @@
## Show that yaml2obj uses the correct set of symbols for relocation sections
## referencing the dynamic symbol table.
# RUN: yaml2obj %s -o %t
# RUN: llvm-readelf -r %t | FileCheck %s
# CHECK: Relocation section '.rela.dyn' at offset {{.*}} contains 2 entries:
# CHECK-NEXT: Offset Info Type Symbol's Value Symbol's Name
# CHECK-NEXT: 0000000000000000 0000000100000000 R_X86_64_NONE 0000000012345678 dynamic
# CHECK-NEXT: 0000000000000008 0000000200000000 R_X86_64_NONE 0000000087654321 both
# CHECK-EMPTY:
# CHECK-NEXT: Relocation section '.rela.data' at offset {{.*}} contains 2 entries:
# CHECK-NEXT: Offset Info Type Symbol's Value Symbol's Name
# CHECK-NEXT: 0000000000000010 0000000200000000 R_X86_64_NONE 0000000011223344 static
# CHECK-NEXT: 0000000000000018 0000000100000000 R_X86_64_NONE 0000000088776655 both
!ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .data
Type: SHT_PROGBITS
- Name: .rela.dyn
Type: SHT_REL
Link: .dynsym
Info: .data
Relocations:
- Offset: 0
Type: R_X86_64_NONE
Symbol: dynamic
- Offset: 8
Type: R_X86_64_NONE
Symbol: both
- Name: .rela.data
Type: SHT_REL
Link: .symtab
Info: .data
Relocations:
- Offset: 16
Type: R_X86_64_NONE
Symbol: static
- Offset: 24
Type: R_X86_64_NONE
Symbol: both
Symbols:
- Name: both
Section: .data
Value: 0x88776655
Binding: STB_GLOBAL
- Name: static
Section: .data
Value: 0x11223344
Binding: STB_GLOBAL
DynamicSymbols:
- Name: dynamic
Section: .data
Value: 0x12345678
Binding: STB_GLOBAL
- Name: both
Section: .data
Value: 0x87654321
Binding: STB_GLOBAL

View File

@ -14,6 +14,10 @@ Sections:
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_WRITE ]
DynamicSymbols:
- Name: dynlocal
Type: STT_OBJECT
Section: .data
Binding: STB_LOCAL
- Name: dynglobal
Type: STT_OBJECT
Section: .data
@ -22,10 +26,6 @@ DynamicSymbols:
Type: STT_OBJECT
Section: .data
Binding: STB_WEAK
- Name: dynlocal
Type: STT_OBJECT
Section: .data
Binding: STB_LOCAL
# SECTION: Name: .dynsym
# SECTION-NEXT: Type: SHT_DYNSYM
@ -36,6 +36,6 @@ DynamicSymbols:
# SECTION-NEXT: Flags
# SECTION-NEXT: SHF_ALLOC
# SYMBOL-DAG: d dynlocal
# SYMBOL-DAG: D dynglobal
# SYMBOL-DAG: V dynweak
# SYMBOL-DAG: d dynlocal