summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorSimon Atanasyan <simon@atanasyan.com>2014-04-11 04:13:39 +0000
committerSimon Atanasyan <simon@atanasyan.com>2014-04-11 04:13:39 +0000
commiteb0c9094acd5f5a28c0adafb1784797d1d7a4e2d (patch)
treed94849c02e0a4a546c075081bb4ace35f0ea2937 /tools
parent77cf856e56dc568ebe760e7de820323fdcf825a4 (diff)
downloadllvm-eb0c9094acd5f5a28c0adafb1784797d1d7a4e2d.tar.gz
llvm-eb0c9094acd5f5a28c0adafb1784797d1d7a4e2d.tar.bz2
llvm-eb0c9094acd5f5a28c0adafb1784797d1d7a4e2d.tar.xz
[yaml2obj][ELF] ELF Relocations Support.
The patch implements support for both relocation record formats: Elf_Rel and Elf_Rela. It is possible to define relocation against symbol only. Relocations against sections will be implemented later. Now yaml2obj recognizes X86_64, MIPS and Hexagon relocation types. Example of relocation section specification: Sections: - Name: .text Type: SHT_PROGBITS Content: "0000000000000000" AddressAlign: 16 Flags: [SHF_ALLOC] - Name: .rel.text Type: SHT_REL Info: .text AddressAlign: 4 Relocations: - Offset: 0x1 Symbol: glob1 Type: R_MIPS_32 - Offset: 0x2 Symbol: glob2 Type: R_MIPS_CALL16 The patch reviewed by Michael Spencer, Sean Silva, Shankar Easwaran. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206017 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r--tools/yaml2obj/yaml2elf.cpp134
1 files changed, 118 insertions, 16 deletions
diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp
index 4e9ee4dcd6..acbac9c605 100644
--- a/tools/yaml2obj/yaml2elf.cpp
+++ b/tools/yaml2obj/yaml2elf.cpp
@@ -143,6 +143,8 @@ class ELFState {
typedef typename object::ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
typedef typename object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
typedef typename object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+ typedef typename object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
+ typedef typename object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
/// \brief The future ".strtab" section.
StringTableBuilder DotStrtab;
@@ -151,9 +153,12 @@ class ELFState {
StringTableBuilder DotShStrtab;
NameToIdxMap SN2I;
+ NameToIdxMap SymN2I;
const ELFYAML::Object &Doc;
bool buildSectionIndex();
+ bool buildSymbolIndex(std::size_t &StartIndex,
+ const std::vector<ELFYAML::Symbol> &Symbols);
void initELFHeader(Elf_Ehdr &Header);
bool initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
ContiguousBlobAccumulator &CBA);
@@ -164,6 +169,12 @@ class ELFState {
ContiguousBlobAccumulator &CBA);
void addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
std::vector<Elf_Sym> &Syms, unsigned SymbolBinding);
+ void writeSectionContent(Elf_Shdr &SHeader,
+ const ELFYAML::RawContentSection &Section,
+ ContiguousBlobAccumulator &CBA);
+ bool writeSectionContent(Elf_Shdr &SHeader,
+ const ELFYAML::RelocationSection &Section,
+ ContiguousBlobAccumulator &CBA);
// - SHT_NULL entry (placed first, i.e. 0'th entry)
// - symbol table (.symtab) (placed third to last)
@@ -219,26 +230,42 @@ bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
for (const auto &Sec : Doc.Sections) {
zero(SHeader);
- SHeader.sh_name = DotShStrtab.addString(Sec.Name);
- SHeader.sh_type = Sec.Type;
- SHeader.sh_flags = Sec.Flags;
- SHeader.sh_addr = Sec.Address;
+ SHeader.sh_name = DotShStrtab.addString(Sec->Name);
+ SHeader.sh_type = Sec->Type;
+ SHeader.sh_flags = Sec->Flags;
+ SHeader.sh_addr = Sec->Address;
+ SHeader.sh_addralign = Sec->AddressAlign;
- Sec.Content.writeAsBinary(CBA.getOSAndAlignedOffset(SHeader.sh_offset));
- SHeader.sh_size = Sec.Content.binary_size();
-
- if (!Sec.Link.empty()) {
+ if (!Sec->Link.empty()) {
unsigned Index;
- if (SN2I.lookup(Sec.Link, Index)) {
- errs() << "error: Unknown section referenced: '" << Sec.Link
- << "' at YAML section '" << Sec.Name << "'.\n";
- return false;;
+ if (SN2I.lookup(Sec->Link, Index)) {
+ errs() << "error: Unknown section referenced: '" << Sec->Link
+ << "' at YAML section '" << Sec->Name << "'.\n";
+ return false;
}
SHeader.sh_link = Index;
}
- SHeader.sh_info = 0;
- SHeader.sh_addralign = Sec.AddressAlign;
- SHeader.sh_entsize = 0;
+
+ if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec.get()))
+ writeSectionContent(SHeader, *S, CBA);
+ else if (auto S = dyn_cast<ELFYAML::RelocationSection>(Sec.get())) {
+ if (S->Link.empty())
+ // For relocation section set link to .symtab by default.
+ SHeader.sh_link = getDotSymTabSecNo();
+
+ unsigned Index;
+ if (SN2I.lookup(S->Info, Index)) {
+ errs() << "error: Unknown section referenced: '" << S->Info
+ << "' at YAML section '" << S->Name << "'.\n";
+ return false;
+ }
+ SHeader.sh_info = Index;
+
+ if (!writeSectionContent(SHeader, *S, CBA))
+ return false;
+ } else
+ llvm_unreachable("Unknown section type");
+
SHeaders.push_back(SHeader);
}
return true;
@@ -308,13 +335,66 @@ void ELFState<ELFT>::addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
}
}
+template <class ELFT>
+void
+ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
+ const ELFYAML::RawContentSection &Section,
+ ContiguousBlobAccumulator &CBA) {
+ Section.Content.writeAsBinary(CBA.getOSAndAlignedOffset(SHeader.sh_offset));
+ SHeader.sh_entsize = 0;
+ SHeader.sh_size = Section.Content.binary_size();
+}
+
+template <class ELFT>
+bool
+ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
+ const ELFYAML::RelocationSection &Section,
+ ContiguousBlobAccumulator &CBA) {
+ if (Section.Type != llvm::ELF::SHT_REL &&
+ Section.Type != llvm::ELF::SHT_RELA) {
+ errs() << "error: Invalid relocation section type.\n";
+ return false;
+ }
+
+ bool IsRela = Section.Type == llvm::ELF::SHT_RELA;
+ SHeader.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
+ SHeader.sh_size = SHeader.sh_entsize * Section.Relocations.size();
+
+ auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset);
+
+ for (const auto &Rel : Section.Relocations) {
+ unsigned SymIdx;
+ if (SymN2I.lookup(Rel.Symbol, SymIdx)) {
+ errs() << "error: Unknown symbol referenced: '" << Rel.Symbol
+ << "' at YAML relocation.\n";
+ return false;
+ }
+
+ if (IsRela) {
+ Elf_Rela REntry;
+ zero(REntry);
+ REntry.r_offset = Rel.Offset;
+ REntry.r_addend = Rel.Addend;
+ REntry.setSymbolAndType(SymIdx, Rel.Type);
+ OS.write((const char *)&REntry, sizeof(REntry));
+ } else {
+ Elf_Rel REntry;
+ zero(REntry);
+ REntry.r_offset = Rel.Offset;
+ REntry.setSymbolAndType(SymIdx, Rel.Type);
+ OS.write((const char *)&REntry, sizeof(REntry));
+ }
+ }
+ return true;
+}
+
template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
SN2I.addName(".symtab", getDotSymTabSecNo());
SN2I.addName(".strtab", getDotStrTabSecNo());
SN2I.addName(".shstrtab", getDotShStrTabSecNo());
for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) {
- StringRef Name = Doc.Sections[i].Name;
+ StringRef Name = Doc.Sections[i]->Name;
if (Name.empty())
continue;
// "+ 1" to take into account the SHT_NULL entry.
@@ -328,11 +408,33 @@ template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
}
template <class ELFT>
+bool
+ELFState<ELFT>::buildSymbolIndex(std::size_t &StartIndex,
+ const std::vector<ELFYAML::Symbol> &Symbols) {
+ for (const auto &Sym : Symbols) {
+ ++StartIndex;
+ if (Sym.Name.empty())
+ continue;
+ if (SymN2I.addName(Sym.Name, StartIndex)) {
+ errs() << "error: Repeated symbol name: '" << Sym.Name << "'.\n";
+ return false;
+ }
+ }
+ return true;
+}
+
+template <class ELFT>
int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
ELFState<ELFT> State(Doc);
if (!State.buildSectionIndex())
return 1;
+ std::size_t StartSymIndex = 0;
+ if (!State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Local) ||
+ !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Global) ||
+ !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Weak))
+ return 1;
+
Elf_Ehdr Header;
State.initELFHeader(Header);