Home | History | Annotate | Download | only in obj2yaml
      1 //===------ utils/elf2yaml.cpp - obj2yaml conversion tool -------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "Error.h"
     11 #include "obj2yaml.h"
     12 #include "llvm/ADT/STLExtras.h"
     13 #include "llvm/Object/ELFObjectFile.h"
     14 #include "llvm/Object/ELFYAML.h"
     15 #include "llvm/Support/ErrorHandling.h"
     16 #include "llvm/Support/YAMLTraits.h"
     17 
     18 using namespace llvm;
     19 
     20 namespace {
     21 
     22 template <class ELFT>
     23 class ELFDumper {
     24   typedef object::Elf_Sym_Impl<ELFT> Elf_Sym;
     25   typedef typename object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
     26   typedef typename object::ELFFile<ELFT>::Elf_Word Elf_Word;
     27 
     28   const object::ELFFile<ELFT> &Obj;
     29   ArrayRef<Elf_Word> ShndxTable;
     30 
     31   std::error_code dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
     32                              StringRef StrTable, ELFYAML::Symbol &S);
     33   std::error_code dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::Section &S);
     34   std::error_code dumpCommonRelocationSection(const Elf_Shdr *Shdr,
     35                                               ELFYAML::RelocationSection &S);
     36   template <class RelT>
     37   std::error_code dumpRelocation(const RelT *Rel, const Elf_Shdr *SymTab,
     38                                  ELFYAML::Relocation &R);
     39 
     40   ErrorOr<ELFYAML::RelocationSection *> dumpRelSection(const Elf_Shdr *Shdr);
     41   ErrorOr<ELFYAML::RelocationSection *> dumpRelaSection(const Elf_Shdr *Shdr);
     42   ErrorOr<ELFYAML::RawContentSection *>
     43   dumpContentSection(const Elf_Shdr *Shdr);
     44   ErrorOr<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr);
     45   ErrorOr<ELFYAML::Group *> dumpGroup(const Elf_Shdr *Shdr);
     46   ErrorOr<ELFYAML::MipsABIFlags *> dumpMipsABIFlags(const Elf_Shdr *Shdr);
     47 
     48 public:
     49   ELFDumper(const object::ELFFile<ELFT> &O);
     50   ErrorOr<ELFYAML::Object *> dump();
     51 };
     52 
     53 }
     54 
     55 template <class ELFT>
     56 ELFDumper<ELFT>::ELFDumper(const object::ELFFile<ELFT> &O)
     57     : Obj(O) {}
     58 
     59 template <class ELFT>
     60 ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
     61   auto Y = make_unique<ELFYAML::Object>();
     62 
     63   // Dump header
     64   Y->Header.Class = ELFYAML::ELF_ELFCLASS(Obj.getHeader()->getFileClass());
     65   Y->Header.Data = ELFYAML::ELF_ELFDATA(Obj.getHeader()->getDataEncoding());
     66   Y->Header.OSABI = Obj.getHeader()->e_ident[ELF::EI_OSABI];
     67   Y->Header.Type = Obj.getHeader()->e_type;
     68   Y->Header.Machine = Obj.getHeader()->e_machine;
     69   Y->Header.Flags = Obj.getHeader()->e_flags;
     70   Y->Header.Entry = Obj.getHeader()->e_entry;
     71 
     72   const Elf_Shdr *Symtab = nullptr;
     73 
     74   // Dump sections
     75   for (const Elf_Shdr &Sec : Obj.sections()) {
     76     switch (Sec.sh_type) {
     77     case ELF::SHT_NULL:
     78     case ELF::SHT_DYNSYM:
     79     case ELF::SHT_STRTAB:
     80       // Do not dump these sections.
     81       break;
     82     case ELF::SHT_SYMTAB:
     83       Symtab = &Sec;
     84       break;
     85     case ELF::SHT_SYMTAB_SHNDX: {
     86       ErrorOr<ArrayRef<Elf_Word>> TableOrErr = Obj.getSHNDXTable(Sec);
     87       if (std::error_code EC = TableOrErr.getError())
     88         return EC;
     89       ShndxTable = *TableOrErr;
     90       break;
     91     }
     92     case ELF::SHT_RELA: {
     93       ErrorOr<ELFYAML::RelocationSection *> S = dumpRelaSection(&Sec);
     94       if (std::error_code EC = S.getError())
     95         return EC;
     96       Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
     97       break;
     98     }
     99     case ELF::SHT_REL: {
    100       ErrorOr<ELFYAML::RelocationSection *> S = dumpRelSection(&Sec);
    101       if (std::error_code EC = S.getError())
    102         return EC;
    103       Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
    104       break;
    105     }
    106     case ELF::SHT_GROUP: {
    107       ErrorOr<ELFYAML::Group *> G = dumpGroup(&Sec);
    108       if (std::error_code EC = G.getError())
    109         return EC;
    110       Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(G.get()));
    111       break;
    112     }
    113     case ELF::SHT_MIPS_ABIFLAGS: {
    114       ErrorOr<ELFYAML::MipsABIFlags *> G = dumpMipsABIFlags(&Sec);
    115       if (std::error_code EC = G.getError())
    116         return EC;
    117       Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(G.get()));
    118       break;
    119     }
    120     case ELF::SHT_NOBITS: {
    121       ErrorOr<ELFYAML::NoBitsSection *> S = dumpNoBitsSection(&Sec);
    122       if (std::error_code EC = S.getError())
    123         return EC;
    124       Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
    125       break;
    126     }
    127     default: {
    128       ErrorOr<ELFYAML::RawContentSection *> S = dumpContentSection(&Sec);
    129       if (std::error_code EC = S.getError())
    130         return EC;
    131       Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
    132     }
    133     }
    134   }
    135 
    136   // Dump symbols
    137   ErrorOr<StringRef> StrTableOrErr = Obj.getStringTableForSymtab(*Symtab);
    138   if (std::error_code EC = StrTableOrErr.getError())
    139     return EC;
    140   StringRef StrTable = *StrTableOrErr;
    141 
    142   bool IsFirstSym = true;
    143   for (const Elf_Sym &Sym : Obj.symbols(Symtab)) {
    144     if (IsFirstSym) {
    145       IsFirstSym = false;
    146       continue;
    147     }
    148 
    149     ELFYAML::Symbol S;
    150     if (std::error_code EC =
    151             ELFDumper<ELFT>::dumpSymbol(&Sym, Symtab, StrTable, S))
    152       return EC;
    153 
    154     switch (Sym.getBinding())
    155     {
    156     case ELF::STB_LOCAL:
    157       Y->Symbols.Local.push_back(S);
    158       break;
    159     case ELF::STB_GLOBAL:
    160       Y->Symbols.Global.push_back(S);
    161       break;
    162     case ELF::STB_WEAK:
    163       Y->Symbols.Weak.push_back(S);
    164       break;
    165     default:
    166       llvm_unreachable("Unknown ELF symbol binding");
    167     }
    168   }
    169 
    170   return Y.release();
    171 }
    172 
    173 template <class ELFT>
    174 std::error_code
    175 ELFDumper<ELFT>::dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
    176                             StringRef StrTable, ELFYAML::Symbol &S) {
    177   S.Type = Sym->getType();
    178   S.Value = Sym->st_value;
    179   S.Size = Sym->st_size;
    180   S.Other = Sym->st_other;
    181 
    182   ErrorOr<StringRef> NameOrErr = Sym->getName(StrTable);
    183   if (std::error_code EC = NameOrErr.getError())
    184     return EC;
    185   S.Name = NameOrErr.get();
    186 
    187   ErrorOr<const Elf_Shdr *> ShdrOrErr = Obj.getSection(Sym, SymTab, ShndxTable);
    188   if (std::error_code EC = ShdrOrErr.getError())
    189     return EC;
    190   const Elf_Shdr *Shdr = *ShdrOrErr;
    191   if (!Shdr)
    192     return obj2yaml_error::success;
    193 
    194   NameOrErr = Obj.getSectionName(Shdr);
    195   if (std::error_code EC = NameOrErr.getError())
    196     return EC;
    197   S.Section = NameOrErr.get();
    198 
    199   return obj2yaml_error::success;
    200 }
    201 
    202 template <class ELFT>
    203 template <class RelT>
    204 std::error_code ELFDumper<ELFT>::dumpRelocation(const RelT *Rel,
    205                                                 const Elf_Shdr *SymTab,
    206                                                 ELFYAML::Relocation &R) {
    207   R.Type = Rel->getType(Obj.isMips64EL());
    208   R.Offset = Rel->r_offset;
    209   R.Addend = 0;
    210 
    211   const Elf_Sym *Sym = Obj.getRelocationSymbol(Rel, SymTab);
    212   ErrorOr<const Elf_Shdr *> StrTabSec = Obj.getSection(SymTab->sh_link);
    213   if (std::error_code EC = StrTabSec.getError())
    214     return EC;
    215   ErrorOr<StringRef> StrTabOrErr = Obj.getStringTable(*StrTabSec);
    216   if (std::error_code EC = StrTabOrErr.getError())
    217     return EC;
    218   StringRef StrTab = *StrTabOrErr;
    219 
    220   ErrorOr<StringRef> NameOrErr = Sym->getName(StrTab);
    221   if (std::error_code EC = NameOrErr.getError())
    222     return EC;
    223   R.Symbol = NameOrErr.get();
    224 
    225   return obj2yaml_error::success;
    226 }
    227 
    228 template <class ELFT>
    229 std::error_code ELFDumper<ELFT>::dumpCommonSection(const Elf_Shdr *Shdr,
    230                                                    ELFYAML::Section &S) {
    231   S.Type = Shdr->sh_type;
    232   S.Flags = Shdr->sh_flags;
    233   S.Address = Shdr->sh_addr;
    234   S.AddressAlign = Shdr->sh_addralign;
    235 
    236   ErrorOr<StringRef> NameOrErr = Obj.getSectionName(Shdr);
    237   if (std::error_code EC = NameOrErr.getError())
    238     return EC;
    239   S.Name = NameOrErr.get();
    240 
    241   if (Shdr->sh_link != ELF::SHN_UNDEF) {
    242     ErrorOr<const Elf_Shdr *> LinkSection = Obj.getSection(Shdr->sh_link);
    243     if (std::error_code EC = LinkSection.getError())
    244       return EC;
    245     NameOrErr = Obj.getSectionName(*LinkSection);
    246     if (std::error_code EC = NameOrErr.getError())
    247       return EC;
    248     S.Link = NameOrErr.get();
    249   }
    250 
    251   return obj2yaml_error::success;
    252 }
    253 
    254 template <class ELFT>
    255 std::error_code
    256 ELFDumper<ELFT>::dumpCommonRelocationSection(const Elf_Shdr *Shdr,
    257                                              ELFYAML::RelocationSection &S) {
    258   if (std::error_code EC = dumpCommonSection(Shdr, S))
    259     return EC;
    260 
    261   ErrorOr<const Elf_Shdr *> InfoSection = Obj.getSection(Shdr->sh_info);
    262   if (std::error_code EC = InfoSection.getError())
    263     return EC;
    264 
    265   ErrorOr<StringRef> NameOrErr = Obj.getSectionName(*InfoSection);
    266   if (std::error_code EC = NameOrErr.getError())
    267     return EC;
    268   S.Info = NameOrErr.get();
    269 
    270   return obj2yaml_error::success;
    271 }
    272 
    273 template <class ELFT>
    274 ErrorOr<ELFYAML::RelocationSection *>
    275 ELFDumper<ELFT>::dumpRelSection(const Elf_Shdr *Shdr) {
    276   assert(Shdr->sh_type == ELF::SHT_REL && "Section type is not SHT_REL");
    277   auto S = make_unique<ELFYAML::RelocationSection>();
    278 
    279   if (std::error_code EC = dumpCommonRelocationSection(Shdr, *S))
    280     return EC;
    281 
    282   ErrorOr<const Elf_Shdr *> SymTabOrErr = Obj.getSection(Shdr->sh_link);
    283   if (std::error_code EC = SymTabOrErr.getError())
    284     return EC;
    285   const Elf_Shdr *SymTab = *SymTabOrErr;
    286 
    287   for (auto RI = Obj.rel_begin(Shdr), RE = Obj.rel_end(Shdr); RI != RE; ++RI) {
    288     ELFYAML::Relocation R;
    289     if (std::error_code EC = dumpRelocation(&*RI, SymTab, R))
    290       return EC;
    291     S->Relocations.push_back(R);
    292   }
    293 
    294   return S.release();
    295 }
    296 
    297 template <class ELFT>
    298 ErrorOr<ELFYAML::RelocationSection *>
    299 ELFDumper<ELFT>::dumpRelaSection(const Elf_Shdr *Shdr) {
    300   assert(Shdr->sh_type == ELF::SHT_RELA && "Section type is not SHT_RELA");
    301   auto S = make_unique<ELFYAML::RelocationSection>();
    302 
    303   if (std::error_code EC = dumpCommonRelocationSection(Shdr, *S))
    304     return EC;
    305 
    306   ErrorOr<const Elf_Shdr *> SymTabOrErr = Obj.getSection(Shdr->sh_link);
    307   if (std::error_code EC = SymTabOrErr.getError())
    308     return EC;
    309   const Elf_Shdr *SymTab = *SymTabOrErr;
    310 
    311   for (auto RI = Obj.rela_begin(Shdr), RE = Obj.rela_end(Shdr); RI != RE;
    312        ++RI) {
    313     ELFYAML::Relocation R;
    314     if (std::error_code EC = dumpRelocation(&*RI, SymTab, R))
    315       return EC;
    316     R.Addend = RI->r_addend;
    317     S->Relocations.push_back(R);
    318   }
    319 
    320   return S.release();
    321 }
    322 
    323 template <class ELFT>
    324 ErrorOr<ELFYAML::RawContentSection *>
    325 ELFDumper<ELFT>::dumpContentSection(const Elf_Shdr *Shdr) {
    326   auto S = make_unique<ELFYAML::RawContentSection>();
    327 
    328   if (std::error_code EC = dumpCommonSection(Shdr, *S))
    329     return EC;
    330 
    331   ErrorOr<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(Shdr);
    332   if (std::error_code EC = ContentOrErr.getError())
    333     return EC;
    334   S->Content = yaml::BinaryRef(ContentOrErr.get());
    335   S->Size = S->Content.binary_size();
    336 
    337   return S.release();
    338 }
    339 
    340 template <class ELFT>
    341 ErrorOr<ELFYAML::NoBitsSection *>
    342 ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) {
    343   auto S = make_unique<ELFYAML::NoBitsSection>();
    344 
    345   if (std::error_code EC = dumpCommonSection(Shdr, *S))
    346     return EC;
    347   S->Size = Shdr->sh_size;
    348 
    349   return S.release();
    350 }
    351 
    352 template <class ELFT>
    353 ErrorOr<ELFYAML::Group *> ELFDumper<ELFT>::dumpGroup(const Elf_Shdr *Shdr) {
    354   auto S = make_unique<ELFYAML::Group>();
    355 
    356   if (std::error_code EC = dumpCommonSection(Shdr, *S))
    357     return EC;
    358   // Get sh_info which is the signature.
    359   ErrorOr<const Elf_Shdr *> SymtabOrErr = Obj.getSection(Shdr->sh_link);
    360   if (std::error_code EC = SymtabOrErr.getError())
    361     return EC;
    362   const Elf_Shdr *Symtab = *SymtabOrErr;
    363   const Elf_Sym *symbol = Obj.getSymbol(Symtab, Shdr->sh_info);
    364   ErrorOr<StringRef> StrTabOrErr = Obj.getStringTableForSymtab(*Symtab);
    365   if (std::error_code EC = StrTabOrErr.getError())
    366     return EC;
    367   StringRef StrTab = *StrTabOrErr;
    368   auto sectionContents = Obj.getSectionContents(Shdr);
    369   if (std::error_code ec = sectionContents.getError())
    370     return ec;
    371   ErrorOr<StringRef> symbolName = symbol->getName(StrTab);
    372   if (std::error_code EC = symbolName.getError())
    373     return EC;
    374   S->Info = *symbolName;
    375   const Elf_Word *groupMembers =
    376       reinterpret_cast<const Elf_Word *>(sectionContents->data());
    377   const long count = (Shdr->sh_size) / sizeof(Elf_Word);
    378   ELFYAML::SectionOrType s;
    379   for (int i = 0; i < count; i++) {
    380     if (groupMembers[i] == llvm::ELF::GRP_COMDAT) {
    381       s.sectionNameOrType = "GRP_COMDAT";
    382     } else {
    383       ErrorOr<const Elf_Shdr *> sHdr = Obj.getSection(groupMembers[i]);
    384       if (std::error_code EC = sHdr.getError())
    385         return EC;
    386       ErrorOr<StringRef> sectionName = Obj.getSectionName(*sHdr);
    387       if (std::error_code ec = sectionName.getError())
    388         return ec;
    389       s.sectionNameOrType = *sectionName;
    390     }
    391     S->Members.push_back(s);
    392   }
    393   return S.release();
    394 }
    395 
    396 template <class ELFT>
    397 ErrorOr<ELFYAML::MipsABIFlags *>
    398 ELFDumper<ELFT>::dumpMipsABIFlags(const Elf_Shdr *Shdr) {
    399   assert(Shdr->sh_type == ELF::SHT_MIPS_ABIFLAGS &&
    400          "Section type is not SHT_MIPS_ABIFLAGS");
    401   auto S = make_unique<ELFYAML::MipsABIFlags>();
    402   if (std::error_code EC = dumpCommonSection(Shdr, *S))
    403     return EC;
    404 
    405   ErrorOr<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(Shdr);
    406   if (std::error_code EC = ContentOrErr.getError())
    407     return EC;
    408 
    409   auto *Flags = reinterpret_cast<const object::Elf_Mips_ABIFlags<ELFT> *>(
    410       ContentOrErr.get().data());
    411   S->Version = Flags->version;
    412   S->ISALevel = Flags->isa_level;
    413   S->ISARevision = Flags->isa_rev;
    414   S->GPRSize = Flags->gpr_size;
    415   S->CPR1Size = Flags->cpr1_size;
    416   S->CPR2Size = Flags->cpr2_size;
    417   S->FpABI = Flags->fp_abi;
    418   S->ISAExtension = Flags->isa_ext;
    419   S->ASEs = Flags->ases;
    420   S->Flags1 = Flags->flags1;
    421   S->Flags2 = Flags->flags2;
    422   return S.release();
    423 }
    424 
    425 template <class ELFT>
    426 static std::error_code elf2yaml(raw_ostream &Out,
    427                                 const object::ELFFile<ELFT> &Obj) {
    428   ELFDumper<ELFT> Dumper(Obj);
    429   ErrorOr<ELFYAML::Object *> YAMLOrErr = Dumper.dump();
    430   if (std::error_code EC = YAMLOrErr.getError())
    431     return EC;
    432 
    433   std::unique_ptr<ELFYAML::Object> YAML(YAMLOrErr.get());
    434   yaml::Output Yout(Out);
    435   Yout << *YAML;
    436 
    437   return std::error_code();
    438 }
    439 
    440 std::error_code elf2yaml(raw_ostream &Out, const object::ObjectFile &Obj) {
    441   if (const auto *ELFObj = dyn_cast<object::ELF32LEObjectFile>(&Obj))
    442     return elf2yaml(Out, *ELFObj->getELFFile());
    443 
    444   if (const auto *ELFObj = dyn_cast<object::ELF32BEObjectFile>(&Obj))
    445     return elf2yaml(Out, *ELFObj->getELFFile());
    446 
    447   if (const auto *ELFObj = dyn_cast<object::ELF64LEObjectFile>(&Obj))
    448     return elf2yaml(Out, *ELFObj->getELFFile());
    449 
    450   if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(&Obj))
    451     return elf2yaml(Out, *ELFObj->getELFFile());
    452 
    453   return obj2yaml_error::unsupported_obj_file_format;
    454 }
    455