blob: b9cdc123d31b9ec9ae99b94ede6c404142e42810 [file] [log] [blame]
Simon Atanasyanae6bb332014-05-14 05:07:47 +00001//===------ utils/elf2yaml.cpp - obj2yaml conversion tool -------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Simon Atanasyanae6bb332014-05-14 05:07:47 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "Error.h"
Rafael Espindola88ee57e2017-09-05 22:30:00 +000010#include "llvm/ADT/DenseSet.h"
Simon Atanasyanae6bb332014-05-14 05:07:47 +000011#include "llvm/ADT/STLExtras.h"
12#include "llvm/Object/ELFObjectFile.h"
Rafael Espindolaebd91932016-03-01 19:15:06 +000013#include "llvm/ObjectYAML/ELFYAML.h"
Simon Atanasyanae6bb332014-05-14 05:07:47 +000014#include "llvm/Support/ErrorHandling.h"
15#include "llvm/Support/YAMLTraits.h"
16
17using namespace llvm;
18
19namespace {
20
21template <class ELFT>
22class ELFDumper {
Shankar Easwaran6fbbe202015-02-21 04:28:26 +000023 typedef object::Elf_Sym_Impl<ELFT> Elf_Sym;
George Rimar0e7ed912019-02-09 11:34:28 +000024 typedef typename ELFT::Dyn Elf_Dyn;
Rui Ueyama478d6352018-01-12 02:28:31 +000025 typedef typename ELFT::Shdr Elf_Shdr;
26 typedef typename ELFT::Word Elf_Word;
27 typedef typename ELFT::Rel Elf_Rel;
28 typedef typename ELFT::Rela Elf_Rela;
Simon Atanasyanae6bb332014-05-14 05:07:47 +000029
Rafael Espindola88ee57e2017-09-05 22:30:00 +000030 ArrayRef<Elf_Shdr> Sections;
31
32 // If the file has multiple sections with the same name, we add a
33 // suffix to make them unique.
34 unsigned Suffix = 0;
35 DenseSet<StringRef> UsedSectionNames;
36 std::vector<std::string> SectionNames;
37 Expected<StringRef> getUniquedSectionName(const Elf_Shdr *Sec);
Rafael Espindoladc8b7a92017-09-06 00:57:53 +000038 Expected<StringRef> getSymbolName(const Elf_Sym *Sym, StringRef StrTable,
39 const Elf_Shdr *SymTab);
Rafael Espindola88ee57e2017-09-05 22:30:00 +000040
Simon Atanasyanae6bb332014-05-14 05:07:47 +000041 const object::ELFFile<ELFT> &Obj;
Rafael Espindolaaae55412015-08-10 21:29:35 +000042 ArrayRef<Elf_Word> ShndxTable;
Simon Atanasyanae6bb332014-05-14 05:07:47 +000043
Dave Lee67b49662017-11-16 18:10:15 +000044 std::error_code dumpSymbols(const Elf_Shdr *Symtab,
George Rimar41112992019-03-28 10:52:14 +000045 ELFYAML::SymbolsDef &Symbols);
Rafael Espindolaaae55412015-08-10 21:29:35 +000046 std::error_code dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
47 StringRef StrTable, ELFYAML::Symbol &S);
Rafael Espindola4453e42942014-06-13 03:07:50 +000048 std::error_code dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::Section &S);
49 std::error_code dumpCommonRelocationSection(const Elf_Shdr *Shdr,
50 ELFYAML::RelocationSection &S);
Simon Atanasyanae6bb332014-05-14 05:07:47 +000051 template <class RelT>
Rafael Espindola7d250f72015-09-02 15:07:39 +000052 std::error_code dumpRelocation(const RelT *Rel, const Elf_Shdr *SymTab,
Rafael Espindola4453e42942014-06-13 03:07:50 +000053 ELFYAML::Relocation &R);
George Rimar0e7ed912019-02-09 11:34:28 +000054
55 ErrorOr<ELFYAML::DynamicSection *> dumpDynamicSection(const Elf_Shdr *Shdr);
George Rimarafe8a042019-02-01 07:50:08 +000056 ErrorOr<ELFYAML::RelocationSection *> dumpRelocSection(const Elf_Shdr *Shdr);
Simon Atanasyanae6bb332014-05-14 05:07:47 +000057 ErrorOr<ELFYAML::RawContentSection *>
58 dumpContentSection(const Elf_Shdr *Shdr);
Simon Atanasyan5db02762015-07-03 23:00:54 +000059 ErrorOr<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr);
George Rimar623ae722019-02-21 12:21:43 +000060 ErrorOr<ELFYAML::VerdefSection *> dumpVerdefSection(const Elf_Shdr *Shdr);
George Rimar646af082019-02-19 15:29:07 +000061 ErrorOr<ELFYAML::SymverSection *> dumpSymverSection(const Elf_Shdr *Shdr);
George Rimar0621b792019-02-19 14:53:48 +000062 ErrorOr<ELFYAML::VerneedSection *> dumpVerneedSection(const Elf_Shdr *Shdr);
Shankar Easwaran6fbbe202015-02-21 04:28:26 +000063 ErrorOr<ELFYAML::Group *> dumpGroup(const Elf_Shdr *Shdr);
Simon Atanasyan04d9e652015-05-07 15:40:48 +000064 ErrorOr<ELFYAML::MipsABIFlags *> dumpMipsABIFlags(const Elf_Shdr *Shdr);
Simon Atanasyanae6bb332014-05-14 05:07:47 +000065
66public:
67 ELFDumper(const object::ELFFile<ELFT> &O);
68 ErrorOr<ELFYAML::Object *> dump();
69};
70
71}
72
73template <class ELFT>
74ELFDumper<ELFT>::ELFDumper(const object::ELFFile<ELFT> &O)
75 : Obj(O) {}
76
77template <class ELFT>
Rafael Espindola88ee57e2017-09-05 22:30:00 +000078Expected<StringRef>
79ELFDumper<ELFT>::getUniquedSectionName(const Elf_Shdr *Sec) {
80 unsigned SecIndex = Sec - &Sections[0];
81 assert(&Sections[SecIndex] == Sec);
82 if (!SectionNames[SecIndex].empty())
83 return SectionNames[SecIndex];
84
85 auto NameOrErr = Obj.getSectionName(Sec);
86 if (!NameOrErr)
87 return NameOrErr;
88 StringRef Name = *NameOrErr;
Rafael Espindola8db11a42017-09-05 23:00:51 +000089 std::string &Ret = SectionNames[SecIndex];
90 Ret = Name;
Rafael Espindola88ee57e2017-09-05 22:30:00 +000091 while (!UsedSectionNames.insert(Ret).second)
92 Ret = (Name + to_string(++Suffix)).str();
Rafael Espindola8db11a42017-09-05 23:00:51 +000093 return Ret;
Rafael Espindola88ee57e2017-09-05 22:30:00 +000094}
95
Rafael Espindoladc8b7a92017-09-06 00:57:53 +000096template <class ELFT>
97Expected<StringRef> ELFDumper<ELFT>::getSymbolName(const Elf_Sym *Sym,
98 StringRef StrTable,
99 const Elf_Shdr *SymTab) {
100 Expected<StringRef> SymbolNameOrErr = Sym->getName(StrTable);
101 if (!SymbolNameOrErr)
102 return SymbolNameOrErr;
103 StringRef Name = *SymbolNameOrErr;
104 if (Name.empty() && Sym->getType() == ELF::STT_SECTION) {
105 auto ShdrOrErr = Obj.getSection(Sym, SymTab, ShndxTable);
106 if (!ShdrOrErr)
107 return ShdrOrErr.takeError();
108 return getUniquedSectionName(*ShdrOrErr);
109 }
110 return Name;
111}
112
Rafael Espindola88ee57e2017-09-05 22:30:00 +0000113template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000114 auto Y = make_unique<ELFYAML::Object>();
115
116 // Dump header
117 Y->Header.Class = ELFYAML::ELF_ELFCLASS(Obj.getHeader()->getFileClass());
118 Y->Header.Data = ELFYAML::ELF_ELFDATA(Obj.getHeader()->getDataEncoding());
119 Y->Header.OSABI = Obj.getHeader()->e_ident[ELF::EI_OSABI];
George Rimar6367d7a2018-12-20 10:43:49 +0000120 Y->Header.ABIVersion = Obj.getHeader()->e_ident[ELF::EI_ABIVERSION];
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000121 Y->Header.Type = Obj.getHeader()->e_type;
122 Y->Header.Machine = Obj.getHeader()->e_machine;
123 Y->Header.Flags = Obj.getHeader()->e_flags;
124 Y->Header.Entry = Obj.getHeader()->e_entry;
125
Rafael Espindola94515ab2015-08-10 14:27:50 +0000126 const Elf_Shdr *Symtab = nullptr;
Dave Lee67b49662017-11-16 18:10:15 +0000127 const Elf_Shdr *DynSymtab = nullptr;
Rafael Espindola94515ab2015-08-10 14:27:50 +0000128
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000129 // Dump sections
Rafael Espindola25be8c82016-11-02 14:10:57 +0000130 auto SectionsOrErr = Obj.sections();
Davide Italiano6cf09262016-11-16 05:10:28 +0000131 if (!SectionsOrErr)
132 return errorToErrorCode(SectionsOrErr.takeError());
Rafael Espindola88ee57e2017-09-05 22:30:00 +0000133 Sections = *SectionsOrErr;
134 SectionNames.resize(Sections.size());
135 for (const Elf_Shdr &Sec : Sections) {
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000136 switch (Sec.sh_type) {
George Rimar0e7ed912019-02-09 11:34:28 +0000137 case ELF::SHT_DYNAMIC: {
138 ErrorOr<ELFYAML::DynamicSection *> S = dumpDynamicSection(&Sec);
139 if (std::error_code EC = S.getError())
140 return EC;
141 Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
142 break;
143 }
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000144 case ELF::SHT_NULL:
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000145 case ELF::SHT_STRTAB:
146 // Do not dump these sections.
147 break;
Rafael Espindola94515ab2015-08-10 14:27:50 +0000148 case ELF::SHT_SYMTAB:
149 Symtab = &Sec;
150 break;
Dave Lee67b49662017-11-16 18:10:15 +0000151 case ELF::SHT_DYNSYM:
152 DynSymtab = &Sec;
153 break;
Rafael Espindolaaae55412015-08-10 21:29:35 +0000154 case ELF::SHT_SYMTAB_SHNDX: {
Davide Italiano6cf09262016-11-16 05:10:28 +0000155 auto TableOrErr = Obj.getSHNDXTable(Sec);
156 if (!TableOrErr)
157 return errorToErrorCode(TableOrErr.takeError());
Rafael Espindolaaae55412015-08-10 21:29:35 +0000158 ShndxTable = *TableOrErr;
159 break;
160 }
George Rimarafe8a042019-02-01 07:50:08 +0000161 case ELF::SHT_REL:
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000162 case ELF::SHT_RELA: {
George Rimarafe8a042019-02-01 07:50:08 +0000163 ErrorOr<ELFYAML::RelocationSection *> S = dumpRelocSection(&Sec);
Rafael Espindola4453e42942014-06-13 03:07:50 +0000164 if (std::error_code EC = S.getError())
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000165 return EC;
166 Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
167 break;
168 }
Shankar Easwaran6fbbe202015-02-21 04:28:26 +0000169 case ELF::SHT_GROUP: {
170 ErrorOr<ELFYAML::Group *> G = dumpGroup(&Sec);
171 if (std::error_code EC = G.getError())
172 return EC;
173 Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(G.get()));
174 break;
175 }
Simon Atanasyan04d9e652015-05-07 15:40:48 +0000176 case ELF::SHT_MIPS_ABIFLAGS: {
177 ErrorOr<ELFYAML::MipsABIFlags *> G = dumpMipsABIFlags(&Sec);
178 if (std::error_code EC = G.getError())
179 return EC;
180 Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(G.get()));
181 break;
182 }
Simon Atanasyan5db02762015-07-03 23:00:54 +0000183 case ELF::SHT_NOBITS: {
184 ErrorOr<ELFYAML::NoBitsSection *> S = dumpNoBitsSection(&Sec);
185 if (std::error_code EC = S.getError())
186 return EC;
187 Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
188 break;
189 }
George Rimar623ae722019-02-21 12:21:43 +0000190 case ELF::SHT_GNU_verdef: {
191 ErrorOr<ELFYAML::VerdefSection *> S = dumpVerdefSection(&Sec);
192 if (std::error_code EC = S.getError())
193 return EC;
194 Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
195 break;
196 }
George Rimar646af082019-02-19 15:29:07 +0000197 case ELF::SHT_GNU_versym: {
198 ErrorOr<ELFYAML::SymverSection *> S = dumpSymverSection(&Sec);
199 if (std::error_code EC = S.getError())
200 return EC;
201 Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
202 break;
203 }
George Rimar0621b792019-02-19 14:53:48 +0000204 case ELF::SHT_GNU_verneed: {
205 ErrorOr<ELFYAML::VerneedSection *> S = dumpVerneedSection(&Sec);
206 if (std::error_code EC = S.getError())
207 return EC;
208 Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
209 break;
210 }
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000211 default: {
212 ErrorOr<ELFYAML::RawContentSection *> S = dumpContentSection(&Sec);
Rafael Espindola4453e42942014-06-13 03:07:50 +0000213 if (std::error_code EC = S.getError())
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000214 return EC;
215 Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
216 }
217 }
218 }
219
Dave Lee67b49662017-11-16 18:10:15 +0000220 if (auto EC = dumpSymbols(Symtab, Y->Symbols))
221 return EC;
222 if (auto EC = dumpSymbols(DynSymtab, Y->DynamicSymbols))
223 return EC;
224
225 return Y.release();
226}
227
228template <class ELFT>
George Rimar41112992019-03-28 10:52:14 +0000229std::error_code ELFDumper<ELFT>::dumpSymbols(const Elf_Shdr *Symtab,
230 ELFYAML::SymbolsDef &Symbols) {
Alexander Richardsonc46750e2017-09-22 09:30:40 +0000231 if (!Symtab)
Dave Lee67b49662017-11-16 18:10:15 +0000232 return std::error_code();
233
Davide Italiano6cf09262016-11-16 05:10:28 +0000234 auto StrTableOrErr = Obj.getStringTableForSymtab(*Symtab);
235 if (!StrTableOrErr)
236 return errorToErrorCode(StrTableOrErr.takeError());
Rafael Espindolabd051012015-07-21 18:04:29 +0000237 StringRef StrTable = *StrTableOrErr;
238
Rafael Espindola9ea68342016-11-03 13:43:30 +0000239 auto SymtabOrErr = Obj.symbols(Symtab);
Davide Italiano6cf09262016-11-16 05:10:28 +0000240 if (!SymtabOrErr)
241 return errorToErrorCode(SymtabOrErr.takeError());
Dave Lee67b49662017-11-16 18:10:15 +0000242
243 bool IsFirstSym = true;
244 for (const auto &Sym : *SymtabOrErr) {
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000245 if (IsFirstSym) {
246 IsFirstSym = false;
247 continue;
248 }
249
250 ELFYAML::Symbol S;
Dave Lee67b49662017-11-16 18:10:15 +0000251 if (auto EC = dumpSymbol(&Sym, Symtab, StrTable, S))
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000252 return EC;
253
Dave Lee67b49662017-11-16 18:10:15 +0000254 switch (Sym.getBinding()) {
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000255 case ELF::STB_LOCAL:
Dave Lee67b49662017-11-16 18:10:15 +0000256 Symbols.Local.push_back(S);
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000257 break;
258 case ELF::STB_GLOBAL:
Dave Lee67b49662017-11-16 18:10:15 +0000259 Symbols.Global.push_back(S);
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000260 break;
261 case ELF::STB_WEAK:
Dave Lee67b49662017-11-16 18:10:15 +0000262 Symbols.Weak.push_back(S);
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000263 break;
George Rimar41112992019-03-28 10:52:14 +0000264 case ELF::STB_GNU_UNIQUE:
265 Symbols.GNUUnique.push_back(S);
266 break;
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000267 default:
268 llvm_unreachable("Unknown ELF symbol binding");
269 }
270 }
271
Dave Lee67b49662017-11-16 18:10:15 +0000272 return std::error_code();
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000273}
274
275template <class ELFT>
Rafael Espindolaaae55412015-08-10 21:29:35 +0000276std::error_code
277ELFDumper<ELFT>::dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
278 StringRef StrTable, ELFYAML::Symbol &S) {
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000279 S.Type = Sym->getType();
280 S.Value = Sym->st_value;
281 S.Size = Sym->st_size;
Simon Atanasyan60e1a792014-11-06 22:46:24 +0000282 S.Other = Sym->st_other;
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000283
Rafael Espindoladc8b7a92017-09-06 00:57:53 +0000284 Expected<StringRef> SymbolNameOrErr = getSymbolName(Sym, StrTable, SymTab);
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000285 if (!SymbolNameOrErr)
286 return errorToErrorCode(SymbolNameOrErr.takeError());
287 S.Name = SymbolNameOrErr.get();
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000288
George Rimar11358dd2019-02-22 08:45:21 +0000289 if (Sym->st_shndx >= ELF::SHN_LORESERVE) {
290 if (Sym->st_shndx == ELF::SHN_XINDEX)
291 return obj2yaml_error::not_implemented;
292 S.Index = (ELFYAML::ELF_SHN)Sym->st_shndx;
293 return obj2yaml_error::success;
294 }
295
Davide Italiano6cf09262016-11-16 05:10:28 +0000296 auto ShdrOrErr = Obj.getSection(Sym, SymTab, ShndxTable);
297 if (!ShdrOrErr)
298 return errorToErrorCode(ShdrOrErr.takeError());
Rafael Espindola6def3042015-07-01 12:56:27 +0000299 const Elf_Shdr *Shdr = *ShdrOrErr;
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000300 if (!Shdr)
301 return obj2yaml_error::success;
302
Rafael Espindola88ee57e2017-09-05 22:30:00 +0000303 auto NameOrErr = getUniquedSectionName(Shdr);
Davide Italiano6cf09262016-11-16 05:10:28 +0000304 if (!NameOrErr)
305 return errorToErrorCode(NameOrErr.takeError());
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000306 S.Section = NameOrErr.get();
307
308 return obj2yaml_error::success;
309}
310
311template <class ELFT>
312template <class RelT>
Rafael Espindola7d250f72015-09-02 15:07:39 +0000313std::error_code ELFDumper<ELFT>::dumpRelocation(const RelT *Rel,
314 const Elf_Shdr *SymTab,
Rafael Espindola4453e42942014-06-13 03:07:50 +0000315 ELFYAML::Relocation &R) {
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000316 R.Type = Rel->getType(Obj.isMips64EL());
317 R.Offset = Rel->r_offset;
318 R.Addend = 0;
319
Rafael Espindolaed1395a2016-11-03 18:05:33 +0000320 auto SymOrErr = Obj.getRelocationSymbol(Rel, SymTab);
Davide Italiano6cf09262016-11-16 05:10:28 +0000321 if (!SymOrErr)
322 return errorToErrorCode(SymOrErr.takeError());
Rafael Espindolaed1395a2016-11-03 18:05:33 +0000323 const Elf_Sym *Sym = *SymOrErr;
Davide Italiano6cf09262016-11-16 05:10:28 +0000324 auto StrTabSec = Obj.getSection(SymTab->sh_link);
325 if (!StrTabSec)
326 return errorToErrorCode(StrTabSec.takeError());
327 auto StrTabOrErr = Obj.getStringTable(*StrTabSec);
328 if (!StrTabOrErr)
329 return errorToErrorCode(StrTabOrErr.takeError());
Rafael Espindola6a1bfb22015-06-29 14:39:25 +0000330 StringRef StrTab = *StrTabOrErr;
Rafael Espindola719dc7c2015-06-29 12:38:31 +0000331
Davide Italiano44f12812017-01-26 23:12:53 +0000332 if (Sym) {
Rafael Espindoladc8b7a92017-09-06 00:57:53 +0000333 Expected<StringRef> NameOrErr = getSymbolName(Sym, StrTab, SymTab);
Davide Italiano44f12812017-01-26 23:12:53 +0000334 if (!NameOrErr)
335 return errorToErrorCode(NameOrErr.takeError());
336 R.Symbol = NameOrErr.get();
337 } else {
338 // We have some edge cases of relocations without a symbol associated,
339 // e.g. an object containing the invalid (according to the System V
340 // ABI) R_X86_64_NONE reloc. Create a symbol with an empty name instead
341 // of crashing.
342 R.Symbol = "";
343 }
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000344
345 return obj2yaml_error::success;
346}
347
348template <class ELFT>
Rafael Espindola4453e42942014-06-13 03:07:50 +0000349std::error_code ELFDumper<ELFT>::dumpCommonSection(const Elf_Shdr *Shdr,
350 ELFYAML::Section &S) {
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000351 S.Type = Shdr->sh_type;
352 S.Flags = Shdr->sh_flags;
353 S.Address = Shdr->sh_addr;
354 S.AddressAlign = Shdr->sh_addralign;
George Rimar31684962019-01-28 15:05:10 +0000355 if (Shdr->sh_entsize)
356 S.EntSize = static_cast<llvm::yaml::Hex64>(Shdr->sh_entsize);
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000357
Rafael Espindola88ee57e2017-09-05 22:30:00 +0000358 auto NameOrErr = getUniquedSectionName(Shdr);
Davide Italiano6cf09262016-11-16 05:10:28 +0000359 if (!NameOrErr)
360 return errorToErrorCode(NameOrErr.takeError());
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000361 S.Name = NameOrErr.get();
362
363 if (Shdr->sh_link != ELF::SHN_UNDEF) {
Davide Italiano6cf09262016-11-16 05:10:28 +0000364 auto LinkSection = Obj.getSection(Shdr->sh_link);
365 if (LinkSection.takeError())
366 return errorToErrorCode(LinkSection.takeError());
Rafael Espindola88ee57e2017-09-05 22:30:00 +0000367 NameOrErr = getUniquedSectionName(*LinkSection);
Davide Italiano6cf09262016-11-16 05:10:28 +0000368 if (!NameOrErr)
369 return errorToErrorCode(NameOrErr.takeError());
Rafael Espindola6def3042015-07-01 12:56:27 +0000370 S.Link = NameOrErr.get();
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000371 }
Simon Atanasyan87459932014-05-29 11:05:31 +0000372
373 return obj2yaml_error::success;
374}
375
376template <class ELFT>
Rafael Espindola4453e42942014-06-13 03:07:50 +0000377std::error_code
Simon Atanasyan87459932014-05-29 11:05:31 +0000378ELFDumper<ELFT>::dumpCommonRelocationSection(const Elf_Shdr *Shdr,
379 ELFYAML::RelocationSection &S) {
Rafael Espindola4453e42942014-06-13 03:07:50 +0000380 if (std::error_code EC = dumpCommonSection(Shdr, S))
Simon Atanasyan87459932014-05-29 11:05:31 +0000381 return EC;
382
Davide Italiano6cf09262016-11-16 05:10:28 +0000383 auto InfoSection = Obj.getSection(Shdr->sh_info);
384 if (!InfoSection)
385 return errorToErrorCode(InfoSection.takeError());
Rafael Espindola6def3042015-07-01 12:56:27 +0000386
Rafael Espindola88ee57e2017-09-05 22:30:00 +0000387 auto NameOrErr = getUniquedSectionName(*InfoSection);
Davide Italiano6cf09262016-11-16 05:10:28 +0000388 if (!NameOrErr)
389 return errorToErrorCode(NameOrErr.takeError());
George Rimarb87ea732019-02-12 09:08:59 +0000390 S.RelocatableSec = NameOrErr.get();
Simon Atanasyan87459932014-05-29 11:05:31 +0000391
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000392 return obj2yaml_error::success;
393}
394
395template <class ELFT>
George Rimar0e7ed912019-02-09 11:34:28 +0000396ErrorOr<ELFYAML::DynamicSection *>
397ELFDumper<ELFT>::dumpDynamicSection(const Elf_Shdr *Shdr) {
398 auto S = make_unique<ELFYAML::DynamicSection>();
399 if (std::error_code EC = dumpCommonSection(Shdr, *S))
400 return EC;
401
402 auto DynTagsOrErr = Obj.template getSectionContentsAsArray<Elf_Dyn>(Shdr);
403 if (!DynTagsOrErr)
404 return errorToErrorCode(DynTagsOrErr.takeError());
405
406 for (const Elf_Dyn &Dyn : *DynTagsOrErr)
407 S->Entries.push_back({(ELFYAML::ELF_DYNTAG)Dyn.getTag(), Dyn.getVal()});
408
409 return S.release();
410}
411
412template <class ELFT>
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000413ErrorOr<ELFYAML::RelocationSection *>
George Rimarafe8a042019-02-01 07:50:08 +0000414ELFDumper<ELFT>::dumpRelocSection(const Elf_Shdr *Shdr) {
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000415 auto S = make_unique<ELFYAML::RelocationSection>();
Rafael Espindola4453e42942014-06-13 03:07:50 +0000416 if (std::error_code EC = dumpCommonRelocationSection(Shdr, *S))
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000417 return EC;
418
Davide Italiano6cf09262016-11-16 05:10:28 +0000419 auto SymTabOrErr = Obj.getSection(Shdr->sh_link);
420 if (!SymTabOrErr)
421 return errorToErrorCode(SymTabOrErr.takeError());
Rafael Espindola7d250f72015-09-02 15:07:39 +0000422 const Elf_Shdr *SymTab = *SymTabOrErr;
423
George Rimarafe8a042019-02-01 07:50:08 +0000424 if (Shdr->sh_type == ELF::SHT_REL) {
425 auto Rels = Obj.rels(Shdr);
426 if (!Rels)
427 return errorToErrorCode(Rels.takeError());
428 for (const Elf_Rel &Rel : *Rels) {
429 ELFYAML::Relocation R;
430 if (std::error_code EC = dumpRelocation(&Rel, SymTab, R))
431 return EC;
432 S->Relocations.push_back(R);
433 }
434 } else {
435 auto Rels = Obj.relas(Shdr);
436 if (!Rels)
437 return errorToErrorCode(Rels.takeError());
438 for (const Elf_Rela &Rel : *Rels) {
439 ELFYAML::Relocation R;
440 if (std::error_code EC = dumpRelocation(&Rel, SymTab, R))
441 return EC;
442 R.Addend = Rel.r_addend;
443 S->Relocations.push_back(R);
444 }
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000445 }
446
447 return S.release();
448}
449
450template <class ELFT>
451ErrorOr<ELFYAML::RawContentSection *>
452ELFDumper<ELFT>::dumpContentSection(const Elf_Shdr *Shdr) {
453 auto S = make_unique<ELFYAML::RawContentSection>();
454
Rafael Espindola4453e42942014-06-13 03:07:50 +0000455 if (std::error_code EC = dumpCommonSection(Shdr, *S))
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000456 return EC;
457
Davide Italiano6cf09262016-11-16 05:10:28 +0000458 auto ContentOrErr = Obj.getSectionContents(Shdr);
459 if (!ContentOrErr)
460 return errorToErrorCode(ContentOrErr.takeError());
Rafael Espindola97de4742014-07-03 02:01:39 +0000461 S->Content = yaml::BinaryRef(ContentOrErr.get());
Simon Atanasyanb83f3802014-05-16 16:01:00 +0000462 S->Size = S->Content.binary_size();
George Rimara7ba1a02019-03-01 10:18:16 +0000463 S->Info = Shdr->sh_info;
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000464
465 return S.release();
466}
467
468template <class ELFT>
Simon Atanasyan5db02762015-07-03 23:00:54 +0000469ErrorOr<ELFYAML::NoBitsSection *>
470ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) {
471 auto S = make_unique<ELFYAML::NoBitsSection>();
472
473 if (std::error_code EC = dumpCommonSection(Shdr, *S))
474 return EC;
475 S->Size = Shdr->sh_size;
476
477 return S.release();
478}
479
480template <class ELFT>
George Rimar623ae722019-02-21 12:21:43 +0000481ErrorOr<ELFYAML::VerdefSection *>
482ELFDumper<ELFT>::dumpVerdefSection(const Elf_Shdr *Shdr) {
483 typedef typename ELFT::Verdef Elf_Verdef;
484 typedef typename ELFT::Verdaux Elf_Verdaux;
485
486 auto S = make_unique<ELFYAML::VerdefSection>();
487 if (std::error_code EC = dumpCommonSection(Shdr, *S))
488 return EC;
489
490 S->Info = Shdr->sh_info;
491
492 auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link);
493 if (!StringTableShdrOrErr)
494 return errorToErrorCode(StringTableShdrOrErr.takeError());
495
496 auto StringTableOrErr = Obj.getStringTable(*StringTableShdrOrErr);
497 if (!StringTableOrErr)
498 return errorToErrorCode(StringTableOrErr.takeError());
499
500 auto Contents = Obj.getSectionContents(Shdr);
501 if (!Contents)
502 return errorToErrorCode(Contents.takeError());
503
504 llvm::ArrayRef<uint8_t> Data = *Contents;
505 const uint8_t *Buf = Data.data();
506 while (Buf) {
507 const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(Buf);
508 ELFYAML::VerdefEntry Entry;
509 Entry.Version = Verdef->vd_version;
510 Entry.Flags = Verdef->vd_flags;
511 Entry.VersionNdx = Verdef->vd_ndx;
512 Entry.Hash = Verdef->vd_hash;
513
514 const uint8_t *BufAux = Buf + Verdef->vd_aux;
515 while (BufAux) {
516 const Elf_Verdaux *Verdaux =
517 reinterpret_cast<const Elf_Verdaux *>(BufAux);
518 Entry.VerNames.push_back(
519 StringTableOrErr->drop_front(Verdaux->vda_name).data());
520 BufAux = Verdaux->vda_next ? BufAux + Verdaux->vda_next : nullptr;
521 }
522
523 S->Entries.push_back(Entry);
524 Buf = Verdef->vd_next ? Buf + Verdef->vd_next : nullptr;
525 }
526
527 return S.release();
528}
529
530template <class ELFT>
George Rimar646af082019-02-19 15:29:07 +0000531ErrorOr<ELFYAML::SymverSection *>
532ELFDumper<ELFT>::dumpSymverSection(const Elf_Shdr *Shdr) {
533 typedef typename ELFT::Half Elf_Half;
534
535 auto S = make_unique<ELFYAML::SymverSection>();
536 if (std::error_code EC = dumpCommonSection(Shdr, *S))
537 return EC;
538
539 auto VersionsOrErr = Obj.template getSectionContentsAsArray<Elf_Half>(Shdr);
540 if (!VersionsOrErr)
541 return errorToErrorCode(VersionsOrErr.takeError());
542 for (const Elf_Half &E : *VersionsOrErr)
543 S->Entries.push_back(E);
544
545 return S.release();
546}
547
548template <class ELFT>
George Rimar0621b792019-02-19 14:53:48 +0000549ErrorOr<ELFYAML::VerneedSection *>
550ELFDumper<ELFT>::dumpVerneedSection(const Elf_Shdr *Shdr) {
551 typedef typename ELFT::Verneed Elf_Verneed;
552 typedef typename ELFT::Vernaux Elf_Vernaux;
553
554 auto S = make_unique<ELFYAML::VerneedSection>();
555 if (std::error_code EC = dumpCommonSection(Shdr, *S))
556 return EC;
557
558 S->Info = Shdr->sh_info;
559
560 auto Contents = Obj.getSectionContents(Shdr);
561 if (!Contents)
562 return errorToErrorCode(Contents.takeError());
563
564 auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link);
565 if (!StringTableShdrOrErr)
566 return errorToErrorCode(StringTableShdrOrErr.takeError());
567
568 auto StringTableOrErr = Obj.getStringTable(*StringTableShdrOrErr);
569 if (!StringTableOrErr)
570 return errorToErrorCode(StringTableOrErr.takeError());
571
572 llvm::ArrayRef<uint8_t> Data = *Contents;
573 const uint8_t *Buf = Data.data();
574 while (Buf) {
575 const Elf_Verneed *Verneed = reinterpret_cast<const Elf_Verneed *>(Buf);
576
577 ELFYAML::VerneedEntry Entry;
578 Entry.Version = Verneed->vn_version;
579 Entry.File =
580 StringRef(StringTableOrErr->drop_front(Verneed->vn_file).data());
581
582 const uint8_t *BufAux = Buf + Verneed->vn_aux;
583 while (BufAux) {
584 const Elf_Vernaux *Vernaux =
585 reinterpret_cast<const Elf_Vernaux *>(BufAux);
586
587 ELFYAML::VernauxEntry Aux;
588 Aux.Hash = Vernaux->vna_hash;
589 Aux.Flags = Vernaux->vna_flags;
590 Aux.Other = Vernaux->vna_other;
591 Aux.Name =
592 StringRef(StringTableOrErr->drop_front(Vernaux->vna_name).data());
593
594 Entry.AuxV.push_back(Aux);
595 BufAux = Vernaux->vna_next ? BufAux + Vernaux->vna_next : nullptr;
596 }
597
598 S->VerneedV.push_back(Entry);
599 Buf = Verneed->vn_next ? Buf + Verneed->vn_next : nullptr;
600 }
601
602 return S.release();
603}
604
605template <class ELFT>
Shankar Easwaran6fbbe202015-02-21 04:28:26 +0000606ErrorOr<ELFYAML::Group *> ELFDumper<ELFT>::dumpGroup(const Elf_Shdr *Shdr) {
607 auto S = make_unique<ELFYAML::Group>();
608
609 if (std::error_code EC = dumpCommonSection(Shdr, *S))
610 return EC;
611 // Get sh_info which is the signature.
Davide Italiano6cf09262016-11-16 05:10:28 +0000612 auto SymtabOrErr = Obj.getSection(Shdr->sh_link);
613 if (!SymtabOrErr)
614 return errorToErrorCode(SymtabOrErr.takeError());
Rafael Espindola651ed6c2015-07-23 12:49:40 +0000615 const Elf_Shdr *Symtab = *SymtabOrErr;
Davide Italiano6cf09262016-11-16 05:10:28 +0000616 auto SymOrErr = Obj.getSymbol(Symtab, Shdr->sh_info);
617 if (!SymOrErr)
618 return errorToErrorCode(SymOrErr.takeError());
George Rimar02334f62016-11-03 08:41:46 +0000619 const Elf_Sym *symbol = *SymOrErr;
Davide Italiano6cf09262016-11-16 05:10:28 +0000620 auto StrTabOrErr = Obj.getStringTableForSymtab(*Symtab);
621 if (!StrTabOrErr)
622 return errorToErrorCode(StrTabOrErr.takeError());
Rafael Espindola6a1bfb22015-06-29 14:39:25 +0000623 StringRef StrTab = *StrTabOrErr;
Shankar Easwaran6fbbe202015-02-21 04:28:26 +0000624 auto sectionContents = Obj.getSectionContents(Shdr);
Davide Italiano6cf09262016-11-16 05:10:28 +0000625 if (!sectionContents)
626 return errorToErrorCode(sectionContents.takeError());
Rafael Espindoladc8b7a92017-09-06 00:57:53 +0000627 Expected<StringRef> symbolName = getSymbolName(symbol, StrTab, Symtab);
Kevin Enderby81e8b7d2016-04-20 21:24:34 +0000628 if (!symbolName)
629 return errorToErrorCode(symbolName.takeError());
George Rimarb87ea732019-02-12 09:08:59 +0000630 S->Signature = *symbolName;
Shankar Easwaran6fbbe202015-02-21 04:28:26 +0000631 const Elf_Word *groupMembers =
632 reinterpret_cast<const Elf_Word *>(sectionContents->data());
633 const long count = (Shdr->sh_size) / sizeof(Elf_Word);
634 ELFYAML::SectionOrType s;
635 for (int i = 0; i < count; i++) {
636 if (groupMembers[i] == llvm::ELF::GRP_COMDAT) {
637 s.sectionNameOrType = "GRP_COMDAT";
638 } else {
Davide Italiano6cf09262016-11-16 05:10:28 +0000639 auto sHdr = Obj.getSection(groupMembers[i]);
640 if (!sHdr)
641 return errorToErrorCode(sHdr.takeError());
Rafael Espindola88ee57e2017-09-05 22:30:00 +0000642 auto sectionName = getUniquedSectionName(*sHdr);
Davide Italiano6cf09262016-11-16 05:10:28 +0000643 if (!sectionName)
644 return errorToErrorCode(sectionName.takeError());
Shankar Easwaran6fbbe202015-02-21 04:28:26 +0000645 s.sectionNameOrType = *sectionName;
646 }
647 S->Members.push_back(s);
648 }
649 return S.release();
650}
651
652template <class ELFT>
Simon Atanasyan04d9e652015-05-07 15:40:48 +0000653ErrorOr<ELFYAML::MipsABIFlags *>
654ELFDumper<ELFT>::dumpMipsABIFlags(const Elf_Shdr *Shdr) {
655 assert(Shdr->sh_type == ELF::SHT_MIPS_ABIFLAGS &&
656 "Section type is not SHT_MIPS_ABIFLAGS");
657 auto S = make_unique<ELFYAML::MipsABIFlags>();
658 if (std::error_code EC = dumpCommonSection(Shdr, *S))
659 return EC;
660
Davide Italiano6cf09262016-11-16 05:10:28 +0000661 auto ContentOrErr = Obj.getSectionContents(Shdr);
662 if (!ContentOrErr)
663 return errorToErrorCode(ContentOrErr.takeError());
Simon Atanasyan04d9e652015-05-07 15:40:48 +0000664
665 auto *Flags = reinterpret_cast<const object::Elf_Mips_ABIFlags<ELFT> *>(
666 ContentOrErr.get().data());
667 S->Version = Flags->version;
668 S->ISALevel = Flags->isa_level;
669 S->ISARevision = Flags->isa_rev;
670 S->GPRSize = Flags->gpr_size;
671 S->CPR1Size = Flags->cpr1_size;
672 S->CPR2Size = Flags->cpr2_size;
673 S->FpABI = Flags->fp_abi;
674 S->ISAExtension = Flags->isa_ext;
675 S->ASEs = Flags->ases;
676 S->Flags1 = Flags->flags1;
677 S->Flags2 = Flags->flags2;
678 return S.release();
679}
680
681template <class ELFT>
Rafael Espindola4453e42942014-06-13 03:07:50 +0000682static std::error_code elf2yaml(raw_ostream &Out,
683 const object::ELFFile<ELFT> &Obj) {
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000684 ELFDumper<ELFT> Dumper(Obj);
685 ErrorOr<ELFYAML::Object *> YAMLOrErr = Dumper.dump();
Rafael Espindola4453e42942014-06-13 03:07:50 +0000686 if (std::error_code EC = YAMLOrErr.getError())
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000687 return EC;
688
689 std::unique_ptr<ELFYAML::Object> YAML(YAMLOrErr.get());
690 yaml::Output Yout(Out);
691 Yout << *YAML;
692
Rui Ueyama7d099192015-06-09 15:20:42 +0000693 return std::error_code();
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000694}
695
Rafael Espindola4453e42942014-06-13 03:07:50 +0000696std::error_code elf2yaml(raw_ostream &Out, const object::ObjectFile &Obj) {
Simon Atanasyanae6bb332014-05-14 05:07:47 +0000697 if (const auto *ELFObj = dyn_cast<object::ELF32LEObjectFile>(&Obj))
698 return elf2yaml(Out, *ELFObj->getELFFile());
699
700 if (const auto *ELFObj = dyn_cast<object::ELF32BEObjectFile>(&Obj))
701 return elf2yaml(Out, *ELFObj->getELFFile());
702
703 if (const auto *ELFObj = dyn_cast<object::ELF64LEObjectFile>(&Obj))
704 return elf2yaml(Out, *ELFObj->getELFFile());
705
706 if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(&Obj))
707 return elf2yaml(Out, *ELFObj->getELFFile());
708
709 return obj2yaml_error::unsupported_obj_file_format;
710}