yaml2obj.cpp revision 3d3cc32f5fe815b7a38c2cb558b9d5f40fb0bbb1
1//===- yaml2obj - Convert YAML to a binary object file --------------------===//
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// This program takes a YAML description of an object file and outputs the
11// binary equivalent.
12//
13// This is used for writing tests that require binary files.
14//
15//===----------------------------------------------------------------------===//
16
17#include "llvm/ADT/SmallString.h"
18#include "llvm/ADT/StringExtras.h"
19#include "llvm/ADT/StringMap.h"
20#include "llvm/ADT/StringSwitch.h"
21#include "llvm/Support/COFF.h"
22#include "llvm/Support/Casting.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Support/Endian.h"
25#include "llvm/Support/ManagedStatic.h"
26#include "llvm/Support/MemoryBuffer.h"
27#include "llvm/Support/PrettyStackTrace.h"
28#include "llvm/Support/Signals.h"
29#include "llvm/Support/SourceMgr.h"
30#include "llvm/Support/YAMLTraits.h"
31#include "llvm/Support/raw_ostream.h"
32#include "llvm/Support/system_error.h"
33#include <vector>
34
35using namespace llvm;
36
37static cl::opt<std::string>
38  Input(cl::Positional, cl::desc("<input>"), cl::init("-"));
39
40// The structure of the yaml files is not an exact 1:1 match to COFF. In order
41// to use yaml::IO, we use these structures which are closer to the source.
42namespace COFFYAML {
43  struct Section {
44    COFF::section Header;
45    StringRef SectionData;
46    std::vector<COFF::relocation> Relocations;
47    StringRef Name;
48    Section() {
49      memset(&Header, 0, sizeof(COFF::section));
50    }
51  };
52
53  struct Symbol {
54    COFF::symbol Header;
55    COFF::SymbolBaseType SimpleType;
56    COFF::SymbolComplexType ComplexType;
57    StringRef AuxiliaryData;
58    StringRef Name;
59    Symbol() {
60      memset(&Header, 0, sizeof(COFF::symbol));
61    }
62  };
63
64  struct Object {
65    COFF::header Header;
66    std::vector<Section> Sections;
67    std::vector<Symbol> Symbols;
68    Object() {
69      memset(&Header, 0, sizeof(COFF::header));
70    }
71  };
72}
73
74/// This parses a yaml stream that represents a COFF object file.
75/// See docs/yaml2obj for the yaml scheema.
76struct COFFParser {
77  COFFParser(COFFYAML::Object &Obj) : Obj(Obj) {
78    // A COFF string table always starts with a 4 byte size field. Offsets into
79    // it include this size, so allocate it now.
80    StringTable.append(4, 0);
81  }
82
83  bool parseSections() {
84    for (std::vector<COFFYAML::Section>::iterator i = Obj.Sections.begin(),
85           e = Obj.Sections.end(); i != e; ++i) {
86      COFFYAML::Section &Sec = *i;
87
88      // If the name is less than 8 bytes, store it in place, otherwise
89      // store it in the string table.
90      StringRef Name = Sec.Name;
91
92      if (Name.size() <= COFF::NameSize) {
93        std::copy(Name.begin(), Name.end(), Sec.Header.Name);
94      } else {
95        // Add string to the string table and format the index for output.
96        unsigned Index = getStringIndex(Name);
97        std::string str = utostr(Index);
98        if (str.size() > 7) {
99          errs() << "String table got too large";
100          return false;
101        }
102        Sec.Header.Name[0] = '/';
103        std::copy(str.begin(), str.end(), Sec.Header.Name + 1);
104      }
105    }
106    return true;
107  }
108
109  bool parseSymbols() {
110    for (std::vector<COFFYAML::Symbol>::iterator i = Obj.Symbols.begin(),
111           e = Obj.Symbols.end(); i != e; ++i) {
112      COFFYAML::Symbol &Sym = *i;
113
114      // If the name is less than 8 bytes, store it in place, otherwise
115      // store it in the string table.
116      StringRef Name = Sym.Name;
117      if (Name.size() <= COFF::NameSize) {
118        std::copy(Name.begin(), Name.end(), Sym.Header.Name);
119      } else {
120        // Add string to the string table and format the index for output.
121        unsigned Index = getStringIndex(Name);
122        *reinterpret_cast<support::aligned_ulittle32_t*>(
123            Sym.Header.Name + 4) = Index;
124      }
125
126      Sym.Header.Type = Sym.SimpleType;
127      Sym.Header.Type |= Sym.ComplexType << COFF::SCT_COMPLEX_TYPE_SHIFT;
128    }
129    return true;
130  }
131
132  bool parse() {
133    if (!parseSections())
134      return false;
135    if (!parseSymbols())
136      return false;
137    return true;
138  }
139
140  unsigned getStringIndex(StringRef Str) {
141    StringMap<unsigned>::iterator i = StringTableMap.find(Str);
142    if (i == StringTableMap.end()) {
143      unsigned Index = StringTable.size();
144      StringTable.append(Str.begin(), Str.end());
145      StringTable.push_back(0);
146      StringTableMap[Str] = Index;
147      return Index;
148    }
149    return i->second;
150  }
151
152  COFFYAML::Object &Obj;
153
154  StringMap<unsigned> StringTableMap;
155  std::string StringTable;
156};
157
158// Take a CP and assign addresses and sizes to everything. Returns false if the
159// layout is not valid to do.
160static bool layoutCOFF(COFFParser &CP) {
161  uint32_t SectionTableStart = 0;
162  uint32_t SectionTableSize  = 0;
163
164  // The section table starts immediately after the header, including the
165  // optional header.
166  SectionTableStart = sizeof(COFF::header) + CP.Obj.Header.SizeOfOptionalHeader;
167  SectionTableSize = sizeof(COFF::section) * CP.Obj.Sections.size();
168
169  uint32_t CurrentSectionDataOffset = SectionTableStart + SectionTableSize;
170
171  // Assign each section data address consecutively.
172  for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
173                                                e = CP.Obj.Sections.end();
174                                                i != e; ++i) {
175    if (!i->SectionData.empty()) {
176      i->Header.SizeOfRawData = i->SectionData.size()/2;
177      i->Header.PointerToRawData = CurrentSectionDataOffset;
178      CurrentSectionDataOffset += i->Header.SizeOfRawData;
179      if (!i->Relocations.empty()) {
180        i->Header.PointerToRelocations = CurrentSectionDataOffset;
181        i->Header.NumberOfRelocations = i->Relocations.size();
182        CurrentSectionDataOffset += i->Header.NumberOfRelocations *
183          COFF::RelocationSize;
184      }
185      // TODO: Handle alignment.
186    } else {
187      i->Header.SizeOfRawData = 0;
188      i->Header.PointerToRawData = 0;
189    }
190  }
191
192  uint32_t SymbolTableStart = CurrentSectionDataOffset;
193
194  // Calculate number of symbols.
195  uint32_t NumberOfSymbols = 0;
196  for (std::vector<COFFYAML::Symbol>::iterator i = CP.Obj.Symbols.begin(),
197                                               e = CP.Obj.Symbols.end();
198                                               i != e; ++i) {
199    unsigned AuxBytes = i->AuxiliaryData.size() / 2;
200    if (AuxBytes % COFF::SymbolSize != 0) {
201      errs() << "AuxiliaryData size not a multiple of symbol size!\n";
202      return false;
203    }
204    i->Header.NumberOfAuxSymbols = AuxBytes / COFF::SymbolSize;
205    NumberOfSymbols += 1 + i->Header.NumberOfAuxSymbols;
206  }
207
208  // Store all the allocated start addresses in the header.
209  CP.Obj.Header.NumberOfSections = CP.Obj.Sections.size();
210  CP.Obj.Header.NumberOfSymbols = NumberOfSymbols;
211  CP.Obj.Header.PointerToSymbolTable = SymbolTableStart;
212
213  *reinterpret_cast<support::ulittle32_t *>(&CP.StringTable[0])
214    = CP.StringTable.size();
215
216  return true;
217}
218
219template <typename value_type>
220struct binary_le_impl {
221  value_type Value;
222  binary_le_impl(value_type V) : Value(V) {}
223};
224
225template <typename value_type>
226raw_ostream &operator <<( raw_ostream &OS
227                        , const binary_le_impl<value_type> &BLE) {
228  char Buffer[sizeof(BLE.Value)];
229  support::endian::write<value_type, support::little, support::unaligned>(
230    Buffer, BLE.Value);
231  OS.write(Buffer, sizeof(BLE.Value));
232  return OS;
233}
234
235template <typename value_type>
236binary_le_impl<value_type> binary_le(value_type V) {
237  return binary_le_impl<value_type>(V);
238}
239
240static bool writeHexData(StringRef Data, raw_ostream &OS) {
241  unsigned Size = Data.size();
242  if (Size % 2)
243    return false;
244
245  for (unsigned I = 0; I != Size; I += 2) {
246    uint8_t Byte;
247    if (Data.substr(I,  2).getAsInteger(16, Byte))
248      return false;
249    OS.write(Byte);
250  }
251
252  return true;
253}
254
255bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
256  OS << binary_le(CP.Obj.Header.Machine)
257     << binary_le(CP.Obj.Header.NumberOfSections)
258     << binary_le(CP.Obj.Header.TimeDateStamp)
259     << binary_le(CP.Obj.Header.PointerToSymbolTable)
260     << binary_le(CP.Obj.Header.NumberOfSymbols)
261     << binary_le(CP.Obj.Header.SizeOfOptionalHeader)
262     << binary_le(CP.Obj.Header.Characteristics);
263
264  // Output section table.
265  for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
266                                                e = CP.Obj.Sections.end();
267                                                i != e; ++i) {
268    OS.write(i->Header.Name, COFF::NameSize);
269    OS << binary_le(i->Header.VirtualSize)
270       << binary_le(i->Header.VirtualAddress)
271       << binary_le(i->Header.SizeOfRawData)
272       << binary_le(i->Header.PointerToRawData)
273       << binary_le(i->Header.PointerToRelocations)
274       << binary_le(i->Header.PointerToLineNumbers)
275       << binary_le(i->Header.NumberOfRelocations)
276       << binary_le(i->Header.NumberOfLineNumbers)
277       << binary_le(i->Header.Characteristics);
278  }
279
280  // Output section data.
281  for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
282                                                e = CP.Obj.Sections.end();
283                                                i != e; ++i) {
284    if (!i->SectionData.empty()) {
285      if (!writeHexData(i->SectionData, OS)) {
286        errs() << "SectionData must be a collection of pairs of hex bytes";
287        return false;
288      }
289    }
290    for (unsigned I2 = 0, E2 = i->Relocations.size(); I2 != E2; ++I2) {
291      const COFF::relocation &R = i->Relocations[I2];
292      OS << binary_le(R.VirtualAddress)
293         << binary_le(R.SymbolTableIndex)
294         << binary_le(R.Type);
295    }
296  }
297
298  // Output symbol table.
299
300  for (std::vector<COFFYAML::Symbol>::const_iterator i = CP.Obj.Symbols.begin(),
301                                                     e = CP.Obj.Symbols.end();
302                                                     i != e; ++i) {
303    OS.write(i->Header.Name, COFF::NameSize);
304    OS << binary_le(i->Header.Value)
305       << binary_le(i->Header.SectionNumber)
306       << binary_le(i->Header.Type)
307       << binary_le(i->Header.StorageClass)
308       << binary_le(i->Header.NumberOfAuxSymbols);
309    if (!i->AuxiliaryData.empty()) {
310      if (!writeHexData(i->AuxiliaryData, OS)) {
311        errs() << "AuxiliaryData must be a collection of pairs of hex bytes";
312        return false;
313      }
314    }
315  }
316
317  // Output string table.
318  OS.write(&CP.StringTable[0], CP.StringTable.size());
319  return true;
320}
321
322LLVM_YAML_IS_SEQUENCE_VECTOR(COFF::relocation)
323LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Section)
324LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Symbol)
325
326namespace llvm {
327
328namespace COFF {
329  Characteristics operator|(Characteristics a, Characteristics b) {
330    uint32_t Ret = static_cast<uint32_t>(a) | static_cast<uint32_t>(b);
331    return static_cast<Characteristics>(Ret);
332  }
333
334  SectionCharacteristics
335  operator|(SectionCharacteristics a, SectionCharacteristics b) {
336    uint32_t Ret = static_cast<uint32_t>(a) | static_cast<uint32_t>(b);
337    return static_cast<SectionCharacteristics>(Ret);
338  }
339}
340
341namespace yaml {
342
343#define BCase(X) IO.bitSetCase(Value, #X, COFF::X);
344
345template <>
346struct ScalarBitSetTraits<COFF::SectionCharacteristics> {
347  static void bitset(IO &IO, COFF::SectionCharacteristics &Value) {
348    BCase(IMAGE_SCN_TYPE_NO_PAD);
349    BCase(IMAGE_SCN_CNT_CODE);
350    BCase(IMAGE_SCN_CNT_INITIALIZED_DATA);
351    BCase(IMAGE_SCN_CNT_UNINITIALIZED_DATA);
352    BCase(IMAGE_SCN_LNK_OTHER);
353    BCase(IMAGE_SCN_LNK_INFO);
354    BCase(IMAGE_SCN_LNK_REMOVE);
355    BCase(IMAGE_SCN_LNK_COMDAT);
356    BCase(IMAGE_SCN_GPREL);
357    BCase(IMAGE_SCN_MEM_PURGEABLE);
358    BCase(IMAGE_SCN_MEM_16BIT);
359    BCase(IMAGE_SCN_MEM_LOCKED);
360    BCase(IMAGE_SCN_MEM_PRELOAD);
361    BCase(IMAGE_SCN_ALIGN_1BYTES);
362    BCase(IMAGE_SCN_ALIGN_2BYTES);
363    BCase(IMAGE_SCN_ALIGN_4BYTES);
364    BCase(IMAGE_SCN_ALIGN_8BYTES);
365    BCase(IMAGE_SCN_ALIGN_16BYTES);
366    BCase(IMAGE_SCN_ALIGN_32BYTES);
367    BCase(IMAGE_SCN_ALIGN_64BYTES);
368    BCase(IMAGE_SCN_ALIGN_128BYTES);
369    BCase(IMAGE_SCN_ALIGN_256BYTES);
370    BCase(IMAGE_SCN_ALIGN_512BYTES);
371    BCase(IMAGE_SCN_ALIGN_1024BYTES);
372    BCase(IMAGE_SCN_ALIGN_2048BYTES);
373    BCase(IMAGE_SCN_ALIGN_4096BYTES);
374    BCase(IMAGE_SCN_ALIGN_8192BYTES);
375    BCase(IMAGE_SCN_LNK_NRELOC_OVFL);
376    BCase(IMAGE_SCN_MEM_DISCARDABLE);
377    BCase(IMAGE_SCN_MEM_NOT_CACHED);
378    BCase(IMAGE_SCN_MEM_NOT_PAGED);
379    BCase(IMAGE_SCN_MEM_SHARED);
380    BCase(IMAGE_SCN_MEM_EXECUTE);
381    BCase(IMAGE_SCN_MEM_READ);
382    BCase(IMAGE_SCN_MEM_WRITE);
383  }
384};
385
386template <>
387struct ScalarBitSetTraits<COFF::Characteristics> {
388  static void bitset(IO &IO, COFF::Characteristics &Value) {
389    BCase(IMAGE_FILE_RELOCS_STRIPPED);
390    BCase(IMAGE_FILE_EXECUTABLE_IMAGE);
391    BCase(IMAGE_FILE_LINE_NUMS_STRIPPED);
392    BCase(IMAGE_FILE_LOCAL_SYMS_STRIPPED);
393    BCase(IMAGE_FILE_AGGRESSIVE_WS_TRIM);
394    BCase(IMAGE_FILE_LARGE_ADDRESS_AWARE);
395    BCase(IMAGE_FILE_BYTES_REVERSED_LO);
396    BCase(IMAGE_FILE_32BIT_MACHINE);
397    BCase(IMAGE_FILE_DEBUG_STRIPPED);
398    BCase(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP);
399    BCase(IMAGE_FILE_NET_RUN_FROM_SWAP);
400    BCase(IMAGE_FILE_SYSTEM);
401    BCase(IMAGE_FILE_DLL);
402    BCase(IMAGE_FILE_UP_SYSTEM_ONLY);
403    BCase(IMAGE_FILE_BYTES_REVERSED_HI);
404  }
405};
406#undef BCase
407
408#define ECase(X) IO.enumCase(Value, #X, COFF::X);
409
410template <>
411struct ScalarEnumerationTraits<COFF::SymbolComplexType> {
412  static void enumeration(IO &IO, COFF::SymbolComplexType &Value) {
413    ECase(IMAGE_SYM_DTYPE_NULL);
414    ECase(IMAGE_SYM_DTYPE_POINTER);
415    ECase(IMAGE_SYM_DTYPE_FUNCTION);
416    ECase(IMAGE_SYM_DTYPE_ARRAY);
417  }
418};
419
420template <>
421struct ScalarEnumerationTraits<COFF::SymbolStorageClass> {
422  static void enumeration(IO &IO, COFF::SymbolStorageClass &Value) {
423    ECase(IMAGE_SYM_CLASS_END_OF_FUNCTION);
424    ECase(IMAGE_SYM_CLASS_NULL);
425    ECase(IMAGE_SYM_CLASS_AUTOMATIC);
426    ECase(IMAGE_SYM_CLASS_EXTERNAL);
427    ECase(IMAGE_SYM_CLASS_STATIC);
428    ECase(IMAGE_SYM_CLASS_REGISTER);
429    ECase(IMAGE_SYM_CLASS_EXTERNAL_DEF);
430    ECase(IMAGE_SYM_CLASS_LABEL);
431    ECase(IMAGE_SYM_CLASS_UNDEFINED_LABEL);
432    ECase(IMAGE_SYM_CLASS_MEMBER_OF_STRUCT);
433    ECase(IMAGE_SYM_CLASS_ARGUMENT);
434    ECase(IMAGE_SYM_CLASS_STRUCT_TAG);
435    ECase(IMAGE_SYM_CLASS_MEMBER_OF_UNION);
436    ECase(IMAGE_SYM_CLASS_UNION_TAG);
437    ECase(IMAGE_SYM_CLASS_TYPE_DEFINITION);
438    ECase(IMAGE_SYM_CLASS_UNDEFINED_STATIC);
439    ECase(IMAGE_SYM_CLASS_ENUM_TAG);
440    ECase(IMAGE_SYM_CLASS_MEMBER_OF_ENUM);
441    ECase(IMAGE_SYM_CLASS_REGISTER_PARAM);
442    ECase(IMAGE_SYM_CLASS_BIT_FIELD);
443    ECase(IMAGE_SYM_CLASS_BLOCK);
444    ECase(IMAGE_SYM_CLASS_FUNCTION);
445    ECase(IMAGE_SYM_CLASS_END_OF_STRUCT);
446    ECase(IMAGE_SYM_CLASS_FILE);
447    ECase(IMAGE_SYM_CLASS_SECTION);
448    ECase(IMAGE_SYM_CLASS_WEAK_EXTERNAL);
449    ECase(IMAGE_SYM_CLASS_CLR_TOKEN);
450  }
451};
452
453template <>
454struct ScalarEnumerationTraits<COFF::SymbolBaseType> {
455  static void enumeration(IO &IO, COFF::SymbolBaseType &Value) {
456    ECase(IMAGE_SYM_TYPE_NULL);
457    ECase(IMAGE_SYM_TYPE_VOID);
458    ECase(IMAGE_SYM_TYPE_CHAR);
459    ECase(IMAGE_SYM_TYPE_SHORT);
460    ECase(IMAGE_SYM_TYPE_INT);
461    ECase(IMAGE_SYM_TYPE_LONG);
462    ECase(IMAGE_SYM_TYPE_FLOAT);
463    ECase(IMAGE_SYM_TYPE_DOUBLE);
464    ECase(IMAGE_SYM_TYPE_STRUCT);
465    ECase(IMAGE_SYM_TYPE_UNION);
466    ECase(IMAGE_SYM_TYPE_ENUM);
467    ECase(IMAGE_SYM_TYPE_MOE);
468    ECase(IMAGE_SYM_TYPE_BYTE);
469    ECase(IMAGE_SYM_TYPE_WORD);
470    ECase(IMAGE_SYM_TYPE_UINT);
471    ECase(IMAGE_SYM_TYPE_DWORD);
472  }
473};
474
475template <>
476struct ScalarEnumerationTraits<COFF::MachineTypes> {
477  static void enumeration(IO &IO, COFF::MachineTypes &Value) {
478    ECase(IMAGE_FILE_MACHINE_UNKNOWN);
479    ECase(IMAGE_FILE_MACHINE_AM33);
480    ECase(IMAGE_FILE_MACHINE_AMD64);
481    ECase(IMAGE_FILE_MACHINE_ARM);
482    ECase(IMAGE_FILE_MACHINE_ARMV7);
483    ECase(IMAGE_FILE_MACHINE_EBC);
484    ECase(IMAGE_FILE_MACHINE_I386);
485    ECase(IMAGE_FILE_MACHINE_IA64);
486    ECase(IMAGE_FILE_MACHINE_M32R);
487    ECase(IMAGE_FILE_MACHINE_MIPS16);
488    ECase(IMAGE_FILE_MACHINE_MIPSFPU);
489    ECase(IMAGE_FILE_MACHINE_MIPSFPU16);
490    ECase(IMAGE_FILE_MACHINE_POWERPC);
491    ECase(IMAGE_FILE_MACHINE_POWERPCFP);
492    ECase(IMAGE_FILE_MACHINE_R4000);
493    ECase(IMAGE_FILE_MACHINE_SH3);
494    ECase(IMAGE_FILE_MACHINE_SH3DSP);
495    ECase(IMAGE_FILE_MACHINE_SH4);
496    ECase(IMAGE_FILE_MACHINE_SH5);
497    ECase(IMAGE_FILE_MACHINE_THUMB);
498    ECase(IMAGE_FILE_MACHINE_WCEMIPSV2);
499  }
500};
501
502template <>
503struct ScalarEnumerationTraits<COFF::RelocationTypeX86> {
504  static void enumeration(IO &IO, COFF::RelocationTypeX86 &Value) {
505    ECase(IMAGE_REL_I386_ABSOLUTE);
506    ECase(IMAGE_REL_I386_DIR16);
507    ECase(IMAGE_REL_I386_REL16);
508    ECase(IMAGE_REL_I386_DIR32);
509    ECase(IMAGE_REL_I386_DIR32NB);
510    ECase(IMAGE_REL_I386_SEG12);
511    ECase(IMAGE_REL_I386_SECTION);
512    ECase(IMAGE_REL_I386_SECREL);
513    ECase(IMAGE_REL_I386_TOKEN);
514    ECase(IMAGE_REL_I386_SECREL7);
515    ECase(IMAGE_REL_I386_REL32);
516    ECase(IMAGE_REL_AMD64_ABSOLUTE);
517    ECase(IMAGE_REL_AMD64_ADDR64);
518    ECase(IMAGE_REL_AMD64_ADDR32);
519    ECase(IMAGE_REL_AMD64_ADDR32NB);
520    ECase(IMAGE_REL_AMD64_REL32);
521    ECase(IMAGE_REL_AMD64_REL32_1);
522    ECase(IMAGE_REL_AMD64_REL32_2);
523    ECase(IMAGE_REL_AMD64_REL32_3);
524    ECase(IMAGE_REL_AMD64_REL32_4);
525    ECase(IMAGE_REL_AMD64_REL32_5);
526    ECase(IMAGE_REL_AMD64_SECTION);
527    ECase(IMAGE_REL_AMD64_SECREL);
528    ECase(IMAGE_REL_AMD64_SECREL7);
529    ECase(IMAGE_REL_AMD64_TOKEN);
530    ECase(IMAGE_REL_AMD64_SREL32);
531    ECase(IMAGE_REL_AMD64_PAIR);
532    ECase(IMAGE_REL_AMD64_SSPAN32);
533  }
534};
535
536#undef ECase
537
538template <>
539struct MappingTraits<COFFYAML::Symbol> {
540  struct NStorageClass {
541    NStorageClass(IO&) : StorageClass(COFF::SymbolStorageClass(0)) {
542    }
543    NStorageClass(IO&, uint8_t S) : StorageClass(COFF::SymbolStorageClass(S)) {
544    }
545    uint8_t denormalize(IO &) {
546      return StorageClass;
547    }
548
549    COFF::SymbolStorageClass StorageClass;
550  };
551
552  static void mapping(IO &IO, COFFYAML::Symbol &S) {
553    MappingNormalization<NStorageClass, uint8_t> NS(IO, S.Header.StorageClass);
554
555    IO.mapRequired("SimpleType", S.SimpleType);
556    IO.mapOptional("NumberOfAuxSymbols", S.Header.NumberOfAuxSymbols);
557    IO.mapRequired("Name", S.Name);
558    IO.mapRequired("StorageClass", NS->StorageClass);
559    IO.mapOptional("AuxiliaryData", S.AuxiliaryData);
560    IO.mapRequired("ComplexType", S.ComplexType);
561    IO.mapRequired("Value", S.Header.Value);
562    IO.mapRequired("SectionNumber", S.Header.SectionNumber);
563  }
564};
565
566template <>
567struct MappingTraits<COFF::header> {
568  struct NMachine {
569    NMachine(IO&) : Machine(COFF::MachineTypes(0)) {
570    }
571    NMachine(IO&, uint16_t M) : Machine(COFF::MachineTypes(M)) {
572    }
573    uint16_t denormalize(IO &) {
574      return Machine;
575    }
576    COFF::MachineTypes Machine;
577  };
578
579  struct NCharacteristics {
580    NCharacteristics(IO&) : Characteristics(COFF::Characteristics(0)) {
581    }
582    NCharacteristics(IO&, uint16_t C) :
583      Characteristics(COFF::Characteristics(C)) {
584    }
585    uint16_t denormalize(IO &) {
586      return Characteristics;
587    }
588
589    COFF::Characteristics Characteristics;
590  };
591
592  static void mapping(IO &IO, COFF::header &H) {
593    MappingNormalization<NMachine, uint16_t> NM(IO, H.Machine);
594    MappingNormalization<NCharacteristics, uint16_t> NC(IO, H.Characteristics);
595
596    IO.mapRequired("Machine", NM->Machine);
597    IO.mapOptional("Characteristics", NC->Characteristics);
598  }
599};
600
601template <>
602struct MappingTraits<COFF::relocation> {
603  struct NType {
604    NType(IO &) : Type(COFF::RelocationTypeX86(0)) {
605    }
606    NType(IO &, uint16_t T) : Type(COFF::RelocationTypeX86(T)) {
607    }
608    uint16_t denormalize(IO &) {
609      return Type;
610    }
611    COFF::RelocationTypeX86 Type;
612  };
613
614  static void mapping(IO &IO, COFF::relocation &Rel) {
615    MappingNormalization<NType, uint16_t> NT(IO, Rel.Type);
616
617    IO.mapRequired("Type", NT->Type);
618    IO.mapRequired("VirtualAddress", Rel.VirtualAddress);
619    IO.mapRequired("SymbolTableIndex", Rel.SymbolTableIndex);
620  }
621};
622
623template <>
624struct MappingTraits<COFFYAML::Section> {
625  struct NCharacteristics {
626    NCharacteristics(IO &) : Characteristics(COFF::SectionCharacteristics(0)) {
627    }
628    NCharacteristics(IO &, uint32_t C) :
629      Characteristics(COFF::SectionCharacteristics(C)) {
630    }
631    uint32_t denormalize(IO &) {
632      return Characteristics;
633    }
634    COFF::SectionCharacteristics Characteristics;
635  };
636
637  static void mapping(IO &IO, COFFYAML::Section &Sec) {
638    MappingNormalization<NCharacteristics, uint32_t> NC(IO,
639                                                    Sec.Header.Characteristics);
640    IO.mapOptional("Relocations", Sec.Relocations);
641    IO.mapRequired("SectionData", Sec.SectionData);
642    IO.mapRequired("Characteristics", NC->Characteristics);
643    IO.mapRequired("Name", Sec.Name);
644  }
645};
646
647template <>
648struct MappingTraits<COFFYAML::Object> {
649  static void mapping(IO &IO, COFFYAML::Object &Obj) {
650    IO.mapRequired("sections", Obj.Sections);
651    IO.mapRequired("header", Obj.Header);
652    IO.mapRequired("symbols", Obj.Symbols);
653  }
654};
655} // end namespace yaml
656} // end namespace llvm
657
658int main(int argc, char **argv) {
659  cl::ParseCommandLineOptions(argc, argv);
660  sys::PrintStackTraceOnErrorSignal();
661  PrettyStackTraceProgram X(argc, argv);
662  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
663
664  OwningPtr<MemoryBuffer> Buf;
665  if (MemoryBuffer::getFileOrSTDIN(Input, Buf))
666    return 1;
667
668  yaml::Input YIn(Buf->getBuffer());
669  COFFYAML::Object Doc;
670  YIn >> Doc;
671  if (YIn.error()) {
672    errs() << "yaml2obj: Failed to parse YAML file!\n";
673    return 1;
674  }
675
676  COFFParser CP(Doc);
677  if (!CP.parse()) {
678    errs() << "yaml2obj: Failed to parse YAML file!\n";
679    return 1;
680  }
681
682  if (!layoutCOFF(CP)) {
683    errs() << "yaml2obj: Failed to layout COFF file!\n";
684    return 1;
685  }
686  if (!writeCOFF(CP, outs())) {
687    errs() << "yaml2obj: Failed to write COFF file!\n";
688    return 1;
689  }
690}
691