forked from OSchip/llvm-project
[yaml2obj/obj2yaml] - Add support for SHT_LLVM_ADDRSIG sections.
SHT_LLVM_ADDRSIG is described here: https://llvm.org/docs/Extensions.html#sht-llvm-addrsig-section-address-significance-table This patch teaches tools to dump them and to parse the YAML declarations of such sections. Differential revision: https://reviews.llvm.org/D68333 llvm-svn: 373598
This commit is contained in:
parent
c780645736
commit
32cbabfecb
|
@ -137,7 +137,8 @@ struct Section {
|
||||||
StackSizes,
|
StackSizes,
|
||||||
SymtabShndxSection,
|
SymtabShndxSection,
|
||||||
Symver,
|
Symver,
|
||||||
MipsABIFlags
|
MipsABIFlags,
|
||||||
|
Addrsig
|
||||||
};
|
};
|
||||||
SectionKind Kind;
|
SectionKind Kind;
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
|
@ -256,6 +257,25 @@ struct VerneedSection : Section {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AddrsigSymbol {
|
||||||
|
AddrsigSymbol(StringRef N) : Name(N), Index(None) {}
|
||||||
|
AddrsigSymbol(llvm::yaml::Hex32 Ndx) : Name(None), Index(Ndx) {}
|
||||||
|
AddrsigSymbol() : Name(None), Index(None) {}
|
||||||
|
|
||||||
|
Optional<StringRef> Name;
|
||||||
|
Optional<llvm::yaml::Hex32> Index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AddrsigSection : Section {
|
||||||
|
Optional<yaml::BinaryRef> Content;
|
||||||
|
Optional<std::vector<AddrsigSymbol>> Symbols;
|
||||||
|
|
||||||
|
AddrsigSection() : Section(SectionKind::Addrsig) {}
|
||||||
|
static bool classof(const Section *S) {
|
||||||
|
return S->Kind == SectionKind::Addrsig;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct SymverSection : Section {
|
struct SymverSection : Section {
|
||||||
std::vector<uint16_t> Entries;
|
std::vector<uint16_t> Entries;
|
||||||
|
|
||||||
|
@ -362,6 +382,7 @@ struct Object {
|
||||||
} // end namespace ELFYAML
|
} // end namespace ELFYAML
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::AddrsigSymbol)
|
||||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::StackSizeEntry)
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::StackSizeEntry)
|
||||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry)
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry)
|
||||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader)
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader)
|
||||||
|
@ -518,6 +539,10 @@ template <> struct MappingTraits<ELFYAML::VernauxEntry> {
|
||||||
static void mapping(IO &IO, ELFYAML::VernauxEntry &E);
|
static void mapping(IO &IO, ELFYAML::VernauxEntry &E);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct MappingTraits<ELFYAML::AddrsigSymbol> {
|
||||||
|
static void mapping(IO &IO, ELFYAML::AddrsigSymbol &Sym);
|
||||||
|
};
|
||||||
|
|
||||||
template <> struct MappingTraits<ELFYAML::Relocation> {
|
template <> struct MappingTraits<ELFYAML::Relocation> {
|
||||||
static void mapping(IO &IO, ELFYAML::Relocation &Rel);
|
static void mapping(IO &IO, ELFYAML::Relocation &Rel);
|
||||||
};
|
};
|
||||||
|
|
|
@ -174,6 +174,10 @@ template <class ELFT> class ELFState {
|
||||||
void writeSectionContent(Elf_Shdr &SHeader,
|
void writeSectionContent(Elf_Shdr &SHeader,
|
||||||
const ELFYAML::HashSection &Section,
|
const ELFYAML::HashSection &Section,
|
||||||
ContiguousBlobAccumulator &CBA);
|
ContiguousBlobAccumulator &CBA);
|
||||||
|
void writeSectionContent(Elf_Shdr &SHeader,
|
||||||
|
const ELFYAML::AddrsigSection &Section,
|
||||||
|
ContiguousBlobAccumulator &CBA);
|
||||||
|
|
||||||
ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH);
|
ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -423,6 +427,8 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
|
||||||
writeSectionContent(SHeader, *S, CBA);
|
writeSectionContent(SHeader, *S, CBA);
|
||||||
} else if (auto S = dyn_cast<ELFYAML::HashSection>(Sec)) {
|
} else if (auto S = dyn_cast<ELFYAML::HashSection>(Sec)) {
|
||||||
writeSectionContent(SHeader, *S, CBA);
|
writeSectionContent(SHeader, *S, CBA);
|
||||||
|
} else if (auto S = dyn_cast<ELFYAML::AddrsigSection>(Sec)) {
|
||||||
|
writeSectionContent(SHeader, *S, CBA);
|
||||||
} else {
|
} else {
|
||||||
llvm_unreachable("Unknown section type");
|
llvm_unreachable("Unknown section type");
|
||||||
}
|
}
|
||||||
|
@ -990,6 +996,30 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||||
Section.Content->writeAsBinary(OS);
|
Section.Content->writeAsBinary(OS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class ELFT>
|
||||||
|
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||||
|
const ELFYAML::AddrsigSection &Section,
|
||||||
|
ContiguousBlobAccumulator &CBA) {
|
||||||
|
raw_ostream &OS =
|
||||||
|
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||||
|
|
||||||
|
unsigned Link = 0;
|
||||||
|
if (Section.Link.empty() && SN2I.lookup(".symtab", Link))
|
||||||
|
SHeader.sh_link = Link;
|
||||||
|
|
||||||
|
if (Section.Content) {
|
||||||
|
SHeader.sh_size = writeContent(OS, Section.Content, None);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const ELFYAML::AddrsigSymbol &Sym : *Section.Symbols) {
|
||||||
|
uint64_t Val =
|
||||||
|
Sym.Name ? toSymbolIndex(*Sym.Name, Section.Name, /*IsDynamic=*/false)
|
||||||
|
: (uint32_t)*Sym.Index;
|
||||||
|
SHeader.sh_size += encodeULEB128(Val, OS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <class ELFT> void ELFState<ELFT>::buildSectionIndex() {
|
template <class ELFT> void ELFState<ELFT>::buildSectionIndex() {
|
||||||
for (unsigned I = 0, E = Doc.Sections.size(); I != E; ++I) {
|
for (unsigned I = 0, E = Doc.Sections.size(); I != E; ++I) {
|
||||||
StringRef Name = Doc.Sections[I]->Name;
|
StringRef Name = Doc.Sections[I]->Name;
|
||||||
|
|
|
@ -1071,6 +1071,12 @@ static void sectionMapping(IO &IO, ELFYAML::SymtabShndxSection &Section) {
|
||||||
IO.mapRequired("Entries", Section.Entries);
|
IO.mapRequired("Entries", Section.Entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sectionMapping(IO &IO, ELFYAML::AddrsigSection &Section) {
|
||||||
|
commonSectionMapping(IO, Section);
|
||||||
|
IO.mapOptional("Content", Section.Content);
|
||||||
|
IO.mapOptional("Symbols", Section.Symbols);
|
||||||
|
}
|
||||||
|
|
||||||
void MappingTraits<ELFYAML::SectionOrType>::mapping(
|
void MappingTraits<ELFYAML::SectionOrType>::mapping(
|
||||||
IO &IO, ELFYAML::SectionOrType §ionOrType) {
|
IO &IO, ELFYAML::SectionOrType §ionOrType) {
|
||||||
IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType);
|
IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType);
|
||||||
|
@ -1161,6 +1167,11 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping(
|
||||||
Section.reset(new ELFYAML::SymtabShndxSection());
|
Section.reset(new ELFYAML::SymtabShndxSection());
|
||||||
sectionMapping(IO, *cast<ELFYAML::SymtabShndxSection>(Section.get()));
|
sectionMapping(IO, *cast<ELFYAML::SymtabShndxSection>(Section.get()));
|
||||||
break;
|
break;
|
||||||
|
case ELF::SHT_LLVM_ADDRSIG:
|
||||||
|
if (!IO.outputting())
|
||||||
|
Section.reset(new ELFYAML::AddrsigSection());
|
||||||
|
sectionMapping(IO, *cast<ELFYAML::AddrsigSection>(Section.get()));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (!IO.outputting()) {
|
if (!IO.outputting()) {
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
|
@ -1233,6 +1244,26 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate(
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (const auto *Sec = dyn_cast<ELFYAML::AddrsigSection>(Section.get())) {
|
||||||
|
if (!Sec->Symbols && !Sec->Content)
|
||||||
|
return "one of \"Symbols\" or \"Content\" must be specified";
|
||||||
|
|
||||||
|
if (Sec->Content) {
|
||||||
|
if (Sec->Symbols)
|
||||||
|
return "\"Content\" and \"Symbols\" cannot be used together";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Sec->Symbols)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
for (const ELFYAML::AddrsigSymbol &AS : *Sec->Symbols)
|
||||||
|
if (AS.Index && AS.Name)
|
||||||
|
return "\"Index\" and \"Name\" cannot be used together when defining a "
|
||||||
|
"symbol";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1340,6 +1371,12 @@ void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
|
||||||
IO.setContext(nullptr);
|
IO.setContext(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MappingTraits<ELFYAML::AddrsigSymbol>::mapping(IO &IO, ELFYAML::AddrsigSymbol &Sym) {
|
||||||
|
assert(IO.getContext() && "The IO context is not initialized");
|
||||||
|
IO.mapOptional("Name", Sym.Name);
|
||||||
|
IO.mapOptional("Index", Sym.Index);
|
||||||
|
}
|
||||||
|
|
||||||
LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG)
|
LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG)
|
||||||
LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP)
|
LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP)
|
||||||
LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT)
|
LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT)
|
||||||
|
|
|
@ -196,6 +196,7 @@ Sections:
|
||||||
Type: SHT_LLVM_CALL_GRAPH_PROFILE
|
Type: SHT_LLVM_CALL_GRAPH_PROFILE
|
||||||
- Name: llvm_addrsig
|
- Name: llvm_addrsig
|
||||||
Type: SHT_LLVM_ADDRSIG
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
Symbols:
|
||||||
- Name: .deplibs
|
- Name: .deplibs
|
||||||
Type: SHT_LLVM_DEPENDENT_LIBRARIES
|
Type: SHT_LLVM_DEPENDENT_LIBRARIES
|
||||||
- Name: .llvm_sympart.f
|
- Name: .llvm_sympart.f
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
## Check how obj2yaml dumps the SHT_LLVM_ADDRSIG section.
|
||||||
|
|
||||||
|
## Check that when possible obj2yaml tries to produce the "Name" tag when
|
||||||
|
## dumping entries of the SHT_LLVM_ADDRSIG section. It falls back to producing
|
||||||
|
## the "Index" tag when it can't match a symbol index with a symbol table entry.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=1 %s -o %t1
|
||||||
|
# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=NAME
|
||||||
|
|
||||||
|
# NAME: - Name: .llvm_addrsig
|
||||||
|
# NAME-NEXT: Type: SHT_LLVM_ADDRSIG
|
||||||
|
# NAME-NEXT: Link: .symtab
|
||||||
|
# NAME-NEXT: Symbols:
|
||||||
|
# NAME-NEXT: - Name: foo
|
||||||
|
# NAME-NEXT: - Name: bar
|
||||||
|
# NAME-NEXT: - Index: 0x00000003
|
||||||
|
# NAME-NEXT: - Index: 0xFFFFFFFF
|
||||||
|
# NAME: - Name: .llvm_addrsig_unlinked
|
||||||
|
# NAME-NEXT: Type: SHT_LLVM_ADDRSIG
|
||||||
|
# NAME-NEXT: Symbols:
|
||||||
|
# NAME-NEXT: - Index: 0x00000001
|
||||||
|
# NAME-NEXT: - Index: 0x00000002
|
||||||
|
# NAME-NEXT: - Index: 0x00000003
|
||||||
|
# NAME-NEXT: - Index: 0xFFFFFFFF
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .llvm_addrsig
|
||||||
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
Symbols:
|
||||||
|
- Index: 1
|
||||||
|
- Index: 2
|
||||||
|
- Index: 3
|
||||||
|
- Index: 0xFFFFFFFF
|
||||||
|
- Name: .llvm_addrsig_unlinked
|
||||||
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
Link: 0
|
||||||
|
Symbols:
|
||||||
|
- Index: 1
|
||||||
|
- Index: 2
|
||||||
|
- Index: 3
|
||||||
|
- Index: 0xFFFFFFFF
|
||||||
|
Symbols:
|
||||||
|
- Name: foo
|
||||||
|
Type: STT_FUNC
|
||||||
|
Binding: STB_GLOBAL
|
||||||
|
- Name: bar
|
||||||
|
Type: STT_FUNC
|
||||||
|
Binding: STB_GLOBAL
|
||||||
|
|
||||||
|
## Check that obj2yaml dumps the SHT_LLVM_ADDRSIG section
|
||||||
|
## data using the "Content" tag when at least one of the entries is broken,
|
||||||
|
## e.g. because the entry contains a malformed uleb128 value.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=2 %s -o %t2
|
||||||
|
# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=INVALID-ENTRY
|
||||||
|
|
||||||
|
# INVALID-ENTRY: - Name: .llvm_addrsig
|
||||||
|
# INVALID-ENTRY-NEXT: Type: SHT_LLVM_ADDRSIG
|
||||||
|
# INVALID-ENTRY-NEXT: Link: .symtab
|
||||||
|
# INVALID-ENTRY-NEXT: Content: FFFFFFFFFF
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .llvm_addrsig
|
||||||
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
Content: "FFFFFFFFFF"
|
||||||
|
|
||||||
|
## obj2yaml produces a "Symbols" tag when describing an empty SHT_LLVM_ADDRSIG section.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=3 %s -o %t3
|
||||||
|
# RUN: obj2yaml %t3 | FileCheck %s --check-prefix=EMPTY
|
||||||
|
|
||||||
|
# EMPTY: - Name: .llvm_addrsig
|
||||||
|
# EMPTY-NEXT: Type: SHT_LLVM_ADDRSIG
|
||||||
|
# EMPTY-NEXT: Link: .symtab
|
||||||
|
# EMPTY-NEXT: Symbols: []
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .llvm_addrsig
|
||||||
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
Content: ""
|
|
@ -0,0 +1,213 @@
|
||||||
|
## Check how yaml2obj produces SHT_LLVM_ADDRSIG sections.
|
||||||
|
|
||||||
|
## Check we can describe SHT_LLVM_ADDRSIG using the "Symbols" tag. We can define
|
||||||
|
## symbols either using names or indexes.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=1 %s -o %t1
|
||||||
|
# RUN: llvm-readobj --sections --section-data %t1 | FileCheck %s --check-prefix=SYMBOLS
|
||||||
|
|
||||||
|
# SYMBOLS: Section {
|
||||||
|
# SYMBOLS: Index: 1
|
||||||
|
# SYMBOLS-NEXT: Name: .llvm_addrsig
|
||||||
|
# SYMBOLS-NEXT: Type: SHT_LLVM_ADDRSIG
|
||||||
|
# SYMBOLS-NEXT: Flags [
|
||||||
|
# SYMBOLS-NEXT: ]
|
||||||
|
# SYMBOLS-NEXT: Address: 0x0
|
||||||
|
# SYMBOLS-NEXT: Offset: 0x40
|
||||||
|
# SYMBOLS-NEXT: Size: 4
|
||||||
|
# SYMBOLS-NEXT: Link: 2
|
||||||
|
# SYMBOLS-NEXT: Info: 0
|
||||||
|
# SYMBOLS-NEXT: AddressAlignment: 0
|
||||||
|
# SYMBOLS-NEXT: EntrySize: 0
|
||||||
|
# SYMBOLS-NEXT: SectionData (
|
||||||
|
# SYMBOLS-NEXT: 0000: 01020102
|
||||||
|
# SYMBOLS-NEXT: )
|
||||||
|
# SYMBOLS-NEXT: }
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .llvm_addrsig
|
||||||
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
Symbols:
|
||||||
|
- Name: foo
|
||||||
|
- Name: bar
|
||||||
|
- Index: 1
|
||||||
|
- Index: 2
|
||||||
|
Symbols:
|
||||||
|
- Name: foo
|
||||||
|
Type: STT_FUNC
|
||||||
|
Binding: STB_GLOBAL
|
||||||
|
- Name: bar
|
||||||
|
Type: STT_FUNC
|
||||||
|
Binding: STB_GLOBAL
|
||||||
|
|
||||||
|
## We can't specify both "Index" and "Name" when defining a symbol.
|
||||||
|
|
||||||
|
# RUN: not yaml2obj --docnum=2 %s 2>&1 | FileCheck %s --check-prefix=INDEX-NAME
|
||||||
|
|
||||||
|
# INDEX-NAME: error: "Index" and "Name" cannot be used together when defining a symbol
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .llvm_addrsig
|
||||||
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
Symbols:
|
||||||
|
- Name: foo
|
||||||
|
Index: 1
|
||||||
|
Symbols:
|
||||||
|
- Name: foo
|
||||||
|
Type: STT_FUNC
|
||||||
|
Binding: STB_GLOBAL
|
||||||
|
|
||||||
|
## Check we report an error if an unknown symbol is referenced in the
|
||||||
|
## SHT_LLVM_ADDRSIG section description.
|
||||||
|
|
||||||
|
# RUN: not yaml2obj --docnum=3 %s 2>&1 | FileCheck %s --check-prefix=SYMBOL-UNKNOWN
|
||||||
|
|
||||||
|
# SYMBOL-UNKNOWN: error: unknown symbol referenced: 'foo' by YAML section '.llvm_addrsig'
|
||||||
|
# SYMBOL-UNKNOWN: error: unknown symbol referenced: 'bar' by YAML section '.llvm_addrsig'
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .llvm_addrsig
|
||||||
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
Symbols:
|
||||||
|
- Name: foo
|
||||||
|
- Name: bar
|
||||||
|
|
||||||
|
## Check we can specify any arbitrary symbol indices.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=4 %s -o %t4
|
||||||
|
# RUN: llvm-readobj --sections --section-data %t4 | FileCheck %s --check-prefix=SYMBOL-INDEX
|
||||||
|
|
||||||
|
# SYMBOL-INDEX: Type: SHT_LLVM_ADDRSIG
|
||||||
|
# SYMBOL-INDEX: SectionData (
|
||||||
|
# SYMBOL-INDEX-NEXT: 0000: 00FF01C4 E6888901 FFFFFFFF 0F
|
||||||
|
# SYMBOL-INDEX-NEXT: )
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .llvm_addrsig
|
||||||
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
Symbols:
|
||||||
|
- Index: 0
|
||||||
|
- Index: 255
|
||||||
|
- Index: 0x11223344
|
||||||
|
## 0xFFFFFFFF is a maximum allowed index value.
|
||||||
|
- Index: 0xFFFFFFFF
|
||||||
|
|
||||||
|
## Check that the maximum symbol index size is 32 bits.
|
||||||
|
|
||||||
|
# RUN: not yaml2obj --docnum=5 %s 2>&1 | FileCheck %s --check-prefix=SYMBOL-INDEX-OVERFLOW
|
||||||
|
|
||||||
|
# SYMBOL-INDEX-OVERFLOW: error: out of range hex32 number
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .llvm_addrsig
|
||||||
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
Symbols:
|
||||||
|
- Index: 0x1122334455
|
||||||
|
|
||||||
|
## Check we can use the "Content" tag to specify any data for SHT_LLVM_ADDRSIG sections.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=6 %s -o %t6
|
||||||
|
# RUN: llvm-readobj --sections --section-data %t6 | FileCheck %s --check-prefix=CONTENT
|
||||||
|
|
||||||
|
# CONTENT: Type: SHT_LLVM_ADDRSIG
|
||||||
|
# CONTENT: Size:
|
||||||
|
# CONTENT-SAME: 5
|
||||||
|
# CONTENT: SectionData (
|
||||||
|
# CONTENT-NEXT: 0000: 11223344 55
|
||||||
|
# CONTENT-NEXT: )
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .llvm_addrsig
|
||||||
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
Content: "1122334455"
|
||||||
|
|
||||||
|
## Either "Content" or "Symbols" must be specifed for SHT_LLVM_ADDRSIG sections.
|
||||||
|
|
||||||
|
# RUN: not yaml2obj --docnum=7 %s 2>&1 | FileCheck %s --check-prefix=NO-TAGS
|
||||||
|
|
||||||
|
# NO-TAGS: error: one of "Symbols" or "Content" must be specified
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .llvm_addrsig
|
||||||
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
|
||||||
|
## "Content" and "Symbols" cannot be used together to describe the SHT_LLVM_ADDRSIG section.
|
||||||
|
|
||||||
|
# RUN: not yaml2obj --docnum=8 %s 2>&1 | FileCheck %s --check-prefix=CONTENT-SYMBOLS
|
||||||
|
|
||||||
|
# CONTENT-SYMBOLS: error: "Content" and "Symbols" cannot be used together
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .llvm_addrsig
|
||||||
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
Content: ""
|
||||||
|
Symbols:
|
||||||
|
|
||||||
|
## Check we can set an arbitrary sh_link value for SHT_LLVM_ADDRSIG sections.
|
||||||
|
|
||||||
|
# RUN: yaml2obj --docnum=9 %s -o %t9
|
||||||
|
# RUN: llvm-readobj --sections %t9 | FileCheck %s --check-prefix=LINK
|
||||||
|
|
||||||
|
# LINK: Name: .llvm_addrsig
|
||||||
|
# LINK: Link:
|
||||||
|
# LINK-SAME: 123{{$}}
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .llvm_addrsig
|
||||||
|
Type: SHT_LLVM_ADDRSIG
|
||||||
|
Link: 123
|
||||||
|
Content: ""
|
|
@ -41,6 +41,7 @@ class ELFDumper {
|
||||||
Expected<StringRef> getUniquedSymbolName(const Elf_Sym *Sym,
|
Expected<StringRef> getUniquedSymbolName(const Elf_Sym *Sym,
|
||||||
StringRef StrTable,
|
StringRef StrTable,
|
||||||
const Elf_Shdr *SymTab);
|
const Elf_Shdr *SymTab);
|
||||||
|
Expected<StringRef> getSymbolName(uint32_t SymtabNdx, uint32_t SymbolNdx);
|
||||||
|
|
||||||
const object::ELFFile<ELFT> &Obj;
|
const object::ELFFile<ELFT> &Obj;
|
||||||
ArrayRef<Elf_Word> ShndxTable;
|
ArrayRef<Elf_Word> ShndxTable;
|
||||||
|
@ -56,6 +57,7 @@ class ELFDumper {
|
||||||
Error dumpRelocation(const RelT *Rel, const Elf_Shdr *SymTab,
|
Error dumpRelocation(const RelT *Rel, const Elf_Shdr *SymTab,
|
||||||
ELFYAML::Relocation &R);
|
ELFYAML::Relocation &R);
|
||||||
|
|
||||||
|
Expected<ELFYAML::AddrsigSection *> dumpAddrsigSection(const Elf_Shdr *Shdr);
|
||||||
Expected<ELFYAML::DynamicSection *> dumpDynamicSection(const Elf_Shdr *Shdr);
|
Expected<ELFYAML::DynamicSection *> dumpDynamicSection(const Elf_Shdr *Shdr);
|
||||||
Expected<ELFYAML::RelocationSection *> dumpRelocSection(const Elf_Shdr *Shdr);
|
Expected<ELFYAML::RelocationSection *> dumpRelocSection(const Elf_Shdr *Shdr);
|
||||||
Expected<ELFYAML::RawContentSection *>
|
Expected<ELFYAML::RawContentSection *>
|
||||||
|
@ -284,6 +286,13 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
||||||
Y->Sections.emplace_back(*SecOrErr);
|
Y->Sections.emplace_back(*SecOrErr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ELF::SHT_LLVM_ADDRSIG: {
|
||||||
|
Expected<ELFYAML::AddrsigSection *> SecOrErr = dumpAddrsigSection(&Sec);
|
||||||
|
if (!SecOrErr)
|
||||||
|
return SecOrErr.takeError();
|
||||||
|
Y->Sections.emplace_back(*SecOrErr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ELF::SHT_NULL: {
|
case ELF::SHT_NULL: {
|
||||||
// We only dump the SHT_NULL section at index 0 when it
|
// We only dump the SHT_NULL section at index 0 when it
|
||||||
// has at least one non-null field, because yaml2obj
|
// has at least one non-null field, because yaml2obj
|
||||||
|
@ -519,6 +528,45 @@ ELFDumper<ELFT>::dumpStackSizesSection(const Elf_Shdr *Shdr) {
|
||||||
return S.release();
|
return S.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class ELFT>
|
||||||
|
Expected<ELFYAML::AddrsigSection *>
|
||||||
|
ELFDumper<ELFT>::dumpAddrsigSection(const Elf_Shdr *Shdr) {
|
||||||
|
auto S = std::make_unique<ELFYAML::AddrsigSection>();
|
||||||
|
if (Error E = dumpCommonSection(Shdr, *S))
|
||||||
|
return std::move(E);
|
||||||
|
|
||||||
|
auto ContentOrErr = Obj.getSectionContents(Shdr);
|
||||||
|
if (!ContentOrErr)
|
||||||
|
return ContentOrErr.takeError();
|
||||||
|
|
||||||
|
ArrayRef<uint8_t> Content = *ContentOrErr;
|
||||||
|
DataExtractor::Cursor Cur(0);
|
||||||
|
DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0);
|
||||||
|
std::vector<ELFYAML::AddrsigSymbol> Symbols;
|
||||||
|
while (Cur && Cur.tell() < Content.size()) {
|
||||||
|
uint64_t SymNdx = Data.getULEB128(Cur);
|
||||||
|
if (!Cur)
|
||||||
|
break;
|
||||||
|
|
||||||
|
Expected<StringRef> SymbolName = getSymbolName(Shdr->sh_link, SymNdx);
|
||||||
|
if (!SymbolName || SymbolName->empty()) {
|
||||||
|
consumeError(SymbolName.takeError());
|
||||||
|
Symbols.emplace_back(SymNdx);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Symbols.emplace_back(*SymbolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cur) {
|
||||||
|
S->Symbols = std::move(Symbols);
|
||||||
|
return S.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
S->Content = yaml::BinaryRef(Content);
|
||||||
|
return S.release();
|
||||||
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
Expected<ELFYAML::DynamicSection *>
|
Expected<ELFYAML::DynamicSection *>
|
||||||
ELFDumper<ELFT>::dumpDynamicSection(const Elf_Shdr *Shdr) {
|
ELFDumper<ELFT>::dumpDynamicSection(const Elf_Shdr *Shdr) {
|
||||||
|
@ -790,26 +838,32 @@ ELFDumper<ELFT>::dumpVerneedSection(const Elf_Shdr *Shdr) {
|
||||||
return S.release();
|
return S.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class ELFT>
|
||||||
|
Expected<StringRef> ELFDumper<ELFT>::getSymbolName(uint32_t SymtabNdx,
|
||||||
|
uint32_t SymbolNdx) {
|
||||||
|
auto SymtabOrErr = Obj.getSection(SymtabNdx);
|
||||||
|
if (!SymtabOrErr)
|
||||||
|
return SymtabOrErr.takeError();
|
||||||
|
|
||||||
|
const Elf_Shdr *Symtab = *SymtabOrErr;
|
||||||
|
auto SymOrErr = Obj.getSymbol(Symtab, SymbolNdx);
|
||||||
|
if (!SymOrErr)
|
||||||
|
return SymOrErr.takeError();
|
||||||
|
|
||||||
|
auto StrTabOrErr = Obj.getStringTableForSymtab(*Symtab);
|
||||||
|
if (!StrTabOrErr)
|
||||||
|
return StrTabOrErr.takeError();
|
||||||
|
return getUniquedSymbolName(*SymOrErr, *StrTabOrErr, Symtab);
|
||||||
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
Expected<ELFYAML::Group *> ELFDumper<ELFT>::dumpGroup(const Elf_Shdr *Shdr) {
|
Expected<ELFYAML::Group *> ELFDumper<ELFT>::dumpGroup(const Elf_Shdr *Shdr) {
|
||||||
auto S = std::make_unique<ELFYAML::Group>();
|
auto S = std::make_unique<ELFYAML::Group>();
|
||||||
if (Error E = dumpCommonSection(Shdr, *S))
|
if (Error E = dumpCommonSection(Shdr, *S))
|
||||||
return std::move(E);
|
return std::move(E);
|
||||||
|
|
||||||
auto SymtabOrErr = Obj.getSection(Shdr->sh_link);
|
// Get symbol with index sh_info. This symbol's name is the signature of the group.
|
||||||
if (!SymtabOrErr)
|
Expected<StringRef> SymbolName = getSymbolName(Shdr->sh_link, Shdr->sh_info);
|
||||||
return SymtabOrErr.takeError();
|
|
||||||
// Get symbol with index sh_info which name is the signature of the group.
|
|
||||||
const Elf_Shdr *Symtab = *SymtabOrErr;
|
|
||||||
auto SymOrErr = Obj.getSymbol(Symtab, Shdr->sh_info);
|
|
||||||
if (!SymOrErr)
|
|
||||||
return SymOrErr.takeError();
|
|
||||||
auto StrTabOrErr = Obj.getStringTableForSymtab(*Symtab);
|
|
||||||
if (!StrTabOrErr)
|
|
||||||
return StrTabOrErr.takeError();
|
|
||||||
|
|
||||||
Expected<StringRef> SymbolName =
|
|
||||||
getUniquedSymbolName(*SymOrErr, *StrTabOrErr, Symtab);
|
|
||||||
if (!SymbolName)
|
if (!SymbolName)
|
||||||
return SymbolName.takeError();
|
return SymbolName.takeError();
|
||||||
S->Signature = *SymbolName;
|
S->Signature = *SymbolName;
|
||||||
|
|
Loading…
Reference in New Issue