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. 498 const uint8_t *StringTableAddr = base() + COFFHeader->PointerToSymbolTable 499 + COFFHeader->NumberOfSymbols * sizeof(coff_symbol); 500 const uint32_t *StringTableSizePtr; 501 if ((ec = getObject(StringTableSizePtr, Data, StringTableAddr))) 502 return; 503 StringTableSize = *StringTableSizePtr; 504 if ((ec = getObject(StringTable, Data, StringTableAddr, StringTableSize))) 505 return; 506 507 // Check that the string table is null terminated if has any in it. 508 if (StringTableSize < 4 509 || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) { 510 ec = object_error::parse_failed; 511 return; 512 } 513 } 514 515 ec = object_error::success; 516 } 517 518 symbol_iterator COFFObjectFile::begin_symbols() const { 519 DataRefImpl ret; 520 ret.p = reinterpret_cast<intptr_t>(SymbolTable); 521 return symbol_iterator(SymbolRef(ret, this)); 522 } 523 524 symbol_iterator COFFObjectFile::end_symbols() const { 525 // The symbol table ends where the string table begins. 526 DataRefImpl ret; 527 ret.p = reinterpret_cast<intptr_t>(StringTable); 528 return symbol_iterator(SymbolRef(ret, this)); 529 } 530 531 symbol_iterator COFFObjectFile::begin_dynamic_symbols() const { 532 // TODO: implement 533 report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); 534 } 535 536 symbol_iterator COFFObjectFile::end_dynamic_symbols() const { 537 // TODO: implement 538 report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); 539 } 540 541 library_iterator COFFObjectFile::begin_libraries_needed() const { 542 // TODO: implement 543 report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 544 } 545 546 library_iterator COFFObjectFile::end_libraries_needed() const { 547 // TODO: implement 548 report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 549 } 550 551 StringRef COFFObjectFile::getLoadName() const { 552 // COFF does not have this field. 553 return ""; 554 } 555 556 557 section_iterator COFFObjectFile::begin_sections() const { 558 DataRefImpl ret; 559 ret.p = reinterpret_cast<intptr_t>(SectionTable); 560 return section_iterator(SectionRef(ret, this)); 561 } 562 563 section_iterator COFFObjectFile::end_sections() const { 564 DataRefImpl ret; 565 ret.p = reinterpret_cast<intptr_t>(SectionTable + COFFHeader->NumberOfSections); 566 return section_iterator(SectionRef(ret, this)); 567 } 568 569 uint8_t COFFObjectFile::getBytesInAddress() const { 570 return getArch() == Triple::x86_64 ? 8 : 4; 571 } 572 573 StringRef COFFObjectFile::getFileFormatName() const { 574 switch(COFFHeader->Machine) { 575 case COFF::IMAGE_FILE_MACHINE_I386: 576 return "COFF-i386"; 577 case COFF::IMAGE_FILE_MACHINE_AMD64: 578 return "COFF-x86-64"; 579 default: 580 return "COFF-<unknown arch>"; 581 } 582 } 583 584 unsigned COFFObjectFile::getArch() const { 585 switch(COFFHeader->Machine) { 586 case COFF::IMAGE_FILE_MACHINE_I386: 587 return Triple::x86; 588 case COFF::IMAGE_FILE_MACHINE_AMD64: 589 return Triple::x86_64; 590 default: 591 return Triple::UnknownArch; 592 } 593 } 594 595 // This method is kept here because lld uses this. As soon as we make 596 // lld to use getCOFFHeader, this method will be removed. 597 error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const { 598 return getCOFFHeader(Res); 599 } 600 601 error_code COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const { 602 Res = COFFHeader; 603 return object_error::success; 604 } 605 606 error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 607 Res = PE32Header; 608 return object_error::success; 609 } 610 611 error_code COFFObjectFile::getDataDirectory(uint32_t index, 612 const data_directory *&Res) const { 613 // Error if if there's no data directory or the index is out of range. 614 if (!DataDirectory || index > PE32Header->NumberOfRvaAndSize) 615 return object_error::parse_failed; 616 Res = &DataDirectory[index]; 617 return object_error::success; 618 } 619 620 error_code COFFObjectFile::getSection(int32_t index, 621 const coff_section *&Result) const { 622 // Check for special index values. 623 if (index == COFF::IMAGE_SYM_UNDEFINED || 624 index == COFF::IMAGE_SYM_ABSOLUTE || 625 index == COFF::IMAGE_SYM_DEBUG) 626 Result = NULL; 627 else if (index > 0 && index <= COFFHeader->NumberOfSections) 628 // We already verified the section table data, so no need to check again. 629 Result = SectionTable + (index - 1); 630 else 631 return object_error::parse_failed; 632 return object_error::success; 633 } 634 635 error_code COFFObjectFile::getString(uint32_t offset, 636 StringRef &Result) const { 637 if (StringTableSize <= 4) 638 // Tried to get a string from an empty string table. 639 return object_error::parse_failed; 640 if (offset >= StringTableSize) 641 return object_error::unexpected_eof; 642 Result = StringRef(StringTable + offset); 643 return object_error::success; 644 } 645 646 error_code COFFObjectFile::getSymbol(uint32_t index, 647 const coff_symbol *&Result) const { 648 if (index < COFFHeader->NumberOfSymbols) 649 Result = SymbolTable + index; 650 else 651 return object_error::parse_failed; 652 return object_error::success; 653 } 654 655 error_code COFFObjectFile::getSymbolName(const coff_symbol *symbol, 656 StringRef &Res) const { 657 // Check for string table entry. First 4 bytes are 0. 658 if (symbol->Name.Offset.Zeroes == 0) { 659 uint32_t Offset = symbol->Name.Offset.Offset; 660 if (error_code ec = getString(Offset, Res)) 661 return ec; 662 return object_error::success; 663 } 664 665 if (symbol->Name.ShortName[7] == 0) 666 // Null terminated, let ::strlen figure out the length. 667 Res = StringRef(symbol->Name.ShortName); 668 else 669 // Not null terminated, use all 8 bytes. 670 Res = StringRef(symbol->Name.ShortName, 8); 671 return object_error::success; 672 } 673 674 ArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData( 675 const coff_symbol *symbol) const { 676 const uint8_t *aux = NULL; 677 678 if ( symbol->NumberOfAuxSymbols > 0 ) { 679 // AUX data comes immediately after the symbol in COFF 680 aux = reinterpret_cast<const uint8_t *>(symbol + 1); 681 # ifndef NDEBUG 682 // Verify that the aux symbol points to a valid entry in the symbol table. 683 uintptr_t offset = uintptr_t(aux) - uintptr_t(base()); 684 if (offset < COFFHeader->PointerToSymbolTable 685 || offset >= COFFHeader->PointerToSymbolTable 686 + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) 687 report_fatal_error("Aux Symbol data was outside of symbol table."); 688 689 assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) 690 == 0 && "Aux Symbol data did not point to the beginning of a symbol"); 691 # endif 692 } 693 return ArrayRef<uint8_t>(aux, symbol->NumberOfAuxSymbols * sizeof(coff_symbol)); 694 } 695 696 error_code COFFObjectFile::getSectionName(const coff_section *Sec, 697 StringRef &Res) const { 698 StringRef Name; 699 if (Sec->Name[7] == 0) 700 // Null terminated, let ::strlen figure out the length. 701 Name = Sec->Name; 702 else 703 // Not null terminated, use all 8 bytes. 704 Name = StringRef(Sec->Name, 8); 705 706 // Check for string table entry. First byte is '/'. 707 if (Name[0] == '/') { 708 uint32_t Offset; 709 if (Name.substr(1).getAsInteger(10, Offset)) 710 return object_error::parse_failed; 711 if (error_code ec = getString(Offset, Name)) 712 return ec; 713 } 714 715 Res = Name; 716 return object_error::success; 717 } 718 719 error_code COFFObjectFile::getSectionContents(const coff_section *Sec, 720 ArrayRef<uint8_t> &Res) const { 721 // The only thing that we need to verify is that the contents is contained 722 // within the file bounds. We don't need to make sure it doesn't cover other 723 // data, as there's nothing that says that is not allowed. 724 uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 725 uintptr_t ConEnd = ConStart + Sec->SizeOfRawData; 726 if (ConEnd > uintptr_t(Data->getBufferEnd())) 727 return object_error::parse_failed; 728 Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart), 729 Sec->SizeOfRawData); 730 return object_error::success; 731 } 732 733 const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 734 return reinterpret_cast<const coff_relocation*>(Rel.p); 735 } 736 error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, 737 RelocationRef &Res) const { 738 Rel.p = reinterpret_cast<uintptr_t>( 739 reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 740 Res = RelocationRef(Rel, this); 741 return object_error::success; 742 } 743 error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 744 uint64_t &Res) const { 745 report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); 746 } 747 error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, 748 uint64_t &Res) const { 749 Res = toRel(Rel)->VirtualAddress; 750 return object_error::success; 751 } 752 symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 753 const coff_relocation* R = toRel(Rel); 754 DataRefImpl Symb; 755 Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); 756 return symbol_iterator(SymbolRef(Symb, this)); 757 } 758 error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 759 uint64_t &Res) const { 760 const coff_relocation* R = toRel(Rel); 761 Res = R->Type; 762 return object_error::success; 763 } 764 765 const coff_section *COFFObjectFile::getCOFFSection(section_iterator &It) const { 766 return toSec(It->getRawDataRefImpl()); 767 } 768 769 const coff_symbol *COFFObjectFile::getCOFFSymbol(symbol_iterator &It) const { 770 return toSymb(It->getRawDataRefImpl()); 771 } 772 773 const coff_relocation *COFFObjectFile::getCOFFRelocation( 774 relocation_iterator &It) const { 775 return toRel(It->getRawDataRefImpl()); 776 } 777 778 779 #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \ 780 case COFF::enum: res = #enum; break; 781 782 error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 783 SmallVectorImpl<char> &Result) const { 784 const coff_relocation *reloc = toRel(Rel); 785 StringRef res; 786 switch (COFFHeader->Machine) { 787 case COFF::IMAGE_FILE_MACHINE_AMD64: 788 switch (reloc->Type) { 789 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 790 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 791 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 792 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 793 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 794 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 795 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 796 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 797 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 798 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 799 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 800 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 801 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 802 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 803 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 804 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 805 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 806 default: 807 res = "Unknown"; 808 } 809 break; 810 case COFF::IMAGE_FILE_MACHINE_I386: 811 switch (reloc->Type) { 812 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 813 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 814 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 815 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 816 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 817 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 818 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 819 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 820 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 821 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 822 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 823 default: 824 res = "Unknown"; 825 } 826 break; 827 default: 828 res = "Unknown"; 829 } 830 Result.append(res.begin(), res.end()); 831 return object_error::success; 832 } 833 834 #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 835 836 error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, 837 SmallVectorImpl<char> &Result) const { 838 const coff_relocation *reloc = toRel(Rel); 839 const coff_symbol *symb = 0; 840 if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec; 841 DataRefImpl sym; 842 sym.p = reinterpret_cast<uintptr_t>(symb); 843 StringRef symname; 844 if (error_code ec = getSymbolName(sym, symname)) return ec; 845 Result.append(symname.begin(), symname.end()); 846 return object_error::success; 847 } 848 849 error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, 850 LibraryRef &Result) const { 851 report_fatal_error("getLibraryNext not implemented in COFFObjectFile"); 852 } 853 854 error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, 855 StringRef &Result) const { 856 report_fatal_error("getLibraryPath not implemented in COFFObjectFile"); 857 } 858 859 namespace llvm { 860 861 ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { 862 error_code ec; 863 return new COFFObjectFile(Object, ec); 864 } 865 866 } // end namespace llvm 867