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 18using namespace llvm; 19 20namespace { 21 22template <class ELFT> 23class 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_Sym_Iter Elf_Sym_Iter; 27 typedef typename object::ELFFile<ELFT>::Elf_Word Elf_Word; 28 29 const object::ELFFile<ELFT> &Obj; 30 31 std::error_code dumpSymbol(Elf_Sym_Iter Sym, ELFYAML::Symbol &S); 32 std::error_code dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::Section &S); 33 std::error_code dumpCommonRelocationSection(const Elf_Shdr *Shdr, 34 ELFYAML::RelocationSection &S); 35 template <class RelT> 36 std::error_code dumpRelocation(const Elf_Shdr *Shdr, const RelT *Rel, 37 ELFYAML::Relocation &R); 38 39 ErrorOr<ELFYAML::RelocationSection *> dumpRelSection(const Elf_Shdr *Shdr); 40 ErrorOr<ELFYAML::RelocationSection *> dumpRelaSection(const Elf_Shdr *Shdr); 41 ErrorOr<ELFYAML::RawContentSection *> 42 dumpContentSection(const Elf_Shdr *Shdr); 43 ErrorOr<ELFYAML::Group *> dumpGroup(const Elf_Shdr *Shdr); 44 45public: 46 ELFDumper(const object::ELFFile<ELFT> &O); 47 ErrorOr<ELFYAML::Object *> dump(); 48}; 49 50} 51 52template <class ELFT> 53ELFDumper<ELFT>::ELFDumper(const object::ELFFile<ELFT> &O) 54 : Obj(O) {} 55 56template <class ELFT> 57ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() { 58 auto Y = make_unique<ELFYAML::Object>(); 59 60 // Dump header 61 Y->Header.Class = ELFYAML::ELF_ELFCLASS(Obj.getHeader()->getFileClass()); 62 Y->Header.Data = ELFYAML::ELF_ELFDATA(Obj.getHeader()->getDataEncoding()); 63 Y->Header.OSABI = Obj.getHeader()->e_ident[ELF::EI_OSABI]; 64 Y->Header.Type = Obj.getHeader()->e_type; 65 Y->Header.Machine = Obj.getHeader()->e_machine; 66 Y->Header.Flags = Obj.getHeader()->e_flags; 67 Y->Header.Entry = Obj.getHeader()->e_entry; 68 69 // Dump sections 70 for (const Elf_Shdr &Sec : Obj.sections()) { 71 switch (Sec.sh_type) { 72 case ELF::SHT_NULL: 73 case ELF::SHT_SYMTAB: 74 case ELF::SHT_DYNSYM: 75 case ELF::SHT_STRTAB: 76 // Do not dump these sections. 77 break; 78 case ELF::SHT_RELA: { 79 ErrorOr<ELFYAML::RelocationSection *> S = dumpRelaSection(&Sec); 80 if (std::error_code EC = S.getError()) 81 return EC; 82 Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get())); 83 break; 84 } 85 case ELF::SHT_REL: { 86 ErrorOr<ELFYAML::RelocationSection *> S = dumpRelSection(&Sec); 87 if (std::error_code EC = S.getError()) 88 return EC; 89 Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get())); 90 break; 91 } 92 case ELF::SHT_GROUP: { 93 ErrorOr<ELFYAML::Group *> G = dumpGroup(&Sec); 94 if (std::error_code EC = G.getError()) 95 return EC; 96 Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(G.get())); 97 break; 98 } 99 default: { 100 ErrorOr<ELFYAML::RawContentSection *> S = dumpContentSection(&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 } 105 } 106 } 107 108 // Dump symbols 109 bool IsFirstSym = true; 110 for (auto SI = Obj.begin_symbols(), SE = Obj.end_symbols(); SI != SE; ++SI) { 111 if (IsFirstSym) { 112 IsFirstSym = false; 113 continue; 114 } 115 116 ELFYAML::Symbol S; 117 if (std::error_code EC = ELFDumper<ELFT>::dumpSymbol(SI, S)) 118 return EC; 119 120 switch (SI->getBinding()) 121 { 122 case ELF::STB_LOCAL: 123 Y->Symbols.Local.push_back(S); 124 break; 125 case ELF::STB_GLOBAL: 126 Y->Symbols.Global.push_back(S); 127 break; 128 case ELF::STB_WEAK: 129 Y->Symbols.Weak.push_back(S); 130 break; 131 default: 132 llvm_unreachable("Unknown ELF symbol binding"); 133 } 134 } 135 136 return Y.release(); 137} 138 139template <class ELFT> 140std::error_code ELFDumper<ELFT>::dumpSymbol(Elf_Sym_Iter Sym, 141 ELFYAML::Symbol &S) { 142 S.Type = Sym->getType(); 143 S.Value = Sym->st_value; 144 S.Size = Sym->st_size; 145 S.Other = Sym->st_other; 146 147 ErrorOr<StringRef> NameOrErr = Obj.getSymbolName(Sym); 148 if (std::error_code EC = NameOrErr.getError()) 149 return EC; 150 S.Name = NameOrErr.get(); 151 152 const Elf_Shdr *Shdr = Obj.getSection(&*Sym); 153 if (!Shdr) 154 return obj2yaml_error::success; 155 156 NameOrErr = Obj.getSectionName(Shdr); 157 if (std::error_code EC = NameOrErr.getError()) 158 return EC; 159 S.Section = NameOrErr.get(); 160 161 return obj2yaml_error::success; 162} 163 164template <class ELFT> 165template <class RelT> 166std::error_code ELFDumper<ELFT>::dumpRelocation(const Elf_Shdr *Shdr, 167 const RelT *Rel, 168 ELFYAML::Relocation &R) { 169 R.Type = Rel->getType(Obj.isMips64EL()); 170 R.Offset = Rel->r_offset; 171 R.Addend = 0; 172 173 auto NamePair = Obj.getRelocationSymbol(Shdr, Rel); 174 if (!NamePair.first) 175 return obj2yaml_error::success; 176 177 ErrorOr<StringRef> NameOrErr = 178 Obj.getSymbolName(NamePair.first, NamePair.second); 179 if (std::error_code EC = NameOrErr.getError()) 180 return EC; 181 R.Symbol = NameOrErr.get(); 182 183 return obj2yaml_error::success; 184} 185 186template <class ELFT> 187std::error_code ELFDumper<ELFT>::dumpCommonSection(const Elf_Shdr *Shdr, 188 ELFYAML::Section &S) { 189 S.Type = Shdr->sh_type; 190 S.Flags = Shdr->sh_flags; 191 S.Address = Shdr->sh_addr; 192 S.AddressAlign = Shdr->sh_addralign; 193 194 ErrorOr<StringRef> NameOrErr = Obj.getSectionName(Shdr); 195 if (std::error_code EC = NameOrErr.getError()) 196 return EC; 197 S.Name = NameOrErr.get(); 198 199 if (Shdr->sh_link != ELF::SHN_UNDEF) { 200 if (const Elf_Shdr *LinkSection = Obj.getSection(Shdr->sh_link)) { 201 NameOrErr = Obj.getSectionName(LinkSection); 202 if (std::error_code EC = NameOrErr.getError()) 203 return EC; 204 S.Link = NameOrErr.get(); 205 } 206 } 207 208 return obj2yaml_error::success; 209} 210 211template <class ELFT> 212std::error_code 213ELFDumper<ELFT>::dumpCommonRelocationSection(const Elf_Shdr *Shdr, 214 ELFYAML::RelocationSection &S) { 215 if (std::error_code EC = dumpCommonSection(Shdr, S)) 216 return EC; 217 218 if (const Elf_Shdr *InfoSection = Obj.getSection(Shdr->sh_info)) { 219 ErrorOr<StringRef> NameOrErr = Obj.getSectionName(InfoSection); 220 if (std::error_code EC = NameOrErr.getError()) 221 return EC; 222 S.Info = NameOrErr.get(); 223 } 224 225 return obj2yaml_error::success; 226} 227 228template <class ELFT> 229ErrorOr<ELFYAML::RelocationSection *> 230ELFDumper<ELFT>::dumpRelSection(const Elf_Shdr *Shdr) { 231 assert(Shdr->sh_type == ELF::SHT_REL && "Section type is not SHT_REL"); 232 auto S = make_unique<ELFYAML::RelocationSection>(); 233 234 if (std::error_code EC = dumpCommonRelocationSection(Shdr, *S)) 235 return EC; 236 237 for (auto RI = Obj.begin_rel(Shdr), RE = Obj.end_rel(Shdr); RI != RE; 238 ++RI) { 239 ELFYAML::Relocation R; 240 if (std::error_code EC = dumpRelocation(Shdr, &*RI, R)) 241 return EC; 242 S->Relocations.push_back(R); 243 } 244 245 return S.release(); 246} 247 248template <class ELFT> 249ErrorOr<ELFYAML::RelocationSection *> 250ELFDumper<ELFT>::dumpRelaSection(const Elf_Shdr *Shdr) { 251 assert(Shdr->sh_type == ELF::SHT_RELA && "Section type is not SHT_RELA"); 252 auto S = make_unique<ELFYAML::RelocationSection>(); 253 254 if (std::error_code EC = dumpCommonRelocationSection(Shdr, *S)) 255 return EC; 256 257 for (auto RI = Obj.begin_rela(Shdr), RE = Obj.end_rela(Shdr); RI != RE; 258 ++RI) { 259 ELFYAML::Relocation R; 260 if (std::error_code EC = dumpRelocation(Shdr, &*RI, R)) 261 return EC; 262 R.Addend = RI->r_addend; 263 S->Relocations.push_back(R); 264 } 265 266 return S.release(); 267} 268 269template <class ELFT> 270ErrorOr<ELFYAML::RawContentSection *> 271ELFDumper<ELFT>::dumpContentSection(const Elf_Shdr *Shdr) { 272 auto S = make_unique<ELFYAML::RawContentSection>(); 273 274 if (std::error_code EC = dumpCommonSection(Shdr, *S)) 275 return EC; 276 277 ErrorOr<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(Shdr); 278 if (std::error_code EC = ContentOrErr.getError()) 279 return EC; 280 S->Content = yaml::BinaryRef(ContentOrErr.get()); 281 S->Size = S->Content.binary_size(); 282 283 return S.release(); 284} 285 286template <class ELFT> 287ErrorOr<ELFYAML::Group *> ELFDumper<ELFT>::dumpGroup(const Elf_Shdr *Shdr) { 288 auto S = make_unique<ELFYAML::Group>(); 289 290 if (std::error_code EC = dumpCommonSection(Shdr, *S)) 291 return EC; 292 // Get sh_info which is the signature. 293 const Elf_Sym *symbol = Obj.getSymbol(Shdr->sh_info); 294 const Elf_Shdr *symtab = Obj.getSection(Shdr->sh_link); 295 auto sectionContents = Obj.getSectionContents(Shdr); 296 if (std::error_code ec = sectionContents.getError()) 297 return ec; 298 ErrorOr<StringRef> symbolName = Obj.getSymbolName(symtab, symbol); 299 if (std::error_code EC = symbolName.getError()) 300 return EC; 301 S->Info = *symbolName; 302 const Elf_Word *groupMembers = 303 reinterpret_cast<const Elf_Word *>(sectionContents->data()); 304 const long count = (Shdr->sh_size) / sizeof(Elf_Word); 305 ELFYAML::SectionOrType s; 306 for (int i = 0; i < count; i++) { 307 if (groupMembers[i] == llvm::ELF::GRP_COMDAT) { 308 s.sectionNameOrType = "GRP_COMDAT"; 309 } else { 310 const Elf_Shdr *sHdr = Obj.getSection(groupMembers[i]); 311 ErrorOr<StringRef> sectionName = Obj.getSectionName(sHdr); 312 if (std::error_code ec = sectionName.getError()) 313 return ec; 314 s.sectionNameOrType = *sectionName; 315 } 316 S->Members.push_back(s); 317 } 318 return S.release(); 319} 320 321template <class ELFT> 322static std::error_code elf2yaml(raw_ostream &Out, 323 const object::ELFFile<ELFT> &Obj) { 324 ELFDumper<ELFT> Dumper(Obj); 325 ErrorOr<ELFYAML::Object *> YAMLOrErr = Dumper.dump(); 326 if (std::error_code EC = YAMLOrErr.getError()) 327 return EC; 328 329 std::unique_ptr<ELFYAML::Object> YAML(YAMLOrErr.get()); 330 yaml::Output Yout(Out); 331 Yout << *YAML; 332 333 return object::object_error::success; 334} 335 336std::error_code elf2yaml(raw_ostream &Out, const object::ObjectFile &Obj) { 337 if (const auto *ELFObj = dyn_cast<object::ELF32LEObjectFile>(&Obj)) 338 return elf2yaml(Out, *ELFObj->getELFFile()); 339 340 if (const auto *ELFObj = dyn_cast<object::ELF32BEObjectFile>(&Obj)) 341 return elf2yaml(Out, *ELFObj->getELFFile()); 342 343 if (const auto *ELFObj = dyn_cast<object::ELF64LEObjectFile>(&Obj)) 344 return elf2yaml(Out, *ELFObj->getELFFile()); 345 346 if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(&Obj)) 347 return elf2yaml(Out, *ELFObj->getELFFile()); 348 349 return obj2yaml_error::unsupported_obj_file_format; 350} 351