Remove redundant '== true' after a comparison.
[oota-llvm.git] / utils / 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/raw_ostream.h"
29 #include "llvm/Support/Signals.h"
30 #include "llvm/Support/SourceMgr.h"
31 #include "llvm/Support/system_error.h"
32 #include "llvm/Support/YAMLParser.h"
33
34 #include <vector>
35
36 using namespace llvm;
37
38 static cl::opt<std::string>
39   Input(cl::Positional, cl::desc("<input>"), cl::init("-"));
40
41 template<class T>
42 typename llvm::enable_if_c<std::numeric_limits<T>::is_integer, bool>::type
43 getAs(const llvm::yaml::ScalarNode *SN, T &Result) {
44   SmallString<4> Storage;
45   StringRef Value = SN->getValue(Storage);
46   if (Value.getAsInteger(0, Result))
47     return false;
48   return true;
49 }
50
51 // Given a container with begin and end with ::value_type of a character type.
52 // Iterate through pairs of characters in the the set of [a-fA-F0-9] ignoring
53 // all other characters.
54 struct hex_pair_iterator {
55   StringRef::const_iterator Current, End;
56   typedef SmallVector<char, 2> value_type;
57   value_type Pair;
58   bool IsDone;
59
60   hex_pair_iterator(StringRef C)
61     : Current(C.begin()), End(C.end()), IsDone(false) {
62     // Initalize Pair.
63     ++*this;
64   }
65
66   // End iterator.
67   hex_pair_iterator() : Current(), End(), IsDone(true) {}
68
69   value_type operator *() const {
70     return Pair;
71   }
72
73   hex_pair_iterator operator ++() {
74     // We're at the end of the input.
75     if (Current == End) {
76       IsDone = true;
77       return *this;
78     }
79     Pair = value_type();
80     for (; Current != End && Pair.size() != 2; ++Current) {
81       // Is a valid hex digit.
82       if ((*Current >= '0' && *Current <= '9') ||
83           (*Current >= 'a' && *Current <= 'f') ||
84           (*Current >= 'A' && *Current <= 'F'))
85         Pair.push_back(*Current);
86     }
87     // Hit the end without getting 2 hex digits. Pair is invalid.
88     if (Pair.size() != 2)
89       IsDone = true;
90     return *this;
91   }
92
93   bool operator ==(const hex_pair_iterator Other) {
94     return (IsDone == Other.IsDone) ||
95            (Current == Other.Current && End == Other.End);
96   }
97
98   bool operator !=(const hex_pair_iterator Other) {
99     return !(*this == Other);
100   }
101 };
102
103 template <class ContainerOut>
104 static bool hexStringToByteArray(StringRef Str, ContainerOut &Out) {
105   for (hex_pair_iterator I(Str), E; I != E; ++I) {
106     typename hex_pair_iterator::value_type Pair = *I;
107     typename ContainerOut::value_type Byte;
108     if (StringRef(Pair.data(), 2).getAsInteger(16, Byte))
109       return false;
110     Out.push_back(Byte);
111   }
112   return true;
113 }
114
115 /// This parses a yaml stream that represents a COFF object file.
116 /// See docs/yaml2obj for the yaml scheema.
117 struct COFFParser {
118   COFFParser(yaml::Stream &Input) : YS(Input) {
119     std::memset(&Header, 0, sizeof(Header));
120     // A COFF string table always starts with a 4 byte size field. Offsets into
121     // it include this size, so allocate it now.
122     StringTable.append(4, 0);
123   }
124
125   bool parseHeader(yaml::Node *HeaderN) {
126     yaml::MappingNode *MN = dyn_cast<yaml::MappingNode>(HeaderN);
127     if (!MN) {
128       YS.printError(HeaderN, "header's value must be a mapping node");
129       return false;
130     }
131     for (yaml::MappingNode::iterator i = MN->begin(), e = MN->end();
132                                      i != e; ++i) {
133       yaml::ScalarNode *Key = dyn_cast<yaml::ScalarNode>(i->getKey());
134       if (!Key) {
135         YS.printError(i->getKey(), "Keys must be scalar values");
136         return false;
137       }
138       SmallString<32> Storage;
139       StringRef KeyValue = Key->getValue(Storage);
140       if (KeyValue == "Characteristics") {
141         if (!parseHeaderCharacteristics(i->getValue()))
142           return false;
143       } else {
144         yaml::ScalarNode *Value = dyn_cast<yaml::ScalarNode>(i->getValue());
145         if (!Value) {
146           YS.printError(Value,
147             Twine(KeyValue) + " must be a scalar value");
148           return false;
149         }
150         if (KeyValue == "Machine") {
151           uint16_t Machine;
152           if (!getAs(Value, Machine)) {
153             // It's not a raw number, try matching the string.
154             StringRef ValueValue = Value->getValue(Storage);
155             Machine = StringSwitch<COFF::MachineTypes>(ValueValue)
156               .Case( "IMAGE_FILE_MACHINE_UNKNOWN"
157                    , COFF::IMAGE_FILE_MACHINE_UNKNOWN)
158               .Case( "IMAGE_FILE_MACHINE_AM33"
159                    , COFF::IMAGE_FILE_MACHINE_AM33)
160               .Case( "IMAGE_FILE_MACHINE_AMD64"
161                    , COFF::IMAGE_FILE_MACHINE_AMD64)
162               .Case( "IMAGE_FILE_MACHINE_ARM"
163                    , COFF::IMAGE_FILE_MACHINE_ARM)
164               .Case( "IMAGE_FILE_MACHINE_ARMV7"
165                    , COFF::IMAGE_FILE_MACHINE_ARMV7)
166               .Case( "IMAGE_FILE_MACHINE_EBC"
167                    , COFF::IMAGE_FILE_MACHINE_EBC)
168               .Case( "IMAGE_FILE_MACHINE_I386"
169                    , COFF::IMAGE_FILE_MACHINE_I386)
170               .Case( "IMAGE_FILE_MACHINE_IA64"
171                    , COFF::IMAGE_FILE_MACHINE_IA64)
172               .Case( "IMAGE_FILE_MACHINE_M32R"
173                    , COFF::IMAGE_FILE_MACHINE_M32R)
174               .Case( "IMAGE_FILE_MACHINE_MIPS16"
175                    , COFF::IMAGE_FILE_MACHINE_MIPS16)
176               .Case( "IMAGE_FILE_MACHINE_MIPSFPU"
177                    , COFF::IMAGE_FILE_MACHINE_MIPSFPU)
178               .Case( "IMAGE_FILE_MACHINE_MIPSFPU16"
179                    , COFF::IMAGE_FILE_MACHINE_MIPSFPU16)
180               .Case( "IMAGE_FILE_MACHINE_POWERPC"
181                    , COFF::IMAGE_FILE_MACHINE_POWERPC)
182               .Case( "IMAGE_FILE_MACHINE_POWERPCFP"
183                    , COFF::IMAGE_FILE_MACHINE_POWERPCFP)
184               .Case( "IMAGE_FILE_MACHINE_R4000"
185                    , COFF::IMAGE_FILE_MACHINE_R4000)
186               .Case( "IMAGE_FILE_MACHINE_SH3"
187                    , COFF::IMAGE_FILE_MACHINE_SH3)
188               .Case( "IMAGE_FILE_MACHINE_SH3DSP"
189                    , COFF::IMAGE_FILE_MACHINE_SH3DSP)
190               .Case( "IMAGE_FILE_MACHINE_SH4"
191                    , COFF::IMAGE_FILE_MACHINE_SH4)
192               .Case( "IMAGE_FILE_MACHINE_SH5"
193                    , COFF::IMAGE_FILE_MACHINE_SH5)
194               .Case( "IMAGE_FILE_MACHINE_THUMB"
195                    , COFF::IMAGE_FILE_MACHINE_THUMB)
196               .Case( "IMAGE_FILE_MACHINE_WCEMIPSV2"
197                    , COFF::IMAGE_FILE_MACHINE_WCEMIPSV2)
198               .Default(COFF::MT_Invalid);
199             if (Machine == COFF::MT_Invalid) {
200               YS.printError(Value, "Invalid value for Machine");
201               return false;
202             }
203           }
204           Header.Machine = Machine;
205         } else if (KeyValue == "NumberOfSections") {
206           if (!getAs(Value, Header.NumberOfSections)) {
207               YS.printError(Value, "Invalid value for NumberOfSections");
208               return false;
209           }
210         } else if (KeyValue == "TimeDateStamp") {
211           if (!getAs(Value, Header.TimeDateStamp)) {
212               YS.printError(Value, "Invalid value for TimeDateStamp");
213               return false;
214           }
215         } else if (KeyValue == "PointerToSymbolTable") {
216           if (!getAs(Value, Header.PointerToSymbolTable)) {
217               YS.printError(Value, "Invalid value for PointerToSymbolTable");
218               return false;
219           }
220         } else if (KeyValue == "NumberOfSymbols") {
221           if (!getAs(Value, Header.NumberOfSymbols)) {
222               YS.printError(Value, "Invalid value for NumberOfSymbols");
223               return false;
224           }
225         } else if (KeyValue == "SizeOfOptionalHeader") {
226           if (!getAs(Value, Header.SizeOfOptionalHeader)) {
227               YS.printError(Value, "Invalid value for SizeOfOptionalHeader");
228               return false;
229           }
230         } else {
231           YS.printError(Key, "Unrecognized key in header");
232           return false;
233         }
234       }
235     }
236     return true;
237   }
238
239   bool parseHeaderCharacteristics(yaml::Node *Characteristics) {
240     yaml::ScalarNode *Value = dyn_cast<yaml::ScalarNode>(Characteristics);
241     yaml::SequenceNode *SeqValue
242       = dyn_cast<yaml::SequenceNode>(Characteristics);
243     if (!Value && !SeqValue) {
244       YS.printError(Characteristics,
245         "Characteristics must either be a number or sequence");
246       return false;
247     }
248     if (Value) {
249       if (!getAs(Value, Header.Characteristics)) {
250         YS.printError(Value, "Invalid value for Characteristics");
251         return false;
252       }
253     } else {
254       for (yaml::SequenceNode::iterator ci = SeqValue->begin(),
255                                         ce = SeqValue->end();
256                                         ci != ce; ++ci) {
257         yaml::ScalarNode *CharValue = dyn_cast<yaml::ScalarNode>(&*ci);
258         if (!CharValue) {
259           YS.printError(CharValue,
260             "Characteristics must be scalar values");
261           return false;
262         }
263         SmallString<32> Storage;
264         StringRef Char = CharValue->getValue(Storage);
265         uint16_t Characteristic = StringSwitch<COFF::Characteristics>(Char)
266           .Case( "IMAGE_FILE_RELOCS_STRIPPED"
267                 , COFF::IMAGE_FILE_RELOCS_STRIPPED)
268           .Case( "IMAGE_FILE_EXECUTABLE_IMAGE"
269                 , COFF::IMAGE_FILE_EXECUTABLE_IMAGE)
270           .Case( "IMAGE_FILE_LINE_NUMS_STRIPPED"
271                 , COFF::IMAGE_FILE_LINE_NUMS_STRIPPED)
272           .Case( "IMAGE_FILE_LOCAL_SYMS_STRIPPED"
273                 , COFF::IMAGE_FILE_LOCAL_SYMS_STRIPPED)
274           .Case( "IMAGE_FILE_AGGRESSIVE_WS_TRIM"
275                 , COFF::IMAGE_FILE_AGGRESSIVE_WS_TRIM)
276           .Case( "IMAGE_FILE_LARGE_ADDRESS_AWARE"
277                 , COFF::IMAGE_FILE_LARGE_ADDRESS_AWARE)
278           .Case( "IMAGE_FILE_BYTES_REVERSED_LO"
279                 , COFF::IMAGE_FILE_BYTES_REVERSED_LO)
280           .Case( "IMAGE_FILE_32BIT_MACHINE"
281                 , COFF::IMAGE_FILE_32BIT_MACHINE)
282           .Case( "IMAGE_FILE_DEBUG_STRIPPED"
283                 , COFF::IMAGE_FILE_DEBUG_STRIPPED)
284           .Case( "IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP"
285                 , COFF::IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP)
286           .Case( "IMAGE_FILE_SYSTEM"
287                 , COFF::IMAGE_FILE_SYSTEM)
288           .Case( "IMAGE_FILE_DLL"
289                 , COFF::IMAGE_FILE_DLL)
290           .Case( "IMAGE_FILE_UP_SYSTEM_ONLY"
291                 , COFF::IMAGE_FILE_UP_SYSTEM_ONLY)
292           .Default(COFF::C_Invalid);
293         if (Characteristic == COFF::C_Invalid) {
294           // TODO: Typo-correct.
295           YS.printError(CharValue,
296             "Invalid value for Characteristic");
297           return false;
298         }
299         Header.Characteristics |= Characteristic;
300       }
301     }
302     return true;
303   }
304
305   bool parseSections(yaml::Node *SectionsN) {
306     yaml::SequenceNode *SN = dyn_cast<yaml::SequenceNode>(SectionsN);
307     if (!SN) {
308       YS.printError(SectionsN, "Sections must be a sequence");
309       return false;
310     }
311     for (yaml::SequenceNode::iterator i = SN->begin(), e = SN->end();
312                                       i != e; ++i) {
313       Section Sec;
314       std::memset(&Sec.Header, 0, sizeof(Sec.Header));
315       yaml::MappingNode *SecMap = dyn_cast<yaml::MappingNode>(&*i);
316       if (!SecMap) {
317         YS.printError(&*i, "Section entry must be a map");
318         return false;
319       }
320       for (yaml::MappingNode::iterator si = SecMap->begin(), se = SecMap->end();
321                                        si != se; ++si) {
322         yaml::ScalarNode *Key = dyn_cast<yaml::ScalarNode>(si->getKey());
323         if (!Key) {
324           YS.printError(si->getKey(), "Keys must be scalar values");
325           return false;
326         }
327         SmallString<32> Storage;
328         StringRef KeyValue = Key->getValue(Storage);
329
330         yaml::ScalarNode *Value = dyn_cast<yaml::ScalarNode>(si->getValue());
331         if (KeyValue == "Name") {
332           // If the name is less than 8 bytes, store it in place, otherwise
333           // store it in the string table.
334           StringRef Name = Value->getValue(Storage);
335           std::fill_n(Sec.Header.Name, unsigned(COFF::NameSize), 0);
336           if (Name.size() <= COFF::NameSize) {
337             std::copy(Name.begin(), Name.end(), Sec.Header.Name);
338           } else {
339             // Add string to the string table and format the index for output.
340             unsigned Index = getStringIndex(Name);
341             std::string str = utostr(Index);
342             if (str.size() > 7) {
343               YS.printError(Value, "String table got too large");
344               return false;
345             }
346             Sec.Header.Name[0] = '/';
347             std::copy(str.begin(), str.end(), Sec.Header.Name + 1);
348           }
349         } else if (KeyValue == "VirtualSize") {
350           if (!getAs(Value, Sec.Header.VirtualSize)) {
351             YS.printError(Value, "Invalid value for VirtualSize");
352             return false;
353           }
354         } else if (KeyValue == "VirtualAddress") {
355           if (!getAs(Value, Sec.Header.VirtualAddress)) {
356             YS.printError(Value, "Invalid value for VirtualAddress");
357             return false;
358           }
359         } else if (KeyValue == "SizeOfRawData") {
360           if (!getAs(Value, Sec.Header.SizeOfRawData)) {
361             YS.printError(Value, "Invalid value for SizeOfRawData");
362             return false;
363           }
364         } else if (KeyValue == "PointerToRawData") {
365           if (!getAs(Value, Sec.Header.PointerToRawData)) {
366             YS.printError(Value, "Invalid value for PointerToRawData");
367             return false;
368           }
369         } else if (KeyValue == "PointerToRelocations") {
370           if (!getAs(Value, Sec.Header.PointerToRelocations)) {
371             YS.printError(Value, "Invalid value for PointerToRelocations");
372             return false;
373           }
374         } else if (KeyValue == "PointerToLineNumbers") {
375           if (!getAs(Value, Sec.Header.PointerToLineNumbers)) {
376             YS.printError(Value, "Invalid value for PointerToLineNumbers");
377             return false;
378           }
379         } else if (KeyValue == "NumberOfRelocations") {
380           if (!getAs(Value, Sec.Header.NumberOfRelocations)) {
381             YS.printError(Value, "Invalid value for NumberOfRelocations");
382             return false;
383           }
384         } else if (KeyValue == "NumberOfLineNumbers") {
385           if (!getAs(Value, Sec.Header.NumberOfLineNumbers)) {
386             YS.printError(Value, "Invalid value for NumberOfLineNumbers");
387             return false;
388           }
389         } else if (KeyValue == "Characteristics") {
390           yaml::SequenceNode *SeqValue
391             = dyn_cast<yaml::SequenceNode>(si->getValue());
392           if (!Value && !SeqValue) {
393             YS.printError(si->getValue(),
394               "Characteristics must either be a number or sequence");
395             return false;
396           }
397           if (Value) {
398             if (!getAs(Value, Sec.Header.Characteristics)) {
399               YS.printError(Value, "Invalid value for Characteristics");
400               return false;
401             }
402           } else {
403             for (yaml::SequenceNode::iterator ci = SeqValue->begin(),
404                                               ce = SeqValue->end();
405                                               ci != ce; ++ci) {
406               yaml::ScalarNode *CharValue = dyn_cast<yaml::ScalarNode>(&*ci);
407               if (!CharValue) {
408                 YS.printError(CharValue, "Invalid value for Characteristics");
409                 return false;
410               }
411               StringRef Char = CharValue->getValue(Storage);
412               uint32_t Characteristic =
413                 StringSwitch<COFF::SectionCharacteristics>(Char)
414                 .Case( "IMAGE_SCN_TYPE_NO_PAD"
415                      , COFF::IMAGE_SCN_TYPE_NO_PAD)
416                 .Case( "IMAGE_SCN_CNT_CODE"
417                      , COFF::IMAGE_SCN_CNT_CODE)
418                 .Case( "IMAGE_SCN_CNT_INITIALIZED_DATA"
419                      , COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
420                 .Case( "IMAGE_SCN_CNT_UNINITIALIZED_DATA"
421                      , COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
422                 .Case( "IMAGE_SCN_LNK_OTHER"
423                      , COFF::IMAGE_SCN_LNK_OTHER)
424                 .Case( "IMAGE_SCN_LNK_INFO"
425                      , COFF::IMAGE_SCN_LNK_INFO)
426                 .Case( "IMAGE_SCN_LNK_REMOVE"
427                      , COFF::IMAGE_SCN_LNK_REMOVE)
428                 .Case( "IMAGE_SCN_LNK_COMDAT"
429                      , COFF::IMAGE_SCN_LNK_COMDAT)
430                 .Case( "IMAGE_SCN_GPREL"
431                      , COFF::IMAGE_SCN_GPREL)
432                 .Case( "IMAGE_SCN_MEM_PURGEABLE"
433                      , COFF::IMAGE_SCN_MEM_PURGEABLE)
434                 .Case( "IMAGE_SCN_MEM_16BIT"
435                      , COFF::IMAGE_SCN_MEM_16BIT)
436                 .Case( "IMAGE_SCN_MEM_LOCKED"
437                      , COFF::IMAGE_SCN_MEM_LOCKED)
438                 .Case( "IMAGE_SCN_MEM_PRELOAD"
439                      , COFF::IMAGE_SCN_MEM_PRELOAD)
440                 .Case( "IMAGE_SCN_ALIGN_1BYTES"
441                      , COFF::IMAGE_SCN_ALIGN_1BYTES)
442                 .Case( "IMAGE_SCN_ALIGN_2BYTES"
443                      , COFF::IMAGE_SCN_ALIGN_2BYTES)
444                 .Case( "IMAGE_SCN_ALIGN_4BYTES"
445                      , COFF::IMAGE_SCN_ALIGN_4BYTES)
446                 .Case( "IMAGE_SCN_ALIGN_8BYTES"
447                      , COFF::IMAGE_SCN_ALIGN_8BYTES)
448                 .Case( "IMAGE_SCN_ALIGN_16BYTES"
449                      , COFF::IMAGE_SCN_ALIGN_16BYTES)
450                 .Case( "IMAGE_SCN_ALIGN_32BYTES"
451                      , COFF::IMAGE_SCN_ALIGN_32BYTES)
452                 .Case( "IMAGE_SCN_ALIGN_64BYTES"
453                      , COFF::IMAGE_SCN_ALIGN_64BYTES)
454                 .Case( "IMAGE_SCN_ALIGN_128BYTES"
455                      , COFF::IMAGE_SCN_ALIGN_128BYTES)
456                 .Case( "IMAGE_SCN_ALIGN_256BYTES"
457                      , COFF::IMAGE_SCN_ALIGN_256BYTES)
458                 .Case( "IMAGE_SCN_ALIGN_512BYTES"
459                      , COFF::IMAGE_SCN_ALIGN_512BYTES)
460                 .Case( "IMAGE_SCN_ALIGN_1024BYTES"
461                      , COFF::IMAGE_SCN_ALIGN_1024BYTES)
462                 .Case( "IMAGE_SCN_ALIGN_2048BYTES"
463                      , COFF::IMAGE_SCN_ALIGN_2048BYTES)
464                 .Case( "IMAGE_SCN_ALIGN_4096BYTES"
465                      , COFF::IMAGE_SCN_ALIGN_4096BYTES)
466                 .Case( "IMAGE_SCN_ALIGN_8192BYTES"
467                      , COFF::IMAGE_SCN_ALIGN_8192BYTES)
468                 .Case( "IMAGE_SCN_LNK_NRELOC_OVFL"
469                      , COFF::IMAGE_SCN_LNK_NRELOC_OVFL)
470                 .Case( "IMAGE_SCN_MEM_DISCARDABLE"
471                      , COFF::IMAGE_SCN_MEM_DISCARDABLE)
472                 .Case( "IMAGE_SCN_MEM_NOT_CACHED"
473                      , COFF::IMAGE_SCN_MEM_NOT_CACHED)
474                 .Case( "IMAGE_SCN_MEM_NOT_PAGED"
475                      , COFF::IMAGE_SCN_MEM_NOT_PAGED)
476                 .Case( "IMAGE_SCN_MEM_SHARED"
477                      , COFF::IMAGE_SCN_MEM_SHARED)
478                 .Case( "IMAGE_SCN_MEM_EXECUTE"
479                      , COFF::IMAGE_SCN_MEM_EXECUTE)
480                 .Case( "IMAGE_SCN_MEM_READ"
481                      , COFF::IMAGE_SCN_MEM_READ)
482                 .Case( "IMAGE_SCN_MEM_WRITE"
483                      , COFF::IMAGE_SCN_MEM_WRITE)
484                 .Default(COFF::SC_Invalid);
485               if (Characteristic == COFF::SC_Invalid) {
486                 YS.printError(CharValue, "Invalid value for Characteristic");
487                 return false;
488               }
489               Sec.Header.Characteristics |= Characteristic;
490             }
491           }
492         } else if (KeyValue == "SectionData") {
493           yaml::ScalarNode *Value = dyn_cast<yaml::ScalarNode>(si->getValue());
494           SmallString<32> Storage;
495           StringRef Data = Value->getValue(Storage);
496           if (!hexStringToByteArray(Data, Sec.Data)) {
497             YS.printError(Value, "SectionData must be a collection of pairs of"
498                                  "hex bytes");
499             return false;
500           }
501         } else
502           si->skip();
503       }
504       Sections.push_back(Sec);
505     }
506     return true;
507   }
508
509   bool parseSymbols(yaml::Node *SymbolsN) {
510     yaml::SequenceNode *SN = dyn_cast<yaml::SequenceNode>(SymbolsN);
511     if (!SN) {
512       YS.printError(SymbolsN, "Symbols must be a sequence");
513       return false;
514     }
515     for (yaml::SequenceNode::iterator i = SN->begin(), e = SN->end();
516                                       i != e; ++i) {
517       Symbol Sym;
518       std::memset(&Sym.Header, 0, sizeof(Sym.Header));
519       yaml::MappingNode *SymMap = dyn_cast<yaml::MappingNode>(&*i);
520       if (!SymMap) {
521         YS.printError(&*i, "Symbol must be a map");
522         return false;
523       }
524       for (yaml::MappingNode::iterator si = SymMap->begin(), se = SymMap->end();
525                                        si != se; ++si) {
526         yaml::ScalarNode *Key = dyn_cast<yaml::ScalarNode>(si->getKey());
527         if (!Key) {
528           YS.printError(si->getKey(), "Keys must be scalar values");
529           return false;
530         }
531         SmallString<32> Storage;
532         StringRef KeyValue = Key->getValue(Storage);
533
534         yaml::ScalarNode *Value = dyn_cast<yaml::ScalarNode>(si->getValue());
535         if (!Value) {
536           YS.printError(si->getValue(), "Must be a scalar value");
537           return false;
538         }
539         if (KeyValue == "Name") {
540           // If the name is less than 8 bytes, store it in place, otherwise
541           // store it in the string table.
542           StringRef Name = Value->getValue(Storage);
543           std::fill_n(Sym.Header.Name, unsigned(COFF::NameSize), 0);
544           if (Name.size() <= COFF::NameSize) {
545             std::copy(Name.begin(), Name.end(), Sym.Header.Name);
546           } else {
547             // Add string to the string table and format the index for output.
548             unsigned Index = getStringIndex(Name);
549             *reinterpret_cast<support::aligned_ulittle32_t*>(
550               Sym.Header.Name + 4) = Index;
551           }
552         } else if (KeyValue == "Value") {
553           if (!getAs(Value, Sym.Header.Value)) {
554             YS.printError(Value, "Invalid value for Value");
555             return false;
556           }
557         } else if (KeyValue == "SimpleType") {
558           Sym.Header.Type |= StringSwitch<COFF::SymbolBaseType>(
559             Value->getValue(Storage))
560             .Case("IMAGE_SYM_TYPE_NULL", COFF::IMAGE_SYM_TYPE_NULL)
561             .Case("IMAGE_SYM_TYPE_VOID", COFF::IMAGE_SYM_TYPE_VOID)
562             .Case("IMAGE_SYM_TYPE_CHAR", COFF::IMAGE_SYM_TYPE_CHAR)
563             .Case("IMAGE_SYM_TYPE_SHORT", COFF::IMAGE_SYM_TYPE_SHORT)
564             .Case("IMAGE_SYM_TYPE_INT", COFF::IMAGE_SYM_TYPE_INT)
565             .Case("IMAGE_SYM_TYPE_LONG", COFF::IMAGE_SYM_TYPE_LONG)
566             .Case("IMAGE_SYM_TYPE_FLOAT", COFF::IMAGE_SYM_TYPE_FLOAT)
567             .Case("IMAGE_SYM_TYPE_DOUBLE", COFF::IMAGE_SYM_TYPE_DOUBLE)
568             .Case("IMAGE_SYM_TYPE_STRUCT", COFF::IMAGE_SYM_TYPE_STRUCT)
569             .Case("IMAGE_SYM_TYPE_UNION", COFF::IMAGE_SYM_TYPE_UNION)
570             .Case("IMAGE_SYM_TYPE_ENUM", COFF::IMAGE_SYM_TYPE_ENUM)
571             .Case("IMAGE_SYM_TYPE_MOE", COFF::IMAGE_SYM_TYPE_MOE)
572             .Case("IMAGE_SYM_TYPE_BYTE", COFF::IMAGE_SYM_TYPE_BYTE)
573             .Case("IMAGE_SYM_TYPE_WORD", COFF::IMAGE_SYM_TYPE_WORD)
574             .Case("IMAGE_SYM_TYPE_UINT", COFF::IMAGE_SYM_TYPE_UINT)
575             .Case("IMAGE_SYM_TYPE_DWORD", COFF::IMAGE_SYM_TYPE_DWORD)
576             .Default(COFF::IMAGE_SYM_TYPE_NULL);
577         } else if (KeyValue == "ComplexType") {
578           Sym.Header.Type |= StringSwitch<COFF::SymbolComplexType>(
579             Value->getValue(Storage))
580             .Case("IMAGE_SYM_DTYPE_NULL", COFF::IMAGE_SYM_DTYPE_NULL)
581             .Case("IMAGE_SYM_DTYPE_POINTER", COFF::IMAGE_SYM_DTYPE_POINTER)
582             .Case("IMAGE_SYM_DTYPE_FUNCTION", COFF::IMAGE_SYM_DTYPE_FUNCTION)
583             .Case("IMAGE_SYM_DTYPE_ARRAY", COFF::IMAGE_SYM_DTYPE_ARRAY)
584             .Default(COFF::IMAGE_SYM_DTYPE_NULL)
585             << COFF::SCT_COMPLEX_TYPE_SHIFT;
586         } else if (KeyValue == "StorageClass") {
587           Sym.Header.StorageClass = StringSwitch<COFF::SymbolStorageClass>(
588             Value->getValue(Storage))
589             .Case( "IMAGE_SYM_CLASS_END_OF_FUNCTION"
590                  , COFF::IMAGE_SYM_CLASS_END_OF_FUNCTION)
591             .Case( "IMAGE_SYM_CLASS_NULL"
592                  , COFF::IMAGE_SYM_CLASS_NULL)
593             .Case( "IMAGE_SYM_CLASS_AUTOMATIC"
594                  , COFF::IMAGE_SYM_CLASS_AUTOMATIC)
595             .Case( "IMAGE_SYM_CLASS_EXTERNAL"
596                  , COFF::IMAGE_SYM_CLASS_EXTERNAL)
597             .Case( "IMAGE_SYM_CLASS_STATIC"
598                  , COFF::IMAGE_SYM_CLASS_STATIC)
599             .Case( "IMAGE_SYM_CLASS_REGISTER"
600                  , COFF::IMAGE_SYM_CLASS_REGISTER)
601             .Case( "IMAGE_SYM_CLASS_EXTERNAL_DEF"
602                  , COFF::IMAGE_SYM_CLASS_EXTERNAL_DEF)
603             .Case( "IMAGE_SYM_CLASS_LABEL"
604                  , COFF::IMAGE_SYM_CLASS_LABEL)
605             .Case( "IMAGE_SYM_CLASS_UNDEFINED_LABEL"
606                  , COFF::IMAGE_SYM_CLASS_UNDEFINED_LABEL)
607             .Case( "IMAGE_SYM_CLASS_MEMBER_OF_STRUCT"
608                  , COFF::IMAGE_SYM_CLASS_MEMBER_OF_STRUCT)
609             .Case( "IMAGE_SYM_CLASS_ARGUMENT"
610                  , COFF::IMAGE_SYM_CLASS_ARGUMENT)
611             .Case( "IMAGE_SYM_CLASS_STRUCT_TAG"
612                  , COFF::IMAGE_SYM_CLASS_STRUCT_TAG)
613             .Case( "IMAGE_SYM_CLASS_MEMBER_OF_UNION"
614                  , COFF::IMAGE_SYM_CLASS_MEMBER_OF_UNION)
615             .Case( "IMAGE_SYM_CLASS_UNION_TAG"
616                  , COFF::IMAGE_SYM_CLASS_UNION_TAG)
617             .Case( "IMAGE_SYM_CLASS_TYPE_DEFINITION"
618                  , COFF::IMAGE_SYM_CLASS_TYPE_DEFINITION)
619             .Case( "IMAGE_SYM_CLASS_UNDEFINED_STATIC"
620                  , COFF::IMAGE_SYM_CLASS_UNDEFINED_STATIC)
621             .Case( "IMAGE_SYM_CLASS_ENUM_TAG"
622                  , COFF::IMAGE_SYM_CLASS_ENUM_TAG)
623             .Case( "IMAGE_SYM_CLASS_MEMBER_OF_ENUM"
624                  , COFF::IMAGE_SYM_CLASS_MEMBER_OF_ENUM)
625             .Case( "IMAGE_SYM_CLASS_REGISTER_PARAM"
626                  , COFF::IMAGE_SYM_CLASS_REGISTER_PARAM)
627             .Case( "IMAGE_SYM_CLASS_BIT_FIELD"
628                  , COFF::IMAGE_SYM_CLASS_BIT_FIELD)
629             .Case( "IMAGE_SYM_CLASS_BLOCK"
630                  , COFF::IMAGE_SYM_CLASS_BLOCK)
631             .Case( "IMAGE_SYM_CLASS_FUNCTION"
632                  , COFF::IMAGE_SYM_CLASS_FUNCTION)
633             .Case( "IMAGE_SYM_CLASS_END_OF_STRUCT"
634                  , COFF::IMAGE_SYM_CLASS_END_OF_STRUCT)
635             .Case( "IMAGE_SYM_CLASS_FILE"
636                  , COFF::IMAGE_SYM_CLASS_FILE)
637             .Case( "IMAGE_SYM_CLASS_SECTION"
638                  , COFF::IMAGE_SYM_CLASS_SECTION)
639             .Case( "IMAGE_SYM_CLASS_WEAK_EXTERNAL"
640                  , COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL)
641             .Case( "IMAGE_SYM_CLASS_CLR_TOKEN"
642                  , COFF::IMAGE_SYM_CLASS_CLR_TOKEN)
643             .Default(COFF::SSC_Invalid);
644           if (Sym.Header.StorageClass == COFF::SSC_Invalid) {
645             YS.printError(Value, "Invalid value for StorageClass");
646             return false;
647           }
648         } else if (KeyValue == "SectionNumber") {
649           if (!getAs(Value, Sym.Header.SectionNumber)) {
650               YS.printError(Value, "Invalid value for SectionNumber");
651               return false;
652           }
653         } else if (KeyValue == "AuxillaryData") {
654           StringRef Data = Value->getValue(Storage);
655           if (!hexStringToByteArray(Data, Sym.AuxSymbols)) {
656             YS.printError(Value, "AuxillaryData must be a collection of pairs"
657                                  "of hex bytes");
658             return false;
659           }
660         } else
661           si->skip();
662       }
663       Symbols.push_back(Sym);
664     }
665     return true;
666   }
667
668   bool parse() {
669     yaml::Document &D = *YS.begin();
670     yaml::MappingNode *Root = dyn_cast<yaml::MappingNode>(D.getRoot());
671     if (!Root) {
672       YS.printError(D.getRoot(), "Root node must be a map");
673       return false;
674     }
675     for (yaml::MappingNode::iterator i = Root->begin(), e = Root->end();
676                                      i != e; ++i) {
677       yaml::ScalarNode *Key = dyn_cast<yaml::ScalarNode>(i->getKey());
678       if (!Key) {
679         YS.printError(i->getKey(), "Keys must be scalar values");
680         return false;
681       }
682       SmallString<32> Storage;
683       StringRef KeyValue = Key->getValue(Storage);
684       if (KeyValue == "header") {
685         if (!parseHeader(i->getValue()))
686           return false;
687       } else if (KeyValue == "sections") {
688         if (!parseSections(i->getValue()))
689           return false;
690       } else if (KeyValue == "symbols") {
691         if (!parseSymbols(i->getValue()))
692           return false;
693       }
694     }
695     return !YS.failed();
696   }
697
698   unsigned getStringIndex(StringRef Str) {
699     StringMap<unsigned>::iterator i = StringTableMap.find(Str);
700     if (i == StringTableMap.end()) {
701       unsigned Index = StringTable.size();
702       StringTable.append(Str.begin(), Str.end());
703       StringTable.push_back(0);
704       StringTableMap[Str] = Index;
705       return Index;
706     }
707     return i->second;
708   }
709
710   yaml::Stream &YS;
711   COFF::header Header;
712
713   struct Section {
714     COFF::section Header;
715     std::vector<uint8_t> Data;
716     std::vector<COFF::relocation> Relocations;
717   };
718
719   struct Symbol {
720     COFF::symbol Header;
721     std::vector<uint8_t> AuxSymbols;
722   };
723
724   std::vector<Section> Sections;
725   std::vector<Symbol> Symbols;
726   StringMap<unsigned> StringTableMap;
727   std::string StringTable;
728 };
729
730 // Take a CP and assign addresses and sizes to everything. Returns false if the
731 // layout is not valid to do.
732 static bool layoutCOFF(COFFParser &CP) {
733   uint32_t SectionTableStart = 0;
734   uint32_t SectionTableSize  = 0;
735
736   // The section table starts immediately after the header, including the
737   // optional header.
738   SectionTableStart = sizeof(COFF::header) + CP.Header.SizeOfOptionalHeader;
739   SectionTableSize = sizeof(COFF::section) * CP.Sections.size();
740
741   uint32_t CurrentSectionDataOffset = SectionTableStart + SectionTableSize;
742
743   // Assign each section data address consecutively.
744   for (std::vector<COFFParser::Section>::iterator i = CP.Sections.begin(),
745                                                   e = CP.Sections.end();
746                                                   i != e; ++i) {
747     if (!i->Data.empty()) {
748       i->Header.SizeOfRawData = i->Data.size();
749       i->Header.PointerToRawData = CurrentSectionDataOffset;
750       CurrentSectionDataOffset += i->Header.SizeOfRawData;
751       // TODO: Handle alignment.
752     } else {
753       i->Header.SizeOfRawData = 0;
754       i->Header.PointerToRawData = 0;
755     }
756   }
757
758   uint32_t SymbolTableStart = CurrentSectionDataOffset;
759
760   // Calculate number of symbols.
761   uint32_t NumberOfSymbols = 0;
762   for (std::vector<COFFParser::Symbol>::iterator i = CP.Symbols.begin(),
763                                                  e = CP.Symbols.end();
764                                                  i != e; ++i) {
765     if (i->AuxSymbols.size() % COFF::SymbolSize != 0) {
766       errs() << "AuxillaryData size not a multiple of symbol size!\n";
767       return false;
768     }
769     i->Header.NumberOfAuxSymbols = i->AuxSymbols.size() / COFF::SymbolSize;
770     NumberOfSymbols += 1 + i->Header.NumberOfAuxSymbols;
771   }
772
773   // Store all the allocated start addresses in the header.
774   CP.Header.NumberOfSections = CP.Sections.size();
775   CP.Header.NumberOfSymbols = NumberOfSymbols;
776   CP.Header.PointerToSymbolTable = SymbolTableStart;
777
778   *reinterpret_cast<support::ulittle32_t *>(&CP.StringTable[0])
779     = CP.StringTable.size();
780
781   return true;
782 }
783
784 template <typename value_type>
785 struct binary_le_impl {
786   value_type Value;
787   binary_le_impl(value_type V) : Value(V) {}
788 };
789
790 template <typename value_type>
791 raw_ostream &operator <<( raw_ostream &OS
792                         , const binary_le_impl<value_type> &BLE) {
793   char Buffer[sizeof(BLE.Value)];
794   support::endian::write_le<value_type, support::unaligned>(Buffer, BLE.Value);
795   OS.write(Buffer, sizeof(BLE.Value));
796   return OS;
797 }
798
799 template <typename value_type>
800 binary_le_impl<value_type> binary_le(value_type V) {
801   return binary_le_impl<value_type>(V);
802 }
803
804 void writeCOFF(COFFParser &CP, raw_ostream &OS) {
805   OS << binary_le(CP.Header.Machine)
806      << binary_le(CP.Header.NumberOfSections)
807      << binary_le(CP.Header.TimeDateStamp)
808      << binary_le(CP.Header.PointerToSymbolTable)
809      << binary_le(CP.Header.NumberOfSymbols)
810      << binary_le(CP.Header.SizeOfOptionalHeader)
811      << binary_le(CP.Header.Characteristics);
812
813   // Output section table.
814   for (std::vector<COFFParser::Section>::const_iterator i = CP.Sections.begin(),
815                                                         e = CP.Sections.end();
816                                                         i != e; ++i) {
817     OS.write(i->Header.Name, COFF::NameSize);
818     OS << binary_le(i->Header.VirtualSize)
819        << binary_le(i->Header.VirtualAddress)
820        << binary_le(i->Header.SizeOfRawData)
821        << binary_le(i->Header.PointerToRawData)
822        << binary_le(i->Header.PointerToRelocations)
823        << binary_le(i->Header.PointerToLineNumbers)
824        << binary_le(i->Header.NumberOfRelocations)
825        << binary_le(i->Header.NumberOfLineNumbers)
826        << binary_le(i->Header.Characteristics);
827   }
828
829   // Output section data.
830   for (std::vector<COFFParser::Section>::const_iterator i = CP.Sections.begin(),
831                                                         e = CP.Sections.end();
832                                                         i != e; ++i) {
833     if (!i->Data.empty())
834       OS.write(reinterpret_cast<const char*>(&i->Data[0]), i->Data.size());
835   }
836
837   // Output symbol table.
838
839   for (std::vector<COFFParser::Symbol>::const_iterator i = CP.Symbols.begin(),
840                                                        e = CP.Symbols.end();
841                                                        i != e; ++i) {
842     OS.write(i->Header.Name, COFF::NameSize);
843     OS << binary_le(i->Header.Value)
844        << binary_le(i->Header.SectionNumber)
845        << binary_le(i->Header.Type)
846        << binary_le(i->Header.StorageClass)
847        << binary_le(i->Header.NumberOfAuxSymbols);
848     if (!i->AuxSymbols.empty())
849       OS.write( reinterpret_cast<const char*>(&i->AuxSymbols[0])
850               , i->AuxSymbols.size());
851   }
852
853   // Output string table.
854   OS.write(&CP.StringTable[0], CP.StringTable.size());
855 }
856
857 int main(int argc, char **argv) {
858   cl::ParseCommandLineOptions(argc, argv);
859   sys::PrintStackTraceOnErrorSignal();
860   PrettyStackTraceProgram X(argc, argv);
861   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
862
863   OwningPtr<MemoryBuffer> Buf;
864   if (MemoryBuffer::getFileOrSTDIN(Input, Buf))
865     return 1;
866
867   SourceMgr SM;
868   yaml::Stream S(Buf->getBuffer(), SM);
869   COFFParser CP(S);
870   if (!CP.parse()) {
871     errs() << "yaml2obj: Failed to parse YAML file!\n";
872     return 1;
873   }
874   if (!layoutCOFF(CP)) {
875     errs() << "yaml2obj: Failed to layout COFF file!\n";
876     return 1;
877   }
878   writeCOFF(CP, outs());
879 }