1 //===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===// 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 file declares the COFFObjectFile class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Object/COFF.h" 15 #include "llvm/ADT/ArrayRef.h" 16 #include "llvm/ADT/SmallString.h" 17 #include "llvm/ADT/StringSwitch.h" 18 #include "llvm/ADT/Triple.h" 19 20 using namespace llvm; 21 using namespace object; 22 23 namespace { 24 using support::ulittle8_t; 25 using support::ulittle16_t; 26 using support::ulittle32_t; 27 using support::little16_t; 28 } 29 30 namespace { 31 // Returns false if size is greater than the buffer size. And sets ec. 32 bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) { 33 if (m->getBufferSize() < size) { 34 ec = object_error::unexpected_eof; 35 return false; 36 } 37 return true; 38 } 39 40 // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 41 // Returns unexpected_eof if error. 42 template<typename T> 43 error_code getObject(const T *&Obj, const MemoryBuffer *M, const uint8_t *Ptr, 44 const size_t Size = sizeof(T)) { 45 uintptr_t Addr = uintptr_t(Ptr); 46 if (Addr + Size < Addr || 47 Addr + Size < Size || 48 Addr + Size > uintptr_t(M->getBufferEnd())) { 49 return object_error::unexpected_eof; 50 } 51 Obj = reinterpret_cast<const T *>(Addr); 52 return object_error::success; 53 } 54 } 55 56 const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const { 57 const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p); 58 59 # ifndef NDEBUG 60 // Verify that the symbol points to a valid entry in the symbol table. 61 uintptr_t offset = uintptr_t(addr) - uintptr_t(base()); 62 if (offset < COFFHeader->PointerToSymbolTable 63 || offset >= COFFHeader->PointerToSymbolTable 64 + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) 65 report_fatal_error("Symbol was outside of symbol table."); 66 67 assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) 68 == 0 && "Symbol did not point to the beginning of a symbol"); 69 # endif 70 71 return addr; 72 } 73 74 const coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const { 75 const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p); 76 77 # ifndef NDEBUG 78 // Verify that the section points to a valid entry in the section table. 79 if (addr < SectionTable 80 || addr >= (SectionTable + COFFHeader->NumberOfSections)) 81 report_fatal_error("Section was outside of section table."); 82 83 uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable); 84 assert(offset % sizeof(coff_section) == 0 && 85 "Section did not point to the beginning of a section"); 86 # endif 87 88 return addr; 89 } 90 91 error_code COFFObjectFile::getSymbolNext(DataRefImpl Symb, 92 SymbolRef &Result) const { 93 const coff_symbol *symb = toSymb(Symb); 94 symb += 1 + symb->NumberOfAuxSymbols; 95 Symb.p = reinterpret_cast<uintptr_t>(symb); 96 Result = SymbolRef(Symb, this); 97 return object_error::success; 98 } 99 100 error_code COFFObjectFile::getSymbolName(DataRefImpl Symb, 101 StringRef &Result) const { 102 const coff_symbol *symb = toSymb(Symb); 103 return getSymbolName(symb, Result); 104 } 105 106 error_code COFFObjectFile::getSymbolFileOffset(DataRefImpl Symb, 107 uint64_t &Result) const { 108 const coff_symbol *symb = toSymb(Symb); 109 const coff_section *Section = NULL; 110 if (error_code ec = getSection(symb->SectionNumber, Section)) 111 return ec; 112 char Type; 113 if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 114 return ec; 115 if (Type == 'U' || Type == 'w') 116 Result = UnknownAddressOrSize; 117 else if (Section) 118 Result = Section->PointerToRawData + symb->Value; 119 else 120 Result = symb->Value; 121 return object_error::success; 122 } 123 124 error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, 125 uint64_t &Result) const { 126 const coff_symbol *symb = toSymb(Symb); 127 const coff_section *Section = NULL; 128 if (error_code ec = getSection(symb->SectionNumber, Section)) 129 return ec; 130 char Type; 131 if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 132 return ec; 133 if (Type == 'U' || Type == 'w') 134 Result = UnknownAddressOrSize; 135 else if (Section) 136 Result = Section->VirtualAddress + symb->Value; 137 else 138 Result = symb->Value; 139 return object_error::success; 140 } 141 142 error_code COFFObjectFile::getSymbolType(DataRefImpl Symb, 143 SymbolRef::Type &Result) const { 144 const coff_symbol *symb = toSymb(Symb); 145 Result = SymbolRef::ST_Other; 146 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 147 symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { 148 Result = SymbolRef::ST_Unknown; 149 } else { 150 if (symb->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { 151 Result = SymbolRef::ST_Function; 152 } else { 153 char Type; 154 if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 155 return ec; 156 if (Type == 'r' || Type == 'R') { 157 Result = SymbolRef::ST_Data; 158 } 159 } 160 } 161 return object_error::success; 162 } 163 164 error_code COFFObjectFile::getSymbolFlags(DataRefImpl Symb, 165 uint32_t &Result) const { 166 const coff_symbol *symb = toSymb(Symb); 167 Result = SymbolRef::SF_None; 168 169 // TODO: Correctly set SF_FormatSpecific, SF_ThreadLocal, SF_Common 170 171 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 172 symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) 173 Result |= SymbolRef::SF_Undefined; 174 175 // TODO: This are certainly too restrictive. 176 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) 177 Result |= SymbolRef::SF_Global; 178 179 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) 180 Result |= SymbolRef::SF_Weak; 181 182 if (symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE) 183 Result |= SymbolRef::SF_Absolute; 184 185 return object_error::success; 186 } 187 188 error_code COFFObjectFile::getSymbolSize(DataRefImpl Symb, 189 uint64_t &Result) const { 190 // FIXME: Return the correct size. This requires looking at all the symbols 191 // in the same section as this symbol, and looking for either the next 192 // symbol, or the end of the section. 193 const coff_symbol *symb = toSymb(Symb); 194 const coff_section *Section = NULL; 195 if (error_code ec = getSection(symb->SectionNumber, Section)) 196 return ec; 197 char Type; 198 if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 199 return ec; 200 if (Type == 'U' || Type == 'w') 201 Result = UnknownAddressOrSize; 202 else if (Section) 203 Result = Section->SizeOfRawData - symb->Value; 204 else 205 Result = 0; 206 return object_error::success; 207 } 208 209 error_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, 210 char &Result) const { 211 const coff_symbol *symb = toSymb(Symb); 212 StringRef name; 213 if (error_code ec = getSymbolName(Symb, name)) 214 return ec; 215 char ret = StringSwitch<char>(name) 216 .StartsWith(".debug", 'N') 217 .StartsWith(".sxdata", 'N') 218 .Default('?'); 219 220 if (ret != '?') { 221 Result = ret; 222 return object_error::success; 223 } 224 225 uint32_t Characteristics = 0; 226 if (symb->SectionNumber > 0) { 227 const coff_section *Section = NULL; 228 if (error_code ec = getSection(symb->SectionNumber, Section)) 229 return ec; 230 Characteristics = Section->Characteristics; 231 } 232 233 switch (symb->SectionNumber) { 234 case COFF::IMAGE_SYM_UNDEFINED: 235 // Check storage classes. 236 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) { 237 Result = 'w'; 238 return object_error::success; // Don't do ::toupper. 239 } else if (symb->Value != 0) // Check for common symbols. 240 ret = 'c'; 241 else 242 ret = 'u'; 243 break; 244 case COFF::IMAGE_SYM_ABSOLUTE: 245 ret = 'a'; 246 break; 247 case COFF::IMAGE_SYM_DEBUG: 248 ret = 'n'; 249 break; 250 default: 251 // Check section type. 252 if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) 253 ret = 't'; 254 else if ( Characteristics & COFF::IMAGE_SCN_MEM_READ 255 && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. 256 ret = 'r'; 257 else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) 258 ret = 'd'; 259 else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) 260 ret = 'b'; 261 else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) 262 ret = 'i'; 263 264 // Check for section symbol. 265 else if ( symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC 266 && symb->Value == 0) 267 ret = 's'; 268 } 269 270 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) 271 ret = ::toupper(static_cast<unsigned char>(ret)); 272 273 Result = ret; 274 return object_error::success; 275 } 276 277 error_code COFFObjectFile::getSymbolSection(DataRefImpl Symb, 278 section_iterator &Result) const { 279 const coff_symbol *symb = toSymb(Symb); 280 if (symb->SectionNumber <= COFF::IMAGE_SYM_UNDEFINED) 281 Result = end_sections(); 282 else { 283 const coff_section *sec = 0; 284 if (error_code ec = getSection(symb->SectionNumber, sec)) return ec; 285 DataRefImpl Sec; 286 Sec.p = reinterpret_cast<uintptr_t>(sec); 287 Result = section_iterator(SectionRef(Sec, this)); 288 } 289 return object_error::success; 290 } 291 292 error_code COFFObjectFile::getSymbolValue(DataRefImpl Symb, 293 uint64_t &Val) const { 294 report_fatal_error("getSymbolValue unimplemented in COFFObjectFile"); 295 } 296 297 error_code COFFObjectFile::getSectionNext(DataRefImpl Sec, 298 SectionRef &Result) const { 299 const coff_section *sec = toSec(Sec); 300 sec += 1; 301 Sec.p = reinterpret_cast<uintptr_t>(sec); 302 Result = SectionRef(Sec, this); 303 return object_error::success; 304 } 305 306 error_code COFFObjectFile::getSectionName(DataRefImpl Sec, 307 StringRef &Result) const { 308 const coff_section *sec = toSec(Sec); 309 return getSectionName(sec, Result); 310 } 311 312 error_code COFFObjectFile::getSectionAddress(DataRefImpl Sec, 313 uint64_t &Result) const { 314 const coff_section *sec = toSec(Sec); 315 Result = sec->VirtualAddress; 316 return object_error::success; 317 } 318 319 error_code COFFObjectFile::getSectionSize(DataRefImpl Sec, 320 uint64_t &Result) const { 321 const coff_section *sec = toSec(Sec); 322 Result = sec->SizeOfRawData; 323 return object_error::success; 324 } 325 326 error_code COFFObjectFile::getSectionContents(DataRefImpl Sec, 327 StringRef &Result) const { 328 const coff_section *sec = toSec(Sec); 329 ArrayRef<uint8_t> Res; 330 error_code EC = getSectionContents(sec, Res); 331 Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 332 return EC; 333 } 334 335 error_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec, 336 uint64_t &Res) const { 337 const coff_section *sec = toSec(Sec); 338 if (!sec) 339 return object_error::parse_failed; 340 Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1); 341 return object_error::success; 342 } 343 344 error_code COFFObjectFile::isSectionText(DataRefImpl Sec, 345 bool &Result) const { 346 const coff_section *sec = toSec(Sec); 347 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 348 return object_error::success; 349 } 350 351 error_code COFFObjectFile::isSectionData(DataRefImpl Sec, 352 bool &Result) const { 353 const coff_section *sec = toSec(Sec); 354 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 355 return object_error::success; 356 } 357 358 error_code COFFObjectFile::isSectionBSS(DataRefImpl Sec, 359 bool &Result) const { 360 const coff_section *sec = toSec(Sec); 361 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 362 return object_error::success; 363 } 364 365 error_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 366 bool &Result) const { 367 // FIXME: Unimplemented 368 Result = true; 369 return object_error::success; 370 } 371 372 error_code COFFObjectFile::isSectionVirtual(DataRefImpl Sec, 373 bool &Result) const { 374 const coff_section *sec = toSec(Sec); 375 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 376 return object_error::success; 377 } 378 379 error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Sec, 380 bool &Result) const { 381 // FIXME: Unimplemented. 382 Result = false; 383 return object_error::success; 384 } 385 386 error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 387 bool &Result) const { 388 // FIXME: Unimplemented. 389 Result = false; 390 return object_error::success; 391 } 392 393 error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, 394 DataRefImpl Symb, 395 bool &Result) const { 396 const coff_section *sec = toSec(Sec); 397 const coff_symbol *symb = toSymb(Symb); 398 const coff_section *symb_sec = 0; 399 if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec; 400 if (symb_sec == sec) 401 Result = true; 402 else 403 Result = false; 404 return object_error::success; 405 } 406 407 relocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 408 const coff_section *sec = toSec(Sec); 409 DataRefImpl ret; 410 if (sec->NumberOfRelocations == 0) 411 ret.p = 0; 412 else 413 ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations); 414 415 return relocation_iterator(RelocationRef(ret, this)); 416 } 417 418 relocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 419 const coff_section *sec = toSec(Sec); 420 DataRefImpl ret; 421 if (sec->NumberOfRelocations == 0) 422 ret.p = 0; 423 else 424 ret.p = reinterpret_cast<uintptr_t>( 425 reinterpret_cast<const coff_relocation*>( 426 base() + sec->PointerToRelocations) 427 + sec->NumberOfRelocations); 428 429 return relocation_iterator(RelocationRef(ret, this)); 430 } 431 432 COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) 433 : ObjectFile(Binary::ID_COFF, Object) 434 , COFFHeader(0) 435 , PE32Header(0) 436 , DataDirectory(0) 437 , SectionTable(0) 438 , SymbolTable(0) 439 , StringTable(0) 440 , StringTableSize(0) { 441 // Check that we at least have enough room for a header. 442 if (!checkSize(Data, ec, sizeof(coff_file_header))) return; 443 444 // The current location in the file where we are looking at. 445 uint64_t CurPtr = 0; 446 447 // PE header is optional and is present only in executables. If it exists, 448 // it is placed right after COFF header. 449 bool hasPEHeader = false; 450 451 // Check if this is a PE/COFF file. 452 if (base()[0] == 0x4d && base()[1] == 0x5a) { 453 // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 454 // PE signature to find 'normal' COFF header. 455 if (!checkSize(Data, ec, 0x3c + 8)) return; 456 CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c); 457 // Check the PE magic bytes. ("PE\0\0") 458 if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) { 459 ec = object_error::parse_failed; 460 return; 461 } 462 CurPtr += 4; // Skip the PE magic bytes. 463 hasPEHeader = true; 464 } 465 466 if ((ec = getObject(COFFHeader, Data, base() + CurPtr))) 467 return; 468 CurPtr += sizeof(coff_file_header); 469 470 if (hasPEHeader) { 471 if ((ec = getObject(PE32Header, Data, base() + CurPtr))) 472 return; 473 if (PE32Header->Magic != 0x10b) { 474 // We only support PE32. If this is PE32 (not PE32+), the magic byte 475 // should be 0x10b. If this is not PE32, continue as if there's no PE 476 // header in this file. 477 PE32Header = 0; 478 } else if (PE32Header->NumberOfRvaAndSize > 0) { 479 const uint8_t *addr = base() + CurPtr + sizeof(pe32_header); 480 uint64_t size = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 481 if ((ec = getObject(DataDirectory, Data, addr, size))) 482 return; 483 } 484 CurPtr += COFFHeader->SizeOfOptionalHeader; 485 } 486 487 if ((ec = getObject(SectionTable, Data, base() + CurPtr, 488 COFFHeader->NumberOfSections * sizeof(coff_section)))) 489 return; 490 491 if (COFFHeader->PointerToSymbolTable != 0) { 492 if ((ec = getObject(SymbolTable, Data, 493 base() + COFFHeader->PointerToSymbolTable, 494 COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))) 495 return; 496 497 // Find string table. The first four byte of the string table contains the 498 // total size of the string table, including the size field itself. If the 499 // string table is empty, the value of the first four byte would be 4. 500 const uint8_t *StringTableAddr = base() + COFFHeader->PointerToSymbolTable 501 + COFFHeader->NumberOfSymbols * sizeof(coff_symbol); 502 const ulittle32_t *StringTableSizePtr; 503 if ((ec = getObject(StringTableSizePtr, Data, StringTableAddr))) 504 return; 505 StringTableSize = *StringTableSizePtr; 506 if ((ec = getObject(StringTable, Data, StringTableAddr, StringTableSize))) 507 return; 508 509 // Check that the string table is null terminated if has any in it. 510 if (StringTableSize < 4 511 || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) { 512 ec = object_error::parse_failed; 513 return; 514 } 515 } 516 517 ec = object_error::success; 518 } 519 520 symbol_iterator COFFObjectFile::begin_symbols() const { 521 DataRefImpl ret; 522 ret.p = reinterpret_cast<intptr_t>(SymbolTable); 523 return symbol_iterator(SymbolRef(ret, this)); 524 } 525 526 symbol_iterator COFFObjectFile::end_symbols() const { 527 // The symbol table ends where the string table begins. 528 DataRefImpl ret; 529 ret.p = reinterpret_cast<intptr_t>(StringTable); 530 return symbol_iterator(SymbolRef(ret, this)); 531 } 532 533 symbol_iterator COFFObjectFile::begin_dynamic_symbols() const { 534 // TODO: implement 535 report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); 536 } 537 538 symbol_iterator COFFObjectFile::end_dynamic_symbols() const { 539 // TODO: implement 540 report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); 541 } 542 543 library_iterator COFFObjectFile::begin_libraries_needed() const { 544 // TODO: implement 545 report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 546 } 547 548 library_iterator COFFObjectFile::end_libraries_needed() const { 549 // TODO: implement 550 report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 551 } 552 553 StringRef COFFObjectFile::getLoadName() const { 554 // COFF does not have this field. 555 return ""; 556 } 557 558 559 section_iterator COFFObjectFile::begin_sections() const { 560 DataRefImpl ret; 561 ret.p = reinterpret_cast<intptr_t>(SectionTable); 562 return section_iterator(SectionRef(ret, this)); 563 } 564 565 section_iterator COFFObjectFile::end_sections() const { 566 DataRefImpl ret; 567 ret.p = reinterpret_cast<intptr_t>(SectionTable + COFFHeader->NumberOfSections); 568 return section_iterator(SectionRef(ret, this)); 569 } 570 571 uint8_t COFFObjectFile::getBytesInAddress() const { 572 return getArch() == Triple::x86_64 ? 8 : 4; 573 } 574 575 StringRef COFFObjectFile::getFileFormatName() const { 576 switch(COFFHeader->Machine) { 577 case COFF::IMAGE_FILE_MACHINE_I386: 578 return "COFF-i386"; 579 case COFF::IMAGE_FILE_MACHINE_AMD64: 580 return "COFF-x86-64"; 581 default: 582 return "COFF-<unknown arch>"; 583 } 584 } 585 586 unsigned COFFObjectFile::getArch() const { 587 switch(COFFHeader->Machine) { 588 case COFF::IMAGE_FILE_MACHINE_I386: 589 return Triple::x86; 590 case COFF::IMAGE_FILE_MACHINE_AMD64: 591 return Triple::x86_64; 592 default: 593 return Triple::UnknownArch; 594 } 595 } 596 597 // This method is kept here because lld uses this. As soon as we make 598 // lld to use getCOFFHeader, this method will be removed. 599 error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const { 600 return getCOFFHeader(Res); 601 } 602 603 error_code COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const { 604 Res = COFFHeader; 605 return object_error::success; 606 } 607 608 error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 609 Res = PE32Header; 610 return object_error::success; 611 } 612 613 error_code COFFObjectFile::getDataDirectory(uint32_t index, 614 const data_directory *&Res) const { 615 // Error if if there's no data directory or the index is out of range. 616 if (!DataDirectory || index > PE32Header->NumberOfRvaAndSize) 617 return object_error::parse_failed; 618 Res = &DataDirectory[index]; 619 return object_error::success; 620 } 621 622 error_code COFFObjectFile::getSection(int32_t index, 623 const coff_section *&Result) const { 624 // Check for special index values. 625 if (index == COFF::IMAGE_SYM_UNDEFINED || 626 index == COFF::IMAGE_SYM_ABSOLUTE || 627 index == COFF::IMAGE_SYM_DEBUG) 628 Result = NULL; 629 else if (index > 0 && index <= COFFHeader->NumberOfSections) 630 // We already verified the section table data, so no need to check again. 631 Result = SectionTable + (index - 1); 632 else 633 return object_error::parse_failed; 634 return object_error::success; 635 } 636 637 error_code COFFObjectFile::getString(uint32_t offset, 638 StringRef &Result) const { 639 if (StringTableSize <= 4) 640 // Tried to get a string from an empty string table. 641 return object_error::parse_failed; 642 if (offset >= StringTableSize) 643 return object_error::unexpected_eof; 644 Result = StringRef(StringTable + offset); 645 return object_error::success; 646 } 647 648 error_code COFFObjectFile::getSymbol(uint32_t index, 649 const coff_symbol *&Result) const { 650 if (index < COFFHeader->NumberOfSymbols) 651 Result = SymbolTable + index; 652 else 653 return object_error::parse_failed; 654 return object_error::success; 655 } 656 657 error_code COFFObjectFile::getSymbolName(const coff_symbol *symbol, 658 StringRef &Res) const { 659 // Check for string table entry. First 4 bytes are 0. 660 if (symbol->Name.Offset.Zeroes == 0) { 661 uint32_t Offset = symbol->Name.Offset.Offset; 662 if (error_code ec = getString(Offset, Res)) 663 return ec; 664 return object_error::success; 665 } 666 667 if (symbol->Name.ShortName[7] == 0) 668 // Null terminated, let ::strlen figure out the length. 669 Res = StringRef(symbol->Name.ShortName); 670 else 671 // Not null terminated, use all 8 bytes. 672 Res = StringRef(symbol->Name.ShortName, 8); 673 return object_error::success; 674 } 675 676 ArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData( 677 const coff_symbol *symbol) const { 678 const uint8_t *aux = NULL; 679 680 if ( symbol->NumberOfAuxSymbols > 0 ) { 681 // AUX data comes immediately after the symbol in COFF 682 aux = reinterpret_cast<const uint8_t *>(symbol + 1); 683 # ifndef NDEBUG 684 // Verify that the aux symbol points to a valid entry in the symbol table. 685 uintptr_t offset = uintptr_t(aux) - uintptr_t(base()); 686 if (offset < COFFHeader->PointerToSymbolTable 687 || offset >= COFFHeader->PointerToSymbolTable 688 + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) 689 report_fatal_error("Aux Symbol data was outside of symbol table."); 690 691 assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) 692 == 0 && "Aux Symbol data did not point to the beginning of a symbol"); 693 # endif 694 } 695 return ArrayRef<uint8_t>(aux, symbol->NumberOfAuxSymbols * sizeof(coff_symbol)); 696 } 697 698 error_code COFFObjectFile::getSectionName(const coff_section *Sec, 699 StringRef &Res) const { 700 StringRef Name; 701 if (Sec->Name[7] == 0) 702 // Null terminated, let ::strlen figure out the length. 703 Name = Sec->Name; 704 else 705 // Not null terminated, use all 8 bytes. 706 Name = StringRef(Sec->Name, 8); 707 708 // Check for string table entry. First byte is '/'. 709 if (Name[0] == '/') { 710 uint32_t Offset; 711 if (Name.substr(1).getAsInteger(10, Offset)) 712 return object_error::parse_failed; 713 if (error_code ec = getString(Offset, Name)) 714 return ec; 715 } 716 717 Res = Name; 718 return object_error::success; 719 } 720 721 error_code COFFObjectFile::getSectionContents(const coff_section *Sec, 722 ArrayRef<uint8_t> &Res) const { 723 // The only thing that we need to verify is that the contents is contained 724 // within the file bounds. We don't need to make sure it doesn't cover other 725 // data, as there's nothing that says that is not allowed. 726 uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 727 uintptr_t ConEnd = ConStart + Sec->SizeOfRawData; 728 if (ConEnd > uintptr_t(Data->getBufferEnd())) 729 return object_error::parse_failed; 730 Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart), 731 Sec->SizeOfRawData); 732 return object_error::success; 733 } 734 735 const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 736 return reinterpret_cast<const coff_relocation*>(Rel.p); 737 } 738 error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, 739 RelocationRef &Res) const { 740 Rel.p = reinterpret_cast<uintptr_t>( 741 reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 742 Res = RelocationRef(Rel, this); 743 return object_error::success; 744 } 745 error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 746 uint64_t &Res) const { 747 report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); 748 } 749 error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, 750 uint64_t &Res) const { 751 Res = toRel(Rel)->VirtualAddress; 752 return object_error::success; 753 } 754 symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 755 const coff_relocation* R = toRel(Rel); 756 DataRefImpl Symb; 757 Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); 758 return symbol_iterator(SymbolRef(Symb, this)); 759 } 760 error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 761 uint64_t &Res) const { 762 const coff_relocation* R = toRel(Rel); 763 Res = R->Type; 764 return object_error::success; 765 } 766 767 const coff_section *COFFObjectFile::getCOFFSection(section_iterator &It) const { 768 return toSec(It->getRawDataRefImpl()); 769 } 770 771 const coff_symbol *COFFObjectFile::getCOFFSymbol(symbol_iterator &It) const { 772 return toSymb(It->getRawDataRefImpl()); 773 } 774 775 const coff_relocation *COFFObjectFile::getCOFFRelocation( 776 relocation_iterator &It) const { 777 return toRel(It->getRawDataRefImpl()); 778 } 779 780 781 #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \ 782 case COFF::enum: res = #enum; break; 783 784 error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 785 SmallVectorImpl<char> &Result) const { 786 const coff_relocation *reloc = toRel(Rel); 787 StringRef res; 788 switch (COFFHeader->Machine) { 789 case COFF::IMAGE_FILE_MACHINE_AMD64: 790 switch (reloc->Type) { 791 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 792 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 793 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 794 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 795 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 796 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 797 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 798 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 799 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 800 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 801 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 802 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 803 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 804 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 805 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 806 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 807 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 808 default: 809 res = "Unknown"; 810 } 811 break; 812 case COFF::IMAGE_FILE_MACHINE_I386: 813 switch (reloc->Type) { 814 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 815 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 816 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 817 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 818 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 819 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 820 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 821 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 822 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 823 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 824 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 825 default: 826 res = "Unknown"; 827 } 828 break; 829 default: 830 res = "Unknown"; 831 } 832 Result.append(res.begin(), res.end()); 833 return object_error::success; 834 } 835 836 #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 837 838 error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, 839 SmallVectorImpl<char> &Result) const { 840 const coff_relocation *reloc = toRel(Rel); 841 const coff_symbol *symb = 0; 842 if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec; 843 DataRefImpl sym; 844 sym.p = reinterpret_cast<uintptr_t>(symb); 845 StringRef symname; 846 if (error_code ec = getSymbolName(sym, symname)) return ec; 847 Result.append(symname.begin(), symname.end()); 848 return object_error::success; 849 } 850 851 error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, 852 LibraryRef &Result) const { 853 report_fatal_error("getLibraryNext not implemented in COFFObjectFile"); 854 } 855 856 error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, 857 StringRef &Result) const { 858 report_fatal_error("getLibraryPath not implemented in COFFObjectFile"); 859 } 860 861 namespace llvm { 862 863 ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { 864 error_code ec; 865 return new COFFObjectFile(Object, ec); 866 } 867 868 } // end namespace llvm 869