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