coff2yaml.cpp revision 9e39d0bc2092f97c531591737af8abda48211169
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
13using namespace llvm;
14
15template <typename One, typename Two>
16struct pod_pair { // I'd much rather use std::pair, but it's not a POD
17  One first;
18  Two second;
19};
20
21#define STRING_PAIR(x)  {COFF::x, #x}
22static const pod_pair<COFF::MachineTypes, const char *>
23MachineTypePairs [] = {
24  STRING_PAIR(IMAGE_FILE_MACHINE_UNKNOWN),
25  STRING_PAIR(IMAGE_FILE_MACHINE_AM33),
26  STRING_PAIR(IMAGE_FILE_MACHINE_AMD64),
27  STRING_PAIR(IMAGE_FILE_MACHINE_ARM),
28  STRING_PAIR(IMAGE_FILE_MACHINE_ARMV7),
29  STRING_PAIR(IMAGE_FILE_MACHINE_EBC),
30  STRING_PAIR(IMAGE_FILE_MACHINE_I386),
31  STRING_PAIR(IMAGE_FILE_MACHINE_IA64),
32  STRING_PAIR(IMAGE_FILE_MACHINE_M32R),
33  STRING_PAIR(IMAGE_FILE_MACHINE_MIPS16),
34  STRING_PAIR(IMAGE_FILE_MACHINE_MIPSFPU),
35  STRING_PAIR(IMAGE_FILE_MACHINE_MIPSFPU16),
36  STRING_PAIR(IMAGE_FILE_MACHINE_POWERPC),
37  STRING_PAIR(IMAGE_FILE_MACHINE_POWERPCFP),
38  STRING_PAIR(IMAGE_FILE_MACHINE_R4000),
39  STRING_PAIR(IMAGE_FILE_MACHINE_SH3),
40  STRING_PAIR(IMAGE_FILE_MACHINE_SH3DSP),
41  STRING_PAIR(IMAGE_FILE_MACHINE_SH4),
42  STRING_PAIR(IMAGE_FILE_MACHINE_SH5),
43  STRING_PAIR(IMAGE_FILE_MACHINE_THUMB),
44  STRING_PAIR(IMAGE_FILE_MACHINE_WCEMIPSV2)
45};
46
47static const pod_pair<COFF::SectionCharacteristics, const char *>
48SectionCharacteristicsPairs1 [] = {
49  STRING_PAIR(IMAGE_SCN_TYPE_NO_PAD),
50  STRING_PAIR(IMAGE_SCN_CNT_CODE),
51  STRING_PAIR(IMAGE_SCN_CNT_INITIALIZED_DATA),
52  STRING_PAIR(IMAGE_SCN_CNT_UNINITIALIZED_DATA),
53  STRING_PAIR(IMAGE_SCN_LNK_OTHER),
54  STRING_PAIR(IMAGE_SCN_LNK_INFO),
55  STRING_PAIR(IMAGE_SCN_LNK_REMOVE),
56  STRING_PAIR(IMAGE_SCN_LNK_COMDAT),
57  STRING_PAIR(IMAGE_SCN_GPREL),
58  STRING_PAIR(IMAGE_SCN_MEM_PURGEABLE),
59  STRING_PAIR(IMAGE_SCN_MEM_16BIT),
60  STRING_PAIR(IMAGE_SCN_MEM_LOCKED),
61  STRING_PAIR(IMAGE_SCN_MEM_PRELOAD)
62};
63
64static const pod_pair<COFF::SectionCharacteristics, const char *>
65SectionCharacteristicsPairsAlignment [] = {
66  STRING_PAIR(IMAGE_SCN_ALIGN_1BYTES),
67  STRING_PAIR(IMAGE_SCN_ALIGN_2BYTES),
68  STRING_PAIR(IMAGE_SCN_ALIGN_4BYTES),
69  STRING_PAIR(IMAGE_SCN_ALIGN_8BYTES),
70  STRING_PAIR(IMAGE_SCN_ALIGN_16BYTES),
71  STRING_PAIR(IMAGE_SCN_ALIGN_32BYTES),
72  STRING_PAIR(IMAGE_SCN_ALIGN_64BYTES),
73  STRING_PAIR(IMAGE_SCN_ALIGN_128BYTES),
74  STRING_PAIR(IMAGE_SCN_ALIGN_256BYTES),
75  STRING_PAIR(IMAGE_SCN_ALIGN_512BYTES),
76  STRING_PAIR(IMAGE_SCN_ALIGN_1024BYTES),
77  STRING_PAIR(IMAGE_SCN_ALIGN_2048BYTES),
78  STRING_PAIR(IMAGE_SCN_ALIGN_4096BYTES),
79  STRING_PAIR(IMAGE_SCN_ALIGN_8192BYTES)
80};
81
82static const pod_pair<COFF::SectionCharacteristics, const char *>
83SectionCharacteristicsPairs2 [] = {
84  STRING_PAIR(IMAGE_SCN_LNK_NRELOC_OVFL),
85  STRING_PAIR(IMAGE_SCN_MEM_DISCARDABLE),
86  STRING_PAIR(IMAGE_SCN_MEM_NOT_CACHED),
87  STRING_PAIR(IMAGE_SCN_MEM_NOT_PAGED),
88  STRING_PAIR(IMAGE_SCN_MEM_SHARED),
89  STRING_PAIR(IMAGE_SCN_MEM_EXECUTE),
90  STRING_PAIR(IMAGE_SCN_MEM_READ),
91  STRING_PAIR(IMAGE_SCN_MEM_WRITE)
92};
93
94static const pod_pair<COFF::SymbolBaseType, const char *>
95SymbolBaseTypePairs [] = {
96  STRING_PAIR(IMAGE_SYM_TYPE_NULL),
97  STRING_PAIR(IMAGE_SYM_TYPE_VOID),
98  STRING_PAIR(IMAGE_SYM_TYPE_CHAR),
99  STRING_PAIR(IMAGE_SYM_TYPE_SHORT),
100  STRING_PAIR(IMAGE_SYM_TYPE_INT),
101  STRING_PAIR(IMAGE_SYM_TYPE_LONG),
102  STRING_PAIR(IMAGE_SYM_TYPE_FLOAT),
103  STRING_PAIR(IMAGE_SYM_TYPE_DOUBLE),
104  STRING_PAIR(IMAGE_SYM_TYPE_STRUCT),
105  STRING_PAIR(IMAGE_SYM_TYPE_UNION),
106  STRING_PAIR(IMAGE_SYM_TYPE_ENUM),
107  STRING_PAIR(IMAGE_SYM_TYPE_MOE),
108  STRING_PAIR(IMAGE_SYM_TYPE_BYTE),
109  STRING_PAIR(IMAGE_SYM_TYPE_WORD),
110  STRING_PAIR(IMAGE_SYM_TYPE_UINT),
111  STRING_PAIR(IMAGE_SYM_TYPE_DWORD)
112};
113
114static const pod_pair<COFF::SymbolComplexType, const char *>
115SymbolComplexTypePairs [] = {
116  STRING_PAIR(IMAGE_SYM_DTYPE_NULL),
117  STRING_PAIR(IMAGE_SYM_DTYPE_POINTER),
118  STRING_PAIR(IMAGE_SYM_DTYPE_FUNCTION),
119  STRING_PAIR(IMAGE_SYM_DTYPE_ARRAY),
120};
121
122static const pod_pair<COFF::SymbolStorageClass, const char *>
123SymbolStorageClassPairs [] = {
124  STRING_PAIR(IMAGE_SYM_CLASS_END_OF_FUNCTION),
125  STRING_PAIR(IMAGE_SYM_CLASS_NULL),
126  STRING_PAIR(IMAGE_SYM_CLASS_AUTOMATIC),
127  STRING_PAIR(IMAGE_SYM_CLASS_EXTERNAL),
128  STRING_PAIR(IMAGE_SYM_CLASS_STATIC),
129  STRING_PAIR(IMAGE_SYM_CLASS_REGISTER),
130  STRING_PAIR(IMAGE_SYM_CLASS_EXTERNAL_DEF),
131  STRING_PAIR(IMAGE_SYM_CLASS_LABEL),
132  STRING_PAIR(IMAGE_SYM_CLASS_UNDEFINED_LABEL),
133  STRING_PAIR(IMAGE_SYM_CLASS_MEMBER_OF_STRUCT),
134  STRING_PAIR(IMAGE_SYM_CLASS_ARGUMENT),
135  STRING_PAIR(IMAGE_SYM_CLASS_STRUCT_TAG),
136  STRING_PAIR(IMAGE_SYM_CLASS_MEMBER_OF_UNION),
137  STRING_PAIR(IMAGE_SYM_CLASS_UNION_TAG),
138  STRING_PAIR(IMAGE_SYM_CLASS_TYPE_DEFINITION),
139  STRING_PAIR(IMAGE_SYM_CLASS_UNDEFINED_STATIC),
140  STRING_PAIR(IMAGE_SYM_CLASS_ENUM_TAG),
141  STRING_PAIR(IMAGE_SYM_CLASS_MEMBER_OF_ENUM),
142  STRING_PAIR(IMAGE_SYM_CLASS_REGISTER_PARAM),
143  STRING_PAIR(IMAGE_SYM_CLASS_BIT_FIELD),
144  STRING_PAIR(IMAGE_SYM_CLASS_BLOCK),
145  STRING_PAIR(IMAGE_SYM_CLASS_FUNCTION),
146  STRING_PAIR(IMAGE_SYM_CLASS_END_OF_STRUCT),
147  STRING_PAIR(IMAGE_SYM_CLASS_FILE),
148  STRING_PAIR(IMAGE_SYM_CLASS_SECTION),
149  STRING_PAIR(IMAGE_SYM_CLASS_WEAK_EXTERNAL),
150  STRING_PAIR(IMAGE_SYM_CLASS_CLR_TOKEN),
151};
152
153static const pod_pair<COFF::RelocationTypeX86, const char *>
154RelocationTypeX86Pairs [] = {
155  STRING_PAIR(IMAGE_REL_I386_ABSOLUTE),
156  STRING_PAIR(IMAGE_REL_I386_DIR16),
157  STRING_PAIR(IMAGE_REL_I386_REL16),
158  STRING_PAIR(IMAGE_REL_I386_DIR32),
159  STRING_PAIR(IMAGE_REL_I386_DIR32NB),
160  STRING_PAIR(IMAGE_REL_I386_SEG12),
161  STRING_PAIR(IMAGE_REL_I386_SECTION),
162  STRING_PAIR(IMAGE_REL_I386_SECREL),
163  STRING_PAIR(IMAGE_REL_I386_TOKEN),
164  STRING_PAIR(IMAGE_REL_I386_SECREL7),
165  STRING_PAIR(IMAGE_REL_I386_REL32),
166  STRING_PAIR(IMAGE_REL_AMD64_ABSOLUTE),
167  STRING_PAIR(IMAGE_REL_AMD64_ADDR64),
168  STRING_PAIR(IMAGE_REL_AMD64_ADDR32),
169  STRING_PAIR(IMAGE_REL_AMD64_ADDR32NB),
170  STRING_PAIR(IMAGE_REL_AMD64_REL32),
171  STRING_PAIR(IMAGE_REL_AMD64_REL32_1),
172  STRING_PAIR(IMAGE_REL_AMD64_REL32_2),
173  STRING_PAIR(IMAGE_REL_AMD64_REL32_3),
174  STRING_PAIR(IMAGE_REL_AMD64_REL32_4),
175  STRING_PAIR(IMAGE_REL_AMD64_REL32_5),
176  STRING_PAIR(IMAGE_REL_AMD64_SECTION),
177  STRING_PAIR(IMAGE_REL_AMD64_SECREL),
178  STRING_PAIR(IMAGE_REL_AMD64_SECREL7),
179  STRING_PAIR(IMAGE_REL_AMD64_TOKEN),
180  STRING_PAIR(IMAGE_REL_AMD64_SREL32),
181  STRING_PAIR(IMAGE_REL_AMD64_PAIR),
182  STRING_PAIR(IMAGE_REL_AMD64_SSPAN32)
183};
184
185static const pod_pair<COFF::RelocationTypesARM, const char *>
186RelocationTypesARMPairs [] = {
187  STRING_PAIR(IMAGE_REL_ARM_ABSOLUTE),
188  STRING_PAIR(IMAGE_REL_ARM_ADDR32),
189  STRING_PAIR(IMAGE_REL_ARM_ADDR32NB),
190  STRING_PAIR(IMAGE_REL_ARM_BRANCH24),
191  STRING_PAIR(IMAGE_REL_ARM_BRANCH11),
192  STRING_PAIR(IMAGE_REL_ARM_TOKEN),
193  STRING_PAIR(IMAGE_REL_ARM_BLX24),
194  STRING_PAIR(IMAGE_REL_ARM_BLX11),
195  STRING_PAIR(IMAGE_REL_ARM_SECTION),
196  STRING_PAIR(IMAGE_REL_ARM_SECREL),
197  STRING_PAIR(IMAGE_REL_ARM_MOV32A),
198  STRING_PAIR(IMAGE_REL_ARM_MOV32T),
199  STRING_PAIR(IMAGE_REL_ARM_BRANCH20T),
200  STRING_PAIR(IMAGE_REL_ARM_BRANCH24T),
201  STRING_PAIR(IMAGE_REL_ARM_BLX23T)
202};
203#undef STRING_PAIR
204
205static raw_ostream &writeName(raw_ostream &Out,
206                              const char *Name, std::size_t NameSize) {
207  for (std::size_t i = 0; i < NameSize; ++i) {
208    if (!Name[i]) break;
209    Out << Name[i];
210  }
211  return Out;
212}
213
214// Given an array of pod_pair<enum, const char *>, write all enums that match
215template <typename T, std::size_t N>
216static raw_ostream &writeBitMask(raw_ostream &Out,
217                                 const pod_pair<T, const char *> (&Arr)[N],
218                                 unsigned long Val) {
219  for (std::size_t i = 0; i < N; ++i)
220    if (Val & Arr[i].first)
221      Out << Arr[i].second << ", ";
222  return Out;
223}
224
225// Given an array of pod_pair<enum, const char *>, look up a value
226template <typename T, std::size_t N>
227const char *nameLookup(const pod_pair<T, const char *> (&Arr)[N],
228                       unsigned long Val, const char *NotFound = NULL) {
229  T n = static_cast<T>(Val);
230  for (std::size_t i = 0; i < N; ++i)
231    if (n == Arr[i].first)
232      return Arr[i].second;
233  return NotFound;
234}
235
236static raw_ostream &yamlCOFFHeader(const object::coff_file_header *Header,
237                                   raw_ostream &Out) {
238  COFF::header H;
239  H.Machine = Header->Machine;
240  H.Characteristics = Header->Characteristics;
241
242  Out << "header: !Header\n";
243  Out << "  Machine: ";
244  Out << nameLookup(MachineTypePairs, Header->Machine, "# Unknown_MachineTypes")
245      << " # (";
246  return yaml::writeHexNumber(Out, Header->Machine) << ")\n\n";
247}
248
249
250static raw_ostream &yamlCOFFSections(object::COFFObjectFile &Obj,
251                                     std::size_t NumSections,
252                                     raw_ostream &Out) {
253  error_code ec;
254  Out << "sections:\n";
255  for (object::section_iterator iter = Obj.begin_sections();
256       iter != Obj.end_sections(); iter.increment(ec)) {
257    const object::coff_section *sect = Obj.getCOFFSection(iter);
258
259    Out << "  - !Section\n";
260    Out << "    Name: ";
261    writeName(Out, sect->Name, sizeof(sect->Name)) << '\n';
262
263    Out << "    Characteristics: [";
264    writeBitMask(Out, SectionCharacteristicsPairs1, sect->Characteristics);
265    Out << nameLookup(SectionCharacteristicsPairsAlignment,
266        sect->Characteristics & 0x00F00000, "# Unrecognized_IMAGE_SCN_ALIGN")
267        << ", ";
268    writeBitMask(Out, SectionCharacteristicsPairs2, sect->Characteristics);
269    Out << "] # ";
270    yaml::writeHexNumber(Out, sect->Characteristics) << '\n';
271
272    ArrayRef<uint8_t> sectionData;
273    Obj.getSectionContents(sect, sectionData);
274    Out << "    SectionData: ";
275    yaml::writeHexStream(Out, sectionData) << '\n';
276    if (iter->begin_relocations() != iter->end_relocations())
277      Out << "    Relocations:\n";
278    for (object::relocation_iterator rIter = iter->begin_relocations();
279                       rIter != iter->end_relocations(); rIter.increment(ec)) {
280      const object::coff_relocation *reloc = Obj.getCOFFRelocation(rIter);
281
282        Out << "      - !Relocation\n";
283        Out << "        VirtualAddress: " ;
284        yaml::writeHexNumber(Out, reloc->VirtualAddress) << '\n';
285        Out << "        SymbolTableIndex: " << reloc->SymbolTableIndex << '\n';
286        Out << "        Type: "
287            << nameLookup(RelocationTypeX86Pairs, reloc->Type) << '\n';
288    // TODO: Use the correct reloc type for the machine.
289        Out << '\n';
290      }
291
292  }
293  return Out;
294}
295
296static raw_ostream& yamlCOFFSymbols(object::COFFObjectFile &Obj,
297                                    std::size_t NumSymbols,
298                                    raw_ostream &Out) {
299  error_code ec;
300  Out << "symbols:\n";
301  for (object::symbol_iterator iter = Obj.begin_symbols();
302       iter != Obj.end_symbols(); iter.increment(ec)) {
303 // Gather all the info that we need
304    StringRef str;
305    const object::coff_symbol *symbol = Obj.getCOFFSymbol(iter);
306    Obj.getSymbolName(symbol, str);
307    std::size_t  simpleType  = symbol->getBaseType();
308    std::size_t complexType  = symbol->getComplexType();
309    std::size_t storageClass = symbol->StorageClass;
310
311    Out << "  - !Symbol\n";
312    Out << "    Name: " << str << '\n';
313
314    Out << "    Value: "         << symbol->Value << '\n';
315    Out << "    SectionNumber: " << symbol->SectionNumber << '\n';
316
317    Out << "    SimpleType: "
318        << nameLookup(SymbolBaseTypePairs, simpleType,
319            "# Unknown_SymbolBaseType")
320        << " # (" << simpleType << ")\n";
321
322    Out << "    ComplexType: "
323        << nameLookup(SymbolComplexTypePairs, complexType,
324                "# Unknown_SymbolComplexType")
325        << " # (" << complexType << ")\n";
326
327    Out << "    StorageClass: "
328        << nameLookup(SymbolStorageClassPairs, storageClass,
329              "# Unknown_StorageClass")
330        << " # (" << (int) storageClass << ")\n";
331
332    if (symbol->NumberOfAuxSymbols > 0) {
333      ArrayRef<uint8_t> aux = Obj.getSymbolAuxData(symbol);
334      Out << "    NumberOfAuxSymbols: "
335          << (int) symbol->NumberOfAuxSymbols << '\n';
336      Out << "    AuxillaryData: ";
337      yaml::writeHexStream(Out, aux);
338    }
339
340    Out << '\n';
341  }
342
343  return Out;
344}
345
346
347error_code coff2yaml(raw_ostream &Out, MemoryBuffer *TheObj) {
348  error_code ec;
349  object::COFFObjectFile obj(TheObj, ec);
350  if (ec)
351    return ec;
352
353  const object::coff_file_header *hd;
354  ec = obj.getHeader(hd);
355  if (ec)
356    return ec;
357
358  yamlCOFFHeader(hd, Out);
359  yamlCOFFSections(obj, hd->NumberOfSections, Out);
360  yamlCOFFSymbols(obj, hd->NumberOfSymbols, Out);
361
362  return ec;
363}
364