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