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