mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 02:52:53 +02:00
[yaml2obj, obj2yaml] - Add support for SHT_NOTE sections.
SHT_NOTE is the section that consists of namesz, descsz, type, name + padding, desc + padding data. This patch teaches yaml2obj, obj2yaml to dump and parse them. This patch implements the section how it is described here: https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-18048.html Which says: "For 64–bit objects and 32–bit objects, each entry is an array of 4-byte words in the format of the target processor" The official specification is different http://www.sco.com/developers/gabi/latest/ch5.pheader.html#note_section And says: "n 64-bit objects (files with e_ident[EI_CLASS] equal to ELFCLASS64), each entry is an array of 8-byte words in the format of the target processor. In 32-bit objects (files with e_ident[EI_CLASS] equal to ELFCLASS32), each entry is an array of 4-byte words in the format of the target processor" Since LLVM uses the first, 32-bit way, this patch follows it. Differential revision: https://reviews.llvm.org/D68983
This commit is contained in:
parent
e77c71b3bf
commit
f4f8838607
@ -124,6 +124,12 @@ struct StackSizeEntry {
|
||||
llvm::yaml::Hex64 Size;
|
||||
};
|
||||
|
||||
struct NoteEntry {
|
||||
StringRef Name;
|
||||
yaml::BinaryRef Desc;
|
||||
llvm::yaml::Hex32 Type;
|
||||
};
|
||||
|
||||
struct Section {
|
||||
enum class SectionKind {
|
||||
Dynamic,
|
||||
@ -131,6 +137,7 @@ struct Section {
|
||||
RawContent,
|
||||
Relocation,
|
||||
NoBits,
|
||||
Note,
|
||||
Hash,
|
||||
Verdef,
|
||||
Verneed,
|
||||
@ -222,6 +229,15 @@ struct NoBitsSection : Section {
|
||||
}
|
||||
};
|
||||
|
||||
struct NoteSection : Section {
|
||||
Optional<yaml::BinaryRef> Content;
|
||||
Optional<llvm::yaml::Hex64> Size;
|
||||
Optional<std::vector<ELFYAML::NoteEntry>> Notes;
|
||||
|
||||
NoteSection() : Section(SectionKind::Note) {}
|
||||
static bool classof(const Section *S) { return S->Kind == SectionKind::Note; }
|
||||
};
|
||||
|
||||
struct HashSection : Section {
|
||||
Optional<yaml::BinaryRef> Content;
|
||||
Optional<llvm::yaml::Hex64> Size;
|
||||
@ -386,6 +402,7 @@ struct Object {
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::AddrsigSymbol)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::StackSizeEntry)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::NoteEntry)
|
||||
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)
|
||||
@ -528,6 +545,10 @@ template <> struct MappingTraits<ELFYAML::DynamicEntry> {
|
||||
static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel);
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<ELFYAML::NoteEntry> {
|
||||
static void mapping(IO &IO, ELFYAML::NoteEntry &N);
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<ELFYAML::VerdefEntry> {
|
||||
static void mapping(IO &IO, ELFYAML::VerdefEntry &E);
|
||||
};
|
||||
|
@ -649,8 +649,7 @@ inline bool isBool(StringRef S) {
|
||||
inline QuotingType needsQuotes(StringRef S) {
|
||||
if (S.empty())
|
||||
return QuotingType::Single;
|
||||
if (isspace(static_cast<unsigned char>(S.front())) ||
|
||||
isspace(static_cast<unsigned char>(S.back())))
|
||||
if (isspace(S.front()) || isspace(S.back()))
|
||||
return QuotingType::Single;
|
||||
if (isNull(S))
|
||||
return QuotingType::Single;
|
||||
|
@ -36,6 +36,16 @@ class ContiguousBlobAccumulator {
|
||||
SmallVector<char, 128> Buf;
|
||||
raw_svector_ostream OS;
|
||||
|
||||
public:
|
||||
ContiguousBlobAccumulator(uint64_t InitialOffset_)
|
||||
: InitialOffset(InitialOffset_), Buf(), OS(Buf) {}
|
||||
|
||||
template <class Integer>
|
||||
raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align) {
|
||||
Offset = padToAlignment(Align);
|
||||
return OS;
|
||||
}
|
||||
|
||||
/// \returns The new offset.
|
||||
uint64_t padToAlignment(unsigned Align) {
|
||||
if (Align == 0)
|
||||
@ -46,14 +56,6 @@ class ContiguousBlobAccumulator {
|
||||
return AlignedOffset; // == CurrentOffset;
|
||||
}
|
||||
|
||||
public:
|
||||
ContiguousBlobAccumulator(uint64_t InitialOffset_)
|
||||
: InitialOffset(InitialOffset_), Buf(), OS(Buf) {}
|
||||
template <class Integer>
|
||||
raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align) {
|
||||
Offset = padToAlignment(Align);
|
||||
return OS;
|
||||
}
|
||||
void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); }
|
||||
};
|
||||
|
||||
@ -177,6 +179,9 @@ template <class ELFT> class ELFState {
|
||||
void writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::AddrsigSection &Section,
|
||||
ContiguousBlobAccumulator &CBA);
|
||||
void writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::NoteSection &Section,
|
||||
ContiguousBlobAccumulator &CBA);
|
||||
|
||||
ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH);
|
||||
|
||||
@ -440,6 +445,8 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
|
||||
writeSectionContent(SHeader, *S, CBA);
|
||||
} else if (auto S = dyn_cast<ELFYAML::AddrsigSection>(Sec)) {
|
||||
writeSectionContent(SHeader, *S, CBA);
|
||||
} else if (auto S = dyn_cast<ELFYAML::NoteSection>(Sec)) {
|
||||
writeSectionContent(SHeader, *S, CBA);
|
||||
} else {
|
||||
llvm_unreachable("Unknown section type");
|
||||
}
|
||||
@ -1035,6 +1042,55 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::NoteSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
uint64_t Offset = OS.tell();
|
||||
|
||||
if (Section.Content || Section.Size) {
|
||||
SHeader.sh_size = writeContent(OS, Section.Content, Section.Size);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const ELFYAML::NoteEntry &NE : *Section.Notes) {
|
||||
// Write name size.
|
||||
if (NE.Name.empty())
|
||||
support::endian::write<uint32_t>(OS, 0, ELFT::TargetEndianness);
|
||||
else
|
||||
support::endian::write<uint32_t>(OS, NE.Name.size() + 1,
|
||||
ELFT::TargetEndianness);
|
||||
|
||||
// Write description size.
|
||||
if (NE.Desc.binary_size() == 0)
|
||||
support::endian::write<uint32_t>(OS, 0, ELFT::TargetEndianness);
|
||||
else
|
||||
support::endian::write<uint32_t>(OS, NE.Desc.binary_size(),
|
||||
ELFT::TargetEndianness);
|
||||
|
||||
// Write type.
|
||||
support::endian::write<uint32_t>(OS, NE.Type, ELFT::TargetEndianness);
|
||||
|
||||
// Write name, null terminator and padding.
|
||||
if (!NE.Name.empty()) {
|
||||
support::endian::write<uint8_t>(OS, arrayRefFromStringRef(NE.Name),
|
||||
ELFT::TargetEndianness);
|
||||
support::endian::write<uint8_t>(OS, 0, ELFT::TargetEndianness);
|
||||
CBA.padToAlignment(4);
|
||||
}
|
||||
|
||||
// Write description and padding.
|
||||
if (NE.Desc.binary_size() != 0) {
|
||||
NE.Desc.writeAsBinary(OS);
|
||||
CBA.padToAlignment(4);
|
||||
}
|
||||
}
|
||||
|
||||
SHeader.sh_size = OS.tell() - Offset;
|
||||
}
|
||||
|
||||
template <class ELFT> void ELFState<ELFT>::buildSectionIndex() {
|
||||
for (unsigned I = 0, E = Doc.Sections.size(); I != E; ++I) {
|
||||
StringRef Name = Doc.Sections[I]->Name;
|
||||
|
@ -1032,6 +1032,13 @@ static void sectionMapping(IO &IO, ELFYAML::HashSection &Section) {
|
||||
IO.mapOptional("Size", Section.Size);
|
||||
}
|
||||
|
||||
static void sectionMapping(IO &IO, ELFYAML::NoteSection &Section) {
|
||||
commonSectionMapping(IO, Section);
|
||||
IO.mapOptional("Content", Section.Content);
|
||||
IO.mapOptional("Size", Section.Size);
|
||||
IO.mapOptional("Notes", Section.Notes);
|
||||
}
|
||||
|
||||
static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) {
|
||||
commonSectionMapping(IO, Section);
|
||||
IO.mapOptional("Size", Section.Size, Hex64(0));
|
||||
@ -1143,6 +1150,11 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping(
|
||||
Section.reset(new ELFYAML::HashSection());
|
||||
sectionMapping(IO, *cast<ELFYAML::HashSection>(Section.get()));
|
||||
break;
|
||||
case ELF::SHT_NOTE:
|
||||
if (!IO.outputting())
|
||||
Section.reset(new ELFYAML::NoteSection());
|
||||
sectionMapping(IO, *cast<ELFYAML::NoteSection>(Section.get()));
|
||||
break;
|
||||
case ELF::SHT_MIPS_ABIFLAGS:
|
||||
if (!IO.outputting())
|
||||
Section.reset(new ELFYAML::MipsABIFlags());
|
||||
@ -1270,6 +1282,24 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate(
|
||||
return {};
|
||||
}
|
||||
|
||||
if (const auto *NS = dyn_cast<ELFYAML::NoteSection>(Section.get())) {
|
||||
if (!NS->Content && !NS->Size && !NS->Notes)
|
||||
return "one of \"Content\", \"Size\" or \"Notes\" must be "
|
||||
"specified";
|
||||
|
||||
if (!NS->Content && !NS->Size)
|
||||
return {};
|
||||
|
||||
if (NS->Size && NS->Content &&
|
||||
(uint64_t)*NS->Size < NS->Content->binary_size())
|
||||
return "\"Size\" must be greater than or equal to the content "
|
||||
"size";
|
||||
|
||||
if (NS->Notes)
|
||||
return "\"Notes\" cannot be used with \"Content\" or \"Size\"";
|
||||
return {};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -1313,6 +1343,14 @@ void MappingTraits<ELFYAML::DynamicEntry>::mapping(IO &IO,
|
||||
IO.mapRequired("Value", Rel.Val);
|
||||
}
|
||||
|
||||
void MappingTraits<ELFYAML::NoteEntry>::mapping(IO &IO, ELFYAML::NoteEntry &N) {
|
||||
assert(IO.getContext() && "The IO context is not initialized");
|
||||
|
||||
IO.mapOptional("Name", N.Name);
|
||||
IO.mapOptional("Desc", N.Desc);
|
||||
IO.mapRequired("Type", N.Type);
|
||||
}
|
||||
|
||||
void MappingTraits<ELFYAML::VerdefEntry>::mapping(IO &IO,
|
||||
ELFYAML::VerdefEntry &E) {
|
||||
assert(IO.getContext() && "The IO context is not initialized");
|
||||
|
@ -52,3 +52,4 @@ Sections:
|
||||
- Name: .baz
|
||||
Type: SHT_NOTE
|
||||
AddressAlign: 4
|
||||
Notes: []
|
||||
|
@ -155,6 +155,7 @@ Sections:
|
||||
Type: SHT_DYNAMIC
|
||||
- Name: note
|
||||
Type: SHT_NOTE
|
||||
Notes: []
|
||||
- Name: nobits
|
||||
Type: SHT_NOBITS
|
||||
- Name: rel
|
||||
|
@ -119,6 +119,7 @@ FileHeader:
|
||||
Sections:
|
||||
- Name: .note
|
||||
Type: SHT_NOTE
|
||||
Notes: []
|
||||
ShOffset: 0xffff0000
|
||||
|
||||
## Test tools report an error if a note section has invalid size
|
||||
@ -140,6 +141,7 @@ Sections:
|
||||
- Name: .note
|
||||
Type: SHT_NOTE
|
||||
ShSize: 0xffff0000
|
||||
Notes: []
|
||||
|
||||
## Test tools report an error if a note program header has an invalid offset that
|
||||
## goes past the end of file.
|
||||
@ -157,8 +159,9 @@ FileHeader:
|
||||
Type: ET_CORE
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .note
|
||||
Type: SHT_NOTE
|
||||
- Name: .note
|
||||
Type: SHT_NOTE
|
||||
Notes: []
|
||||
ProgramHeaders:
|
||||
- Type: PT_NOTE
|
||||
Offset: 0xffff0000
|
||||
@ -181,8 +184,9 @@ FileHeader:
|
||||
Type: ET_CORE
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .note
|
||||
Type: SHT_NOTE
|
||||
- Name: .note
|
||||
Type: SHT_NOTE
|
||||
Notes: []
|
||||
ProgramHeaders:
|
||||
- Type: PT_NOTE
|
||||
FileSize: 0xffff0000
|
||||
|
@ -74,6 +74,7 @@ Sections:
|
||||
Type: SHT_NOTE
|
||||
ShSize: 0x100
|
||||
Address: 0x4000
|
||||
Notes: []
|
||||
- Name: .nobits
|
||||
Type: SHT_NOBITS
|
||||
ShSize: 0x200
|
||||
|
@ -63,6 +63,7 @@ Sections:
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .dynsym
|
||||
Type: SHT_NOTE
|
||||
Size: 0
|
||||
- Name: .dynstr
|
||||
Type: SHT_NOBITS
|
||||
## Needed to set the proper content size for .symtab, so
|
||||
|
@ -27,6 +27,8 @@ class ELFDumper {
|
||||
typedef typename ELFT::Word Elf_Word;
|
||||
typedef typename ELFT::Rel Elf_Rel;
|
||||
typedef typename ELFT::Rela Elf_Rela;
|
||||
using Elf_Nhdr = typename ELFT::Nhdr;
|
||||
using Elf_Note = typename ELFT::Note;
|
||||
|
||||
ArrayRef<Elf_Shdr> Sections;
|
||||
ArrayRef<Elf_Sym> SymTable;
|
||||
@ -66,6 +68,7 @@ class ELFDumper {
|
||||
dumpSymtabShndxSection(const Elf_Shdr *Shdr);
|
||||
Expected<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr);
|
||||
Expected<ELFYAML::HashSection *> dumpHashSection(const Elf_Shdr *Shdr);
|
||||
Expected<ELFYAML::NoteSection *> dumpNoteSection(const Elf_Shdr *Shdr);
|
||||
Expected<ELFYAML::VerdefSection *> dumpVerdefSection(const Elf_Shdr *Shdr);
|
||||
Expected<ELFYAML::SymverSection *> dumpSymverSection(const Elf_Shdr *Shdr);
|
||||
Expected<ELFYAML::VerneedSection *> dumpVerneedSection(const Elf_Shdr *Shdr);
|
||||
@ -262,6 +265,13 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
||||
Y->Sections.emplace_back(*SecOrErr);
|
||||
break;
|
||||
}
|
||||
case ELF::SHT_NOTE: {
|
||||
Expected<ELFYAML::NoteSection *> SecOrErr = dumpNoteSection(&Sec);
|
||||
if (!SecOrErr)
|
||||
return SecOrErr.takeError();
|
||||
Y->Sections.emplace_back(*SecOrErr);
|
||||
break;
|
||||
}
|
||||
case ELF::SHT_HASH: {
|
||||
Expected<ELFYAML::HashSection *> SecOrErr = dumpHashSection(&Sec);
|
||||
if (!SecOrErr)
|
||||
@ -675,6 +685,42 @@ ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) {
|
||||
return S.release();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
Expected<ELFYAML::NoteSection *>
|
||||
ELFDumper<ELFT>::dumpNoteSection(const Elf_Shdr *Shdr) {
|
||||
auto S = std::make_unique<ELFYAML::NoteSection>();
|
||||
if (Error E = dumpCommonSection(Shdr, *S))
|
||||
return std::move(E);
|
||||
|
||||
auto ContentOrErr = Obj.getSectionContents(Shdr);
|
||||
if (!ContentOrErr)
|
||||
return ContentOrErr.takeError();
|
||||
|
||||
std::vector<ELFYAML::NoteEntry> Entries;
|
||||
ArrayRef<uint8_t> Content = *ContentOrErr;
|
||||
while (!Content.empty()) {
|
||||
if (Content.size() < sizeof(Elf_Nhdr)) {
|
||||
S->Content = yaml::BinaryRef(*ContentOrErr);
|
||||
return S.release();
|
||||
}
|
||||
|
||||
const Elf_Nhdr *Header = reinterpret_cast<const Elf_Nhdr *>(Content.data());
|
||||
if (Content.size() < Header->getSize()) {
|
||||
S->Content = yaml::BinaryRef(*ContentOrErr);
|
||||
return S.release();
|
||||
}
|
||||
|
||||
Elf_Note Note(*Header);
|
||||
Entries.push_back(
|
||||
{Note.getName(), Note.getDesc(), (llvm::yaml::Hex32)Note.getType()});
|
||||
|
||||
Content = Content.drop_front(Header->getSize());
|
||||
}
|
||||
|
||||
S->Notes = std::move(Entries);
|
||||
return S.release();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
Expected<ELFYAML::HashSection *>
|
||||
ELFDumper<ELFT>::dumpHashSection(const Elf_Shdr *Shdr) {
|
||||
|
Loading…
Reference in New Issue
Block a user