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