1
0
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:
georgerim 2019-10-25 13:03:19 +03:00
parent e77c71b3bf
commit f4f8838607
10 changed files with 182 additions and 14 deletions

View File

@ -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);
};

View File

@ -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;

View File

@ -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;

View File

@ -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");

View File

@ -52,3 +52,4 @@ Sections:
- Name: .baz
Type: SHT_NOTE
AddressAlign: 4
Notes: []

View File

@ -155,6 +155,7 @@ Sections:
Type: SHT_DYNAMIC
- Name: note
Type: SHT_NOTE
Notes: []
- Name: nobits
Type: SHT_NOBITS
- Name: rel

View File

@ -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

View File

@ -74,6 +74,7 @@ Sections:
Type: SHT_NOTE
ShSize: 0x100
Address: 0x4000
Notes: []
- Name: .nobits
Type: SHT_NOBITS
ShSize: 0x200

View File

@ -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

View File

@ -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) {