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