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