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