mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-25 21:48:12 +00:00
[yaml2obj/obj2yaml] - Allow having the symbols and sections with duplicated names.
The patch teaches yaml2obj/obj2yaml to support parsing/dumping the sections and symbols with the same name. A special suffix is added to a name to make it unique. Differential revision: https://reviews.llvm.org/D63596 llvm-svn: 364282
This commit is contained in:
parent
5b2aa25659
commit
5646c326e2
@ -9,16 +9,16 @@
|
||||
# CHECK: - Name: .text.foo{{$}}
|
||||
# CHECK: - Name: .rela.text.foo{{$}}
|
||||
# CHECK: Info: .text.foo{{$}}
|
||||
# CHECK: - Name: .group1{{$}}
|
||||
# CHECK: - Name: '.group [1]'
|
||||
# CHECK: Members:
|
||||
# CHECK: - SectionOrType: .text.foo2{{$}}
|
||||
# CHECK: - SectionOrType: .rela.text.foo3{{$}}
|
||||
# CHECK: - Name: .text.foo2{{$}}
|
||||
# CHECK: - Name: .rela.text.foo3{{$}}
|
||||
# CHECK: Info: .text.foo2{{$}}
|
||||
# CHECK: - SectionOrType: '.text.foo [1]'
|
||||
# CHECK: - SectionOrType: '.rela.text.foo [1]'
|
||||
# CHECK: - Name: '.text.foo [1]'
|
||||
# CHECK: - Name: '.rela.text.foo [1]'
|
||||
# CHECK: Info: '.text.foo [1]'
|
||||
# CHECK: Symbols:
|
||||
# CHECK: Section: .group{{$}}
|
||||
# CHECK: Section: .group1{{$}}
|
||||
# CHECK: Section: '.group [1]'
|
||||
|
||||
|
||||
.section .text.foo,"axG",@progbits,sym1,comdat
|
||||
|
152
test/tools/obj2yaml/duplicate-symbol-and-section-names.test
Normal file
152
test/tools/obj2yaml/duplicate-symbol-and-section-names.test
Normal file
@ -0,0 +1,152 @@
|
||||
## Check that obj2yaml is able to produce YAML from
|
||||
## an object containing symbols and sections with duplicate
|
||||
## names and produces same-named sections and symbols
|
||||
## with distinguishing suffixes.
|
||||
|
||||
# RUN: yaml2obj --docnum=1 %s -o %t1
|
||||
# RUN: llvm-readobj -s -t %t1 | FileCheck %s
|
||||
|
||||
# CHECK: Name: .foo (
|
||||
# CHECK: Name: .foo (
|
||||
# CHECK: Name: .foo (
|
||||
# CHECK: Name: .bar (
|
||||
# CHECK: Name: .bar (
|
||||
# CHECK: Name: .bar (
|
||||
|
||||
# CHECK: Name: localfoo (
|
||||
# CHECK: Name: localfoo (
|
||||
# CHECK: Name: localfoo (
|
||||
# CHECK: Name: localbar (
|
||||
# CHECK: Name: localbar (
|
||||
# CHECK: Name: localbar (
|
||||
|
||||
# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=CASE1
|
||||
|
||||
# CASE1: --- !ELF
|
||||
# CASE1-NEXT: FileHeader:
|
||||
# CASE1-NEXT: Class: ELFCLASS64
|
||||
# CASE1-NEXT: Data: ELFDATA2LSB
|
||||
# CASE1-NEXT: Type: ET_REL
|
||||
# CASE1-NEXT: Machine: EM_X86_64
|
||||
# CASE1-NEXT: Sections:
|
||||
# CASE1-NEXT: - Name: .foo
|
||||
# CASE1-NEXT: Type: SHT_PROGBITS
|
||||
# CASE1-NEXT: - Name: '.foo [1]'
|
||||
# CASE1-NEXT: Type: SHT_PROGBITS
|
||||
# CASE1-NEXT: - Name: '.foo [2]'
|
||||
# CASE1-NEXT: Type: SHT_PROGBITS
|
||||
# CASE1-NEXT: - Name: .bar
|
||||
# CASE1-NEXT: Type: SHT_PROGBITS
|
||||
# CASE1-NEXT: - Name: '.bar [1]'
|
||||
# CASE1-NEXT: Type: SHT_PROGBITS
|
||||
# CASE1-NEXT: - Name: '.bar [2]'
|
||||
# CASE1-NEXT: Type: SHT_PROGBITS
|
||||
# CASE1-NEXT: Symbols:
|
||||
# CASE1-NEXT: - Name: localfoo
|
||||
# CASE1-NEXT: - Name: 'localfoo [1]'
|
||||
# CASE1-NEXT: - Name: 'localfoo [2]'
|
||||
# CASE1-NEXT: - Name: localbar
|
||||
# CASE1-NEXT: - Name: 'localbar [1]'
|
||||
# CASE1-NEXT: - Name: 'localbar [2]'
|
||||
# CASE1-NEXT: ...
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .foo
|
||||
Type: SHT_PROGBITS
|
||||
- Name: '.foo [555]'
|
||||
Type: SHT_PROGBITS
|
||||
- Name: '.foo [random_tag]'
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .bar
|
||||
Type: SHT_PROGBITS
|
||||
- Name: '.bar [666]'
|
||||
Type: SHT_PROGBITS
|
||||
- Name: '.bar [random_tag]'
|
||||
Type: SHT_PROGBITS
|
||||
Symbols:
|
||||
- Name: 'localfoo [111]'
|
||||
- Name: 'localfoo [222]'
|
||||
- Name: 'localfoo [random_tag]'
|
||||
- Name: 'localbar [333]'
|
||||
- Name: 'localbar [444]'
|
||||
- Name: 'localbar [random_tag]'
|
||||
|
||||
## Check we can refer to symbols with the same
|
||||
## name from relocations.
|
||||
|
||||
# RUN: yaml2obj --docnum=2 %s -o %t2
|
||||
# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=CASE2
|
||||
|
||||
# CASE2: Relocations:
|
||||
# CASE2-NEXT: - Offset: 0x0000000000000000
|
||||
# CASE2-NEXT: Symbol: 'foo [1]'
|
||||
# CASE2-NEXT: Type: R_X86_64_PC32
|
||||
# CASE2-NEXT: - Offset: 0x0000000000000004
|
||||
# CASE2-NEXT: Symbol: foo
|
||||
# CASE2-NEXT: Type: R_X86_64_PC32
|
||||
# CASE2-NEXT: Symbols:
|
||||
# CASE2-NEXT: - Name: foo
|
||||
# CASE2-NEXT: - Name: 'foo [1]'
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
Size: 8
|
||||
- Name: .rela.text
|
||||
Type: SHT_RELA
|
||||
Info: .text
|
||||
Link: .symtab
|
||||
Relocations:
|
||||
- Type: R_X86_64_PC32
|
||||
Offset: 0
|
||||
Symbol: 'foo [1]'
|
||||
- Type: R_X86_64_PC32
|
||||
Offset: 4
|
||||
Symbol: foo
|
||||
Symbols:
|
||||
- Name: foo
|
||||
- Name: 'foo [1]'
|
||||
|
||||
## Check obj2yaml does not add a suffix to a name if the
|
||||
## symbol is in .symtab and .dynsym at the same time.
|
||||
|
||||
# RUN: yaml2obj --docnum=3 %s -o %t3
|
||||
# RUN: obj2yaml %t3 | FileCheck %s --check-prefix=CASE3
|
||||
|
||||
# CASE3: --- !ELF
|
||||
# CASE3-NEXT: FileHeader:
|
||||
# CASE3-NEXT: Class: ELFCLASS64
|
||||
# CASE3-NEXT: Data: ELFDATA2LSB
|
||||
# CASE3-NEXT: Type: ET_DYN
|
||||
# CASE3-NEXT: Machine: EM_X86_64
|
||||
# CASE3-NEXT: Symbols:
|
||||
# CASE3-NEXT: - Name: foo
|
||||
# CASE3-NEXT: Binding: STB_GLOBAL
|
||||
# CASE3-NEXT: DynamicSymbols:
|
||||
# CASE3-NEXT: - Name: foo
|
||||
# CASE3-NEXT: Binding: STB_GLOBAL
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_DYN
|
||||
Machine: EM_X86_64
|
||||
Symbols:
|
||||
- Name: foo
|
||||
Binding: STB_GLOBAL
|
||||
DynamicSymbols:
|
||||
- Name: foo
|
||||
Binding: STB_GLOBAL
|
170
test/tools/yaml2obj/duplicate-section-names.test
Normal file
170
test/tools/yaml2obj/duplicate-section-names.test
Normal file
@ -0,0 +1,170 @@
|
||||
## Check that yaml2obj is able to produce an object from YAML
|
||||
## containing sections with duplicate names (but different name suffixes).
|
||||
|
||||
# RUN: yaml2obj --docnum=1 %s -o %t1
|
||||
# RUN: llvm-readobj -s %t1 | FileCheck %s --check-prefix=CASE1
|
||||
|
||||
# CASE1: Name: .foo1 (
|
||||
# CASE1: Name: .foo (
|
||||
# CASE1: Name: .foo (
|
||||
# CASE1: Name: .foo2 (
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .foo1
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .foo
|
||||
Type: SHT_PROGBITS
|
||||
- Name: '.foo [1]'
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .foo2
|
||||
Type: SHT_PROGBITS
|
||||
|
||||
## Check that yaml2obj reports an error in case we have
|
||||
## sections with equal names and suffixes.
|
||||
|
||||
# RUN: not yaml2obj --docnum=2 %s 2>&1 | FileCheck %s --check-prefix=CASE2
|
||||
# CASE2: error: Repeated section name: '.foo [1]' at YAML section number 1.
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: '.foo [1]'
|
||||
Type: SHT_PROGBITS
|
||||
- Name: '.foo [1]'
|
||||
Type: SHT_PROGBITS
|
||||
|
||||
## Check that yaml2obj reports an error in case we have
|
||||
## symbols without suffixes in the names and their
|
||||
## names are equal.
|
||||
|
||||
# RUN: not yaml2obj --docnum=3 %s 2>&1 | FileCheck %s --check-prefix=CASE3
|
||||
# CASE3: error: Repeated section name: '.foo' at YAML section number 1.
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .foo
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .foo
|
||||
Type: SHT_PROGBITS
|
||||
|
||||
## Check that yaml2obj can produce an object when symbols are defined
|
||||
## relative to sections with duplicate names (but different name suffixes).
|
||||
|
||||
# RUN: yaml2obj --docnum=4 %s -o %t4
|
||||
# RUN: llvm-readobj -s -t %t4 | FileCheck %s --check-prefix=CASE4
|
||||
|
||||
# CASE4: Section {
|
||||
# CASE4: Index: 1
|
||||
# CASE4-NEXT: Name: .foo
|
||||
# CASE4: Index: 2
|
||||
# CASE4-NEXT: Name: .foo
|
||||
|
||||
# CASE4: Symbol {
|
||||
# CASE4: Name: foo
|
||||
# CASE4-NEXT: Value:
|
||||
# CASE4-NEXT: Size:
|
||||
# CASE4-NEXT: Binding:
|
||||
# CASE4-NEXT: Type:
|
||||
# CASE4-NEXT: Other:
|
||||
# CASE4-NEXT: Section: .foo (0x1)
|
||||
# CASE4: Name: bar
|
||||
# CASE4-NEXT: Value:
|
||||
# CASE4-NEXT: Size:
|
||||
# CASE4-NEXT: Binding:
|
||||
# CASE4-NEXT: Type:
|
||||
# CASE4-NEXT: Other:
|
||||
# CASE4-NEXT: Section: .foo (0x2)
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .foo
|
||||
Type: SHT_PROGBITS
|
||||
- Name: '.foo [1]'
|
||||
Type: SHT_PROGBITS
|
||||
Symbols:
|
||||
- Name: foo
|
||||
Section: .foo
|
||||
- Name: bar
|
||||
Section: '.foo [1]'
|
||||
|
||||
## Check that yaml2obj can produce SHT_GROUP sections that
|
||||
## reference sections and symbols with name suffixes.
|
||||
|
||||
# RUN: yaml2obj --docnum=5 %s -o %t5
|
||||
# RUN: llvm-readobj --elf-section-groups %t5 | FileCheck %s --check-prefix=CASE5
|
||||
|
||||
# CASE5: Groups {
|
||||
# CASE5-NEXT: Group {
|
||||
# CASE5-NEXT: Name: .group (1)
|
||||
# CASE5-NEXT: Index: 1
|
||||
# CASE5-NEXT: Link: 5
|
||||
# CASE5-NEXT: Info: 1
|
||||
# CASE5-NEXT: Type: COMDAT (0x1)
|
||||
# CASE5-NEXT: Signature: foo
|
||||
# CASE5-NEXT: Section(s) in group [
|
||||
# CASE5-NEXT: .text.foo (2)
|
||||
# CASE5-NEXT: ]
|
||||
# CASE5-NEXT: }
|
||||
# CASE5-NEXT: Group {
|
||||
# CASE5-NEXT: Name: .group (1)
|
||||
# CASE5-NEXT: Index: 3
|
||||
# CASE5-NEXT: Link: 5
|
||||
# CASE5-NEXT: Info: 2
|
||||
# CASE5-NEXT: Type: COMDAT (0x1)
|
||||
# CASE5-NEXT: Signature: foo
|
||||
# CASE5-NEXT: Section(s) in group [
|
||||
# CASE5-NEXT: .text.foo (4)
|
||||
# CASE5-NEXT: ]
|
||||
# CASE5-NEXT: }
|
||||
# CASE5-NEXT: }
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .group
|
||||
Type: SHT_GROUP
|
||||
Link: .symtab
|
||||
Info: foo
|
||||
Members:
|
||||
- SectionOrType: GRP_COMDAT
|
||||
- SectionOrType: .text.foo
|
||||
- Name: .text.foo
|
||||
Type: SHT_PROGBITS
|
||||
- Name: '.group [1]'
|
||||
Type: SHT_GROUP
|
||||
Link: .symtab
|
||||
Info: 'foo [1]'
|
||||
Members:
|
||||
- SectionOrType: GRP_COMDAT
|
||||
- SectionOrType: '.text.foo [1]'
|
||||
- Name: '.text.foo [1]'
|
||||
Type: SHT_PROGBITS
|
||||
Symbols:
|
||||
- Name: foo
|
||||
Section: .text.foo
|
||||
- Name: 'foo [1]'
|
||||
Section: '.text.foo [1]'
|
100
test/tools/yaml2obj/duplicate-symbol-names.test
Normal file
100
test/tools/yaml2obj/duplicate-symbol-names.test
Normal file
@ -0,0 +1,100 @@
|
||||
## Check that yaml2obj is able to produce an object from YAML
|
||||
## containing symbols with duplicate names (but different name suffixes).
|
||||
|
||||
# RUN: yaml2obj --docnum=1 %s -o %t1
|
||||
# RUN: llvm-readobj -t %t1 | FileCheck %s --check-prefix=CASE1
|
||||
|
||||
# CASE1: Name: localfoo (1)
|
||||
# CASE1: Name: localfoo (1)
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Symbols:
|
||||
- Name: localfoo
|
||||
- Name: 'localfoo [1]'
|
||||
|
||||
## Check that yaml2obj reports an error when we have
|
||||
## symbols with equal names and suffixes.
|
||||
|
||||
# RUN: not yaml2obj --docnum=2 %s 2>&1| FileCheck %s --check-prefix=CASE2
|
||||
# CASE2: error: Repeated symbol name: 'localfoo [1]'.
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Symbols:
|
||||
- Name: 'localfoo [1]'
|
||||
- Name: 'localfoo [1]'
|
||||
|
||||
## Check that yaml2obj reports an error when we have
|
||||
## symbols without suffixes in the names and their
|
||||
## names are equal.
|
||||
|
||||
# RUN: not yaml2obj --docnum=3 %s 2>&1| FileCheck %s --check-prefix=CASE3
|
||||
# CASE3: error: Repeated symbol name: 'localfoo'.
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Symbols:
|
||||
- Name: localfoo
|
||||
Section: .text.foo.1
|
||||
- Name: localfoo
|
||||
Section: .text.foo.2
|
||||
|
||||
## Check that yaml2obj can produce correct relocations that
|
||||
## reference symbols with name suffixes.
|
||||
|
||||
# RUN: yaml2obj --docnum=4 %s -o %t4
|
||||
# RUN: llvm-readobj -r --expand-relocs %t4 | FileCheck %s --check-prefix=CASE4
|
||||
|
||||
# CASE4: Relocations [
|
||||
# CASE4-NEXT: Section {{.*}} .rela.text {
|
||||
# CASE4-NEXT: Relocation {
|
||||
# CASE4-NEXT: Offset: 0x0
|
||||
# CASE4-NEXT: Type: R_X86_64_NONE
|
||||
# CASE4-NEXT: Symbol: foo (1)
|
||||
# CASE4-NEXT: Addend: 0x0
|
||||
# CASE4-NEXT: }
|
||||
# CASE4-NEXT: Relocation {
|
||||
# CASE4-NEXT: Offset: 0x1
|
||||
# CASE4-NEXT: Type: R_X86_64_NONE
|
||||
# CASE4-NEXT: Symbol: foo (2)
|
||||
# CASE4-NEXT: Addend: 0x0
|
||||
# CASE4-NEXT: }
|
||||
# CASE4-NEXT: }
|
||||
# CASE4-NEXT: ]
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .rela.text
|
||||
Type: SHT_RELA
|
||||
Info: .text
|
||||
Link: .symtab
|
||||
Relocations:
|
||||
- Offset: 0x0
|
||||
Type: R_X86_64_NONE
|
||||
Symbol: foo
|
||||
- Offset: 0x1
|
||||
Type: R_X86_64_NONE
|
||||
Symbol: 'foo [1]'
|
||||
Symbols:
|
||||
- Name: foo
|
||||
- Name: 'foo [1]'
|
@ -28,15 +28,18 @@ class ELFDumper {
|
||||
typedef typename ELFT::Rela Elf_Rela;
|
||||
|
||||
ArrayRef<Elf_Shdr> Sections;
|
||||
ArrayRef<Elf_Sym> SymTable;
|
||||
|
||||
// If the file has multiple sections with the same name, we add a
|
||||
// suffix to make them unique.
|
||||
unsigned Suffix = 0;
|
||||
DenseSet<StringRef> UsedSectionNames;
|
||||
DenseMap<StringRef, uint32_t> UsedSectionNames;
|
||||
std::vector<std::string> SectionNames;
|
||||
|
||||
DenseMap<StringRef, uint32_t> UsedSymbolNames;
|
||||
std::vector<std::string> SymbolNames;
|
||||
|
||||
Expected<StringRef> getUniquedSectionName(const Elf_Shdr *Sec);
|
||||
Expected<StringRef> getSymbolName(const Elf_Sym *Sym, StringRef StrTable,
|
||||
const Elf_Shdr *SymTab);
|
||||
Expected<StringRef> getUniquedSymbolName(const Elf_Sym *Sym,
|
||||
StringRef StrTable,
|
||||
const Elf_Shdr *SymTab);
|
||||
|
||||
const object::ELFFile<ELFT> &Obj;
|
||||
ArrayRef<Elf_Word> ShndxTable;
|
||||
@ -87,16 +90,19 @@ ELFDumper<ELFT>::getUniquedSectionName(const Elf_Shdr *Sec) {
|
||||
return NameOrErr;
|
||||
StringRef Name = *NameOrErr;
|
||||
std::string &Ret = SectionNames[SecIndex];
|
||||
Ret = Name;
|
||||
while (!UsedSectionNames.insert(Ret).second)
|
||||
Ret = (Name + to_string(++Suffix)).str();
|
||||
|
||||
auto It = UsedSectionNames.insert({Name, 0});
|
||||
if (!It.second)
|
||||
Ret = (Name + " [" + Twine(++It.first->second) + "]").str();
|
||||
else
|
||||
Ret = Name;
|
||||
return Ret;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
Expected<StringRef> ELFDumper<ELFT>::getSymbolName(const Elf_Sym *Sym,
|
||||
StringRef StrTable,
|
||||
const Elf_Shdr *SymTab) {
|
||||
Expected<StringRef>
|
||||
ELFDumper<ELFT>::getUniquedSymbolName(const Elf_Sym *Sym, StringRef StrTable,
|
||||
const Elf_Shdr *SymTab) {
|
||||
Expected<StringRef> SymbolNameOrErr = Sym->getName(StrTable);
|
||||
if (!SymbolNameOrErr)
|
||||
return SymbolNameOrErr;
|
||||
@ -107,6 +113,24 @@ Expected<StringRef> ELFDumper<ELFT>::getSymbolName(const Elf_Sym *Sym,
|
||||
return ShdrOrErr.takeError();
|
||||
return getUniquedSectionName(*ShdrOrErr);
|
||||
}
|
||||
|
||||
// Symbols in .symtab can have duplicate names. For example, it is a common
|
||||
// situation for local symbols in a relocatable object. Here we assign unique
|
||||
// suffixes for such symbols so that we can differentiate them.
|
||||
if (SymTab->sh_type == ELF::SHT_SYMTAB) {
|
||||
unsigned Index = Sym - SymTable.data();
|
||||
if (!SymbolNames[Index].empty())
|
||||
return SymbolNames[Index];
|
||||
|
||||
auto It = UsedSymbolNames.insert({Name, 0});
|
||||
if (!It.second)
|
||||
SymbolNames[Index] =
|
||||
(Name + " [" + Twine(++It.first->second) + "]").str();
|
||||
else
|
||||
SymbolNames[Index] = Name;
|
||||
return SymbolNames[Index];
|
||||
}
|
||||
|
||||
return Name;
|
||||
}
|
||||
|
||||
@ -123,15 +147,24 @@ template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
||||
Y->Header.Flags = Obj.getHeader()->e_flags;
|
||||
Y->Header.Entry = Obj.getHeader()->e_entry;
|
||||
|
||||
const Elf_Shdr *Symtab = nullptr;
|
||||
const Elf_Shdr *DynSymtab = nullptr;
|
||||
|
||||
// Dump sections
|
||||
auto SectionsOrErr = Obj.sections();
|
||||
if (!SectionsOrErr)
|
||||
return errorToErrorCode(SectionsOrErr.takeError());
|
||||
Sections = *SectionsOrErr;
|
||||
SectionNames.resize(Sections.size());
|
||||
|
||||
// Dump symbols. We need to do this early because other sections might want
|
||||
// to access the deduplicated symbol names that we also create here.
|
||||
for (const Elf_Shdr &Sec : Sections) {
|
||||
if (Sec.sh_type == ELF::SHT_SYMTAB)
|
||||
if (auto EC = dumpSymbols(&Sec, Y->Symbols))
|
||||
return EC;
|
||||
if (Sec.sh_type == ELF::SHT_DYNSYM)
|
||||
if (auto EC = dumpSymbols(&Sec, Y->DynamicSymbols))
|
||||
return EC;
|
||||
}
|
||||
|
||||
for (const Elf_Shdr &Sec : Sections) {
|
||||
switch (Sec.sh_type) {
|
||||
case ELF::SHT_DYNAMIC: {
|
||||
@ -143,13 +176,9 @@ template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
||||
}
|
||||
case ELF::SHT_NULL:
|
||||
case ELF::SHT_STRTAB:
|
||||
// Do not dump these sections.
|
||||
break;
|
||||
case ELF::SHT_SYMTAB:
|
||||
Symtab = &Sec;
|
||||
break;
|
||||
case ELF::SHT_DYNSYM:
|
||||
DynSymtab = &Sec;
|
||||
// Do not dump these sections.
|
||||
break;
|
||||
case ELF::SHT_SYMTAB_SHNDX: {
|
||||
auto TableOrErr = Obj.getSHNDXTable(Sec);
|
||||
@ -217,11 +246,6 @@ template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
||||
}
|
||||
}
|
||||
|
||||
if (auto EC = dumpSymbols(Symtab, Y->Symbols))
|
||||
return EC;
|
||||
if (auto EC = dumpSymbols(DynSymtab, Y->DynamicSymbols))
|
||||
return EC;
|
||||
|
||||
return Y.release();
|
||||
}
|
||||
|
||||
@ -241,6 +265,11 @@ ELFDumper<ELFT>::dumpSymbols(const Elf_Shdr *Symtab,
|
||||
if (!SymtabOrErr)
|
||||
return errorToErrorCode(SymtabOrErr.takeError());
|
||||
|
||||
if (Symtab->sh_type == ELF::SHT_SYMTAB) {
|
||||
SymTable = *SymtabOrErr;
|
||||
SymbolNames.resize(SymTable.size());
|
||||
}
|
||||
|
||||
for (const auto &Sym : (*SymtabOrErr).drop_front()) {
|
||||
ELFYAML::Symbol S;
|
||||
if (auto EC = dumpSymbol(&Sym, Symtab, StrTable, S))
|
||||
@ -261,7 +290,8 @@ ELFDumper<ELFT>::dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
|
||||
S.Other = Sym->st_other;
|
||||
S.Binding = Sym->getBinding();
|
||||
|
||||
Expected<StringRef> SymbolNameOrErr = getSymbolName(Sym, StrTable, SymTab);
|
||||
Expected<StringRef> SymbolNameOrErr =
|
||||
getUniquedSymbolName(Sym, StrTable, SymTab);
|
||||
if (!SymbolNameOrErr)
|
||||
return errorToErrorCode(SymbolNameOrErr.takeError());
|
||||
S.Name = SymbolNameOrErr.get();
|
||||
@ -310,7 +340,7 @@ std::error_code ELFDumper<ELFT>::dumpRelocation(const RelT *Rel,
|
||||
StringRef StrTab = *StrTabOrErr;
|
||||
|
||||
if (Sym) {
|
||||
Expected<StringRef> NameOrErr = getSymbolName(Sym, StrTab, SymTab);
|
||||
Expected<StringRef> NameOrErr = getUniquedSymbolName(Sym, StrTab, SymTab);
|
||||
if (!NameOrErr)
|
||||
return errorToErrorCode(NameOrErr.takeError());
|
||||
R.Symbol = NameOrErr.get();
|
||||
@ -603,7 +633,7 @@ ErrorOr<ELFYAML::Group *> ELFDumper<ELFT>::dumpGroup(const Elf_Shdr *Shdr) {
|
||||
return errorToErrorCode(StrTabOrErr.takeError());
|
||||
|
||||
Expected<StringRef> SymbolName =
|
||||
getSymbolName(*SymOrErr, *StrTabOrErr, Symtab);
|
||||
getUniquedSymbolName(*SymOrErr, *StrTabOrErr, Symtab);
|
||||
if (!SymbolName)
|
||||
return errorToErrorCode(SymbolName.takeError());
|
||||
S->Signature = *SymbolName;
|
||||
|
@ -266,6 +266,13 @@ bool ELFState<ELFT>::initImplicitHeader(ELFState<ELFT> &State,
|
||||
return true;
|
||||
}
|
||||
|
||||
static StringRef dropUniqueSuffix(StringRef S) {
|
||||
size_t SuffixPos = S.rfind(" [");
|
||||
if (SuffixPos == StringRef::npos)
|
||||
return S;
|
||||
return S.substr(0, SuffixPos);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
bool ELFState<ELFT>::initSectionHeaders(ELFState<ELFT> &State,
|
||||
std::vector<Elf_Shdr> &SHeaders,
|
||||
@ -299,7 +306,7 @@ bool ELFState<ELFT>::initSectionHeaders(ELFState<ELFT> &State,
|
||||
assert(Sec && "It can't be null unless it is an implicit section. But all "
|
||||
"implicit sections should already have been handled above.");
|
||||
|
||||
SHeader.sh_name = DotShStrtab.getOffset(SecName);
|
||||
SHeader.sh_name = DotShStrtab.getOffset(dropUniqueSuffix(SecName));
|
||||
SHeader.sh_type = Sec->Type;
|
||||
if (Sec->Flags)
|
||||
SHeader.sh_flags = *Sec->Flags;
|
||||
@ -391,7 +398,7 @@ toELFSymbols(NameToIdxMap &SN2I, ArrayRef<ELFYAML::Symbol> Symbols,
|
||||
if (Sym.NameIndex)
|
||||
Symbol.st_name = *Sym.NameIndex;
|
||||
else if (!Sym.Name.empty())
|
||||
Symbol.st_name = Strtab.getOffset(Sym.Name);
|
||||
Symbol.st_name = Strtab.getOffset(dropUniqueSuffix(Sym.Name));
|
||||
|
||||
Symbol.setBindingAndType(Sym.Binding, Sym.Type);
|
||||
if (!Sym.Section.empty()) {
|
||||
@ -901,7 +908,7 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||
template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
|
||||
for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) {
|
||||
StringRef Name = Doc.Sections[i]->Name;
|
||||
DotShStrtab.add(Name);
|
||||
DotShStrtab.add(dropUniqueSuffix(Name));
|
||||
// "+ 1" to take into account the SHT_NULL entry.
|
||||
if (!SN2I.addName(Name, i + 1)) {
|
||||
WithColor::error() << "Repeated section name: '" << Name
|
||||
@ -950,12 +957,12 @@ bool ELFState<ELFT>::buildSymbolIndex(ArrayRef<ELFYAML::Symbol> Symbols) {
|
||||
template <class ELFT> void ELFState<ELFT>::finalizeStrings() {
|
||||
// Add the regular symbol names to .strtab section.
|
||||
for (const ELFYAML::Symbol &Sym : Doc.Symbols)
|
||||
DotStrtab.add(Sym.Name);
|
||||
DotStrtab.add(dropUniqueSuffix(Sym.Name));
|
||||
DotStrtab.finalize();
|
||||
|
||||
// Add the dynamic symbol names to .dynstr section.
|
||||
for (const ELFYAML::Symbol &Sym : Doc.DynamicSymbols)
|
||||
DotDynstr.add(Sym.Name);
|
||||
DotDynstr.add(dropUniqueSuffix(Sym.Name));
|
||||
|
||||
// SHT_GNU_verdef and SHT_GNU_verneed sections might also
|
||||
// add strings to .dynstr section.
|
||||
|
Loading…
x
Reference in New Issue
Block a user