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