[PowerPC] Add future work for vector insert/extract to README_ALTIVEC.txt
[oota-llvm.git] / tools / obj2yaml / elf2yaml.cpp
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_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
45 public:
46   ELFDumper(const object::ELFFile<ELFT> &O);
47   ErrorOr<ELFYAML::Object *> dump();
48 };
49
50 }
51
52 template <class ELFT>
53 ELFDumper<ELFT>::ELFDumper(const object::ELFFile<ELFT> &O)
54     : Obj(O) {}
55
56 template <class ELFT>
57 ErrorOr<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
139 template <class ELFT>
140 std::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
164 template <class ELFT>
165 template <class RelT>
166 std::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
186 template <class ELFT>
187 std::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
211 template <class ELFT>
212 std::error_code
213 ELFDumper<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
228 template <class ELFT>
229 ErrorOr<ELFYAML::RelocationSection *>
230 ELFDumper<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
248 template <class ELFT>
249 ErrorOr<ELFYAML::RelocationSection *>
250 ELFDumper<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
269 template <class ELFT>
270 ErrorOr<ELFYAML::RawContentSection *>
271 ELFDumper<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
286 template <class ELFT>
287 ErrorOr<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
321 template <class ELFT>
322 static 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
336 std::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 }