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