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