mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 19:12:56 +02:00
[obj2yaml] - Don't crash when an object has an empty symbol table.
Currently we crash when we have an object with SHT_SYMTAB/SHT_DYNSYM sections of size 0. With this patch instead of the crash we start to dump them properly. Differential revision: https://reviews.llvm.org/D93697
This commit is contained in:
parent
10f626b307
commit
65aa867260
@ -37,3 +37,37 @@ FileHeader:
|
|||||||
Data: ELFDATA2LSB
|
Data: ELFDATA2LSB
|
||||||
Type: ET_DYN
|
Type: ET_DYN
|
||||||
Symbols: []
|
Symbols: []
|
||||||
|
|
||||||
|
## A symbol table without the null entry is non-conforming.
|
||||||
|
## Check we don't print "Symbols" and "DynamicSymbols" keys in this case.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=3 %s -o %t3
|
||||||
|
# RUN: obj2yaml %t3 | FileCheck %s --check-prefix=EMPTY
|
||||||
|
|
||||||
|
# EMPTY: Sections:
|
||||||
|
# EMPTY-NEXT: - Name: .symtab
|
||||||
|
# EMPTY-NEXT: Type: SHT_SYMTAB
|
||||||
|
# EMPTY-NEXT: Link: .strtab
|
||||||
|
## TODO: we shouldn't dump the default "EntSize" value.
|
||||||
|
# EMPTY-NEXT: EntSize: 0x18
|
||||||
|
# EMPTY-NEXT: Size: 0x0
|
||||||
|
# EMPTY-NEXT: - Name: .dynsym
|
||||||
|
# EMPTY-NEXT: Type: SHT_DYNSYM
|
||||||
|
# EMPTY-NEXT: Flags: [ SHF_ALLOC ]
|
||||||
|
## TODO: we shouldn't dump the default "EntSize" value.
|
||||||
|
# EMPTY-NEXT: EntSize: 0x18
|
||||||
|
# EMPTY-NEXT: Size: 0x0
|
||||||
|
# EMPTY-NEXT: ...
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Sections:
|
||||||
|
- Name: .symtab
|
||||||
|
Type: SHT_SYMTAB
|
||||||
|
Size: 0
|
||||||
|
- Name: .dynsym
|
||||||
|
Type: SHT_DYNSYM
|
||||||
|
Size: 0
|
||||||
|
@ -55,7 +55,7 @@ class ELFDumper {
|
|||||||
dumpDWARFSections(std::vector<std::unique_ptr<ELFYAML::Chunk>> &Sections);
|
dumpDWARFSections(std::vector<std::unique_ptr<ELFYAML::Chunk>> &Sections);
|
||||||
|
|
||||||
Error dumpSymbols(const Elf_Shdr *Symtab,
|
Error dumpSymbols(const Elf_Shdr *Symtab,
|
||||||
std::vector<ELFYAML::Symbol> &Symbols);
|
Optional<std::vector<ELFYAML::Symbol>> &Symbols);
|
||||||
Error dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
|
Error dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
|
||||||
StringRef StrTable, ELFYAML::Symbol &S);
|
StringRef StrTable, ELFYAML::Symbol &S);
|
||||||
Expected<std::vector<std::unique_ptr<ELFYAML::Chunk>>> dumpSections();
|
Expected<std::vector<std::unique_ptr<ELFYAML::Chunk>>> dumpSections();
|
||||||
@ -219,9 +219,12 @@ bool ELFDumper<ELFT>::shouldPrintSection(const ELFYAML::Section &S,
|
|||||||
// Generally we are trying to reduce noise in the YAML output. Because
|
// Generally we are trying to reduce noise in the YAML output. Because
|
||||||
// of that we do not print non-allocatable versions of such sections and
|
// of that we do not print non-allocatable versions of such sections and
|
||||||
// assume they are placed at the end.
|
// assume they are placed at the end.
|
||||||
|
// We also dump symbol tables when the Size field is set. It happens when they
|
||||||
|
// are empty, which should not normally happen.
|
||||||
if (S.Type == ELF::SHT_STRTAB || S.Type == ELF::SHT_SYMTAB ||
|
if (S.Type == ELF::SHT_STRTAB || S.Type == ELF::SHT_SYMTAB ||
|
||||||
S.Type == ELF::SHT_DYNSYM)
|
S.Type == ELF::SHT_DYNSYM) {
|
||||||
return S.Flags.getValueOr(ELFYAML::ELF_SHF(0)) & ELF::SHF_ALLOC;
|
return S.Size || S.Flags.getValueOr(ELFYAML::ELF_SHF(0)) & ELF::SHF_ALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -325,17 +328,13 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SymTab) {
|
if (SymTab)
|
||||||
Y->Symbols.emplace();
|
if (Error E = dumpSymbols(SymTab, Y->Symbols))
|
||||||
if (Error E = dumpSymbols(SymTab, *Y->Symbols))
|
|
||||||
return std::move(E);
|
return std::move(E);
|
||||||
}
|
|
||||||
|
|
||||||
if (DynSymTab) {
|
if (DynSymTab)
|
||||||
Y->DynamicSymbols.emplace();
|
if (Error E = dumpSymbols(DynSymTab, Y->DynamicSymbols))
|
||||||
if (Error E = dumpSymbols(DynSymTab, *Y->DynamicSymbols))
|
|
||||||
return std::move(E);
|
return std::move(E);
|
||||||
}
|
|
||||||
|
|
||||||
// We dump all sections first. It is simple and allows us to verify that all
|
// We dump all sections first. It is simple and allows us to verify that all
|
||||||
// sections are valid and also to generalize the code. But we are not going to
|
// sections are valid and also to generalize the code. But we are not going to
|
||||||
@ -516,6 +515,13 @@ ELFDumper<ELFT>::dumpPlaceholderSection(const Elf_Shdr *Shdr) {
|
|||||||
auto S = std::make_unique<ELFYAML::RawContentSection>();
|
auto S = std::make_unique<ELFYAML::RawContentSection>();
|
||||||
if (Error E = dumpCommonSection(Shdr, *S.get()))
|
if (Error E = dumpCommonSection(Shdr, *S.get()))
|
||||||
return std::move(E);
|
return std::move(E);
|
||||||
|
|
||||||
|
// Normally symbol tables should not be empty. We dump the "Size"
|
||||||
|
// key when they are.
|
||||||
|
if ((Shdr->sh_type == ELF::SHT_SYMTAB || Shdr->sh_type == ELF::SHT_DYNSYM) &&
|
||||||
|
!Shdr->sh_size)
|
||||||
|
S->Size.emplace();
|
||||||
|
|
||||||
return S.release();
|
return S.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,30 +627,33 @@ ELFDumper<ELFT>::dumpSections() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
Error ELFDumper<ELFT>::dumpSymbols(const Elf_Shdr *Symtab,
|
Error ELFDumper<ELFT>::dumpSymbols(
|
||||||
std::vector<ELFYAML::Symbol> &Symbols) {
|
const Elf_Shdr *Symtab, Optional<std::vector<ELFYAML::Symbol>> &Symbols) {
|
||||||
if (!Symtab)
|
if (!Symtab)
|
||||||
return Error::success();
|
return Error::success();
|
||||||
|
|
||||||
|
auto SymtabOrErr = Obj.symbols(Symtab);
|
||||||
|
if (!SymtabOrErr)
|
||||||
|
return SymtabOrErr.takeError();
|
||||||
|
|
||||||
|
if (SymtabOrErr->empty())
|
||||||
|
return Error::success();
|
||||||
|
|
||||||
auto StrTableOrErr = Obj.getStringTableForSymtab(*Symtab);
|
auto StrTableOrErr = Obj.getStringTableForSymtab(*Symtab);
|
||||||
if (!StrTableOrErr)
|
if (!StrTableOrErr)
|
||||||
return StrTableOrErr.takeError();
|
return StrTableOrErr.takeError();
|
||||||
StringRef StrTable = *StrTableOrErr;
|
|
||||||
|
|
||||||
auto SymtabOrErr = Obj.symbols(Symtab);
|
|
||||||
if (!SymtabOrErr)
|
|
||||||
return SymtabOrErr.takeError();
|
|
||||||
|
|
||||||
if (Symtab->sh_type == ELF::SHT_SYMTAB) {
|
if (Symtab->sh_type == ELF::SHT_SYMTAB) {
|
||||||
SymTable = *SymtabOrErr;
|
SymTable = *SymtabOrErr;
|
||||||
SymbolNames.resize(SymTable.size());
|
SymbolNames.resize(SymTable.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Symbols.emplace();
|
||||||
for (const auto &Sym : (*SymtabOrErr).drop_front()) {
|
for (const auto &Sym : (*SymtabOrErr).drop_front()) {
|
||||||
ELFYAML::Symbol S;
|
ELFYAML::Symbol S;
|
||||||
if (auto EC = dumpSymbol(&Sym, Symtab, StrTable, S))
|
if (auto EC = dumpSymbol(&Sym, Symtab, *StrTableOrErr, S))
|
||||||
return EC;
|
return EC;
|
||||||
Symbols.push_back(S);
|
Symbols->push_back(S);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Error::success();
|
return Error::success();
|
||||||
|
Loading…
Reference in New Issue
Block a user