1 //===- COFFObjectFile.cpp - COFF object file implementation ---------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file declares the COFFObjectFile class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ADT/ArrayRef.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/ADT/Triple.h" 16 #include "llvm/ADT/iterator_range.h" 17 #include "llvm/BinaryFormat/COFF.h" 18 #include "llvm/Object/Binary.h" 19 #include "llvm/Object/COFF.h" 20 #include "llvm/Object/Error.h" 21 #include "llvm/Object/ObjectFile.h" 22 #include "llvm/Support/BinaryStreamReader.h" 23 #include "llvm/Support/Endian.h" 24 #include "llvm/Support/Error.h" 25 #include "llvm/Support/ErrorHandling.h" 26 #include "llvm/Support/MathExtras.h" 27 #include "llvm/Support/MemoryBuffer.h" 28 #include <algorithm> 29 #include <cassert> 30 #include <cstddef> 31 #include <cstdint> 32 #include <cstring> 33 #include <limits> 34 #include <memory> 35 #include <system_error> 36 37 using namespace llvm; 38 using namespace object; 39 40 using support::ulittle16_t; 41 using support::ulittle32_t; 42 using support::ulittle64_t; 43 using support::little16_t; 44 45 // Returns false if size is greater than the buffer size. And sets ec. 46 static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) { 47 if (M.getBufferSize() < Size) { 48 EC = object_error::unexpected_eof; 49 return false; 50 } 51 return true; 52 } 53 54 // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 55 // Returns unexpected_eof if error. 56 template <typename T> 57 static std::error_code getObject(const T *&Obj, MemoryBufferRef M, 58 const void *Ptr, 59 const uint64_t Size = sizeof(T)) { 60 uintptr_t Addr = uintptr_t(Ptr); 61 if (std::error_code EC = Binary::checkOffset(M, Addr, Size)) 62 return EC; 63 Obj = reinterpret_cast<const T *>(Addr); 64 return std::error_code(); 65 } 66 67 // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 68 // prefixed slashes. 69 static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 70 assert(Str.size() <= 6 && "String too long, possible overflow."); 71 if (Str.size() > 6) 72 return true; 73 74 uint64_t Value = 0; 75 while (!Str.empty()) { 76 unsigned CharVal; 77 if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 78 CharVal = Str[0] - 'A'; 79 else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 80 CharVal = Str[0] - 'a' + 26; 81 else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 82 CharVal = Str[0] - '0' + 52; 83 else if (Str[0] == '+') // 62 84 CharVal = 62; 85 else if (Str[0] == '/') // 63 86 CharVal = 63; 87 else 88 return true; 89 90 Value = (Value * 64) + CharVal; 91 Str = Str.substr(1); 92 } 93 94 if (Value > std::numeric_limits<uint32_t>::max()) 95 return true; 96 97 Result = static_cast<uint32_t>(Value); 98 return false; 99 } 100 101 template <typename coff_symbol_type> 102 const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { 103 const coff_symbol_type *Addr = 104 reinterpret_cast<const coff_symbol_type *>(Ref.p); 105 106 assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr))); 107 #ifndef NDEBUG 108 // Verify that the symbol points to a valid entry in the symbol table. 109 uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); 110 111 assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && 112 "Symbol did not point to the beginning of a symbol"); 113 #endif 114 115 return Addr; 116 } 117 118 const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 119 const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 120 121 #ifndef NDEBUG 122 // Verify that the section points to a valid entry in the section table. 123 if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) 124 report_fatal_error("Section was outside of section table."); 125 126 uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); 127 assert(Offset % sizeof(coff_section) == 0 && 128 "Section did not point to the beginning of a section"); 129 #endif 130 131 return Addr; 132 } 133 134 void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 135 auto End = reinterpret_cast<uintptr_t>(StringTable); 136 if (SymbolTable16) { 137 const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref); 138 Symb += 1 + Symb->NumberOfAuxSymbols; 139 Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 140 } else if (SymbolTable32) { 141 const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref); 142 Symb += 1 + Symb->NumberOfAuxSymbols; 143 Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 144 } else { 145 llvm_unreachable("no symbol table pointer!"); 146 } 147 } 148 149 Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const { 150 COFFSymbolRef Symb = getCOFFSymbol(Ref); 151 StringRef Result; 152 if (std::error_code EC = getSymbolName(Symb, Result)) 153 return errorCodeToError(EC); 154 return Result; 155 } 156 157 uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const { 158 return getCOFFSymbol(Ref).getValue(); 159 } 160 161 uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const { 162 // MSVC/link.exe seems to align symbols to the next-power-of-2 163 // up to 32 bytes. 164 COFFSymbolRef Symb = getCOFFSymbol(Ref); 165 return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue())); 166 } 167 168 Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { 169 uint64_t Result = getSymbolValue(Ref); 170 COFFSymbolRef Symb = getCOFFSymbol(Ref); 171 int32_t SectionNumber = Symb.getSectionNumber(); 172 173 if (Symb.isAnyUndefined() || Symb.isCommon() || 174 COFF::isReservedSectionNumber(SectionNumber)) 175 return Result; 176 177 const coff_section *Section = nullptr; 178 if (std::error_code EC = getSection(SectionNumber, Section)) 179 return errorCodeToError(EC); 180 Result += Section->VirtualAddress; 181 182 // The section VirtualAddress does not include ImageBase, and we want to 183 // return virtual addresses. 184 Result += getImageBase(); 185 186 return Result; 187 } 188 189 Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const { 190 COFFSymbolRef Symb = getCOFFSymbol(Ref); 191 int32_t SectionNumber = Symb.getSectionNumber(); 192 193 if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) 194 return SymbolRef::ST_Function; 195 if (Symb.isAnyUndefined()) 196 return SymbolRef::ST_Unknown; 197 if (Symb.isCommon()) 198 return SymbolRef::ST_Data; 199 if (Symb.isFileRecord()) 200 return SymbolRef::ST_File; 201 202 // TODO: perhaps we need a new symbol type ST_Section. 203 if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition()) 204 return SymbolRef::ST_Debug; 205 206 if (!COFF::isReservedSectionNumber(SectionNumber)) 207 return SymbolRef::ST_Data; 208 209 return SymbolRef::ST_Other; 210 } 211 212 uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 213 COFFSymbolRef Symb = getCOFFSymbol(Ref); 214 uint32_t Result = SymbolRef::SF_None; 215 216 if (Symb.isExternal() || Symb.isWeakExternal()) 217 Result |= SymbolRef::SF_Global; 218 219 if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) { 220 Result |= SymbolRef::SF_Weak; 221 if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS) 222 Result |= SymbolRef::SF_Undefined; 223 } 224 225 if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 226 Result |= SymbolRef::SF_Absolute; 227 228 if (Symb.isFileRecord()) 229 Result |= SymbolRef::SF_FormatSpecific; 230 231 if (Symb.isSectionDefinition()) 232 Result |= SymbolRef::SF_FormatSpecific; 233 234 if (Symb.isCommon()) 235 Result |= SymbolRef::SF_Common; 236 237 if (Symb.isUndefined()) 238 Result |= SymbolRef::SF_Undefined; 239 240 return Result; 241 } 242 243 uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const { 244 COFFSymbolRef Symb = getCOFFSymbol(Ref); 245 return Symb.getValue(); 246 } 247 248 Expected<section_iterator> 249 COFFObjectFile::getSymbolSection(DataRefImpl Ref) const { 250 COFFSymbolRef Symb = getCOFFSymbol(Ref); 251 if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) 252 return section_end(); 253 const coff_section *Sec = nullptr; 254 if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) 255 return errorCodeToError(EC); 256 DataRefImpl Ret; 257 Ret.p = reinterpret_cast<uintptr_t>(Sec); 258 return section_iterator(SectionRef(Ret, this)); 259 } 260 261 unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 262 COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl()); 263 return Symb.getSectionNumber(); 264 } 265 266 void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 267 const coff_section *Sec = toSec(Ref); 268 Sec += 1; 269 Ref.p = reinterpret_cast<uintptr_t>(Sec); 270 } 271 272 std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, 273 StringRef &Result) const { 274 const coff_section *Sec = toSec(Ref); 275 return getSectionName(Sec, Result); 276 } 277 278 uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 279 const coff_section *Sec = toSec(Ref); 280 uint64_t Result = Sec->VirtualAddress; 281 282 // The section VirtualAddress does not include ImageBase, and we want to 283 // return virtual addresses. 284 Result += getImageBase(); 285 return Result; 286 } 287 288 uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const { 289 return toSec(Sec) - SectionTable; 290 } 291 292 uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 293 return getSectionSize(toSec(Ref)); 294 } 295 296 std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 297 StringRef &Result) const { 298 const coff_section *Sec = toSec(Ref); 299 ArrayRef<uint8_t> Res; 300 std::error_code EC = getSectionContents(Sec, Res); 301 Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 302 return EC; 303 } 304 305 uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 306 const coff_section *Sec = toSec(Ref); 307 return Sec->getAlignment(); 308 } 309 310 bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 311 return false; 312 } 313 314 bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 315 const coff_section *Sec = toSec(Ref); 316 return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 317 } 318 319 bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 320 const coff_section *Sec = toSec(Ref); 321 return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 322 } 323 324 bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 325 const coff_section *Sec = toSec(Ref); 326 const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 327 COFF::IMAGE_SCN_MEM_READ | 328 COFF::IMAGE_SCN_MEM_WRITE; 329 return (Sec->Characteristics & BssFlags) == BssFlags; 330 } 331 332 unsigned COFFObjectFile::getSectionID(SectionRef Sec) const { 333 uintptr_t Offset = 334 uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable); 335 assert((Offset % sizeof(coff_section)) == 0); 336 return (Offset / sizeof(coff_section)) + 1; 337 } 338 339 bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 340 const coff_section *Sec = toSec(Ref); 341 // In COFF, a virtual section won't have any in-file 342 // content, so the file pointer to the content will be zero. 343 return Sec->PointerToRawData == 0; 344 } 345 346 static uint32_t getNumberOfRelocations(const coff_section *Sec, 347 MemoryBufferRef M, const uint8_t *base) { 348 // The field for the number of relocations in COFF section table is only 349 // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 350 // NumberOfRelocations field, and the actual relocation count is stored in the 351 // VirtualAddress field in the first relocation entry. 352 if (Sec->hasExtendedRelocations()) { 353 const coff_relocation *FirstReloc; 354 if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>( 355 base + Sec->PointerToRelocations))) 356 return 0; 357 // -1 to exclude this first relocation entry. 358 return FirstReloc->VirtualAddress - 1; 359 } 360 return Sec->NumberOfRelocations; 361 } 362 363 static const coff_relocation * 364 getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { 365 uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); 366 if (!NumRelocs) 367 return nullptr; 368 auto begin = reinterpret_cast<const coff_relocation *>( 369 Base + Sec->PointerToRelocations); 370 if (Sec->hasExtendedRelocations()) { 371 // Skip the first relocation entry repurposed to store the number of 372 // relocations. 373 begin++; 374 } 375 if (Binary::checkOffset(M, uintptr_t(begin), 376 sizeof(coff_relocation) * NumRelocs)) 377 return nullptr; 378 return begin; 379 } 380 381 relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 382 const coff_section *Sec = toSec(Ref); 383 const coff_relocation *begin = getFirstReloc(Sec, Data, base()); 384 if (begin && Sec->VirtualAddress != 0) 385 report_fatal_error("Sections with relocations should have an address of 0"); 386 DataRefImpl Ret; 387 Ret.p = reinterpret_cast<uintptr_t>(begin); 388 return relocation_iterator(RelocationRef(Ret, this)); 389 } 390 391 relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 392 const coff_section *Sec = toSec(Ref); 393 const coff_relocation *I = getFirstReloc(Sec, Data, base()); 394 if (I) 395 I += getNumberOfRelocations(Sec, Data, base()); 396 DataRefImpl Ret; 397 Ret.p = reinterpret_cast<uintptr_t>(I); 398 return relocation_iterator(RelocationRef(Ret, this)); 399 } 400 401 // Initialize the pointer to the symbol table. 402 std::error_code COFFObjectFile::initSymbolTablePtr() { 403 if (COFFHeader) 404 if (std::error_code EC = getObject( 405 SymbolTable16, Data, base() + getPointerToSymbolTable(), 406 (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 407 return EC; 408 409 if (COFFBigObjHeader) 410 if (std::error_code EC = getObject( 411 SymbolTable32, Data, base() + getPointerToSymbolTable(), 412 (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 413 return EC; 414 415 // Find string table. The first four byte of the string table contains the 416 // total size of the string table, including the size field itself. If the 417 // string table is empty, the value of the first four byte would be 4. 418 uint32_t StringTableOffset = getPointerToSymbolTable() + 419 getNumberOfSymbols() * getSymbolTableEntrySize(); 420 const uint8_t *StringTableAddr = base() + StringTableOffset; 421 const ulittle32_t *StringTableSizePtr; 422 if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 423 return EC; 424 StringTableSize = *StringTableSizePtr; 425 if (std::error_code EC = 426 getObject(StringTable, Data, StringTableAddr, StringTableSize)) 427 return EC; 428 429 // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 430 // tools like cvtres write a size of 0 for an empty table instead of 4. 431 if (StringTableSize < 4) 432 StringTableSize = 4; 433 434 // Check that the string table is null terminated if has any in it. 435 if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 436 return object_error::parse_failed; 437 return std::error_code(); 438 } 439 440 uint64_t COFFObjectFile::getImageBase() const { 441 if (PE32Header) 442 return PE32Header->ImageBase; 443 else if (PE32PlusHeader) 444 return PE32PlusHeader->ImageBase; 445 // This actually comes up in practice. 446 return 0; 447 } 448 449 // Returns the file offset for the given VA. 450 std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 451 uint64_t ImageBase = getImageBase(); 452 uint64_t Rva = Addr - ImageBase; 453 assert(Rva <= UINT32_MAX); 454 return getRvaPtr((uint32_t)Rva, Res); 455 } 456 457 // Returns the file offset for the given RVA. 458 std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 459 for (const SectionRef &S : sections()) { 460 const coff_section *Section = getCOFFSection(S); 461 uint32_t SectionStart = Section->VirtualAddress; 462 uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 463 if (SectionStart <= Addr && Addr < SectionEnd) { 464 uint32_t Offset = Addr - SectionStart; 465 Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 466 return std::error_code(); 467 } 468 } 469 return object_error::parse_failed; 470 } 471 472 std::error_code 473 COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 474 ArrayRef<uint8_t> &Contents) const { 475 for (const SectionRef &S : sections()) { 476 const coff_section *Section = getCOFFSection(S); 477 uint32_t SectionStart = Section->VirtualAddress; 478 // Check if this RVA is within the section bounds. Be careful about integer 479 // overflow. 480 uint32_t OffsetIntoSection = RVA - SectionStart; 481 if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize && 482 Size <= Section->VirtualSize - OffsetIntoSection) { 483 uintptr_t Begin = 484 uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection; 485 Contents = 486 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); 487 return std::error_code(); 488 } 489 } 490 return object_error::parse_failed; 491 } 492 493 // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 494 // table entry. 495 std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 496 StringRef &Name) const { 497 uintptr_t IntPtr = 0; 498 if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 499 return EC; 500 const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 501 Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 502 Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 503 return std::error_code(); 504 } 505 506 std::error_code 507 COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, 508 const codeview::DebugInfo *&PDBInfo, 509 StringRef &PDBFileName) const { 510 ArrayRef<uint8_t> InfoBytes; 511 if (std::error_code EC = getRvaAndSizeAsBytes( 512 DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) 513 return EC; 514 if (InfoBytes.size() < sizeof(*PDBInfo) + 1) 515 return object_error::parse_failed; 516 PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data()); 517 InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo)); 518 PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), 519 InfoBytes.size()); 520 // Truncate the name at the first null byte. Ignore any padding. 521 PDBFileName = PDBFileName.split('\0').first; 522 return std::error_code(); 523 } 524 525 std::error_code 526 COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo, 527 StringRef &PDBFileName) const { 528 for (const debug_directory &D : debug_directories()) 529 if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) 530 return getDebugPDBInfo(&D, PDBInfo, PDBFileName); 531 // If we get here, there is no PDB info to return. 532 PDBInfo = nullptr; 533 PDBFileName = StringRef(); 534 return std::error_code(); 535 } 536 537 // Find the import table. 538 std::error_code COFFObjectFile::initImportTablePtr() { 539 // First, we get the RVA of the import table. If the file lacks a pointer to 540 // the import table, do nothing. 541 const data_directory *DataEntry; 542 if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 543 return std::error_code(); 544 545 // Do nothing if the pointer to import table is NULL. 546 if (DataEntry->RelativeVirtualAddress == 0) 547 return std::error_code(); 548 549 uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 550 551 // Find the section that contains the RVA. This is needed because the RVA is 552 // the import table's memory address which is different from its file offset. 553 uintptr_t IntPtr = 0; 554 if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 555 return EC; 556 if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size)) 557 return EC; 558 ImportDirectory = reinterpret_cast< 559 const coff_import_directory_table_entry *>(IntPtr); 560 return std::error_code(); 561 } 562 563 // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 564 std::error_code COFFObjectFile::initDelayImportTablePtr() { 565 const data_directory *DataEntry; 566 if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 567 return std::error_code(); 568 if (DataEntry->RelativeVirtualAddress == 0) 569 return std::error_code(); 570 571 uint32_t RVA = DataEntry->RelativeVirtualAddress; 572 NumberOfDelayImportDirectory = DataEntry->Size / 573 sizeof(delay_import_directory_table_entry) - 1; 574 575 uintptr_t IntPtr = 0; 576 if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 577 return EC; 578 DelayImportDirectory = reinterpret_cast< 579 const delay_import_directory_table_entry *>(IntPtr); 580 return std::error_code(); 581 } 582 583 // Find the export table. 584 std::error_code COFFObjectFile::initExportTablePtr() { 585 // First, we get the RVA of the export table. If the file lacks a pointer to 586 // the export table, do nothing. 587 const data_directory *DataEntry; 588 if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 589 return std::error_code(); 590 591 // Do nothing if the pointer to export table is NULL. 592 if (DataEntry->RelativeVirtualAddress == 0) 593 return std::error_code(); 594 595 uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 596 uintptr_t IntPtr = 0; 597 if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 598 return EC; 599 ExportDirectory = 600 reinterpret_cast<const export_directory_table_entry *>(IntPtr); 601 return std::error_code(); 602 } 603 604 std::error_code COFFObjectFile::initBaseRelocPtr() { 605 const data_directory *DataEntry; 606 if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) 607 return std::error_code(); 608 if (DataEntry->RelativeVirtualAddress == 0) 609 return std::error_code(); 610 611 uintptr_t IntPtr = 0; 612 if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 613 return EC; 614 BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 615 IntPtr); 616 BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 617 IntPtr + DataEntry->Size); 618 // FIXME: Verify the section containing BaseRelocHeader has at least 619 // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress. 620 return std::error_code(); 621 } 622 623 std::error_code COFFObjectFile::initDebugDirectoryPtr() { 624 // Get the RVA of the debug directory. Do nothing if it does not exist. 625 const data_directory *DataEntry; 626 if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry)) 627 return std::error_code(); 628 629 // Do nothing if the RVA is NULL. 630 if (DataEntry->RelativeVirtualAddress == 0) 631 return std::error_code(); 632 633 // Check that the size is a multiple of the entry size. 634 if (DataEntry->Size % sizeof(debug_directory) != 0) 635 return object_error::parse_failed; 636 637 uintptr_t IntPtr = 0; 638 if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 639 return EC; 640 DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); 641 DebugDirectoryEnd = reinterpret_cast<const debug_directory *>( 642 IntPtr + DataEntry->Size); 643 // FIXME: Verify the section containing DebugDirectoryBegin has at least 644 // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress. 645 return std::error_code(); 646 } 647 648 std::error_code COFFObjectFile::initLoadConfigPtr() { 649 // Get the RVA of the debug directory. Do nothing if it does not exist. 650 const data_directory *DataEntry; 651 if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry)) 652 return std::error_code(); 653 654 // Do nothing if the RVA is NULL. 655 if (DataEntry->RelativeVirtualAddress == 0) 656 return std::error_code(); 657 uintptr_t IntPtr = 0; 658 if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 659 return EC; 660 661 LoadConfig = (const void *)IntPtr; 662 return std::error_code(); 663 } 664 665 COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 666 : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 667 COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 668 DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 669 SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 670 ImportDirectory(nullptr), 671 DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 672 ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), 673 DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) { 674 // Check that we at least have enough room for a header. 675 if (!checkSize(Data, EC, sizeof(coff_file_header))) 676 return; 677 678 // The current location in the file where we are looking at. 679 uint64_t CurPtr = 0; 680 681 // PE header is optional and is present only in executables. If it exists, 682 // it is placed right after COFF header. 683 bool HasPEHeader = false; 684 685 // Check if this is a PE/COFF file. 686 if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 687 // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 688 // PE signature to find 'normal' COFF header. 689 const auto *DH = reinterpret_cast<const dos_header *>(base()); 690 if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 691 CurPtr = DH->AddressOfNewExeHeader; 692 // Check the PE magic bytes. ("PE\0\0") 693 if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 694 EC = object_error::parse_failed; 695 return; 696 } 697 CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 698 HasPEHeader = true; 699 } 700 } 701 702 if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 703 return; 704 705 // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 706 // import libraries share a common prefix but bigobj is more restrictive. 707 if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 708 COFFHeader->NumberOfSections == uint16_t(0xffff) && 709 checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 710 if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 711 return; 712 713 // Verify that we are dealing with bigobj. 714 if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 715 std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 716 sizeof(COFF::BigObjMagic)) == 0) { 717 COFFHeader = nullptr; 718 CurPtr += sizeof(coff_bigobj_file_header); 719 } else { 720 // It's not a bigobj. 721 COFFBigObjHeader = nullptr; 722 } 723 } 724 if (COFFHeader) { 725 // The prior checkSize call may have failed. This isn't a hard error 726 // because we were just trying to sniff out bigobj. 727 EC = std::error_code(); 728 CurPtr += sizeof(coff_file_header); 729 730 if (COFFHeader->isImportLibrary()) 731 return; 732 } 733 734 if (HasPEHeader) { 735 const pe32_header *Header; 736 if ((EC = getObject(Header, Data, base() + CurPtr))) 737 return; 738 739 const uint8_t *DataDirAddr; 740 uint64_t DataDirSize; 741 if (Header->Magic == COFF::PE32Header::PE32) { 742 PE32Header = Header; 743 DataDirAddr = base() + CurPtr + sizeof(pe32_header); 744 DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 745 } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 746 PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 747 DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 748 DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 749 } else { 750 // It's neither PE32 nor PE32+. 751 EC = object_error::parse_failed; 752 return; 753 } 754 if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 755 return; 756 } 757 758 if (COFFHeader) 759 CurPtr += COFFHeader->SizeOfOptionalHeader; 760 761 if ((EC = getObject(SectionTable, Data, base() + CurPtr, 762 (uint64_t)getNumberOfSections() * sizeof(coff_section)))) 763 return; 764 765 // Initialize the pointer to the symbol table. 766 if (getPointerToSymbolTable() != 0) { 767 if ((EC = initSymbolTablePtr())) { 768 SymbolTable16 = nullptr; 769 SymbolTable32 = nullptr; 770 StringTable = nullptr; 771 StringTableSize = 0; 772 } 773 } else { 774 // We had better not have any symbols if we don't have a symbol table. 775 if (getNumberOfSymbols() != 0) { 776 EC = object_error::parse_failed; 777 return; 778 } 779 } 780 781 // Initialize the pointer to the beginning of the import table. 782 if ((EC = initImportTablePtr())) 783 return; 784 if ((EC = initDelayImportTablePtr())) 785 return; 786 787 // Initialize the pointer to the export table. 788 if ((EC = initExportTablePtr())) 789 return; 790 791 // Initialize the pointer to the base relocation table. 792 if ((EC = initBaseRelocPtr())) 793 return; 794 795 // Initialize the pointer to the export table. 796 if ((EC = initDebugDirectoryPtr())) 797 return; 798 799 if ((EC = initLoadConfigPtr())) 800 return; 801 802 EC = std::error_code(); 803 } 804 805 basic_symbol_iterator COFFObjectFile::symbol_begin() const { 806 DataRefImpl Ret; 807 Ret.p = getSymbolTable(); 808 return basic_symbol_iterator(SymbolRef(Ret, this)); 809 } 810 811 basic_symbol_iterator COFFObjectFile::symbol_end() const { 812 // The symbol table ends where the string table begins. 813 DataRefImpl Ret; 814 Ret.p = reinterpret_cast<uintptr_t>(StringTable); 815 return basic_symbol_iterator(SymbolRef(Ret, this)); 816 } 817 818 import_directory_iterator COFFObjectFile::import_directory_begin() const { 819 if (!ImportDirectory) 820 return import_directory_end(); 821 if (ImportDirectory->isNull()) 822 return import_directory_end(); 823 return import_directory_iterator( 824 ImportDirectoryEntryRef(ImportDirectory, 0, this)); 825 } 826 827 import_directory_iterator COFFObjectFile::import_directory_end() const { 828 return import_directory_iterator( 829 ImportDirectoryEntryRef(nullptr, -1, this)); 830 } 831 832 delay_import_directory_iterator 833 COFFObjectFile::delay_import_directory_begin() const { 834 return delay_import_directory_iterator( 835 DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 836 } 837 838 delay_import_directory_iterator 839 COFFObjectFile::delay_import_directory_end() const { 840 return delay_import_directory_iterator( 841 DelayImportDirectoryEntryRef( 842 DelayImportDirectory, NumberOfDelayImportDirectory, this)); 843 } 844 845 export_directory_iterator COFFObjectFile::export_directory_begin() const { 846 return export_directory_iterator( 847 ExportDirectoryEntryRef(ExportDirectory, 0, this)); 848 } 849 850 export_directory_iterator COFFObjectFile::export_directory_end() const { 851 if (!ExportDirectory) 852 return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 853 ExportDirectoryEntryRef Ref(ExportDirectory, 854 ExportDirectory->AddressTableEntries, this); 855 return export_directory_iterator(Ref); 856 } 857 858 section_iterator COFFObjectFile::section_begin() const { 859 DataRefImpl Ret; 860 Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 861 return section_iterator(SectionRef(Ret, this)); 862 } 863 864 section_iterator COFFObjectFile::section_end() const { 865 DataRefImpl Ret; 866 int NumSections = 867 COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 868 Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 869 return section_iterator(SectionRef(Ret, this)); 870 } 871 872 base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 873 return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 874 } 875 876 base_reloc_iterator COFFObjectFile::base_reloc_end() const { 877 return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 878 } 879 880 uint8_t COFFObjectFile::getBytesInAddress() const { 881 return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4; 882 } 883 884 StringRef COFFObjectFile::getFileFormatName() const { 885 switch(getMachine()) { 886 case COFF::IMAGE_FILE_MACHINE_I386: 887 return "COFF-i386"; 888 case COFF::IMAGE_FILE_MACHINE_AMD64: 889 return "COFF-x86-64"; 890 case COFF::IMAGE_FILE_MACHINE_ARMNT: 891 return "COFF-ARM"; 892 case COFF::IMAGE_FILE_MACHINE_ARM64: 893 return "COFF-ARM64"; 894 default: 895 return "COFF-<unknown arch>"; 896 } 897 } 898 899 Triple::ArchType COFFObjectFile::getArch() const { 900 switch (getMachine()) { 901 case COFF::IMAGE_FILE_MACHINE_I386: 902 return Triple::x86; 903 case COFF::IMAGE_FILE_MACHINE_AMD64: 904 return Triple::x86_64; 905 case COFF::IMAGE_FILE_MACHINE_ARMNT: 906 return Triple::thumb; 907 case COFF::IMAGE_FILE_MACHINE_ARM64: 908 return Triple::aarch64; 909 default: 910 return Triple::UnknownArch; 911 } 912 } 913 914 Expected<uint64_t> COFFObjectFile::getStartAddress() const { 915 if (PE32Header) 916 return PE32Header->AddressOfEntryPoint; 917 return 0; 918 } 919 920 iterator_range<import_directory_iterator> 921 COFFObjectFile::import_directories() const { 922 return make_range(import_directory_begin(), import_directory_end()); 923 } 924 925 iterator_range<delay_import_directory_iterator> 926 COFFObjectFile::delay_import_directories() const { 927 return make_range(delay_import_directory_begin(), 928 delay_import_directory_end()); 929 } 930 931 iterator_range<export_directory_iterator> 932 COFFObjectFile::export_directories() const { 933 return make_range(export_directory_begin(), export_directory_end()); 934 } 935 936 iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 937 return make_range(base_reloc_begin(), base_reloc_end()); 938 } 939 940 std::error_code 941 COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const { 942 Res = COFFHeader; 943 return std::error_code(); 944 } 945 946 std::error_code 947 COFFObjectFile::getCOFFBigObjHeader(const coff_bigobj_file_header *&Res) const { 948 Res = COFFBigObjHeader; 949 return std::error_code(); 950 } 951 952 std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 953 Res = PE32Header; 954 return std::error_code(); 955 } 956 957 std::error_code 958 COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 959 Res = PE32PlusHeader; 960 return std::error_code(); 961 } 962 963 std::error_code 964 COFFObjectFile::getDataDirectory(uint32_t Index, 965 const data_directory *&Res) const { 966 // Error if there's no data directory or the index is out of range. 967 if (!DataDirectory) { 968 Res = nullptr; 969 return object_error::parse_failed; 970 } 971 assert(PE32Header || PE32PlusHeader); 972 uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 973 : PE32PlusHeader->NumberOfRvaAndSize; 974 if (Index >= NumEnt) { 975 Res = nullptr; 976 return object_error::parse_failed; 977 } 978 Res = &DataDirectory[Index]; 979 return std::error_code(); 980 } 981 982 std::error_code COFFObjectFile::getSection(int32_t Index, 983 const coff_section *&Result) const { 984 Result = nullptr; 985 if (COFF::isReservedSectionNumber(Index)) 986 return std::error_code(); 987 if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 988 // We already verified the section table data, so no need to check again. 989 Result = SectionTable + (Index - 1); 990 return std::error_code(); 991 } 992 return object_error::parse_failed; 993 } 994 995 std::error_code COFFObjectFile::getSection(StringRef SectionName, 996 const coff_section *&Result) const { 997 Result = nullptr; 998 StringRef SecName; 999 for (const SectionRef &Section : sections()) { 1000 if (std::error_code E = Section.getName(SecName)) 1001 return E; 1002 if (SecName == SectionName) { 1003 Result = getCOFFSection(Section); 1004 return std::error_code(); 1005 } 1006 } 1007 return object_error::parse_failed; 1008 } 1009 1010 std::error_code COFFObjectFile::getString(uint32_t Offset, 1011 StringRef &Result) const { 1012 if (StringTableSize <= 4) 1013 // Tried to get a string from an empty string table. 1014 return object_error::parse_failed; 1015 if (Offset >= StringTableSize) 1016 return object_error::unexpected_eof; 1017 Result = StringRef(StringTable + Offset); 1018 return std::error_code(); 1019 } 1020 1021 std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 1022 StringRef &Res) const { 1023 return getSymbolName(Symbol.getGeneric(), Res); 1024 } 1025 1026 std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol, 1027 StringRef &Res) const { 1028 // Check for string table entry. First 4 bytes are 0. 1029 if (Symbol->Name.Offset.Zeroes == 0) { 1030 if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res)) 1031 return EC; 1032 return std::error_code(); 1033 } 1034 1035 if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 1036 // Null terminated, let ::strlen figure out the length. 1037 Res = StringRef(Symbol->Name.ShortName); 1038 else 1039 // Not null terminated, use all 8 bytes. 1040 Res = StringRef(Symbol->Name.ShortName, COFF::NameSize); 1041 return std::error_code(); 1042 } 1043 1044 ArrayRef<uint8_t> 1045 COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 1046 const uint8_t *Aux = nullptr; 1047 1048 size_t SymbolSize = getSymbolTableEntrySize(); 1049 if (Symbol.getNumberOfAuxSymbols() > 0) { 1050 // AUX data comes immediately after the symbol in COFF 1051 Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 1052 #ifndef NDEBUG 1053 // Verify that the Aux symbol points to a valid entry in the symbol table. 1054 uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 1055 if (Offset < getPointerToSymbolTable() || 1056 Offset >= 1057 getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 1058 report_fatal_error("Aux Symbol data was outside of symbol table."); 1059 1060 assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 1061 "Aux Symbol data did not point to the beginning of a symbol"); 1062 #endif 1063 } 1064 return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 1065 } 1066 1067 uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const { 1068 uintptr_t Offset = 1069 reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable(); 1070 assert(Offset % getSymbolTableEntrySize() == 0 && 1071 "Symbol did not point to the beginning of a symbol"); 1072 size_t Index = Offset / getSymbolTableEntrySize(); 1073 assert(Index < getNumberOfSymbols()); 1074 return Index; 1075 } 1076 1077 std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 1078 StringRef &Res) const { 1079 StringRef Name; 1080 if (Sec->Name[COFF::NameSize - 1] == 0) 1081 // Null terminated, let ::strlen figure out the length. 1082 Name = Sec->Name; 1083 else 1084 // Not null terminated, use all 8 bytes. 1085 Name = StringRef(Sec->Name, COFF::NameSize); 1086 1087 // Check for string table entry. First byte is '/'. 1088 if (Name.startswith("/")) { 1089 uint32_t Offset; 1090 if (Name.startswith("//")) { 1091 if (decodeBase64StringEntry(Name.substr(2), Offset)) 1092 return object_error::parse_failed; 1093 } else { 1094 if (Name.substr(1).getAsInteger(10, Offset)) 1095 return object_error::parse_failed; 1096 } 1097 if (std::error_code EC = getString(Offset, Name)) 1098 return EC; 1099 } 1100 1101 Res = Name; 1102 return std::error_code(); 1103 } 1104 1105 uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 1106 // SizeOfRawData and VirtualSize change what they represent depending on 1107 // whether or not we have an executable image. 1108 // 1109 // For object files, SizeOfRawData contains the size of section's data; 1110 // VirtualSize should be zero but isn't due to buggy COFF writers. 1111 // 1112 // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 1113 // actual section size is in VirtualSize. It is possible for VirtualSize to 1114 // be greater than SizeOfRawData; the contents past that point should be 1115 // considered to be zero. 1116 if (getDOSHeader()) 1117 return std::min(Sec->VirtualSize, Sec->SizeOfRawData); 1118 return Sec->SizeOfRawData; 1119 } 1120 1121 std::error_code 1122 COFFObjectFile::getSectionContents(const coff_section *Sec, 1123 ArrayRef<uint8_t> &Res) const { 1124 // In COFF, a virtual section won't have any in-file 1125 // content, so the file pointer to the content will be zero. 1126 if (Sec->PointerToRawData == 0) 1127 return std::error_code(); 1128 // The only thing that we need to verify is that the contents is contained 1129 // within the file bounds. We don't need to make sure it doesn't cover other 1130 // data, as there's nothing that says that is not allowed. 1131 uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 1132 uint32_t SectionSize = getSectionSize(Sec); 1133 if (checkOffset(Data, ConStart, SectionSize)) 1134 return object_error::parse_failed; 1135 Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 1136 return std::error_code(); 1137 } 1138 1139 const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 1140 return reinterpret_cast<const coff_relocation*>(Rel.p); 1141 } 1142 1143 void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1144 Rel.p = reinterpret_cast<uintptr_t>( 1145 reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 1146 } 1147 1148 uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 1149 const coff_relocation *R = toRel(Rel); 1150 return R->VirtualAddress; 1151 } 1152 1153 symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1154 const coff_relocation *R = toRel(Rel); 1155 DataRefImpl Ref; 1156 if (R->SymbolTableIndex >= getNumberOfSymbols()) 1157 return symbol_end(); 1158 if (SymbolTable16) 1159 Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 1160 else if (SymbolTable32) 1161 Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 1162 else 1163 llvm_unreachable("no symbol table pointer!"); 1164 return symbol_iterator(SymbolRef(Ref, this)); 1165 } 1166 1167 uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 1168 const coff_relocation* R = toRel(Rel); 1169 return R->Type; 1170 } 1171 1172 const coff_section * 1173 COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 1174 return toSec(Section.getRawDataRefImpl()); 1175 } 1176 1177 COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 1178 if (SymbolTable16) 1179 return toSymb<coff_symbol16>(Ref); 1180 if (SymbolTable32) 1181 return toSymb<coff_symbol32>(Ref); 1182 llvm_unreachable("no symbol table pointer!"); 1183 } 1184 1185 COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 1186 return getCOFFSymbol(Symbol.getRawDataRefImpl()); 1187 } 1188 1189 const coff_relocation * 1190 COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 1191 return toRel(Reloc.getRawDataRefImpl()); 1192 } 1193 1194 ArrayRef<coff_relocation> 1195 COFFObjectFile::getRelocations(const coff_section *Sec) const { 1196 return {getFirstReloc(Sec, Data, base()), 1197 getNumberOfRelocations(Sec, Data, base())}; 1198 } 1199 1200 #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 1201 case COFF::reloc_type: \ 1202 return #reloc_type; 1203 1204 StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const { 1205 switch (getMachine()) { 1206 case COFF::IMAGE_FILE_MACHINE_AMD64: 1207 switch (Type) { 1208 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1209 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1210 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1211 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1212 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1213 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1214 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1215 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1216 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1217 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1218 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1219 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1220 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1221 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1222 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1223 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1224 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1225 default: 1226 return "Unknown"; 1227 } 1228 break; 1229 case COFF::IMAGE_FILE_MACHINE_ARMNT: 1230 switch (Type) { 1231 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 1232 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 1233 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 1234 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 1235 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 1236 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 1237 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 1238 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 1239 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 1240 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 1241 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 1242 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 1243 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 1244 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 1245 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 1246 default: 1247 return "Unknown"; 1248 } 1249 break; 1250 case COFF::IMAGE_FILE_MACHINE_ARM64: 1251 switch (Type) { 1252 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE); 1253 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32); 1254 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB); 1255 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26); 1256 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21); 1257 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21); 1258 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A); 1259 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L); 1260 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL); 1261 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A); 1262 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A); 1263 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L); 1264 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN); 1265 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION); 1266 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64); 1267 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19); 1268 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14); 1269 default: 1270 return "Unknown"; 1271 } 1272 break; 1273 case COFF::IMAGE_FILE_MACHINE_I386: 1274 switch (Type) { 1275 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1276 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1277 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1278 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1279 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1280 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1281 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1282 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1283 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1284 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1285 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1286 default: 1287 return "Unknown"; 1288 } 1289 break; 1290 default: 1291 return "Unknown"; 1292 } 1293 } 1294 1295 #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1296 1297 void COFFObjectFile::getRelocationTypeName( 1298 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 1299 const coff_relocation *Reloc = toRel(Rel); 1300 StringRef Res = getRelocationTypeName(Reloc->Type); 1301 Result.append(Res.begin(), Res.end()); 1302 } 1303 1304 bool COFFObjectFile::isRelocatableObject() const { 1305 return !DataDirectory; 1306 } 1307 1308 StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const { 1309 return StringSwitch<StringRef>(Name) 1310 .Case("eh_fram", "eh_frame") 1311 .Default(Name); 1312 } 1313 1314 bool ImportDirectoryEntryRef:: 1315 operator==(const ImportDirectoryEntryRef &Other) const { 1316 return ImportTable == Other.ImportTable && Index == Other.Index; 1317 } 1318 1319 void ImportDirectoryEntryRef::moveNext() { 1320 ++Index; 1321 if (ImportTable[Index].isNull()) { 1322 Index = -1; 1323 ImportTable = nullptr; 1324 } 1325 } 1326 1327 std::error_code ImportDirectoryEntryRef::getImportTableEntry( 1328 const coff_import_directory_table_entry *&Result) const { 1329 return getObject(Result, OwningObject->Data, ImportTable + Index); 1330 } 1331 1332 static imported_symbol_iterator 1333 makeImportedSymbolIterator(const COFFObjectFile *Object, 1334 uintptr_t Ptr, int Index) { 1335 if (Object->getBytesInAddress() == 4) { 1336 auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 1337 return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1338 } 1339 auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 1340 return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1341 } 1342 1343 static imported_symbol_iterator 1344 importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1345 uintptr_t IntPtr = 0; 1346 Object->getRvaPtr(RVA, IntPtr); 1347 return makeImportedSymbolIterator(Object, IntPtr, 0); 1348 } 1349 1350 static imported_symbol_iterator 1351 importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1352 uintptr_t IntPtr = 0; 1353 Object->getRvaPtr(RVA, IntPtr); 1354 // Forward the pointer to the last entry which is null. 1355 int Index = 0; 1356 if (Object->getBytesInAddress() == 4) { 1357 auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1358 while (*Entry++) 1359 ++Index; 1360 } else { 1361 auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1362 while (*Entry++) 1363 ++Index; 1364 } 1365 return makeImportedSymbolIterator(Object, IntPtr, Index); 1366 } 1367 1368 imported_symbol_iterator 1369 ImportDirectoryEntryRef::imported_symbol_begin() const { 1370 return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA, 1371 OwningObject); 1372 } 1373 1374 imported_symbol_iterator 1375 ImportDirectoryEntryRef::imported_symbol_end() const { 1376 return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA, 1377 OwningObject); 1378 } 1379 1380 iterator_range<imported_symbol_iterator> 1381 ImportDirectoryEntryRef::imported_symbols() const { 1382 return make_range(imported_symbol_begin(), imported_symbol_end()); 1383 } 1384 1385 imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const { 1386 return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 1387 OwningObject); 1388 } 1389 1390 imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const { 1391 return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 1392 OwningObject); 1393 } 1394 1395 iterator_range<imported_symbol_iterator> 1396 ImportDirectoryEntryRef::lookup_table_symbols() const { 1397 return make_range(lookup_table_begin(), lookup_table_end()); 1398 } 1399 1400 std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1401 uintptr_t IntPtr = 0; 1402 if (std::error_code EC = 1403 OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1404 return EC; 1405 Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1406 return std::error_code(); 1407 } 1408 1409 std::error_code 1410 ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 1411 Result = ImportTable[Index].ImportLookupTableRVA; 1412 return std::error_code(); 1413 } 1414 1415 std::error_code 1416 ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 1417 Result = ImportTable[Index].ImportAddressTableRVA; 1418 return std::error_code(); 1419 } 1420 1421 bool DelayImportDirectoryEntryRef:: 1422 operator==(const DelayImportDirectoryEntryRef &Other) const { 1423 return Table == Other.Table && Index == Other.Index; 1424 } 1425 1426 void DelayImportDirectoryEntryRef::moveNext() { 1427 ++Index; 1428 } 1429 1430 imported_symbol_iterator 1431 DelayImportDirectoryEntryRef::imported_symbol_begin() const { 1432 return importedSymbolBegin(Table[Index].DelayImportNameTable, 1433 OwningObject); 1434 } 1435 1436 imported_symbol_iterator 1437 DelayImportDirectoryEntryRef::imported_symbol_end() const { 1438 return importedSymbolEnd(Table[Index].DelayImportNameTable, 1439 OwningObject); 1440 } 1441 1442 iterator_range<imported_symbol_iterator> 1443 DelayImportDirectoryEntryRef::imported_symbols() const { 1444 return make_range(imported_symbol_begin(), imported_symbol_end()); 1445 } 1446 1447 std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 1448 uintptr_t IntPtr = 0; 1449 if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 1450 return EC; 1451 Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1452 return std::error_code(); 1453 } 1454 1455 std::error_code DelayImportDirectoryEntryRef:: 1456 getDelayImportTable(const delay_import_directory_table_entry *&Result) const { 1457 Result = Table; 1458 return std::error_code(); 1459 } 1460 1461 std::error_code DelayImportDirectoryEntryRef:: 1462 getImportAddress(int AddrIndex, uint64_t &Result) const { 1463 uint32_t RVA = Table[Index].DelayImportAddressTable + 1464 AddrIndex * (OwningObject->is64() ? 8 : 4); 1465 uintptr_t IntPtr = 0; 1466 if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1467 return EC; 1468 if (OwningObject->is64()) 1469 Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 1470 else 1471 Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 1472 return std::error_code(); 1473 } 1474 1475 bool ExportDirectoryEntryRef:: 1476 operator==(const ExportDirectoryEntryRef &Other) const { 1477 return ExportTable == Other.ExportTable && Index == Other.Index; 1478 } 1479 1480 void ExportDirectoryEntryRef::moveNext() { 1481 ++Index; 1482 } 1483 1484 // Returns the name of the current export symbol. If the symbol is exported only 1485 // by ordinal, the empty string is set as a result. 1486 std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1487 uintptr_t IntPtr = 0; 1488 if (std::error_code EC = 1489 OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1490 return EC; 1491 Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1492 return std::error_code(); 1493 } 1494 1495 // Returns the starting ordinal number. 1496 std::error_code 1497 ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1498 Result = ExportTable->OrdinalBase; 1499 return std::error_code(); 1500 } 1501 1502 // Returns the export ordinal of the current export symbol. 1503 std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1504 Result = ExportTable->OrdinalBase + Index; 1505 return std::error_code(); 1506 } 1507 1508 // Returns the address of the current export symbol. 1509 std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1510 uintptr_t IntPtr = 0; 1511 if (std::error_code EC = 1512 OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1513 return EC; 1514 const export_address_table_entry *entry = 1515 reinterpret_cast<const export_address_table_entry *>(IntPtr); 1516 Result = entry[Index].ExportRVA; 1517 return std::error_code(); 1518 } 1519 1520 // Returns the name of the current export symbol. If the symbol is exported only 1521 // by ordinal, the empty string is set as a result. 1522 std::error_code 1523 ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1524 uintptr_t IntPtr = 0; 1525 if (std::error_code EC = 1526 OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1527 return EC; 1528 const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1529 1530 uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1531 int Offset = 0; 1532 for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1533 I < E; ++I, ++Offset) { 1534 if (*I != Index) 1535 continue; 1536 if (std::error_code EC = 1537 OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1538 return EC; 1539 const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1540 if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1541 return EC; 1542 Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1543 return std::error_code(); 1544 } 1545 Result = ""; 1546 return std::error_code(); 1547 } 1548 1549 std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const { 1550 const data_directory *DataEntry; 1551 if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 1552 return EC; 1553 uint32_t RVA; 1554 if (auto EC = getExportRVA(RVA)) 1555 return EC; 1556 uint32_t Begin = DataEntry->RelativeVirtualAddress; 1557 uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; 1558 Result = (Begin <= RVA && RVA < End); 1559 return std::error_code(); 1560 } 1561 1562 std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { 1563 uint32_t RVA; 1564 if (auto EC = getExportRVA(RVA)) 1565 return EC; 1566 uintptr_t IntPtr = 0; 1567 if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1568 return EC; 1569 Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1570 return std::error_code(); 1571 } 1572 1573 bool ImportedSymbolRef:: 1574 operator==(const ImportedSymbolRef &Other) const { 1575 return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1576 && Index == Other.Index; 1577 } 1578 1579 void ImportedSymbolRef::moveNext() { 1580 ++Index; 1581 } 1582 1583 std::error_code 1584 ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1585 uint32_t RVA; 1586 if (Entry32) { 1587 // If a symbol is imported only by ordinal, it has no name. 1588 if (Entry32[Index].isOrdinal()) 1589 return std::error_code(); 1590 RVA = Entry32[Index].getHintNameRVA(); 1591 } else { 1592 if (Entry64[Index].isOrdinal()) 1593 return std::error_code(); 1594 RVA = Entry64[Index].getHintNameRVA(); 1595 } 1596 uintptr_t IntPtr = 0; 1597 if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1598 return EC; 1599 // +2 because the first two bytes is hint. 1600 Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 1601 return std::error_code(); 1602 } 1603 1604 std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const { 1605 if (Entry32) 1606 Result = Entry32[Index].isOrdinal(); 1607 else 1608 Result = Entry64[Index].isOrdinal(); 1609 return std::error_code(); 1610 } 1611 1612 std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { 1613 if (Entry32) 1614 Result = Entry32[Index].getHintNameRVA(); 1615 else 1616 Result = Entry64[Index].getHintNameRVA(); 1617 return std::error_code(); 1618 } 1619 1620 std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1621 uint32_t RVA; 1622 if (Entry32) { 1623 if (Entry32[Index].isOrdinal()) { 1624 Result = Entry32[Index].getOrdinal(); 1625 return std::error_code(); 1626 } 1627 RVA = Entry32[Index].getHintNameRVA(); 1628 } else { 1629 if (Entry64[Index].isOrdinal()) { 1630 Result = Entry64[Index].getOrdinal(); 1631 return std::error_code(); 1632 } 1633 RVA = Entry64[Index].getHintNameRVA(); 1634 } 1635 uintptr_t IntPtr = 0; 1636 if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1637 return EC; 1638 Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 1639 return std::error_code(); 1640 } 1641 1642 Expected<std::unique_ptr<COFFObjectFile>> 1643 ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1644 std::error_code EC; 1645 std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1646 if (EC) 1647 return errorCodeToError(EC); 1648 return std::move(Ret); 1649 } 1650 1651 bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 1652 return Header == Other.Header && Index == Other.Index; 1653 } 1654 1655 void BaseRelocRef::moveNext() { 1656 // Header->BlockSize is the size of the current block, including the 1657 // size of the header itself. 1658 uint32_t Size = sizeof(*Header) + 1659 sizeof(coff_base_reloc_block_entry) * (Index + 1); 1660 if (Size == Header->BlockSize) { 1661 // .reloc contains a list of base relocation blocks. Each block 1662 // consists of the header followed by entries. The header contains 1663 // how many entories will follow. When we reach the end of the 1664 // current block, proceed to the next block. 1665 Header = reinterpret_cast<const coff_base_reloc_block_header *>( 1666 reinterpret_cast<const uint8_t *>(Header) + Size); 1667 Index = 0; 1668 } else { 1669 ++Index; 1670 } 1671 } 1672 1673 std::error_code BaseRelocRef::getType(uint8_t &Type) const { 1674 auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 1675 Type = Entry[Index].getType(); 1676 return std::error_code(); 1677 } 1678 1679 std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { 1680 auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 1681 Result = Header->PageRVA + Entry[Index].getOffset(); 1682 return std::error_code(); 1683 } 1684 1685 #define RETURN_IF_ERROR(E) \ 1686 if (E) \ 1687 return E; 1688 1689 Expected<ArrayRef<UTF16>> 1690 ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) { 1691 BinaryStreamReader Reader = BinaryStreamReader(BBS); 1692 Reader.setOffset(Offset); 1693 uint16_t Length; 1694 RETURN_IF_ERROR(Reader.readInteger(Length)); 1695 ArrayRef<UTF16> RawDirString; 1696 RETURN_IF_ERROR(Reader.readArray(RawDirString, Length)); 1697 return RawDirString; 1698 } 1699 1700 Expected<ArrayRef<UTF16>> 1701 ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) { 1702 return getDirStringAtOffset(Entry.Identifier.getNameOffset()); 1703 } 1704 1705 Expected<const coff_resource_dir_table &> 1706 ResourceSectionRef::getTableAtOffset(uint32_t Offset) { 1707 const coff_resource_dir_table *Table = nullptr; 1708 1709 BinaryStreamReader Reader(BBS); 1710 Reader.setOffset(Offset); 1711 RETURN_IF_ERROR(Reader.readObject(Table)); 1712 assert(Table != nullptr); 1713 return *Table; 1714 } 1715 1716 Expected<const coff_resource_dir_table &> 1717 ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) { 1718 return getTableAtOffset(Entry.Offset.value()); 1719 } 1720 1721 Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() { 1722 return getTableAtOffset(0); 1723 } 1724