mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-13 22:58:50 +00:00
[yaml2obj][obj2yaml] - Support SHT_GNU_verdef (.gnu.version_d) section.
This patch adds support for parsing/dumping the .gnu.version section. Description of the section is: https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/symverdefs.html Differential revision: https://reviews.llvm.org/D58437 llvm-svn: 354574
This commit is contained in:
parent
a13d56908a
commit
b6a05e83ac
@ -121,6 +121,7 @@ struct Section {
|
||||
RawContent,
|
||||
Relocation,
|
||||
NoBits,
|
||||
Verdef,
|
||||
Verneed,
|
||||
Symver,
|
||||
MipsABIFlags
|
||||
@ -203,6 +204,25 @@ struct SymverSection : Section {
|
||||
}
|
||||
};
|
||||
|
||||
struct VerdefEntry {
|
||||
uint16_t Version;
|
||||
uint16_t Flags;
|
||||
uint16_t VersionNdx;
|
||||
uint32_t Hash;
|
||||
std::vector<StringRef> VerNames;
|
||||
};
|
||||
|
||||
struct VerdefSection : Section {
|
||||
std::vector<VerdefEntry> Entries;
|
||||
llvm::yaml::Hex64 Info;
|
||||
|
||||
VerdefSection() : Section(SectionKind::Verdef) {}
|
||||
|
||||
static bool classof(const Section *S) {
|
||||
return S->Kind == SectionKind::Verdef;
|
||||
}
|
||||
};
|
||||
|
||||
struct Group : Section {
|
||||
// Members of a group contain a flag and a list of section indices
|
||||
// that are part of the group.
|
||||
@ -274,6 +294,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Section>)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerdefEntry)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VernauxEntry)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerneedEntry)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation)
|
||||
@ -419,6 +440,10 @@ template <> struct MappingTraits<ELFYAML::DynamicEntry> {
|
||||
static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel);
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<ELFYAML::VerdefEntry> {
|
||||
static void mapping(IO &IO, ELFYAML::VerdefEntry &E);
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<ELFYAML::VerneedEntry> {
|
||||
static void mapping(IO &IO, ELFYAML::VerneedEntry &E);
|
||||
};
|
||||
|
@ -868,6 +868,12 @@ static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) {
|
||||
IO.mapOptional("Size", Section.Size, Hex64(0));
|
||||
}
|
||||
|
||||
static void sectionMapping(IO &IO, ELFYAML::VerdefSection &Section) {
|
||||
commonSectionMapping(IO, Section);
|
||||
IO.mapRequired("Info", Section.Info);
|
||||
IO.mapRequired("Entries", Section.Entries);
|
||||
}
|
||||
|
||||
static void sectionMapping(IO &IO, ELFYAML::SymverSection &Section) {
|
||||
commonSectionMapping(IO, Section);
|
||||
IO.mapRequired("Entries", Section.Entries);
|
||||
@ -956,6 +962,11 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping(
|
||||
Section.reset(new ELFYAML::MipsABIFlags());
|
||||
sectionMapping(IO, *cast<ELFYAML::MipsABIFlags>(Section.get()));
|
||||
break;
|
||||
case ELF::SHT_GNU_verdef:
|
||||
if (!IO.outputting())
|
||||
Section.reset(new ELFYAML::VerdefSection());
|
||||
sectionMapping(IO, *cast<ELFYAML::VerdefSection>(Section.get()));
|
||||
break;
|
||||
case ELF::SHT_GNU_versym:
|
||||
if (!IO.outputting())
|
||||
Section.reset(new ELFYAML::SymverSection());
|
||||
@ -1014,6 +1025,17 @@ void MappingTraits<ELFYAML::DynamicEntry>::mapping(IO &IO,
|
||||
IO.mapRequired("Value", Rel.Val);
|
||||
}
|
||||
|
||||
void MappingTraits<ELFYAML::VerdefEntry>::mapping(IO &IO,
|
||||
ELFYAML::VerdefEntry &E) {
|
||||
assert(IO.getContext() && "The IO context is not initialized");
|
||||
|
||||
IO.mapRequired("Version", E.Version);
|
||||
IO.mapRequired("Flags", E.Flags);
|
||||
IO.mapRequired("VersionNdx", E.VersionNdx);
|
||||
IO.mapRequired("Hash", E.Hash);
|
||||
IO.mapRequired("Names", E.VerNames);
|
||||
}
|
||||
|
||||
void MappingTraits<ELFYAML::VerneedEntry>::mapping(IO &IO,
|
||||
ELFYAML::VerneedEntry &E) {
|
||||
assert(IO.getContext() && "The IO context is not initialized");
|
||||
|
72
test/tools/obj2yaml/verdef-section.yaml
Normal file
72
test/tools/obj2yaml/verdef-section.yaml
Normal file
@ -0,0 +1,72 @@
|
||||
# RUN: yaml2obj %s -o %t
|
||||
# RUN: obj2yaml %t | FileCheck %s
|
||||
|
||||
## Check we are able to yamalize SHT_GNU_verdef section.
|
||||
|
||||
# CHECK: - Name: .gnu.version_d
|
||||
# CHECK-NEXT: Type: SHT_GNU_verdef
|
||||
# CHECK-NEXT: Flags: [ SHF_ALLOC ]
|
||||
# CHECK-NEXT: Address: 0x0000000000000230
|
||||
# CHECK-NEXT: Link: .dynstr
|
||||
# CHECK-NEXT: AddressAlign: 0x0000000000000004
|
||||
# CHECK-NEXT: Info: 0x0000000000000004
|
||||
# CHECK-NEXT: Entries:
|
||||
# CHECK-NEXT: - Version: 1
|
||||
# CHECK-NEXT: Flags: 1
|
||||
# CHECK-NEXT: VersionNdx: 1
|
||||
# CHECK-NEXT: Hash: 170240160
|
||||
# CHECK-NEXT: Names:
|
||||
# CHECK-NEXT: - dso.so.0
|
||||
# CHECK-NEXT: - Version: 1
|
||||
# CHECK-NEXT: Flags: 2
|
||||
# CHECK-NEXT: VersionNdx: 2
|
||||
# CHECK-NEXT: Hash: 108387921
|
||||
# CHECK-NEXT: Names:
|
||||
# CHECK-NEXT: - VERSION_1
|
||||
# CHECK-NEXT: - Version: 1
|
||||
# CHECK-NEXT: Flags: 3
|
||||
# CHECK-NEXT: VersionNdx: 3
|
||||
# CHECK-NEXT: Hash: 108387922
|
||||
# CHECK-NEXT: Names:
|
||||
# CHECK-NEXT: - VERSION_2
|
||||
# CHECK-NEXT: - VERSION_3
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_DYN
|
||||
Machine: EM_X86_64
|
||||
Entry: 0x0000000000001000
|
||||
Sections:
|
||||
- Name: .gnu.version_d
|
||||
Type: SHT_GNU_verdef
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x0000000000000230
|
||||
Link: .dynstr
|
||||
AddressAlign: 0x0000000000000004
|
||||
Info: 0x0000000000000004
|
||||
Entries:
|
||||
- Version: 1
|
||||
Flags: 1
|
||||
VersionNdx: 1
|
||||
Hash: 170240160
|
||||
Names:
|
||||
- dso.so.0
|
||||
- Version: 1
|
||||
Flags: 2
|
||||
VersionNdx: 2
|
||||
Hash: 108387921
|
||||
Names:
|
||||
- VERSION_1
|
||||
- Version: 1
|
||||
Flags: 3
|
||||
VersionNdx: 3
|
||||
Hash: 108387922
|
||||
Names:
|
||||
- VERSION_2
|
||||
- VERSION_3
|
||||
DynamicSymbols:
|
||||
Global:
|
||||
- Name: foo
|
||||
...
|
69
test/tools/yaml2obj/verdef-section.yaml
Normal file
69
test/tools/yaml2obj/verdef-section.yaml
Normal file
@ -0,0 +1,69 @@
|
||||
# RUN: yaml2obj %s -o %t
|
||||
# RUN: llvm-readelf -V %t | FileCheck %s
|
||||
|
||||
# Check we are able to handle the SHT_GNU_verdef sections.
|
||||
|
||||
# CHECK: SHT_GNU_verdef {
|
||||
# CHECK-NEXT: Definition {
|
||||
# CHECK-NEXT: Version: 1
|
||||
# CHECK-NEXT: Flags: Base
|
||||
# CHECK-NEXT: Index: 1
|
||||
# CHECK-NEXT: Hash: 170240160
|
||||
# CHECK-NEXT: Name: dso.so.0
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Definition {
|
||||
# CHECK-NEXT: Version: 1
|
||||
# CHECK-NEXT: Flags: Weak
|
||||
# CHECK-NEXT: Index: 2
|
||||
# CHECK-NEXT: Hash: 108387921
|
||||
# CHECK-NEXT: Name: VERSION_1
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Definition {
|
||||
# CHECK-NEXT: Version: 1
|
||||
# CHECK-NEXT: Flags: 0x3
|
||||
# CHECK-NEXT: Index: 3
|
||||
# CHECK-NEXT: Hash: 108387922
|
||||
# CHECK-NEXT: Name: VERSION_2
|
||||
# CHECK-NEXT: Predecessor: VERSION_3
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: }
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_DYN
|
||||
Machine: EM_X86_64
|
||||
Entry: 0x0000000000001000
|
||||
Sections:
|
||||
- Name: .gnu.version_d
|
||||
Type: SHT_GNU_verdef
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x0000000000000230
|
||||
Link: .dynstr
|
||||
AddressAlign: 0x0000000000000004
|
||||
Info: 0x0000000000000003
|
||||
Entries:
|
||||
- Version: 1
|
||||
Flags: 1
|
||||
VersionNdx: 1
|
||||
Hash: 170240160
|
||||
Names:
|
||||
- dso.so.0
|
||||
- Version: 1
|
||||
Flags: 2
|
||||
VersionNdx: 2
|
||||
Hash: 108387921
|
||||
Names:
|
||||
- VERSION_1
|
||||
- Version: 1
|
||||
Flags: 3
|
||||
VersionNdx: 3
|
||||
Hash: 108387922
|
||||
Names:
|
||||
- VERSION_2
|
||||
- VERSION_3
|
||||
DynamicSymbols:
|
||||
Global:
|
||||
- Name: foo
|
||||
...
|
@ -57,6 +57,7 @@ class ELFDumper {
|
||||
ErrorOr<ELFYAML::RawContentSection *>
|
||||
dumpContentSection(const Elf_Shdr *Shdr);
|
||||
ErrorOr<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr);
|
||||
ErrorOr<ELFYAML::VerdefSection *> dumpVerdefSection(const Elf_Shdr *Shdr);
|
||||
ErrorOr<ELFYAML::SymverSection *> dumpSymverSection(const Elf_Shdr *Shdr);
|
||||
ErrorOr<ELFYAML::VerneedSection *> dumpVerneedSection(const Elf_Shdr *Shdr);
|
||||
ErrorOr<ELFYAML::Group *> dumpGroup(const Elf_Shdr *Shdr);
|
||||
@ -186,6 +187,13 @@ template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
||||
Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
|
||||
break;
|
||||
}
|
||||
case ELF::SHT_GNU_verdef: {
|
||||
ErrorOr<ELFYAML::VerdefSection *> S = dumpVerdefSection(&Sec);
|
||||
if (std::error_code EC = S.getError())
|
||||
return EC;
|
||||
Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
|
||||
break;
|
||||
}
|
||||
case ELF::SHT_GNU_versym: {
|
||||
ErrorOr<ELFYAML::SymverSection *> S = dumpSymverSection(&Sec);
|
||||
if (std::error_code EC = S.getError())
|
||||
@ -459,6 +467,56 @@ ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) {
|
||||
return S.release();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
ErrorOr<ELFYAML::VerdefSection *>
|
||||
ELFDumper<ELFT>::dumpVerdefSection(const Elf_Shdr *Shdr) {
|
||||
typedef typename ELFT::Verdef Elf_Verdef;
|
||||
typedef typename ELFT::Verdaux Elf_Verdaux;
|
||||
|
||||
auto S = make_unique<ELFYAML::VerdefSection>();
|
||||
if (std::error_code EC = dumpCommonSection(Shdr, *S))
|
||||
return EC;
|
||||
|
||||
S->Info = Shdr->sh_info;
|
||||
|
||||
auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link);
|
||||
if (!StringTableShdrOrErr)
|
||||
return errorToErrorCode(StringTableShdrOrErr.takeError());
|
||||
|
||||
auto StringTableOrErr = Obj.getStringTable(*StringTableShdrOrErr);
|
||||
if (!StringTableOrErr)
|
||||
return errorToErrorCode(StringTableOrErr.takeError());
|
||||
|
||||
auto Contents = Obj.getSectionContents(Shdr);
|
||||
if (!Contents)
|
||||
return errorToErrorCode(Contents.takeError());
|
||||
|
||||
llvm::ArrayRef<uint8_t> Data = *Contents;
|
||||
const uint8_t *Buf = Data.data();
|
||||
while (Buf) {
|
||||
const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(Buf);
|
||||
ELFYAML::VerdefEntry Entry;
|
||||
Entry.Version = Verdef->vd_version;
|
||||
Entry.Flags = Verdef->vd_flags;
|
||||
Entry.VersionNdx = Verdef->vd_ndx;
|
||||
Entry.Hash = Verdef->vd_hash;
|
||||
|
||||
const uint8_t *BufAux = Buf + Verdef->vd_aux;
|
||||
while (BufAux) {
|
||||
const Elf_Verdaux *Verdaux =
|
||||
reinterpret_cast<const Elf_Verdaux *>(BufAux);
|
||||
Entry.VerNames.push_back(
|
||||
StringTableOrErr->drop_front(Verdaux->vda_name).data());
|
||||
BufAux = Verdaux->vda_next ? BufAux + Verdaux->vda_next : nullptr;
|
||||
}
|
||||
|
||||
S->Entries.push_back(Entry);
|
||||
Buf = Verdef->vd_next ? Buf + Verdef->vd_next : nullptr;
|
||||
}
|
||||
|
||||
return S.release();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
ErrorOr<ELFYAML::SymverSection *>
|
||||
ELFDumper<ELFT>::dumpSymverSection(const Elf_Shdr *Shdr) {
|
||||
|
@ -163,6 +163,9 @@ class ELFState {
|
||||
bool writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::VerneedSection &Section,
|
||||
ContiguousBlobAccumulator &CBA);
|
||||
bool writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::VerdefSection &Section,
|
||||
ContiguousBlobAccumulator &CBA);
|
||||
bool writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::MipsABIFlags &Section,
|
||||
ContiguousBlobAccumulator &CBA);
|
||||
@ -311,6 +314,8 @@ bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
|
||||
writeSectionContent(SHeader, *S, CBA);
|
||||
} else if (auto S = dyn_cast<ELFYAML::VerneedSection>(Sec.get())) {
|
||||
writeSectionContent(SHeader, *S, CBA);
|
||||
} else if (auto S = dyn_cast<ELFYAML::VerdefSection>(Sec.get())) {
|
||||
writeSectionContent(SHeader, *S, CBA);
|
||||
} else
|
||||
llvm_unreachable("Unknown section type");
|
||||
|
||||
@ -585,6 +590,51 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::VerdefSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
typedef typename ELFT::Verdef Elf_Verdef;
|
||||
typedef typename ELFT::Verdaux Elf_Verdaux;
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
|
||||
uint64_t AuxCnt = 0;
|
||||
for (size_t I = 0; I < Section.Entries.size(); ++I) {
|
||||
const ELFYAML::VerdefEntry &E = Section.Entries[I];
|
||||
|
||||
Elf_Verdef VerDef;
|
||||
VerDef.vd_version = E.Version;
|
||||
VerDef.vd_flags = E.Flags;
|
||||
VerDef.vd_ndx = E.VersionNdx;
|
||||
VerDef.vd_hash = E.Hash;
|
||||
VerDef.vd_aux = sizeof(Elf_Verdef);
|
||||
VerDef.vd_cnt = E.VerNames.size();
|
||||
if (I == Section.Entries.size() - 1)
|
||||
VerDef.vd_next = 0;
|
||||
else
|
||||
VerDef.vd_next =
|
||||
sizeof(Elf_Verdef) + E.VerNames.size() * sizeof(Elf_Verdaux);
|
||||
OS.write((const char *)&VerDef, sizeof(Elf_Verdef));
|
||||
|
||||
for (size_t J = 0; J < E.VerNames.size(); ++J, ++AuxCnt) {
|
||||
Elf_Verdaux VernAux;
|
||||
VernAux.vda_name = DotDynstr.getOffset(E.VerNames[J]);
|
||||
if (J == E.VerNames.size() - 1)
|
||||
VernAux.vda_next = 0;
|
||||
else
|
||||
VernAux.vda_next = sizeof(Elf_Verdaux);
|
||||
OS.write((const char *)&VernAux, sizeof(Elf_Verdaux));
|
||||
}
|
||||
}
|
||||
|
||||
SHeader.sh_size = Section.Entries.size() * sizeof(Elf_Verdef) +
|
||||
AuxCnt * sizeof(Elf_Verdaux);
|
||||
SHeader.sh_info = Section.Info;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::VerneedSection &Section,
|
||||
@ -746,16 +796,19 @@ template <class ELFT> void ELFState<ELFT>::finalizeStrings() {
|
||||
// Add the dynamic symbol names to .dynstr section.
|
||||
AddSymbols(DotDynstr, Doc.DynamicSymbols);
|
||||
|
||||
// SHT_GNU_verneed section also adds strings to .dynstr section.
|
||||
// SHT_GNU_verdef and SHT_GNU_verneed sections might also
|
||||
// add strings to .dynstr section.
|
||||
for (const std::unique_ptr<ELFYAML::Section> &Sec : Doc.Sections) {
|
||||
auto VerNeed = dyn_cast<ELFYAML::VerneedSection>(Sec.get());
|
||||
if (!VerNeed)
|
||||
continue;
|
||||
|
||||
for (const ELFYAML::VerneedEntry &VE : VerNeed->VerneedV) {
|
||||
DotDynstr.add(VE.File);
|
||||
for (const ELFYAML::VernauxEntry &Aux : VE.AuxV)
|
||||
DotDynstr.add(Aux.Name);
|
||||
if (auto VerNeed = dyn_cast<ELFYAML::VerneedSection>(Sec.get())) {
|
||||
for (const ELFYAML::VerneedEntry &VE : VerNeed->VerneedV) {
|
||||
DotDynstr.add(VE.File);
|
||||
for (const ELFYAML::VernauxEntry &Aux : VE.AuxV)
|
||||
DotDynstr.add(Aux.Name);
|
||||
}
|
||||
} else if (auto VerDef = dyn_cast<ELFYAML::VerdefSection>(Sec.get())) {
|
||||
for (const ELFYAML::VerdefEntry &E : VerDef->Entries)
|
||||
for (StringRef Name : E.VerNames)
|
||||
DotDynstr.add(Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user