OSDN Git Service

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