COFFObjectFile.cpp revision 261991
1218885Sdim//===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file declares the COFFObjectFile class. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14224145Sdim#include "llvm/Object/COFF.h" 15234353Sdim#include "llvm/ADT/ArrayRef.h" 16226633Sdim#include "llvm/ADT/SmallString.h" 17218885Sdim#include "llvm/ADT/StringSwitch.h" 18218885Sdim#include "llvm/ADT/Triple.h" 19261991Sdim#include "llvm/Support/Debug.h" 20261991Sdim#include "llvm/Support/raw_ostream.h" 21261991Sdim#include <cctype> 22218885Sdim 23218885Sdimusing namespace llvm; 24218885Sdimusing namespace object; 25218885Sdim 26218885Sdimnamespace { 27218885Sdimusing support::ulittle8_t; 28218885Sdimusing support::ulittle16_t; 29218885Sdimusing support::ulittle32_t; 30218885Sdimusing support::little16_t; 31218885Sdim} 32218885Sdim 33218885Sdimnamespace { 34224145Sdim// Returns false if size is greater than the buffer size. And sets ec. 35224145Sdimbool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) { 36224145Sdim if (m->getBufferSize() < size) { 37224145Sdim ec = object_error::unexpected_eof; 38224145Sdim return false; 39224145Sdim } 40224145Sdim return true; 41218885Sdim} 42218885Sdim 43261991Sdim// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 44261991Sdim// Returns unexpected_eof if error. 45261991Sdimtemplate<typename T> 46261991Sdimerror_code getObject(const T *&Obj, const MemoryBuffer *M, const uint8_t *Ptr, 47261991Sdim const size_t Size = sizeof(T)) { 48261991Sdim uintptr_t Addr = uintptr_t(Ptr); 49261991Sdim if (Addr + Size < Addr || 50261991Sdim Addr + Size < Size || 51261991Sdim Addr + Size > uintptr_t(M->getBufferEnd())) { 52261991Sdim return object_error::unexpected_eof; 53224145Sdim } 54261991Sdim Obj = reinterpret_cast<const T *>(Addr); 55261991Sdim return object_error::success; 56224145Sdim} 57224145Sdim} 58218885Sdim 59224145Sdimconst coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const { 60224145Sdim const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p); 61218885Sdim 62224145Sdim# ifndef NDEBUG 63224145Sdim // Verify that the symbol points to a valid entry in the symbol table. 64224145Sdim uintptr_t offset = uintptr_t(addr) - uintptr_t(base()); 65261991Sdim if (offset < COFFHeader->PointerToSymbolTable 66261991Sdim || offset >= COFFHeader->PointerToSymbolTable 67261991Sdim + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) 68224145Sdim report_fatal_error("Symbol was outside of symbol table."); 69218885Sdim 70261991Sdim assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) 71224145Sdim == 0 && "Symbol did not point to the beginning of a symbol"); 72224145Sdim# endif 73218885Sdim 74224145Sdim return addr; 75218885Sdim} 76218885Sdim 77224145Sdimconst coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const { 78224145Sdim const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p); 79218885Sdim 80224145Sdim# ifndef NDEBUG 81224145Sdim // Verify that the section points to a valid entry in the section table. 82224145Sdim if (addr < SectionTable 83261991Sdim || addr >= (SectionTable + COFFHeader->NumberOfSections)) 84224145Sdim report_fatal_error("Section was outside of section table."); 85218885Sdim 86224145Sdim uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable); 87224145Sdim assert(offset % sizeof(coff_section) == 0 && 88224145Sdim "Section did not point to the beginning of a section"); 89224145Sdim# endif 90218885Sdim 91224145Sdim return addr; 92224145Sdim} 93218885Sdim 94224145Sdimerror_code COFFObjectFile::getSymbolNext(DataRefImpl Symb, 95224145Sdim SymbolRef &Result) const { 96224145Sdim const coff_symbol *symb = toSymb(Symb); 97218885Sdim symb += 1 + symb->NumberOfAuxSymbols; 98224145Sdim Symb.p = reinterpret_cast<uintptr_t>(symb); 99224145Sdim Result = SymbolRef(Symb, this); 100224145Sdim return object_error::success; 101218885Sdim} 102218885Sdim 103224145Sdim error_code COFFObjectFile::getSymbolName(DataRefImpl Symb, 104224145Sdim StringRef &Result) const { 105224145Sdim const coff_symbol *symb = toSymb(Symb); 106234353Sdim return getSymbolName(symb, Result); 107218885Sdim} 108218885Sdim 109234353Sdimerror_code COFFObjectFile::getSymbolFileOffset(DataRefImpl Symb, 110224145Sdim uint64_t &Result) const { 111224145Sdim const coff_symbol *symb = toSymb(Symb); 112224145Sdim const coff_section *Section = NULL; 113224145Sdim if (error_code ec = getSection(symb->SectionNumber, Section)) 114224145Sdim return ec; 115261991Sdim 116261991Sdim if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) 117224145Sdim Result = UnknownAddressOrSize; 118224145Sdim else if (Section) 119234353Sdim Result = Section->PointerToRawData + symb->Value; 120224145Sdim else 121224145Sdim Result = symb->Value; 122224145Sdim return object_error::success; 123218885Sdim} 124218885Sdim 125226633Sdimerror_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, 126226633Sdim uint64_t &Result) const { 127226633Sdim const coff_symbol *symb = toSymb(Symb); 128226633Sdim const coff_section *Section = NULL; 129226633Sdim if (error_code ec = getSection(symb->SectionNumber, Section)) 130226633Sdim return ec; 131261991Sdim 132261991Sdim if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) 133226633Sdim Result = UnknownAddressOrSize; 134226633Sdim else if (Section) 135234353Sdim Result = Section->VirtualAddress + symb->Value; 136226633Sdim else 137234353Sdim Result = symb->Value; 138226633Sdim return object_error::success; 139226633Sdim} 140226633Sdim 141226633Sdimerror_code COFFObjectFile::getSymbolType(DataRefImpl Symb, 142234353Sdim SymbolRef::Type &Result) const { 143226633Sdim const coff_symbol *symb = toSymb(Symb); 144226633Sdim Result = SymbolRef::ST_Other; 145226633Sdim if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 146226633Sdim symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { 147234353Sdim Result = SymbolRef::ST_Unknown; 148226633Sdim } else { 149234353Sdim if (symb->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { 150226633Sdim Result = SymbolRef::ST_Function; 151226633Sdim } else { 152261991Sdim uint32_t Characteristics = 0; 153261991Sdim if (symb->SectionNumber > 0) { 154261991Sdim const coff_section *Section = NULL; 155261991Sdim if (error_code ec = getSection(symb->SectionNumber, Section)) 156261991Sdim return ec; 157261991Sdim Characteristics = Section->Characteristics; 158261991Sdim } 159261991Sdim if (Characteristics & COFF::IMAGE_SCN_MEM_READ && 160261991Sdim ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. 161226633Sdim Result = SymbolRef::ST_Data; 162226633Sdim } 163226633Sdim } 164226633Sdim return object_error::success; 165226633Sdim} 166226633Sdim 167234353Sdimerror_code COFFObjectFile::getSymbolFlags(DataRefImpl Symb, 168234353Sdim uint32_t &Result) const { 169226633Sdim const coff_symbol *symb = toSymb(Symb); 170234353Sdim Result = SymbolRef::SF_None; 171234353Sdim 172234353Sdim // TODO: Correctly set SF_FormatSpecific, SF_ThreadLocal, SF_Common 173234353Sdim 174234353Sdim if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 175234353Sdim symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) 176234353Sdim Result |= SymbolRef::SF_Undefined; 177234353Sdim 178234353Sdim // TODO: This are certainly too restrictive. 179234353Sdim if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) 180234353Sdim Result |= SymbolRef::SF_Global; 181234353Sdim 182234353Sdim if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) 183234353Sdim Result |= SymbolRef::SF_Weak; 184234353Sdim 185234353Sdim if (symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE) 186234353Sdim Result |= SymbolRef::SF_Absolute; 187234353Sdim 188226633Sdim return object_error::success; 189226633Sdim} 190226633Sdim 191224145Sdimerror_code COFFObjectFile::getSymbolSize(DataRefImpl Symb, 192224145Sdim uint64_t &Result) const { 193218885Sdim // FIXME: Return the correct size. This requires looking at all the symbols 194218885Sdim // in the same section as this symbol, and looking for either the next 195218885Sdim // symbol, or the end of the section. 196224145Sdim const coff_symbol *symb = toSymb(Symb); 197224145Sdim const coff_section *Section = NULL; 198224145Sdim if (error_code ec = getSection(symb->SectionNumber, Section)) 199224145Sdim return ec; 200261991Sdim 201261991Sdim if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) 202224145Sdim Result = UnknownAddressOrSize; 203224145Sdim else if (Section) 204224145Sdim Result = Section->SizeOfRawData - symb->Value; 205224145Sdim else 206224145Sdim Result = 0; 207224145Sdim return object_error::success; 208218885Sdim} 209218885Sdim 210234353Sdimerror_code COFFObjectFile::getSymbolSection(DataRefImpl Symb, 211234353Sdim section_iterator &Result) const { 212234353Sdim const coff_symbol *symb = toSymb(Symb); 213234353Sdim if (symb->SectionNumber <= COFF::IMAGE_SYM_UNDEFINED) 214234353Sdim Result = end_sections(); 215234353Sdim else { 216234353Sdim const coff_section *sec = 0; 217234353Sdim if (error_code ec = getSection(symb->SectionNumber, sec)) return ec; 218234353Sdim DataRefImpl Sec; 219234353Sdim Sec.p = reinterpret_cast<uintptr_t>(sec); 220234353Sdim Result = section_iterator(SectionRef(Sec, this)); 221234353Sdim } 222224145Sdim return object_error::success; 223218885Sdim} 224218885Sdim 225243830Sdimerror_code COFFObjectFile::getSymbolValue(DataRefImpl Symb, 226243830Sdim uint64_t &Val) const { 227243830Sdim report_fatal_error("getSymbolValue unimplemented in COFFObjectFile"); 228243830Sdim} 229243830Sdim 230224145Sdimerror_code COFFObjectFile::getSectionNext(DataRefImpl Sec, 231224145Sdim SectionRef &Result) const { 232224145Sdim const coff_section *sec = toSec(Sec); 233218885Sdim sec += 1; 234224145Sdim Sec.p = reinterpret_cast<uintptr_t>(sec); 235224145Sdim Result = SectionRef(Sec, this); 236224145Sdim return object_error::success; 237218885Sdim} 238218885Sdim 239224145Sdimerror_code COFFObjectFile::getSectionName(DataRefImpl Sec, 240224145Sdim StringRef &Result) const { 241224145Sdim const coff_section *sec = toSec(Sec); 242234353Sdim return getSectionName(sec, Result); 243218885Sdim} 244218885Sdim 245224145Sdimerror_code COFFObjectFile::getSectionAddress(DataRefImpl Sec, 246224145Sdim uint64_t &Result) const { 247224145Sdim const coff_section *sec = toSec(Sec); 248224145Sdim Result = sec->VirtualAddress; 249224145Sdim return object_error::success; 250218885Sdim} 251218885Sdim 252224145Sdimerror_code COFFObjectFile::getSectionSize(DataRefImpl Sec, 253224145Sdim uint64_t &Result) const { 254224145Sdim const coff_section *sec = toSec(Sec); 255224145Sdim Result = sec->SizeOfRawData; 256224145Sdim return object_error::success; 257218885Sdim} 258218885Sdim 259224145Sdimerror_code COFFObjectFile::getSectionContents(DataRefImpl Sec, 260224145Sdim StringRef &Result) const { 261224145Sdim const coff_section *sec = toSec(Sec); 262234353Sdim ArrayRef<uint8_t> Res; 263234353Sdim error_code EC = getSectionContents(sec, Res); 264234353Sdim Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 265234353Sdim return EC; 266218885Sdim} 267218885Sdim 268226633Sdimerror_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec, 269226633Sdim uint64_t &Res) const { 270226633Sdim const coff_section *sec = toSec(Sec); 271226633Sdim if (!sec) 272226633Sdim return object_error::parse_failed; 273226633Sdim Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1); 274226633Sdim return object_error::success; 275226633Sdim} 276226633Sdim 277224145Sdimerror_code COFFObjectFile::isSectionText(DataRefImpl Sec, 278224145Sdim bool &Result) const { 279224145Sdim const coff_section *sec = toSec(Sec); 280224145Sdim Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 281224145Sdim return object_error::success; 282218885Sdim} 283218885Sdim 284226633Sdimerror_code COFFObjectFile::isSectionData(DataRefImpl Sec, 285226633Sdim bool &Result) const { 286226633Sdim const coff_section *sec = toSec(Sec); 287226633Sdim Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 288226633Sdim return object_error::success; 289226633Sdim} 290226633Sdim 291226633Sdimerror_code COFFObjectFile::isSectionBSS(DataRefImpl Sec, 292226633Sdim bool &Result) const { 293226633Sdim const coff_section *sec = toSec(Sec); 294226633Sdim Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 295226633Sdim return object_error::success; 296226633Sdim} 297226633Sdim 298234353Sdimerror_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 299234353Sdim bool &Result) const { 300234353Sdim // FIXME: Unimplemented 301234353Sdim Result = true; 302234353Sdim return object_error::success; 303234353Sdim} 304234353Sdim 305234353Sdimerror_code COFFObjectFile::isSectionVirtual(DataRefImpl Sec, 306234353Sdim bool &Result) const { 307234353Sdim const coff_section *sec = toSec(Sec); 308234353Sdim Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 309234353Sdim return object_error::success; 310234353Sdim} 311234353Sdim 312234353Sdimerror_code COFFObjectFile::isSectionZeroInit(DataRefImpl Sec, 313234353Sdim bool &Result) const { 314243830Sdim // FIXME: Unimplemented. 315234353Sdim Result = false; 316234353Sdim return object_error::success; 317234353Sdim} 318234353Sdim 319243830Sdimerror_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 320243830Sdim bool &Result) const { 321243830Sdim // FIXME: Unimplemented. 322243830Sdim Result = false; 323243830Sdim return object_error::success; 324243830Sdim} 325243830Sdim 326224145Sdimerror_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, 327224145Sdim DataRefImpl Symb, 328224145Sdim bool &Result) const { 329226633Sdim const coff_section *sec = toSec(Sec); 330226633Sdim const coff_symbol *symb = toSymb(Symb); 331234353Sdim const coff_section *symb_sec = 0; 332226633Sdim if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec; 333226633Sdim if (symb_sec == sec) 334226633Sdim Result = true; 335226633Sdim else 336226633Sdim Result = false; 337224145Sdim return object_error::success; 338224145Sdim} 339221345Sdim 340261991Sdimrelocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Sec) const { 341226633Sdim const coff_section *sec = toSec(Sec); 342226633Sdim DataRefImpl ret; 343226633Sdim if (sec->NumberOfRelocations == 0) 344226633Sdim ret.p = 0; 345226633Sdim else 346226633Sdim ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations); 347226633Sdim 348226633Sdim return relocation_iterator(RelocationRef(ret, this)); 349226633Sdim} 350226633Sdim 351261991Sdimrelocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Sec) const { 352226633Sdim const coff_section *sec = toSec(Sec); 353226633Sdim DataRefImpl ret; 354226633Sdim if (sec->NumberOfRelocations == 0) 355226633Sdim ret.p = 0; 356226633Sdim else 357226633Sdim ret.p = reinterpret_cast<uintptr_t>( 358226633Sdim reinterpret_cast<const coff_relocation*>( 359226633Sdim base() + sec->PointerToRelocations) 360226633Sdim + sec->NumberOfRelocations); 361226633Sdim 362226633Sdim return relocation_iterator(RelocationRef(ret, this)); 363226633Sdim} 364226633Sdim 365261991Sdim// Initialize the pointer to the symbol table. 366261991Sdimerror_code COFFObjectFile::initSymbolTablePtr() { 367261991Sdim if (error_code ec = getObject( 368261991Sdim SymbolTable, Data, base() + COFFHeader->PointerToSymbolTable, 369261991Sdim COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) 370261991Sdim return ec; 371261991Sdim 372261991Sdim // Find string table. The first four byte of the string table contains the 373261991Sdim // total size of the string table, including the size field itself. If the 374261991Sdim // string table is empty, the value of the first four byte would be 4. 375261991Sdim const uint8_t *StringTableAddr = 376261991Sdim base() + COFFHeader->PointerToSymbolTable + 377261991Sdim COFFHeader->NumberOfSymbols * sizeof(coff_symbol); 378261991Sdim const ulittle32_t *StringTableSizePtr; 379261991Sdim if (error_code ec = getObject(StringTableSizePtr, Data, StringTableAddr)) 380261991Sdim return ec; 381261991Sdim StringTableSize = *StringTableSizePtr; 382261991Sdim if (error_code ec = 383261991Sdim getObject(StringTable, Data, StringTableAddr, StringTableSize)) 384261991Sdim return ec; 385261991Sdim 386261991Sdim // Check that the string table is null terminated if has any in it. 387261991Sdim if (StringTableSize < 4 || 388261991Sdim (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) 389261991Sdim return object_error::parse_failed; 390261991Sdim return object_error::success; 391261991Sdim} 392261991Sdim 393261991Sdim// Returns the file offset for the given RVA. 394261991Sdimerror_code COFFObjectFile::getRvaPtr(uint32_t Rva, uintptr_t &Res) const { 395261991Sdim error_code ec; 396261991Sdim for (section_iterator i = begin_sections(), e = end_sections(); i != e; 397261991Sdim i.increment(ec)) { 398261991Sdim if (ec) 399261991Sdim return ec; 400261991Sdim const coff_section *Section = getCOFFSection(i); 401261991Sdim uint32_t SectionStart = Section->VirtualAddress; 402261991Sdim uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 403261991Sdim if (SectionStart <= Rva && Rva < SectionEnd) { 404261991Sdim uint32_t Offset = Rva - SectionStart; 405261991Sdim Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 406261991Sdim return object_error::success; 407261991Sdim } 408261991Sdim } 409261991Sdim return object_error::parse_failed; 410261991Sdim} 411261991Sdim 412261991Sdim// Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 413261991Sdim// table entry. 414261991Sdimerror_code COFFObjectFile:: 415261991SdimgetHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const { 416261991Sdim uintptr_t IntPtr = 0; 417261991Sdim if (error_code ec = getRvaPtr(Rva, IntPtr)) 418261991Sdim return ec; 419261991Sdim const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 420261991Sdim Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 421261991Sdim Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 422261991Sdim return object_error::success; 423261991Sdim} 424261991Sdim 425261991Sdim// Find the import table. 426261991Sdimerror_code COFFObjectFile::initImportTablePtr() { 427261991Sdim // First, we get the RVA of the import table. If the file lacks a pointer to 428261991Sdim // the import table, do nothing. 429261991Sdim const data_directory *DataEntry; 430261991Sdim if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 431261991Sdim return object_error::success; 432261991Sdim 433261991Sdim // Do nothing if the pointer to import table is NULL. 434261991Sdim if (DataEntry->RelativeVirtualAddress == 0) 435261991Sdim return object_error::success; 436261991Sdim 437261991Sdim uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 438261991Sdim NumberOfImportDirectory = DataEntry->Size / 439261991Sdim sizeof(import_directory_table_entry); 440261991Sdim 441261991Sdim // Find the section that contains the RVA. This is needed because the RVA is 442261991Sdim // the import table's memory address which is different from its file offset. 443261991Sdim uintptr_t IntPtr = 0; 444261991Sdim if (error_code ec = getRvaPtr(ImportTableRva, IntPtr)) 445261991Sdim return ec; 446261991Sdim ImportDirectory = reinterpret_cast< 447261991Sdim const import_directory_table_entry *>(IntPtr); 448261991Sdim 449261991Sdim // It's an error if there's no section containing the Import Table RVA. 450261991Sdim return object_error::parse_failed; 451261991Sdim} 452261991Sdim 453224145SdimCOFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) 454251662Sdim : ObjectFile(Binary::ID_COFF, Object) 455261991Sdim , COFFHeader(0) 456261991Sdim , PE32Header(0) 457261991Sdim , DataDirectory(0) 458234353Sdim , SectionTable(0) 459234353Sdim , SymbolTable(0) 460234353Sdim , StringTable(0) 461261991Sdim , StringTableSize(0) 462261991Sdim , ImportDirectory(0) 463261991Sdim , NumberOfImportDirectory(0) { 464224145Sdim // Check that we at least have enough room for a header. 465224145Sdim if (!checkSize(Data, ec, sizeof(coff_file_header))) return; 466221345Sdim 467261991Sdim // The current location in the file where we are looking at. 468261991Sdim uint64_t CurPtr = 0; 469224145Sdim 470261991Sdim // PE header is optional and is present only in executables. If it exists, 471261991Sdim // it is placed right after COFF header. 472261991Sdim bool hasPEHeader = false; 473261991Sdim 474224145Sdim // Check if this is a PE/COFF file. 475224145Sdim if (base()[0] == 0x4d && base()[1] == 0x5a) { 476221345Sdim // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 477221345Sdim // PE signature to find 'normal' COFF header. 478224145Sdim if (!checkSize(Data, ec, 0x3c + 8)) return; 479261991Sdim CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c); 480261991Sdim // Check the PE magic bytes. ("PE\0\0") 481261991Sdim if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) { 482224145Sdim ec = object_error::parse_failed; 483224145Sdim return; 484224145Sdim } 485261991Sdim CurPtr += 4; // Skip the PE magic bytes. 486261991Sdim hasPEHeader = true; 487221345Sdim } 488221345Sdim 489261991Sdim if ((ec = getObject(COFFHeader, Data, base() + CurPtr))) 490224145Sdim return; 491261991Sdim CurPtr += sizeof(coff_file_header); 492226633Sdim 493261991Sdim if (hasPEHeader) { 494261991Sdim if ((ec = getObject(PE32Header, Data, base() + CurPtr))) 495234353Sdim return; 496261991Sdim if (PE32Header->Magic != 0x10b) { 497261991Sdim // We only support PE32. If this is PE32 (not PE32+), the magic byte 498261991Sdim // should be 0x10b. If this is not PE32, continue as if there's no PE 499261991Sdim // header in this file. 500261991Sdim PE32Header = 0; 501261991Sdim } else if (PE32Header->NumberOfRvaAndSize > 0) { 502261991Sdim const uint8_t *addr = base() + CurPtr + sizeof(pe32_header); 503261991Sdim uint64_t size = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 504261991Sdim if ((ec = getObject(DataDirectory, Data, addr, size))) 505261991Sdim return; 506261991Sdim } 507261991Sdim CurPtr += COFFHeader->SizeOfOptionalHeader; 508261991Sdim } 509218885Sdim 510261991Sdim if (!COFFHeader->isImportLibrary()) 511261991Sdim if ((ec = getObject(SectionTable, Data, base() + CurPtr, 512261991Sdim COFFHeader->NumberOfSections * sizeof(coff_section)))) 513234353Sdim return; 514224145Sdim 515261991Sdim // Initialize the pointer to the symbol table. 516261991Sdim if (COFFHeader->PointerToSymbolTable != 0) 517261991Sdim if ((ec = initSymbolTablePtr())) 518234353Sdim return; 519226633Sdim 520261991Sdim // Initialize the pointer to the beginning of the import table. 521261991Sdim if ((ec = initImportTablePtr())) 522261991Sdim return; 523261991Sdim 524224145Sdim ec = object_error::success; 525218885Sdim} 526218885Sdim 527226633Sdimsymbol_iterator COFFObjectFile::begin_symbols() const { 528218885Sdim DataRefImpl ret; 529261991Sdim ret.p = reinterpret_cast<uintptr_t>(SymbolTable); 530218885Sdim return symbol_iterator(SymbolRef(ret, this)); 531218885Sdim} 532218885Sdim 533226633Sdimsymbol_iterator COFFObjectFile::end_symbols() const { 534218885Sdim // The symbol table ends where the string table begins. 535218885Sdim DataRefImpl ret; 536261991Sdim ret.p = reinterpret_cast<uintptr_t>(StringTable); 537218885Sdim return symbol_iterator(SymbolRef(ret, this)); 538218885Sdim} 539218885Sdim 540234353Sdimsymbol_iterator COFFObjectFile::begin_dynamic_symbols() const { 541234353Sdim // TODO: implement 542234353Sdim report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); 543234353Sdim} 544234353Sdim 545234353Sdimsymbol_iterator COFFObjectFile::end_dynamic_symbols() const { 546234353Sdim // TODO: implement 547234353Sdim report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); 548234353Sdim} 549234353Sdim 550234353Sdimlibrary_iterator COFFObjectFile::begin_libraries_needed() const { 551234353Sdim // TODO: implement 552234353Sdim report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 553234353Sdim} 554234353Sdim 555234353Sdimlibrary_iterator COFFObjectFile::end_libraries_needed() const { 556234353Sdim // TODO: implement 557234353Sdim report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 558234353Sdim} 559234353Sdim 560234353SdimStringRef COFFObjectFile::getLoadName() const { 561234353Sdim // COFF does not have this field. 562234353Sdim return ""; 563234353Sdim} 564234353Sdim 565261991Sdimimport_directory_iterator COFFObjectFile::import_directory_begin() const { 566261991Sdim DataRefImpl Imp; 567261991Sdim Imp.p = reinterpret_cast<uintptr_t>(ImportDirectory); 568261991Sdim return import_directory_iterator(ImportDirectoryEntryRef(Imp, this)); 569261991Sdim} 570234353Sdim 571261991Sdimimport_directory_iterator COFFObjectFile::import_directory_end() const { 572261991Sdim DataRefImpl Imp; 573261991Sdim if (ImportDirectory) { 574261991Sdim Imp.p = reinterpret_cast<uintptr_t>( 575261991Sdim ImportDirectory + (NumberOfImportDirectory - 1)); 576261991Sdim } else { 577261991Sdim Imp.p = 0; 578261991Sdim } 579261991Sdim return import_directory_iterator(ImportDirectoryEntryRef(Imp, this)); 580261991Sdim} 581261991Sdim 582226633Sdimsection_iterator COFFObjectFile::begin_sections() const { 583218885Sdim DataRefImpl ret; 584261991Sdim ret.p = reinterpret_cast<uintptr_t>(SectionTable); 585218885Sdim return section_iterator(SectionRef(ret, this)); 586218885Sdim} 587218885Sdim 588226633Sdimsection_iterator COFFObjectFile::end_sections() const { 589218885Sdim DataRefImpl ret; 590261991Sdim int numSections = COFFHeader->isImportLibrary() 591261991Sdim ? 0 : COFFHeader->NumberOfSections; 592261991Sdim ret.p = reinterpret_cast<uintptr_t>(SectionTable + numSections); 593218885Sdim return section_iterator(SectionRef(ret, this)); 594218885Sdim} 595218885Sdim 596218885Sdimuint8_t COFFObjectFile::getBytesInAddress() const { 597218885Sdim return getArch() == Triple::x86_64 ? 8 : 4; 598218885Sdim} 599218885Sdim 600218885SdimStringRef COFFObjectFile::getFileFormatName() const { 601261991Sdim switch(COFFHeader->Machine) { 602218885Sdim case COFF::IMAGE_FILE_MACHINE_I386: 603218885Sdim return "COFF-i386"; 604218885Sdim case COFF::IMAGE_FILE_MACHINE_AMD64: 605218885Sdim return "COFF-x86-64"; 606218885Sdim default: 607218885Sdim return "COFF-<unknown arch>"; 608218885Sdim } 609218885Sdim} 610218885Sdim 611218885Sdimunsigned COFFObjectFile::getArch() const { 612261991Sdim switch(COFFHeader->Machine) { 613218885Sdim case COFF::IMAGE_FILE_MACHINE_I386: 614218885Sdim return Triple::x86; 615218885Sdim case COFF::IMAGE_FILE_MACHINE_AMD64: 616218885Sdim return Triple::x86_64; 617218885Sdim default: 618218885Sdim return Triple::UnknownArch; 619218885Sdim } 620218885Sdim} 621218885Sdim 622261991Sdim// This method is kept here because lld uses this. As soon as we make 623261991Sdim// lld to use getCOFFHeader, this method will be removed. 624234353Sdimerror_code COFFObjectFile::getHeader(const coff_file_header *&Res) const { 625261991Sdim return getCOFFHeader(Res); 626261991Sdim} 627261991Sdim 628261991Sdimerror_code COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const { 629261991Sdim Res = COFFHeader; 630234353Sdim return object_error::success; 631234353Sdim} 632234353Sdim 633261991Sdimerror_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 634261991Sdim Res = PE32Header; 635261991Sdim return object_error::success; 636261991Sdim} 637261991Sdim 638261991Sdimerror_code COFFObjectFile::getDataDirectory(uint32_t index, 639261991Sdim const data_directory *&Res) const { 640261991Sdim // Error if if there's no data directory or the index is out of range. 641261991Sdim if (!DataDirectory || index > PE32Header->NumberOfRvaAndSize) 642261991Sdim return object_error::parse_failed; 643261991Sdim Res = &DataDirectory[index]; 644261991Sdim return object_error::success; 645261991Sdim} 646261991Sdim 647224145Sdimerror_code COFFObjectFile::getSection(int32_t index, 648224145Sdim const coff_section *&Result) const { 649224145Sdim // Check for special index values. 650224145Sdim if (index == COFF::IMAGE_SYM_UNDEFINED || 651224145Sdim index == COFF::IMAGE_SYM_ABSOLUTE || 652224145Sdim index == COFF::IMAGE_SYM_DEBUG) 653224145Sdim Result = NULL; 654261991Sdim else if (index > 0 && index <= COFFHeader->NumberOfSections) 655224145Sdim // We already verified the section table data, so no need to check again. 656224145Sdim Result = SectionTable + (index - 1); 657224145Sdim else 658224145Sdim return object_error::parse_failed; 659224145Sdim return object_error::success; 660218885Sdim} 661218885Sdim 662224145Sdimerror_code COFFObjectFile::getString(uint32_t offset, 663224145Sdim StringRef &Result) const { 664224145Sdim if (StringTableSize <= 4) 665224145Sdim // Tried to get a string from an empty string table. 666224145Sdim return object_error::parse_failed; 667224145Sdim if (offset >= StringTableSize) 668224145Sdim return object_error::unexpected_eof; 669224145Sdim Result = StringRef(StringTable + offset); 670224145Sdim return object_error::success; 671218885Sdim} 672218885Sdim 673226633Sdimerror_code COFFObjectFile::getSymbol(uint32_t index, 674226633Sdim const coff_symbol *&Result) const { 675261991Sdim if (index < COFFHeader->NumberOfSymbols) 676226633Sdim Result = SymbolTable + index; 677226633Sdim else 678226633Sdim return object_error::parse_failed; 679226633Sdim return object_error::success; 680226633Sdim} 681226633Sdim 682234353Sdimerror_code COFFObjectFile::getSymbolName(const coff_symbol *symbol, 683234353Sdim StringRef &Res) const { 684234353Sdim // Check for string table entry. First 4 bytes are 0. 685234353Sdim if (symbol->Name.Offset.Zeroes == 0) { 686234353Sdim uint32_t Offset = symbol->Name.Offset.Offset; 687234353Sdim if (error_code ec = getString(Offset, Res)) 688234353Sdim return ec; 689234353Sdim return object_error::success; 690234353Sdim } 691234353Sdim 692234353Sdim if (symbol->Name.ShortName[7] == 0) 693234353Sdim // Null terminated, let ::strlen figure out the length. 694234353Sdim Res = StringRef(symbol->Name.ShortName); 695234353Sdim else 696234353Sdim // Not null terminated, use all 8 bytes. 697234353Sdim Res = StringRef(symbol->Name.ShortName, 8); 698234353Sdim return object_error::success; 699234353Sdim} 700234353Sdim 701239462SdimArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData( 702239462Sdim const coff_symbol *symbol) const { 703239462Sdim const uint8_t *aux = NULL; 704261991Sdim 705239462Sdim if ( symbol->NumberOfAuxSymbols > 0 ) { 706239462Sdim // AUX data comes immediately after the symbol in COFF 707239462Sdim aux = reinterpret_cast<const uint8_t *>(symbol + 1); 708239462Sdim# ifndef NDEBUG 709239462Sdim // Verify that the aux symbol points to a valid entry in the symbol table. 710239462Sdim uintptr_t offset = uintptr_t(aux) - uintptr_t(base()); 711261991Sdim if (offset < COFFHeader->PointerToSymbolTable 712261991Sdim || offset >= COFFHeader->PointerToSymbolTable 713261991Sdim + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) 714239462Sdim report_fatal_error("Aux Symbol data was outside of symbol table."); 715239462Sdim 716261991Sdim assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) 717239462Sdim == 0 && "Aux Symbol data did not point to the beginning of a symbol"); 718239462Sdim# endif 719239462Sdim } 720239462Sdim return ArrayRef<uint8_t>(aux, symbol->NumberOfAuxSymbols * sizeof(coff_symbol)); 721239462Sdim} 722239462Sdim 723234353Sdimerror_code COFFObjectFile::getSectionName(const coff_section *Sec, 724234353Sdim StringRef &Res) const { 725234353Sdim StringRef Name; 726234353Sdim if (Sec->Name[7] == 0) 727234353Sdim // Null terminated, let ::strlen figure out the length. 728234353Sdim Name = Sec->Name; 729234353Sdim else 730234353Sdim // Not null terminated, use all 8 bytes. 731234353Sdim Name = StringRef(Sec->Name, 8); 732234353Sdim 733234353Sdim // Check for string table entry. First byte is '/'. 734234353Sdim if (Name[0] == '/') { 735234353Sdim uint32_t Offset; 736234353Sdim if (Name.substr(1).getAsInteger(10, Offset)) 737234353Sdim return object_error::parse_failed; 738234353Sdim if (error_code ec = getString(Offset, Name)) 739234353Sdim return ec; 740234353Sdim } 741234353Sdim 742234353Sdim Res = Name; 743234353Sdim return object_error::success; 744234353Sdim} 745234353Sdim 746234353Sdimerror_code COFFObjectFile::getSectionContents(const coff_section *Sec, 747234353Sdim ArrayRef<uint8_t> &Res) const { 748234353Sdim // The only thing that we need to verify is that the contents is contained 749234353Sdim // within the file bounds. We don't need to make sure it doesn't cover other 750234353Sdim // data, as there's nothing that says that is not allowed. 751234353Sdim uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 752234353Sdim uintptr_t ConEnd = ConStart + Sec->SizeOfRawData; 753234353Sdim if (ConEnd > uintptr_t(Data->getBufferEnd())) 754234353Sdim return object_error::parse_failed; 755234353Sdim Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart), 756234353Sdim Sec->SizeOfRawData); 757234353Sdim return object_error::success; 758234353Sdim} 759234353Sdim 760226633Sdimconst coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 761226633Sdim return reinterpret_cast<const coff_relocation*>(Rel.p); 762226633Sdim} 763226633Sdimerror_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, 764226633Sdim RelocationRef &Res) const { 765226633Sdim Rel.p = reinterpret_cast<uintptr_t>( 766226633Sdim reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 767226633Sdim Res = RelocationRef(Rel, this); 768226633Sdim return object_error::success; 769226633Sdim} 770226633Sdimerror_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 771226633Sdim uint64_t &Res) const { 772251662Sdim report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); 773226633Sdim} 774234353Sdimerror_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, 775234353Sdim uint64_t &Res) const { 776234353Sdim Res = toRel(Rel)->VirtualAddress; 777234353Sdim return object_error::success; 778234353Sdim} 779261991Sdimsymbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 780226633Sdim const coff_relocation* R = toRel(Rel); 781226633Sdim DataRefImpl Symb; 782226633Sdim Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); 783261991Sdim return symbol_iterator(SymbolRef(Symb, this)); 784226633Sdim} 785226633Sdimerror_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 786234353Sdim uint64_t &Res) const { 787226633Sdim const coff_relocation* R = toRel(Rel); 788226633Sdim Res = R->Type; 789226633Sdim return object_error::success; 790226633Sdim} 791226633Sdim 792239462Sdimconst coff_section *COFFObjectFile::getCOFFSection(section_iterator &It) const { 793239462Sdim return toSec(It->getRawDataRefImpl()); 794239462Sdim} 795239462Sdim 796239462Sdimconst coff_symbol *COFFObjectFile::getCOFFSymbol(symbol_iterator &It) const { 797239462Sdim return toSymb(It->getRawDataRefImpl()); 798239462Sdim} 799239462Sdim 800239462Sdimconst coff_relocation *COFFObjectFile::getCOFFRelocation( 801239462Sdim relocation_iterator &It) const { 802239462Sdim return toRel(It->getRawDataRefImpl()); 803239462Sdim} 804239462Sdim 805226633Sdim#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \ 806226633Sdim case COFF::enum: res = #enum; break; 807226633Sdim 808226633Sdimerror_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 809226633Sdim SmallVectorImpl<char> &Result) const { 810226633Sdim const coff_relocation *reloc = toRel(Rel); 811226633Sdim StringRef res; 812261991Sdim switch (COFFHeader->Machine) { 813226633Sdim case COFF::IMAGE_FILE_MACHINE_AMD64: 814226633Sdim switch (reloc->Type) { 815226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 816226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 817226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 818226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 819226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 820226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 821226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 822226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 823226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 824226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 825226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 826226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 827226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 828226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 829226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 830226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 831226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 832226633Sdim default: 833226633Sdim res = "Unknown"; 834226633Sdim } 835226633Sdim break; 836226633Sdim case COFF::IMAGE_FILE_MACHINE_I386: 837226633Sdim switch (reloc->Type) { 838226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 839226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 840226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 841226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 842226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 843226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 844226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 845226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 846226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 847226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 848226633Sdim LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 849226633Sdim default: 850226633Sdim res = "Unknown"; 851226633Sdim } 852226633Sdim break; 853226633Sdim default: 854226633Sdim res = "Unknown"; 855226633Sdim } 856226633Sdim Result.append(res.begin(), res.end()); 857226633Sdim return object_error::success; 858226633Sdim} 859226633Sdim 860226633Sdim#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 861226633Sdim 862226633Sdimerror_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, 863226633Sdim SmallVectorImpl<char> &Result) const { 864226633Sdim const coff_relocation *reloc = toRel(Rel); 865226633Sdim const coff_symbol *symb = 0; 866226633Sdim if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec; 867226633Sdim DataRefImpl sym; 868226633Sdim sym.p = reinterpret_cast<uintptr_t>(symb); 869226633Sdim StringRef symname; 870226633Sdim if (error_code ec = getSymbolName(sym, symname)) return ec; 871226633Sdim Result.append(symname.begin(), symname.end()); 872226633Sdim return object_error::success; 873226633Sdim} 874226633Sdim 875234353Sdimerror_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, 876234353Sdim LibraryRef &Result) const { 877234353Sdim report_fatal_error("getLibraryNext not implemented in COFFObjectFile"); 878234353Sdim} 879234353Sdim 880234353Sdimerror_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, 881234353Sdim StringRef &Result) const { 882234353Sdim report_fatal_error("getLibraryPath not implemented in COFFObjectFile"); 883234353Sdim} 884234353Sdim 885261991Sdimbool ImportDirectoryEntryRef:: 886261991Sdimoperator==(const ImportDirectoryEntryRef &Other) const { 887261991Sdim return ImportDirectoryPimpl == Other.ImportDirectoryPimpl; 888261991Sdim} 889261991Sdim 890261991Sdimstatic const import_directory_table_entry *toImportEntry(DataRefImpl Imp) { 891261991Sdim return reinterpret_cast<const import_directory_table_entry *>(Imp.p); 892261991Sdim} 893261991Sdim 894261991Sdimerror_code 895261991SdimImportDirectoryEntryRef::getNext(ImportDirectoryEntryRef &Result) const { 896261991Sdim const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl); 897261991Sdim Dir += 1; 898261991Sdim DataRefImpl Next; 899261991Sdim Next.p = reinterpret_cast<uintptr_t>(Dir); 900261991Sdim Result = ImportDirectoryEntryRef(Next, OwningObject); 901261991Sdim return object_error::success; 902261991Sdim} 903261991Sdim 904261991Sdimerror_code ImportDirectoryEntryRef:: 905261991SdimgetImportTableEntry(const import_directory_table_entry *&Result) const { 906261991Sdim Result = toImportEntry(ImportDirectoryPimpl); 907261991Sdim return object_error::success; 908261991Sdim} 909261991Sdim 910261991Sdimerror_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 911261991Sdim const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl); 912261991Sdim uintptr_t IntPtr = 0; 913261991Sdim if (error_code ec = OwningObject->getRvaPtr(Dir->NameRVA, IntPtr)) 914261991Sdim return ec; 915261991Sdim const char *Ptr = reinterpret_cast<const char *>(IntPtr); 916261991Sdim Result = StringRef(Ptr); 917261991Sdim return object_error::success; 918261991Sdim} 919261991Sdim 920261991Sdimerror_code ImportDirectoryEntryRef::getImportLookupEntry( 921261991Sdim const import_lookup_table_entry32 *&Result) const { 922261991Sdim const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl); 923261991Sdim uintptr_t IntPtr = 0; 924261991Sdim if (error_code ec = OwningObject->getRvaPtr( 925261991Sdim Dir->ImportLookupTableRVA, IntPtr)) 926261991Sdim return ec; 927261991Sdim Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); 928261991Sdim return object_error::success; 929261991Sdim} 930261991Sdim 931218885Sdimnamespace llvm { 932218885Sdim 933218885Sdim ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { 934224145Sdim error_code ec; 935224145Sdim return new COFFObjectFile(Object, ec); 936218885Sdim } 937218885Sdim 938218885Sdim} // end namespace llvm 939