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