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