COFFObjectFile.cpp revision 3fd9b8422328a60664a5c631ec9519b58017fcbc
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 20using namespace llvm; 21using namespace object; 22 23namespace { 24using support::ulittle8_t; 25using support::ulittle16_t; 26using support::ulittle32_t; 27using support::little16_t; 28} 29 30namespace { 31// Returns false if size is greater than the buffer size. And sets ec. 32bool 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. 41bool 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 55const 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 73const 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 90error_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 105error_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 123error_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 141error_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 163error_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 187error_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 208error_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 276error_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 Sec.p = reinterpret_cast<uintptr_t>(sec); 286 Result = section_iterator(SectionRef(Sec, this)); 287 } 288 return object_error::success; 289} 290 291error_code COFFObjectFile::getSectionNext(DataRefImpl Sec, 292 SectionRef &Result) const { 293 const coff_section *sec = toSec(Sec); 294 sec += 1; 295 Sec.p = reinterpret_cast<uintptr_t>(sec); 296 Result = SectionRef(Sec, this); 297 return object_error::success; 298} 299 300error_code COFFObjectFile::getSectionName(DataRefImpl Sec, 301 StringRef &Result) const { 302 const coff_section *sec = toSec(Sec); 303 return getSectionName(sec, Result); 304} 305 306error_code COFFObjectFile::getSectionAddress(DataRefImpl Sec, 307 uint64_t &Result) const { 308 const coff_section *sec = toSec(Sec); 309 Result = sec->VirtualAddress; 310 return object_error::success; 311} 312 313error_code COFFObjectFile::getSectionSize(DataRefImpl Sec, 314 uint64_t &Result) const { 315 const coff_section *sec = toSec(Sec); 316 Result = sec->SizeOfRawData; 317 return object_error::success; 318} 319 320error_code COFFObjectFile::getSectionContents(DataRefImpl Sec, 321 StringRef &Result) const { 322 const coff_section *sec = toSec(Sec); 323 ArrayRef<uint8_t> Res; 324 error_code EC = getSectionContents(sec, Res); 325 Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 326 return EC; 327} 328 329error_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec, 330 uint64_t &Res) const { 331 const coff_section *sec = toSec(Sec); 332 if (!sec) 333 return object_error::parse_failed; 334 Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1); 335 return object_error::success; 336} 337 338error_code COFFObjectFile::isSectionText(DataRefImpl Sec, 339 bool &Result) const { 340 const coff_section *sec = toSec(Sec); 341 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 342 return object_error::success; 343} 344 345error_code COFFObjectFile::isSectionData(DataRefImpl Sec, 346 bool &Result) const { 347 const coff_section *sec = toSec(Sec); 348 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 349 return object_error::success; 350} 351 352error_code COFFObjectFile::isSectionBSS(DataRefImpl Sec, 353 bool &Result) const { 354 const coff_section *sec = toSec(Sec); 355 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 356 return object_error::success; 357} 358 359error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, 360 DataRefImpl Symb, 361 bool &Result) const { 362 const coff_section *sec = toSec(Sec); 363 const coff_symbol *symb = toSymb(Symb); 364 const coff_section *symb_sec = 0; 365 if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec; 366 if (symb_sec == sec) 367 Result = true; 368 else 369 Result = false; 370 return object_error::success; 371} 372 373relocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 374 const coff_section *sec = toSec(Sec); 375 DataRefImpl ret; 376 if (sec->NumberOfRelocations == 0) 377 ret.p = 0; 378 else 379 ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations); 380 381 return relocation_iterator(RelocationRef(ret, this)); 382} 383 384relocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 385 const coff_section *sec = toSec(Sec); 386 DataRefImpl ret; 387 if (sec->NumberOfRelocations == 0) 388 ret.p = 0; 389 else 390 ret.p = reinterpret_cast<uintptr_t>( 391 reinterpret_cast<const coff_relocation*>( 392 base() + sec->PointerToRelocations) 393 + sec->NumberOfRelocations); 394 395 return relocation_iterator(RelocationRef(ret, this)); 396} 397 398COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) 399 : ObjectFile(Binary::ID_COFF, Object, ec) 400 , Header(0) 401 , SectionTable(0) 402 , SymbolTable(0) 403 , StringTable(0) 404 , StringTableSize(0) { 405 // Check that we at least have enough room for a header. 406 if (!checkSize(Data, ec, sizeof(coff_file_header))) return; 407 408 // The actual starting location of the COFF header in the file. This can be 409 // non-zero in PE/COFF files. 410 uint64_t HeaderStart = 0; 411 412 // Check if this is a PE/COFF file. 413 if (base()[0] == 0x4d && base()[1] == 0x5a) { 414 // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 415 // PE signature to find 'normal' COFF header. 416 if (!checkSize(Data, ec, 0x3c + 8)) return; 417 HeaderStart = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c); 418 // Check the PE header. ("PE\0\0") 419 if (std::memcmp(base() + HeaderStart, "PE\0\0", 4) != 0) { 420 ec = object_error::parse_failed; 421 return; 422 } 423 HeaderStart += 4; // Skip the PE Header. 424 } 425 426 Header = reinterpret_cast<const coff_file_header *>(base() + HeaderStart); 427 if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header))) 428 return; 429 430 SectionTable = 431 reinterpret_cast<const coff_section *>( base() 432 + HeaderStart 433 + sizeof(coff_file_header) 434 + Header->SizeOfOptionalHeader); 435 if (!checkAddr(Data, ec, uintptr_t(SectionTable), 436 Header->NumberOfSections * sizeof(coff_section))) 437 return; 438 439 if (Header->PointerToSymbolTable != 0) { 440 SymbolTable = 441 reinterpret_cast<const coff_symbol *>(base() 442 + Header->PointerToSymbolTable); 443 if (!checkAddr(Data, ec, uintptr_t(SymbolTable), 444 Header->NumberOfSymbols * sizeof(coff_symbol))) 445 return; 446 447 // Find string table. 448 StringTable = reinterpret_cast<const char *>(base()) 449 + Header->PointerToSymbolTable 450 + Header->NumberOfSymbols * sizeof(coff_symbol); 451 if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t))) 452 return; 453 454 StringTableSize = *reinterpret_cast<const ulittle32_t *>(StringTable); 455 if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize)) 456 return; 457 // Check that the string table is null terminated if has any in it. 458 if (StringTableSize < 4 459 || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) { 460 ec = object_error::parse_failed; 461 return; 462 } 463 } 464 465 ec = object_error::success; 466} 467 468symbol_iterator COFFObjectFile::begin_symbols() const { 469 DataRefImpl ret; 470 ret.p = reinterpret_cast<intptr_t>(SymbolTable); 471 return symbol_iterator(SymbolRef(ret, this)); 472} 473 474symbol_iterator COFFObjectFile::end_symbols() const { 475 // The symbol table ends where the string table begins. 476 DataRefImpl ret; 477 ret.p = reinterpret_cast<intptr_t>(StringTable); 478 return symbol_iterator(SymbolRef(ret, this)); 479} 480 481symbol_iterator COFFObjectFile::begin_dynamic_symbols() const { 482 // TODO: implement 483 report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); 484} 485 486symbol_iterator COFFObjectFile::end_dynamic_symbols() const { 487 // TODO: implement 488 report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); 489} 490 491library_iterator COFFObjectFile::begin_libraries_needed() const { 492 // TODO: implement 493 report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 494} 495 496library_iterator COFFObjectFile::end_libraries_needed() const { 497 // TODO: implement 498 report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 499} 500 501StringRef COFFObjectFile::getLoadName() const { 502 // COFF does not have this field. 503 return ""; 504} 505 506 507section_iterator COFFObjectFile::begin_sections() const { 508 DataRefImpl ret; 509 ret.p = reinterpret_cast<intptr_t>(SectionTable); 510 return section_iterator(SectionRef(ret, this)); 511} 512 513section_iterator COFFObjectFile::end_sections() const { 514 DataRefImpl ret; 515 ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections); 516 return section_iterator(SectionRef(ret, this)); 517} 518 519uint8_t COFFObjectFile::getBytesInAddress() const { 520 return getArch() == Triple::x86_64 ? 8 : 4; 521} 522 523StringRef COFFObjectFile::getFileFormatName() const { 524 switch(Header->Machine) { 525 case COFF::IMAGE_FILE_MACHINE_I386: 526 return "COFF-i386"; 527 case COFF::IMAGE_FILE_MACHINE_AMD64: 528 return "COFF-x86-64"; 529 default: 530 return "COFF-<unknown arch>"; 531 } 532} 533 534unsigned COFFObjectFile::getArch() const { 535 switch(Header->Machine) { 536 case COFF::IMAGE_FILE_MACHINE_I386: 537 return Triple::x86; 538 case COFF::IMAGE_FILE_MACHINE_AMD64: 539 return Triple::x86_64; 540 default: 541 return Triple::UnknownArch; 542 } 543} 544 545error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const { 546 Res = Header; 547 return object_error::success; 548} 549 550error_code COFFObjectFile::getSection(int32_t index, 551 const coff_section *&Result) const { 552 // Check for special index values. 553 if (index == COFF::IMAGE_SYM_UNDEFINED || 554 index == COFF::IMAGE_SYM_ABSOLUTE || 555 index == COFF::IMAGE_SYM_DEBUG) 556 Result = NULL; 557 else if (index > 0 && index <= Header->NumberOfSections) 558 // We already verified the section table data, so no need to check again. 559 Result = SectionTable + (index - 1); 560 else 561 return object_error::parse_failed; 562 return object_error::success; 563} 564 565error_code COFFObjectFile::getString(uint32_t offset, 566 StringRef &Result) const { 567 if (StringTableSize <= 4) 568 // Tried to get a string from an empty string table. 569 return object_error::parse_failed; 570 if (offset >= StringTableSize) 571 return object_error::unexpected_eof; 572 Result = StringRef(StringTable + offset); 573 return object_error::success; 574} 575 576error_code COFFObjectFile::getSymbol(uint32_t index, 577 const coff_symbol *&Result) const { 578 if (index < Header->NumberOfSymbols) 579 Result = SymbolTable + index; 580 else 581 return object_error::parse_failed; 582 return object_error::success; 583} 584 585error_code COFFObjectFile::getSymbolName(const coff_symbol *symbol, 586 StringRef &Res) const { 587 // Check for string table entry. First 4 bytes are 0. 588 if (symbol->Name.Offset.Zeroes == 0) { 589 uint32_t Offset = symbol->Name.Offset.Offset; 590 if (error_code ec = getString(Offset, Res)) 591 return ec; 592 return object_error::success; 593 } 594 595 if (symbol->Name.ShortName[7] == 0) 596 // Null terminated, let ::strlen figure out the length. 597 Res = StringRef(symbol->Name.ShortName); 598 else 599 // Not null terminated, use all 8 bytes. 600 Res = StringRef(symbol->Name.ShortName, 8); 601 return object_error::success; 602} 603 604error_code COFFObjectFile::getSectionName(const coff_section *Sec, 605 StringRef &Res) const { 606 StringRef Name; 607 if (Sec->Name[7] == 0) 608 // Null terminated, let ::strlen figure out the length. 609 Name = Sec->Name; 610 else 611 // Not null terminated, use all 8 bytes. 612 Name = StringRef(Sec->Name, 8); 613 614 // Check for string table entry. First byte is '/'. 615 if (Name[0] == '/') { 616 uint32_t Offset; 617 if (Name.substr(1).getAsInteger(10, Offset)) 618 return object_error::parse_failed; 619 if (error_code ec = getString(Offset, Name)) 620 return ec; 621 } 622 623 Res = Name; 624 return object_error::success; 625} 626 627error_code COFFObjectFile::getSectionContents(const coff_section *Sec, 628 ArrayRef<uint8_t> &Res) const { 629 // The only thing that we need to verify is that the contents is contained 630 // within the file bounds. We don't need to make sure it doesn't cover other 631 // data, as there's nothing that says that is not allowed. 632 uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 633 uintptr_t ConEnd = ConStart + Sec->SizeOfRawData; 634 if (ConEnd > uintptr_t(Data->getBufferEnd())) 635 return object_error::parse_failed; 636 Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart), 637 Sec->SizeOfRawData); 638 return object_error::success; 639} 640 641const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 642 return reinterpret_cast<const coff_relocation*>(Rel.p); 643} 644error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, 645 RelocationRef &Res) const { 646 Rel.p = reinterpret_cast<uintptr_t>( 647 reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 648 Res = RelocationRef(Rel, this); 649 return object_error::success; 650} 651error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 652 uint64_t &Res) const { 653 Res = toRel(Rel)->VirtualAddress; 654 return object_error::success; 655} 656error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, 657 uint64_t &Res) const { 658 Res = toRel(Rel)->VirtualAddress; 659 return object_error::success; 660} 661error_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel, 662 SymbolRef &Res) const { 663 const coff_relocation* R = toRel(Rel); 664 DataRefImpl Symb; 665 Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); 666 Res = SymbolRef(Symb, this); 667 return object_error::success; 668} 669error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 670 uint64_t &Res) const { 671 const coff_relocation* R = toRel(Rel); 672 Res = R->Type; 673 return object_error::success; 674} 675 676#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \ 677 case COFF::enum: res = #enum; break; 678 679error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 680 SmallVectorImpl<char> &Result) const { 681 const coff_relocation *reloc = toRel(Rel); 682 StringRef res; 683 switch (Header->Machine) { 684 case COFF::IMAGE_FILE_MACHINE_AMD64: 685 switch (reloc->Type) { 686 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 687 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 688 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 689 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 690 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 691 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 692 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 693 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 694 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 695 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 696 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 697 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 698 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 699 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 700 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 701 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 702 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 703 default: 704 res = "Unknown"; 705 } 706 break; 707 case COFF::IMAGE_FILE_MACHINE_I386: 708 switch (reloc->Type) { 709 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 710 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 711 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 712 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 713 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 714 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 715 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 716 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 717 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 718 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 719 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 720 default: 721 res = "Unknown"; 722 } 723 break; 724 default: 725 res = "Unknown"; 726 } 727 Result.append(res.begin(), res.end()); 728 return object_error::success; 729} 730 731#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 732 733error_code COFFObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, 734 int64_t &Res) const { 735 Res = 0; 736 return object_error::success; 737} 738error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, 739 SmallVectorImpl<char> &Result) const { 740 const coff_relocation *reloc = toRel(Rel); 741 const coff_symbol *symb = 0; 742 if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec; 743 DataRefImpl sym; 744 sym.p = reinterpret_cast<uintptr_t>(symb); 745 StringRef symname; 746 if (error_code ec = getSymbolName(sym, symname)) return ec; 747 Result.append(symname.begin(), symname.end()); 748 return object_error::success; 749} 750 751error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, 752 LibraryRef &Result) const { 753 report_fatal_error("getLibraryNext not implemented in COFFObjectFile"); 754} 755 756error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, 757 StringRef &Result) const { 758 report_fatal_error("getLibraryPath not implemented in COFFObjectFile"); 759} 760 761namespace llvm { 762 763 ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { 764 error_code ec; 765 return new COFFObjectFile(Object, ec); 766 } 767 768} // end namespace llvm 769