Don't use 'using std::error_code' in include/llvm.
[oota-llvm.git] / tools / obj2yaml / coff2yaml.cpp
1 //===------ utils/obj2yaml.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 "obj2yaml.h"
11 #include "llvm/Object/COFF.h"
12 #include "llvm/Object/COFFYAML.h"
13 #include "llvm/Support/ErrorHandling.h"
14 #include "llvm/Support/YAMLTraits.h"
15
16 using namespace llvm;
17 using std::error_code;
18
19 namespace {
20
21 class COFFDumper {
22   const object::COFFObjectFile &Obj;
23   COFFYAML::Object YAMLObj;
24   void dumpHeader(const object::coff_file_header *Header);
25   void dumpSections(unsigned numSections);
26   void dumpSymbols(unsigned numSymbols);
27
28 public:
29   COFFDumper(const object::COFFObjectFile &Obj);
30   COFFYAML::Object &getYAMLObj();
31 };
32
33 }
34
35 static void check(error_code ec) {
36   if (ec)
37     report_fatal_error(ec.message());
38 }
39
40 COFFDumper::COFFDumper(const object::COFFObjectFile &Obj) : Obj(Obj) {
41   const object::coff_file_header *Header;
42   check(Obj.getCOFFHeader(Header));
43   dumpHeader(Header);
44   dumpSections(Header->NumberOfSections);
45   dumpSymbols(Header->NumberOfSymbols);
46 }
47
48 void COFFDumper::dumpHeader(const object::coff_file_header *Header) {
49   YAMLObj.Header.Machine = Header->Machine;
50   YAMLObj.Header.Characteristics = Header->Characteristics;
51 }
52
53 void COFFDumper::dumpSections(unsigned NumSections) {
54   std::vector<COFFYAML::Section> &Sections = YAMLObj.Sections;
55   for (const auto &Section : Obj.sections()) {
56     const object::coff_section *Sect = Obj.getCOFFSection(Section);
57     COFFYAML::Section Sec;
58     Sec.Name = Sect->Name; // FIXME: check the null termination!
59     uint32_t Characteristics = Sect->Characteristics;
60     Sec.Header.Characteristics = Characteristics;
61     Sec.Alignment = 1 << (((Characteristics >> 20) & 0xf) - 1);
62
63     ArrayRef<uint8_t> sectionData;
64     Obj.getSectionContents(Sect, sectionData);
65     Sec.SectionData = object::yaml::BinaryRef(sectionData);
66
67     std::vector<COFFYAML::Relocation> Relocations;
68     for (const auto &Reloc : Section.relocations()) {
69       const object::coff_relocation *reloc = Obj.getCOFFRelocation(Reloc);
70       COFFYAML::Relocation Rel;
71       object::symbol_iterator Sym = Reloc.getSymbol();
72       Sym->getName(Rel.SymbolName);
73       Rel.VirtualAddress = reloc->VirtualAddress;
74       Rel.Type = reloc->Type;
75       Relocations.push_back(Rel);
76     }
77     Sec.Relocations = Relocations;
78     Sections.push_back(Sec);
79   }
80 }
81
82 static void
83 dumpFunctionDefinition(COFFYAML::Symbol *Sym,
84                        const object::coff_aux_function_definition *ObjFD) {
85   COFF::AuxiliaryFunctionDefinition YAMLFD;
86   YAMLFD.TagIndex = ObjFD->TagIndex;
87   YAMLFD.TotalSize = ObjFD->TotalSize;
88   YAMLFD.PointerToLinenumber = ObjFD->PointerToLinenumber;
89   YAMLFD.PointerToNextFunction = ObjFD->PointerToNextFunction;
90
91   Sym->FunctionDefinition = YAMLFD;
92 }
93
94 static void
95 dumpbfAndEfLineInfo(COFFYAML::Symbol *Sym,
96                     const object::coff_aux_bf_and_ef_symbol *ObjBES) {
97   COFF::AuxiliarybfAndefSymbol YAMLAAS;
98   YAMLAAS.Linenumber = ObjBES->Linenumber;
99   YAMLAAS.PointerToNextFunction = ObjBES->PointerToNextFunction;
100
101   Sym->bfAndefSymbol = YAMLAAS;
102 }
103
104 static void dumpWeakExternal(COFFYAML::Symbol *Sym,
105                              const object::coff_aux_weak_external *ObjWE) {
106   COFF::AuxiliaryWeakExternal YAMLWE;
107   YAMLWE.TagIndex = ObjWE->TagIndex;
108   YAMLWE.Characteristics = ObjWE->Characteristics;
109
110   Sym->WeakExternal = YAMLWE;
111 }
112
113 static void
114 dumpSectionDefinition(COFFYAML::Symbol *Sym,
115                       const object::coff_aux_section_definition *ObjSD) {
116   COFF::AuxiliarySectionDefinition YAMLASD;
117   YAMLASD.Length = ObjSD->Length;
118   YAMLASD.NumberOfRelocations = ObjSD->NumberOfRelocations;
119   YAMLASD.NumberOfLinenumbers = ObjSD->NumberOfLinenumbers;
120   YAMLASD.CheckSum = ObjSD->CheckSum;
121   YAMLASD.Number = ObjSD->Number;
122   YAMLASD.Selection = ObjSD->Selection;
123
124   Sym->SectionDefinition = YAMLASD;
125 }
126
127 static void
128 dumpCLRTokenDefinition(COFFYAML::Symbol *Sym,
129                        const object::coff_aux_clr_token *ObjCLRToken) {
130   COFF::AuxiliaryCLRToken YAMLCLRToken;
131   YAMLCLRToken.AuxType = ObjCLRToken->AuxType;
132   YAMLCLRToken.SymbolTableIndex = ObjCLRToken->SymbolTableIndex;
133
134   Sym->CLRToken = YAMLCLRToken;
135 }
136
137 void COFFDumper::dumpSymbols(unsigned NumSymbols) {
138   std::vector<COFFYAML::Symbol> &Symbols = YAMLObj.Symbols;
139   for (const auto &S : Obj.symbols()) {
140     const object::coff_symbol *Symbol = Obj.getCOFFSymbol(S);
141     COFFYAML::Symbol Sym;
142     Obj.getSymbolName(Symbol, Sym.Name);
143     Sym.SimpleType = COFF::SymbolBaseType(Symbol->getBaseType());
144     Sym.ComplexType = COFF::SymbolComplexType(Symbol->getComplexType());
145     Sym.Header.StorageClass = Symbol->StorageClass;
146     Sym.Header.Value = Symbol->Value;
147     Sym.Header.SectionNumber = Symbol->SectionNumber;
148     Sym.Header.NumberOfAuxSymbols = Symbol->NumberOfAuxSymbols;
149
150     if (Symbol->NumberOfAuxSymbols > 0) {
151       ArrayRef<uint8_t> AuxData = Obj.getSymbolAuxData(Symbol);
152       if (Symbol->isFunctionDefinition()) {
153         // This symbol represents a function definition.
154         assert(Symbol->NumberOfAuxSymbols == 1 &&
155                "Expected a single aux symbol to describe this function!");
156
157         const object::coff_aux_function_definition *ObjFD =
158             reinterpret_cast<const object::coff_aux_function_definition *>(
159                 AuxData.data());
160         dumpFunctionDefinition(&Sym, ObjFD);
161       } else if (Symbol->isFunctionLineInfo()) {
162         // This symbol describes function line number information.
163         assert(Symbol->NumberOfAuxSymbols == 1 &&
164                "Exepected a single aux symbol to describe this section!");
165
166         const object::coff_aux_bf_and_ef_symbol *ObjBES =
167             reinterpret_cast<const object::coff_aux_bf_and_ef_symbol *>(
168                 AuxData.data());
169         dumpbfAndEfLineInfo(&Sym, ObjBES);
170       } else if (Symbol->isWeakExternal()) {
171         // This symbol represents a weak external definition.
172         assert(Symbol->NumberOfAuxSymbols == 1 &&
173                "Exepected a single aux symbol to describe this section!");
174
175         const object::coff_aux_weak_external *ObjWE =
176             reinterpret_cast<const object::coff_aux_weak_external *>(
177                 AuxData.data());
178         dumpWeakExternal(&Sym, ObjWE);
179       } else if (Symbol->isFileRecord()) {
180         // This symbol represents a file record.
181         Sym.File = StringRef(reinterpret_cast<const char *>(AuxData.data()),
182                              Symbol->NumberOfAuxSymbols * COFF::SymbolSize)
183                        .rtrim(StringRef("\0", /*length=*/1));
184       } else if (Symbol->isSectionDefinition()) {
185         // This symbol represents a section definition.
186         assert(Symbol->NumberOfAuxSymbols == 1 &&
187                "Expected a single aux symbol to describe this section!");
188
189         const object::coff_aux_section_definition *ObjSD =
190             reinterpret_cast<const object::coff_aux_section_definition *>(
191                 AuxData.data());
192         dumpSectionDefinition(&Sym, ObjSD);
193       } else if (Symbol->isCLRToken()) {
194         // This symbol represents a CLR token definition.
195         assert(Symbol->NumberOfAuxSymbols == 1 &&
196                "Expected a single aux symbol to describe this CLR Token");
197
198         const object::coff_aux_clr_token *ObjCLRToken =
199             reinterpret_cast<const object::coff_aux_clr_token *>(
200                 AuxData.data());
201         dumpCLRTokenDefinition(&Sym, ObjCLRToken);
202       } else {
203         llvm_unreachable("Unhandled auxiliary symbol!");
204       }
205     }
206     Symbols.push_back(Sym);
207   }
208 }
209
210 COFFYAML::Object &COFFDumper::getYAMLObj() {
211   return YAMLObj;
212 }
213
214 error_code coff2yaml(raw_ostream &Out, const object::COFFObjectFile &Obj) {
215   COFFDumper Dumper(Obj);
216
217   yaml::Output Yout(Out);
218   Yout << Dumper.getYAMLObj();
219
220   return object::object_error::success;
221 }