18e90adafSMichael J. Spencer //===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===// 28e90adafSMichael J. Spencer // 38e90adafSMichael J. Spencer // The LLVM Compiler Infrastructure 48e90adafSMichael J. Spencer // 58e90adafSMichael J. Spencer // This file is distributed under the University of Illinois Open Source 68e90adafSMichael J. Spencer // License. See LICENSE.TXT for details. 78e90adafSMichael J. Spencer // 88e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 98e90adafSMichael J. Spencer // 108e90adafSMichael J. Spencer // This file declares the COFFObjectFile class. 118e90adafSMichael J. Spencer // 128e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 138e90adafSMichael J. Spencer 14ec29b121SMichael J. Spencer #include "llvm/Object/COFF.h" 159da9e693SMichael J. Spencer #include "llvm/ADT/ArrayRef.h" 16e5fd0047SMichael J. Spencer #include "llvm/ADT/SmallString.h" 178e90adafSMichael J. Spencer #include "llvm/ADT/StringSwitch.h" 188e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h" 19f078eff3SRui Ueyama #include "llvm/Support/COFF.h" 20c2bed429SRui Ueyama #include "llvm/Support/Debug.h" 21c2bed429SRui Ueyama #include "llvm/Support/raw_ostream.h" 22981af002SWill Dietz #include <cctype> 239d2c15efSNico Rieck #include <limits> 248e90adafSMichael J. Spencer 258e90adafSMichael J. Spencer using namespace llvm; 268e90adafSMichael J. Spencer using namespace object; 278e90adafSMichael J. Spencer 288e90adafSMichael J. Spencer using support::ulittle16_t; 298e90adafSMichael J. Spencer using support::ulittle32_t; 308e90adafSMichael J. Spencer using support::little16_t; 318e90adafSMichael J. Spencer 321d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec. 3348af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) { 34c3f9b5a5SRafael Espindola if (M.getBufferSize() < Size) { 358ff24d25SRui Ueyama EC = object_error::unexpected_eof; 361d6167fdSMichael J. Spencer return false; 371d6167fdSMichael J. Spencer } 381d6167fdSMichael J. Spencer return true; 398e90adafSMichael J. Spencer } 408e90adafSMichael J. Spencer 41ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 42ed64342bSRui Ueyama // Returns unexpected_eof if error. 43ed64342bSRui Ueyama template <typename T> 4448af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M, 45db4ed0bdSRafael Espindola const uint8_t *Ptr, 46db4ed0bdSRafael Espindola const size_t Size = sizeof(T)) { 47ed64342bSRui Ueyama uintptr_t Addr = uintptr_t(Ptr); 48c3f9b5a5SRafael Espindola if (Addr + Size < Addr || Addr + Size < Size || 49c3f9b5a5SRafael Espindola Addr + Size > uintptr_t(M.getBufferEnd())) { 50ed64342bSRui Ueyama return object_error::unexpected_eof; 511d6167fdSMichael J. Spencer } 52ed64342bSRui Ueyama Obj = reinterpret_cast<const T *>(Addr); 53ed64342bSRui Ueyama return object_error::success; 541d6167fdSMichael J. Spencer } 551d6167fdSMichael J. Spencer 569d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 579d2c15efSNico Rieck // prefixed slashes. 589d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 599d2c15efSNico Rieck assert(Str.size() <= 6 && "String too long, possible overflow."); 609d2c15efSNico Rieck if (Str.size() > 6) 619d2c15efSNico Rieck return true; 629d2c15efSNico Rieck 639d2c15efSNico Rieck uint64_t Value = 0; 649d2c15efSNico Rieck while (!Str.empty()) { 659d2c15efSNico Rieck unsigned CharVal; 669d2c15efSNico Rieck if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 679d2c15efSNico Rieck CharVal = Str[0] - 'A'; 689d2c15efSNico Rieck else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 699d2c15efSNico Rieck CharVal = Str[0] - 'a' + 26; 709d2c15efSNico Rieck else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 719d2c15efSNico Rieck CharVal = Str[0] - '0' + 52; 729d2c15efSNico Rieck else if (Str[0] == '+') // 62 735500b07cSRui Ueyama CharVal = 62; 749d2c15efSNico Rieck else if (Str[0] == '/') // 63 755500b07cSRui Ueyama CharVal = 63; 769d2c15efSNico Rieck else 779d2c15efSNico Rieck return true; 789d2c15efSNico Rieck 799d2c15efSNico Rieck Value = (Value * 64) + CharVal; 809d2c15efSNico Rieck Str = Str.substr(1); 819d2c15efSNico Rieck } 829d2c15efSNico Rieck 839d2c15efSNico Rieck if (Value > std::numeric_limits<uint32_t>::max()) 849d2c15efSNico Rieck return true; 859d2c15efSNico Rieck 869d2c15efSNico Rieck Result = static_cast<uint32_t>(Value); 879d2c15efSNico Rieck return false; 889d2c15efSNico Rieck } 899d2c15efSNico Rieck 9044f51e51SDavid Majnemer template <typename coff_symbol_type> 9144f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { 9244f51e51SDavid Majnemer const coff_symbol_type *Addr = 9344f51e51SDavid Majnemer reinterpret_cast<const coff_symbol_type *>(Ref.p); 941d6167fdSMichael J. Spencer 951d6167fdSMichael J. Spencer #ifndef NDEBUG 961d6167fdSMichael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 978ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); 9844f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 9944f51e51SDavid Majnemer Offset >= getPointerToSymbolTable() + 10044f51e51SDavid Majnemer (getNumberOfSymbols() * sizeof(coff_symbol_type))) 1011d6167fdSMichael J. Spencer report_fatal_error("Symbol was outside of symbol table."); 1021d6167fdSMichael J. Spencer 10344f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && 10444f51e51SDavid Majnemer "Symbol did not point to the beginning of a symbol"); 1051d6167fdSMichael J. Spencer #endif 1061d6167fdSMichael J. Spencer 1078ff24d25SRui Ueyama return Addr; 1081d6167fdSMichael J. Spencer } 1091d6167fdSMichael J. Spencer 1108ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 1118ff24d25SRui Ueyama const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 1121d6167fdSMichael J. Spencer 1131d6167fdSMichael J. Spencer # ifndef NDEBUG 1141d6167fdSMichael J. Spencer // Verify that the section points to a valid entry in the section table. 11544f51e51SDavid Majnemer if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) 1161d6167fdSMichael J. Spencer report_fatal_error("Section was outside of section table."); 1171d6167fdSMichael J. Spencer 1188ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); 1198ff24d25SRui Ueyama assert(Offset % sizeof(coff_section) == 0 && 1201d6167fdSMichael J. Spencer "Section did not point to the beginning of a section"); 1211d6167fdSMichael J. Spencer # endif 1221d6167fdSMichael J. Spencer 1238ff24d25SRui Ueyama return Addr; 1241d6167fdSMichael J. Spencer } 1251d6167fdSMichael J. Spencer 1265e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 12744f51e51SDavid Majnemer if (SymbolTable16) { 12844f51e51SDavid Majnemer const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref); 1298ff24d25SRui Ueyama Symb += 1 + Symb->NumberOfAuxSymbols; 1308ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Symb); 13144f51e51SDavid Majnemer } else if (SymbolTable32) { 13244f51e51SDavid Majnemer const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref); 13344f51e51SDavid Majnemer Symb += 1 + Symb->NumberOfAuxSymbols; 13444f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(Symb); 13544f51e51SDavid Majnemer } else { 13644f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 13744f51e51SDavid Majnemer } 1381d6167fdSMichael J. Spencer } 1391d6167fdSMichael J. Spencer 140db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolName(DataRefImpl Ref, 1411d6167fdSMichael J. Spencer StringRef &Result) const { 14244f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 1438ff24d25SRui Ueyama return getSymbolName(Symb, Result); 1448e90adafSMichael J. Spencer } 1458e90adafSMichael J. Spencer 146db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, 14775d1cf33SBenjamin Kramer uint64_t &Result) const { 14844f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 1492617dcceSCraig Topper const coff_section *Section = nullptr; 15044f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Section)) 1518ff24d25SRui Ueyama return EC; 152e62ab11fSRafael Espindola 15344f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED) 15475d1cf33SBenjamin Kramer Result = UnknownAddressOrSize; 15575d1cf33SBenjamin Kramer else if (Section) 15644f51e51SDavid Majnemer Result = Section->VirtualAddress + Symb.getValue(); 15775d1cf33SBenjamin Kramer else 15844f51e51SDavid Majnemer Result = Symb.getValue(); 15975d1cf33SBenjamin Kramer return object_error::success; 16075d1cf33SBenjamin Kramer } 16175d1cf33SBenjamin Kramer 162db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, 163d3946676SMichael J. Spencer SymbolRef::Type &Result) const { 16444f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 16575d1cf33SBenjamin Kramer Result = SymbolRef::ST_Other; 16644f51e51SDavid Majnemer 16744f51e51SDavid Majnemer if (Symb.getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL && 16844f51e51SDavid Majnemer Symb.getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED) { 1697e4b976cSDavid Meyer Result = SymbolRef::ST_Unknown; 17044f51e51SDavid Majnemer } else if (Symb.isFunctionDefinition()) { 17175d1cf33SBenjamin Kramer Result = SymbolRef::ST_Function; 17275d1cf33SBenjamin Kramer } else { 17306adfac8SRafael Espindola uint32_t Characteristics = 0; 17444f51e51SDavid Majnemer if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) { 1752617dcceSCraig Topper const coff_section *Section = nullptr; 17644f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Section)) 1778ff24d25SRui Ueyama return EC; 17806adfac8SRafael Espindola Characteristics = Section->Characteristics; 17975d1cf33SBenjamin Kramer } 18006adfac8SRafael Espindola if (Characteristics & COFF::IMAGE_SCN_MEM_READ && 18106adfac8SRafael Espindola ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. 18206adfac8SRafael Espindola Result = SymbolRef::ST_Data; 18375d1cf33SBenjamin Kramer } 18475d1cf33SBenjamin Kramer return object_error::success; 18575d1cf33SBenjamin Kramer } 18675d1cf33SBenjamin Kramer 18720122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 18844f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 18920122a43SRafael Espindola uint32_t Result = SymbolRef::SF_None; 19075d1cf33SBenjamin Kramer 191975e115eSRafael Espindola // TODO: Correctly set SF_FormatSpecific, SF_Common 1927e4b976cSDavid Meyer 19344f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED) { 19444f51e51SDavid Majnemer if (Symb.getValue() == 0) 1957e4b976cSDavid Meyer Result |= SymbolRef::SF_Undefined; 19622fe9c1eSRafael Espindola else 19722fe9c1eSRafael Espindola Result |= SymbolRef::SF_Common; 19822fe9c1eSRafael Espindola } 19922fe9c1eSRafael Espindola 2001df4b84dSDavid Meyer 2011df4b84dSDavid Meyer // TODO: This are certainly too restrictive. 20244f51e51SDavid Majnemer if (Symb.getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL) 2031df4b84dSDavid Meyer Result |= SymbolRef::SF_Global; 2041df4b84dSDavid Meyer 20544f51e51SDavid Majnemer if (Symb.getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) 2061df4b84dSDavid Meyer Result |= SymbolRef::SF_Weak; 2071df4b84dSDavid Meyer 20844f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 2091df4b84dSDavid Meyer Result |= SymbolRef::SF_Absolute; 2101df4b84dSDavid Meyer 21120122a43SRafael Espindola return Result; 21201759754SMichael J. Spencer } 21301759754SMichael J. Spencer 214db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, 2151d6167fdSMichael J. Spencer uint64_t &Result) const { 2168e90adafSMichael J. Spencer // FIXME: Return the correct size. This requires looking at all the symbols 2178e90adafSMichael J. Spencer // in the same section as this symbol, and looking for either the next 2188e90adafSMichael J. Spencer // symbol, or the end of the section. 21944f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2202617dcceSCraig Topper const coff_section *Section = nullptr; 22144f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Section)) 2228ff24d25SRui Ueyama return EC; 223e62ab11fSRafael Espindola 22444f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED) 2251d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 2261d6167fdSMichael J. Spencer else if (Section) 22744f51e51SDavid Majnemer Result = Section->SizeOfRawData - Symb.getValue(); 2281d6167fdSMichael J. Spencer else 2291d6167fdSMichael J. Spencer Result = 0; 2301d6167fdSMichael J. Spencer return object_error::success; 2318e90adafSMichael J. Spencer } 2328e90adafSMichael J. Spencer 233db4ed0bdSRafael Espindola std::error_code 234db4ed0bdSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref, 23532173153SMichael J. Spencer section_iterator &Result) const { 23644f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 23744f51e51SDavid Majnemer if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) { 238b5155a57SRafael Espindola Result = section_end(); 239f078eff3SRui Ueyama } else { 2402617dcceSCraig Topper const coff_section *Sec = nullptr; 24144f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) 242db4ed0bdSRafael Espindola return EC; 2438ff24d25SRui Ueyama DataRefImpl Ref; 2448ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2458ff24d25SRui Ueyama Result = section_iterator(SectionRef(Ref, this)); 24632173153SMichael J. Spencer } 24732173153SMichael J. Spencer return object_error::success; 24832173153SMichael J. Spencer } 24932173153SMichael J. Spencer 2505e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 2518ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2528ff24d25SRui Ueyama Sec += 1; 2538ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2548e90adafSMichael J. Spencer } 2558e90adafSMichael J. Spencer 256db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, 2571d6167fdSMichael J. Spencer StringRef &Result) const { 2588ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2598ff24d25SRui Ueyama return getSectionName(Sec, Result); 2608e90adafSMichael J. Spencer } 2618e90adafSMichael J. Spencer 262db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionAddress(DataRefImpl Ref, 2631d6167fdSMichael J. Spencer uint64_t &Result) const { 2648ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2658ff24d25SRui Ueyama Result = Sec->VirtualAddress; 2661d6167fdSMichael J. Spencer return object_error::success; 2678e90adafSMichael J. Spencer } 2688e90adafSMichael J. Spencer 269db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionSize(DataRefImpl Ref, 2701d6167fdSMichael J. Spencer uint64_t &Result) const { 2718ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2728ff24d25SRui Ueyama Result = Sec->SizeOfRawData; 2731d6167fdSMichael J. Spencer return object_error::success; 2748e90adafSMichael J. Spencer } 2758e90adafSMichael J. Spencer 276db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 2771d6167fdSMichael J. Spencer StringRef &Result) const { 2788ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2799da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 280db4ed0bdSRafael Espindola std::error_code EC = getSectionContents(Sec, Res); 2819da9e693SMichael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 2829da9e693SMichael J. Spencer return EC; 2838e90adafSMichael J. Spencer } 2848e90adafSMichael J. Spencer 285db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionAlignment(DataRefImpl Ref, 2867989460aSMichael J. Spencer uint64_t &Res) const { 2878ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2888ff24d25SRui Ueyama if (!Sec) 2897989460aSMichael J. Spencer return object_error::parse_failed; 2908ff24d25SRui Ueyama Res = uint64_t(1) << (((Sec->Characteristics & 0x00F00000) >> 20) - 1); 2917989460aSMichael J. Spencer return object_error::success; 2927989460aSMichael J. Spencer } 2937989460aSMichael J. Spencer 294db4ed0bdSRafael Espindola std::error_code COFFObjectFile::isSectionText(DataRefImpl Ref, 2951d6167fdSMichael J. Spencer bool &Result) const { 2968ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2978ff24d25SRui Ueyama Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 2981d6167fdSMichael J. Spencer return object_error::success; 2998e90adafSMichael J. Spencer } 3008e90adafSMichael J. Spencer 301db4ed0bdSRafael Espindola std::error_code COFFObjectFile::isSectionData(DataRefImpl Ref, 302800619f2SMichael J. Spencer bool &Result) const { 3038ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3048ff24d25SRui Ueyama Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 305800619f2SMichael J. Spencer return object_error::success; 306800619f2SMichael J. Spencer } 307800619f2SMichael J. Spencer 308db4ed0bdSRafael Espindola std::error_code COFFObjectFile::isSectionBSS(DataRefImpl Ref, 309800619f2SMichael J. Spencer bool &Result) const { 3108ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3118ff24d25SRui Ueyama Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 312800619f2SMichael J. Spencer return object_error::success; 313800619f2SMichael J. Spencer } 314800619f2SMichael J. Spencer 315db4ed0bdSRafael Espindola std::error_code 316db4ed0bdSRafael Espindola COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Ref, 3172138ef6dSPreston Gurd bool &Result) const { 3182138ef6dSPreston Gurd // FIXME: Unimplemented 3192138ef6dSPreston Gurd Result = true; 3202138ef6dSPreston Gurd return object_error::success; 3212138ef6dSPreston Gurd } 3222138ef6dSPreston Gurd 323db4ed0bdSRafael Espindola std::error_code COFFObjectFile::isSectionVirtual(DataRefImpl Ref, 3242138ef6dSPreston Gurd bool &Result) const { 3258ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3268ff24d25SRui Ueyama Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 3272138ef6dSPreston Gurd return object_error::success; 3282138ef6dSPreston Gurd } 3292138ef6dSPreston Gurd 330db4ed0bdSRafael Espindola std::error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Ref, 3312138ef6dSPreston Gurd bool &Result) const { 332b96a320aSAndrew Kaylor // FIXME: Unimplemented. 3332138ef6dSPreston Gurd Result = false; 3342138ef6dSPreston Gurd return object_error::success; 3352138ef6dSPreston Gurd } 3362138ef6dSPreston Gurd 337db4ed0bdSRafael Espindola std::error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Ref, 3383f31fa05SAndrew Kaylor bool &Result) const { 3393f31fa05SAndrew Kaylor // FIXME: Unimplemented. 3403f31fa05SAndrew Kaylor Result = false; 3413f31fa05SAndrew Kaylor return object_error::success; 3423f31fa05SAndrew Kaylor } 3433f31fa05SAndrew Kaylor 344db4ed0bdSRafael Espindola std::error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef, 3458ff24d25SRui Ueyama DataRefImpl SymbRef, 346f6f3e81cSBenjamin Kramer bool &Result) const { 3478ff24d25SRui Ueyama const coff_section *Sec = toSec(SecRef); 34844f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(SymbRef); 3492617dcceSCraig Topper const coff_section *SymbSec = nullptr; 35044f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), SymbSec)) 351db4ed0bdSRafael Espindola return EC; 3528ff24d25SRui Ueyama if (SymbSec == Sec) 3539a28851eSMichael J. Spencer Result = true; 3549a28851eSMichael J. Spencer else 355f6f3e81cSBenjamin Kramer Result = false; 356f6f3e81cSBenjamin Kramer return object_error::success; 357f6f3e81cSBenjamin Kramer } 358f6f3e81cSBenjamin Kramer 3598ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 3608ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3618ff24d25SRui Ueyama DataRefImpl Ret; 362827c8a2bSRui Ueyama if (Sec->NumberOfRelocations == 0) { 3638ff24d25SRui Ueyama Ret.p = 0; 364827c8a2bSRui Ueyama } else { 365827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation*>( 366827c8a2bSRui Ueyama base() + Sec->PointerToRelocations); 367827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 368827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 369827c8a2bSRui Ueyama // relocations. 370827c8a2bSRui Ueyama begin++; 371827c8a2bSRui Ueyama } 372827c8a2bSRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(begin); 373827c8a2bSRui Ueyama } 3748ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 375e5fd0047SMichael J. Spencer } 376e5fd0047SMichael J. Spencer 377827c8a2bSRui Ueyama static uint32_t getNumberOfRelocations(const coff_section *Sec, 378827c8a2bSRui Ueyama const uint8_t *base) { 379827c8a2bSRui Ueyama // The field for the number of relocations in COFF section table is only 380827c8a2bSRui Ueyama // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 381827c8a2bSRui Ueyama // NumberOfRelocations field, and the actual relocation count is stored in the 382827c8a2bSRui Ueyama // VirtualAddress field in the first relocation entry. 383827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 384827c8a2bSRui Ueyama auto *FirstReloc = reinterpret_cast<const coff_relocation*>( 385827c8a2bSRui Ueyama base + Sec->PointerToRelocations); 386827c8a2bSRui Ueyama return FirstReloc->VirtualAddress; 387827c8a2bSRui Ueyama } 388827c8a2bSRui Ueyama return Sec->NumberOfRelocations; 389827c8a2bSRui Ueyama } 390827c8a2bSRui Ueyama 3918ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 3928ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3938ff24d25SRui Ueyama DataRefImpl Ret; 394827c8a2bSRui Ueyama if (Sec->NumberOfRelocations == 0) { 3958ff24d25SRui Ueyama Ret.p = 0; 396827c8a2bSRui Ueyama } else { 397827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation*>( 398827c8a2bSRui Ueyama base() + Sec->PointerToRelocations); 399827c8a2bSRui Ueyama uint32_t NumReloc = getNumberOfRelocations(Sec, base()); 400827c8a2bSRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(begin + NumReloc); 401827c8a2bSRui Ueyama } 4028ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 403e5fd0047SMichael J. Spencer } 404e5fd0047SMichael J. Spencer 405c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 406db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() { 40744f51e51SDavid Majnemer if (COFFHeader) 40844f51e51SDavid Majnemer if (std::error_code EC = 40944f51e51SDavid Majnemer getObject(SymbolTable16, Data, base() + getPointerToSymbolTable(), 41044f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize())) 41144f51e51SDavid Majnemer return EC; 41244f51e51SDavid Majnemer 41344f51e51SDavid Majnemer if (COFFBigObjHeader) 41444f51e51SDavid Majnemer if (std::error_code EC = 41544f51e51SDavid Majnemer getObject(SymbolTable32, Data, base() + getPointerToSymbolTable(), 41644f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize())) 4178ff24d25SRui Ueyama return EC; 418c2bed429SRui Ueyama 419c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 420c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 421c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 422c2bed429SRui Ueyama const uint8_t *StringTableAddr = 42344f51e51SDavid Majnemer base() + getPointerToSymbolTable() + 42444f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 425c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 42648af1c2aSRafael Espindola if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 4278ff24d25SRui Ueyama return EC; 428c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 429db4ed0bdSRafael Espindola if (std::error_code EC = 43048af1c2aSRafael Espindola getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4318ff24d25SRui Ueyama return EC; 432c2bed429SRui Ueyama 433773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 434773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 435773a5795SNico Rieck if (StringTableSize < 4) 436773a5795SNico Rieck StringTableSize = 4; 437773a5795SNico Rieck 438c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 439773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 440c2bed429SRui Ueyama return object_error::parse_failed; 441c2bed429SRui Ueyama return object_error::success; 442c2bed429SRui Ueyama } 443c2bed429SRui Ueyama 444215a586cSRui Ueyama // Returns the file offset for the given VA. 445db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 446b6eb264aSRui Ueyama uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase 447b6eb264aSRui Ueyama : (uint64_t)PE32PlusHeader->ImageBase; 448b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 449b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 450b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 451215a586cSRui Ueyama } 452215a586cSRui Ueyama 453c2bed429SRui Ueyama // Returns the file offset for the given RVA. 454db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 45527dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 45627dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 457c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 458c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 459215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 460215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 461c2bed429SRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 462c2bed429SRui Ueyama return object_error::success; 463c2bed429SRui Ueyama } 464c2bed429SRui Ueyama } 465c2bed429SRui Ueyama return object_error::parse_failed; 466c2bed429SRui Ueyama } 467c2bed429SRui Ueyama 468c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 469c2bed429SRui Ueyama // table entry. 470db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 471db4ed0bdSRafael Espindola StringRef &Name) const { 472c2bed429SRui Ueyama uintptr_t IntPtr = 0; 473db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 4748ff24d25SRui Ueyama return EC; 475c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 476c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 477c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 478c2bed429SRui Ueyama return object_error::success; 479c2bed429SRui Ueyama } 480c2bed429SRui Ueyama 481c2bed429SRui Ueyama // Find the import table. 482db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() { 483c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 484c2bed429SRui Ueyama // the import table, do nothing. 485c2bed429SRui Ueyama const data_directory *DataEntry; 486c2bed429SRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 487c2bed429SRui Ueyama return object_error::success; 488c2bed429SRui Ueyama 489c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 490c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 491c2bed429SRui Ueyama return object_error::success; 492c2bed429SRui Ueyama 493c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 494c2bed429SRui Ueyama NumberOfImportDirectory = DataEntry->Size / 495c2bed429SRui Ueyama sizeof(import_directory_table_entry); 496c2bed429SRui Ueyama 497c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 498c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 499c2bed429SRui Ueyama uintptr_t IntPtr = 0; 500db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 5018ff24d25SRui Ueyama return EC; 502c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 503c2bed429SRui Ueyama const import_directory_table_entry *>(IntPtr); 504ad882ba8SRui Ueyama return object_error::success; 505ad882ba8SRui Ueyama } 506c2bed429SRui Ueyama 507ad882ba8SRui Ueyama // Find the export table. 508db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() { 509ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 510ad882ba8SRui Ueyama // the export table, do nothing. 511ad882ba8SRui Ueyama const data_directory *DataEntry; 512ad882ba8SRui Ueyama if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 513ad882ba8SRui Ueyama return object_error::success; 514ad882ba8SRui Ueyama 515ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 516ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 517ad882ba8SRui Ueyama return object_error::success; 518ad882ba8SRui Ueyama 519ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 520ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 521db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 522ad882ba8SRui Ueyama return EC; 52324fc2d64SRui Ueyama ExportDirectory = 52424fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 525ad882ba8SRui Ueyama return object_error::success; 526c2bed429SRui Ueyama } 527c2bed429SRui Ueyama 52848af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 52948af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 53044f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 53144f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 53244f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 53344f51e51SDavid Majnemer ImportDirectory(nullptr), NumberOfImportDirectory(0), 5342617dcceSCraig Topper ExportDirectory(nullptr) { 5351d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 53648af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 537c3f9b5a5SRafael Espindola return; 538ee066fc4SEric Christopher 53982ebd8e3SRui Ueyama // The current location in the file where we are looking at. 54082ebd8e3SRui Ueyama uint64_t CurPtr = 0; 54182ebd8e3SRui Ueyama 54282ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 54382ebd8e3SRui Ueyama // it is placed right after COFF header. 5448ff24d25SRui Ueyama bool HasPEHeader = false; 545ee066fc4SEric Christopher 5461d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 547ec29b121SMichael J. Spencer if (base()[0] == 0x4d && base()[1] == 0x5a) { 548ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 549ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 55048af1c2aSRafael Espindola if (!checkSize(Data, EC, 0x3c + 8)) 551c3f9b5a5SRafael Espindola return; 55282ebd8e3SRui Ueyama CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c); 55382ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 55444f51e51SDavid Majnemer if (std::memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 55544f51e51SDavid Majnemer 0) { 5568ff24d25SRui Ueyama EC = object_error::parse_failed; 5571d6167fdSMichael J. Spencer return; 5581d6167fdSMichael J. Spencer } 55944f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 5608ff24d25SRui Ueyama HasPEHeader = true; 561ee066fc4SEric Christopher } 562ee066fc4SEric Christopher 56348af1c2aSRafael Espindola if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 5641d6167fdSMichael J. Spencer return; 56544f51e51SDavid Majnemer 56644f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 56744f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 56844f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 56944f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 57044f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 57144f51e51SDavid Majnemer if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 57244f51e51SDavid Majnemer return; 57344f51e51SDavid Majnemer 57444f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 57544f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 57644f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 57744f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 57844f51e51SDavid Majnemer COFFHeader = nullptr; 57944f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 58044f51e51SDavid Majnemer } else { 58144f51e51SDavid Majnemer // It's not a bigobj. 58244f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 58344f51e51SDavid Majnemer } 58444f51e51SDavid Majnemer } 58544f51e51SDavid Majnemer if (COFFHeader) { 58644f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 58744f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 58844f51e51SDavid Majnemer EC = object_error::success; 58982ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 59082ebd8e3SRui Ueyama 59144f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 59244f51e51SDavid Majnemer return; 59344f51e51SDavid Majnemer } 59444f51e51SDavid Majnemer 5958ff24d25SRui Ueyama if (HasPEHeader) { 59610ed9ddcSRui Ueyama const pe32_header *Header; 59748af1c2aSRafael Espindola if ((EC = getObject(Header, Data, base() + CurPtr))) 59882ebd8e3SRui Ueyama return; 59910ed9ddcSRui Ueyama 60010ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 60110ed9ddcSRui Ueyama uint64_t DataDirSize; 60210ed9ddcSRui Ueyama if (Header->Magic == 0x10b) { 60310ed9ddcSRui Ueyama PE32Header = Header; 60410ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 60510ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 60610ed9ddcSRui Ueyama } else if (Header->Magic == 0x20b) { 60710ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 60810ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 60910ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 61010ed9ddcSRui Ueyama } else { 61110ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 61210ed9ddcSRui Ueyama EC = object_error::parse_failed; 613ed64342bSRui Ueyama return; 614ed64342bSRui Ueyama } 61548af1c2aSRafael Espindola if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 61610ed9ddcSRui Ueyama return; 61782ebd8e3SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 61882ebd8e3SRui Ueyama } 6191d6167fdSMichael J. Spencer 62048af1c2aSRafael Espindola if ((EC = getObject(SectionTable, Data, base() + CurPtr, 62144f51e51SDavid Majnemer getNumberOfSections() * sizeof(coff_section)))) 6221d6167fdSMichael J. Spencer return; 6231d6167fdSMichael J. Spencer 624c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 62544f51e51SDavid Majnemer if (getPointerToSymbolTable() != 0) 6268ff24d25SRui Ueyama if ((EC = initSymbolTablePtr())) 6271d6167fdSMichael J. Spencer return; 6288e90adafSMichael J. Spencer 629c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 6308ff24d25SRui Ueyama if ((EC = initImportTablePtr())) 631ed64342bSRui Ueyama return; 6321d6167fdSMichael J. Spencer 633ad882ba8SRui Ueyama // Initialize the pointer to the export table. 6348ff24d25SRui Ueyama if ((EC = initExportTablePtr())) 635ad882ba8SRui Ueyama return; 636ad882ba8SRui Ueyama 6378ff24d25SRui Ueyama EC = object_error::success; 6388e90adafSMichael J. Spencer } 6398e90adafSMichael J. Spencer 640f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { 6418ff24d25SRui Ueyama DataRefImpl Ret; 64244f51e51SDavid Majnemer Ret.p = getSymbolTable(); 643f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 6448e90adafSMichael J. Spencer } 6458e90adafSMichael J. Spencer 646f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { 6478e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 6488ff24d25SRui Ueyama DataRefImpl Ret; 6498ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 650f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 6518e90adafSMichael J. Spencer } 6528e90adafSMichael J. Spencer 653bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 654a045b73aSRui Ueyama return import_directory_iterator( 655a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 656c2bed429SRui Ueyama } 657c2bed429SRui Ueyama 658bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 659a045b73aSRui Ueyama return import_directory_iterator( 660a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this)); 661c2bed429SRui Ueyama } 662c429b80dSDavid Meyer 663ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 664ad882ba8SRui Ueyama return export_directory_iterator( 665ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 666ad882ba8SRui Ueyama } 667ad882ba8SRui Ueyama 668ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 6692617dcceSCraig Topper if (!ExportDirectory) 6702617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 6718ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 672ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 6738ff24d25SRui Ueyama return export_directory_iterator(Ref); 674ad882ba8SRui Ueyama } 675ad882ba8SRui Ueyama 676b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 6778ff24d25SRui Ueyama DataRefImpl Ret; 6788ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 6798ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 6808e90adafSMichael J. Spencer } 6818e90adafSMichael J. Spencer 682b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 6838ff24d25SRui Ueyama DataRefImpl Ret; 68444f51e51SDavid Majnemer int NumSections = 68544f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 6868ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 6878ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 6888e90adafSMichael J. Spencer } 6898e90adafSMichael J. Spencer 6908e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 6910324b672SMichael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 6928e90adafSMichael J. Spencer } 6938e90adafSMichael J. Spencer 6948e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 69544f51e51SDavid Majnemer switch(getMachine()) { 6968e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 6978e90adafSMichael J. Spencer return "COFF-i386"; 6988e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 6998e90adafSMichael J. Spencer return "COFF-x86-64"; 7009b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 7019b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 7028e90adafSMichael J. Spencer default: 7038e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 7048e90adafSMichael J. Spencer } 7058e90adafSMichael J. Spencer } 7068e90adafSMichael J. Spencer 7078e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 70844f51e51SDavid Majnemer switch (getMachine()) { 7098e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 7108e90adafSMichael J. Spencer return Triple::x86; 7118e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 7128e90adafSMichael J. Spencer return Triple::x86_64; 7139b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 7149b7c0af2SSaleem Abdulrasool return Triple::thumb; 7158e90adafSMichael J. Spencer default: 7168e90adafSMichael J. Spencer return Triple::UnknownArch; 7178e90adafSMichael J. Spencer } 7188e90adafSMichael J. Spencer } 7198e90adafSMichael J. Spencer 720db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 72182ebd8e3SRui Ueyama Res = PE32Header; 72289a7a5eaSMichael J. Spencer return object_error::success; 72389a7a5eaSMichael J. Spencer } 72489a7a5eaSMichael J. Spencer 725db4ed0bdSRafael Espindola std::error_code 72610ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 72710ed9ddcSRui Ueyama Res = PE32PlusHeader; 72810ed9ddcSRui Ueyama return object_error::success; 72910ed9ddcSRui Ueyama } 73010ed9ddcSRui Ueyama 731db4ed0bdSRafael Espindola std::error_code 732db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index, 733ed64342bSRui Ueyama const data_directory *&Res) const { 734ed64342bSRui Ueyama // Error if if there's no data directory or the index is out of range. 73510ed9ddcSRui Ueyama if (!DataDirectory) 73610ed9ddcSRui Ueyama return object_error::parse_failed; 73710ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 73810ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 73910ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 74010ed9ddcSRui Ueyama if (Index > NumEnt) 741ed64342bSRui Ueyama return object_error::parse_failed; 7428ff24d25SRui Ueyama Res = &DataDirectory[Index]; 743ed64342bSRui Ueyama return object_error::success; 744ed64342bSRui Ueyama } 745ed64342bSRui Ueyama 746db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index, 7471d6167fdSMichael J. Spencer const coff_section *&Result) const { 7481d6167fdSMichael J. Spencer // Check for special index values. 749f078eff3SRui Ueyama if (COFF::isReservedSectionNumber(Index)) 7502617dcceSCraig Topper Result = nullptr; 75144f51e51SDavid Majnemer else if (Index > 0 && static_cast<uint32_t>(Index) <= getNumberOfSections()) 7521d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 7538ff24d25SRui Ueyama Result = SectionTable + (Index - 1); 7541d6167fdSMichael J. Spencer else 7551d6167fdSMichael J. Spencer return object_error::parse_failed; 7561d6167fdSMichael J. Spencer return object_error::success; 7578e90adafSMichael J. Spencer } 7588e90adafSMichael J. Spencer 759db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset, 7601d6167fdSMichael J. Spencer StringRef &Result) const { 7611d6167fdSMichael J. Spencer if (StringTableSize <= 4) 7621d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 7631d6167fdSMichael J. Spencer return object_error::parse_failed; 7648ff24d25SRui Ueyama if (Offset >= StringTableSize) 7651d6167fdSMichael J. Spencer return object_error::unexpected_eof; 7668ff24d25SRui Ueyama Result = StringRef(StringTable + Offset); 7671d6167fdSMichael J. Spencer return object_error::success; 7688e90adafSMichael J. Spencer } 769022ecdf2SBenjamin Kramer 77044f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 77189a7a5eaSMichael J. Spencer StringRef &Res) const { 77289a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 77344f51e51SDavid Majnemer if (Symbol.getStringTableOffset().Zeroes == 0) { 77444f51e51SDavid Majnemer uint32_t Offset = Symbol.getStringTableOffset().Offset; 775db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Res)) 7768ff24d25SRui Ueyama return EC; 77789a7a5eaSMichael J. Spencer return object_error::success; 77889a7a5eaSMichael J. Spencer } 77989a7a5eaSMichael J. Spencer 78044f51e51SDavid Majnemer if (Symbol.getShortName()[COFF::NameSize - 1] == 0) 78189a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 78244f51e51SDavid Majnemer Res = StringRef(Symbol.getShortName()); 78389a7a5eaSMichael J. Spencer else 78489a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 78544f51e51SDavid Majnemer Res = StringRef(Symbol.getShortName(), COFF::NameSize); 78689a7a5eaSMichael J. Spencer return object_error::success; 78789a7a5eaSMichael J. Spencer } 78889a7a5eaSMichael J. Spencer 78944f51e51SDavid Majnemer ArrayRef<uint8_t> 79044f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 7912617dcceSCraig Topper const uint8_t *Aux = nullptr; 79271757ef3SMarshall Clow 79344f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 79444f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 79571757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 79644f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 79771757ef3SMarshall Clow # ifndef NDEBUG 7988ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 7998ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 80044f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 80144f51e51SDavid Majnemer Offset >= 80244f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 80371757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 80471757ef3SMarshall Clow 80544f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 80644f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 80771757ef3SMarshall Clow # endif 808bfb85e67SMarshall Clow } 80944f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 81071757ef3SMarshall Clow } 81171757ef3SMarshall Clow 812db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 81353c2d547SMichael J. Spencer StringRef &Res) const { 81453c2d547SMichael J. Spencer StringRef Name; 81544f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 81653c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 81753c2d547SMichael J. Spencer Name = Sec->Name; 81853c2d547SMichael J. Spencer else 81953c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 82044f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 82153c2d547SMichael J. Spencer 82253c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 82353c2d547SMichael J. Spencer if (Name[0] == '/') { 82453c2d547SMichael J. Spencer uint32_t Offset; 8259d2c15efSNico Rieck if (Name[1] == '/') { 8269d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 8279d2c15efSNico Rieck return object_error::parse_failed; 8289d2c15efSNico Rieck } else { 82953c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 83053c2d547SMichael J. Spencer return object_error::parse_failed; 8319d2c15efSNico Rieck } 832db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Name)) 8338ff24d25SRui Ueyama return EC; 83453c2d547SMichael J. Spencer } 83553c2d547SMichael J. Spencer 83653c2d547SMichael J. Spencer Res = Name; 83753c2d547SMichael J. Spencer return object_error::success; 83853c2d547SMichael J. Spencer } 83953c2d547SMichael J. Spencer 840db4ed0bdSRafael Espindola std::error_code 841db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec, 8429da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 843*dac39857SDavid Majnemer // PointerToRawData and SizeOfRawData won't make sense for BSS sections, don't 844*dac39857SDavid Majnemer // do anything interesting for them. 845*dac39857SDavid Majnemer assert((Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 && 846*dac39857SDavid Majnemer "BSS sections don't have contents!"); 8479da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 8489da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 8499da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 8509da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 8519da9e693SMichael J. Spencer uintptr_t ConEnd = ConStart + Sec->SizeOfRawData; 85248af1c2aSRafael Espindola if (ConEnd > uintptr_t(Data.getBufferEnd())) 8539da9e693SMichael J. Spencer return object_error::parse_failed; 854e1d12948SCraig Topper Res = makeArrayRef(reinterpret_cast<const uint8_t*>(ConStart), 8559da9e693SMichael J. Spencer Sec->SizeOfRawData); 8569da9e693SMichael J. Spencer return object_error::success; 8579da9e693SMichael J. Spencer } 8589da9e693SMichael J. Spencer 859022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 860e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 861022ecdf2SBenjamin Kramer } 8628ff24d25SRui Ueyama 8635e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 864e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 865e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 866022ecdf2SBenjamin Kramer } 8678ff24d25SRui Ueyama 868db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 869022ecdf2SBenjamin Kramer uint64_t &Res) const { 8701e483879SRafael Espindola report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); 871022ecdf2SBenjamin Kramer } 8728ff24d25SRui Ueyama 873db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, 874cbe72fc9SDanil Malyshev uint64_t &Res) const { 875cbe72fc9SDanil Malyshev Res = toRel(Rel)->VirtualAddress; 876cbe72fc9SDanil Malyshev return object_error::success; 877cbe72fc9SDanil Malyshev } 8788ff24d25SRui Ueyama 879806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 880022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 8818ff24d25SRui Ueyama DataRefImpl Ref; 88244f51e51SDavid Majnemer if (SymbolTable16) 88344f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 88444f51e51SDavid Majnemer else if (SymbolTable32) 88544f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 88644f51e51SDavid Majnemer else 88744f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 8888ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 889022ecdf2SBenjamin Kramer } 8908ff24d25SRui Ueyama 891db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 8927be76590SOwen Anderson uint64_t &Res) const { 893022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 894022ecdf2SBenjamin Kramer Res = R->Type; 895022ecdf2SBenjamin Kramer return object_error::success; 896022ecdf2SBenjamin Kramer } 897e5fd0047SMichael J. Spencer 89827dc8394SAlexey Samsonov const coff_section * 89927dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 90027dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 90171757ef3SMarshall Clow } 90271757ef3SMarshall Clow 90344f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 90444f51e51SDavid Majnemer if (SymbolTable16) 90544f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 90644f51e51SDavid Majnemer if (SymbolTable32) 90744f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 90844f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 90944f51e51SDavid Majnemer } 91044f51e51SDavid Majnemer 91144f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 91244f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 91371757ef3SMarshall Clow } 91471757ef3SMarshall Clow 915f12b8282SRafael Espindola const coff_relocation * 91627dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 91727dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 918d3e2a76cSMarshall Clow } 919d3e2a76cSMarshall Clow 92027dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 92127dc8394SAlexey Samsonov case COFF::reloc_type: \ 92227dc8394SAlexey Samsonov Res = #reloc_type; \ 92327dc8394SAlexey Samsonov break; 924e5fd0047SMichael J. Spencer 925db4ed0bdSRafael Espindola std::error_code 926db4ed0bdSRafael Espindola COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 927e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 9288ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 9298ff24d25SRui Ueyama StringRef Res; 93044f51e51SDavid Majnemer switch (getMachine()) { 931e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 9328ff24d25SRui Ueyama switch (Reloc->Type) { 933e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 934e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 935e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 936e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 937e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 938e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 939e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 940e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 941e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 942e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 943e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 944e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 945e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 946e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 947e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 948e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 949e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 950e5fd0047SMichael J. Spencer default: 9518ff24d25SRui Ueyama Res = "Unknown"; 952e5fd0047SMichael J. Spencer } 953e5fd0047SMichael J. Spencer break; 9545c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 9555c503bf4SSaleem Abdulrasool switch (Reloc->Type) { 9565c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 9575c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 9585c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 9595c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 9605c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 9615c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 9625c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 9635c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 9645c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 9655c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 9665c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 9675c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 9685c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 9695c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 9705c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 9715c503bf4SSaleem Abdulrasool default: 9725c503bf4SSaleem Abdulrasool Res = "Unknown"; 9735c503bf4SSaleem Abdulrasool } 9745c503bf4SSaleem Abdulrasool break; 975e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 9768ff24d25SRui Ueyama switch (Reloc->Type) { 977e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 978e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 979e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 980e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 981e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 982e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 983e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 984e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 985e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 986e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 987e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 988e5fd0047SMichael J. Spencer default: 9898ff24d25SRui Ueyama Res = "Unknown"; 990e5fd0047SMichael J. Spencer } 991e5fd0047SMichael J. Spencer break; 992e5fd0047SMichael J. Spencer default: 9938ff24d25SRui Ueyama Res = "Unknown"; 994e5fd0047SMichael J. Spencer } 9958ff24d25SRui Ueyama Result.append(Res.begin(), Res.end()); 996e5fd0047SMichael J. Spencer return object_error::success; 997e5fd0047SMichael J. Spencer } 998e5fd0047SMichael J. Spencer 999e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1000e5fd0047SMichael J. Spencer 1001db4ed0bdSRafael Espindola std::error_code 1002db4ed0bdSRafael Espindola COFFObjectFile::getRelocationValueString(DataRefImpl Rel, 1003e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 10048ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 10058ff24d25SRui Ueyama DataRefImpl Sym; 100644f51e51SDavid Majnemer ErrorOr<COFFSymbolRef> Symb = getSymbol(Reloc->SymbolTableIndex); 100744f51e51SDavid Majnemer if (std::error_code EC = Symb.getError()) 100844f51e51SDavid Majnemer return EC; 100944f51e51SDavid Majnemer Sym.p = reinterpret_cast<uintptr_t>(Symb->getRawPtr()); 10108ff24d25SRui Ueyama StringRef SymName; 1011db4ed0bdSRafael Espindola if (std::error_code EC = getSymbolName(Sym, SymName)) 1012db4ed0bdSRafael Espindola return EC; 10138ff24d25SRui Ueyama Result.append(SymName.begin(), SymName.end()); 1014e5fd0047SMichael J. Spencer return object_error::success; 1015022ecdf2SBenjamin Kramer } 10168e90adafSMichael J. Spencer 1017c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1018c66d761bSRafael Espindola return !DataDirectory; 1019c66d761bSRafael Espindola } 1020c66d761bSRafael Espindola 1021c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1022c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1023a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1024c2bed429SRui Ueyama } 1025c2bed429SRui Ueyama 10265e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 10275e812afaSRafael Espindola ++Index; 1028c2bed429SRui Ueyama } 1029c2bed429SRui Ueyama 1030db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry( 1031db4ed0bdSRafael Espindola const import_directory_table_entry *&Result) const { 1032a045b73aSRui Ueyama Result = ImportTable; 1033c2bed429SRui Ueyama return object_error::success; 1034c2bed429SRui Ueyama } 1035c2bed429SRui Ueyama 1036db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1037c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1038db4ed0bdSRafael Espindola if (std::error_code EC = 1039db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ImportTable->NameRVA, IntPtr)) 1040a045b73aSRui Ueyama return EC; 1041a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1042c2bed429SRui Ueyama return object_error::success; 1043c2bed429SRui Ueyama } 1044c2bed429SRui Ueyama 1045db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportLookupEntry( 1046c2bed429SRui Ueyama const import_lookup_table_entry32 *&Result) const { 1047c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1048db4ed0bdSRafael Espindola if (std::error_code EC = 1049a045b73aSRui Ueyama OwningObject->getRvaPtr(ImportTable->ImportLookupTableRVA, IntPtr)) 1050a045b73aSRui Ueyama return EC; 1051c2bed429SRui Ueyama Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); 1052c2bed429SRui Ueyama return object_error::success; 1053c2bed429SRui Ueyama } 1054c2bed429SRui Ueyama 1055ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1056ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1057ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1058ad882ba8SRui Ueyama } 1059ad882ba8SRui Ueyama 10605e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 10615e812afaSRafael Espindola ++Index; 1062ad882ba8SRui Ueyama } 1063ad882ba8SRui Ueyama 1064da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1065da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 1066db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1067da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1068db4ed0bdSRafael Espindola if (std::error_code EC = 1069db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1070da49d0d4SRui Ueyama return EC; 1071da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1072da49d0d4SRui Ueyama return object_error::success; 1073da49d0d4SRui Ueyama } 1074da49d0d4SRui Ueyama 1075e5df6095SRui Ueyama // Returns the starting ordinal number. 1076db4ed0bdSRafael Espindola std::error_code 1077db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1078e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 1079e5df6095SRui Ueyama return object_error::success; 1080e5df6095SRui Ueyama } 1081e5df6095SRui Ueyama 1082ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1083db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1084ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 1085ad882ba8SRui Ueyama return object_error::success; 1086ad882ba8SRui Ueyama } 1087ad882ba8SRui Ueyama 1088ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1089db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1090ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1091db4ed0bdSRafael Espindola if (std::error_code EC = 1092db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1093ad882ba8SRui Ueyama return EC; 109424fc2d64SRui Ueyama const export_address_table_entry *entry = 109524fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1096ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 1097ad882ba8SRui Ueyama return object_error::success; 1098ad882ba8SRui Ueyama } 1099ad882ba8SRui Ueyama 1100ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1101ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1102db4ed0bdSRafael Espindola std::error_code 1103db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1104ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1105db4ed0bdSRafael Espindola if (std::error_code EC = 1106db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1107ad882ba8SRui Ueyama return EC; 1108ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1109ad882ba8SRui Ueyama 1110ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1111ad882ba8SRui Ueyama int Offset = 0; 1112ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1113ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1114ad882ba8SRui Ueyama if (*I != Index) 1115ad882ba8SRui Ueyama continue; 1116db4ed0bdSRafael Espindola if (std::error_code EC = 1117db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1118ad882ba8SRui Ueyama return EC; 1119ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1120db4ed0bdSRafael Espindola if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1121ad882ba8SRui Ueyama return EC; 1122ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1123ad882ba8SRui Ueyama return object_error::success; 1124ad882ba8SRui Ueyama } 1125ad882ba8SRui Ueyama Result = ""; 1126ad882ba8SRui Ueyama return object_error::success; 1127ad882ba8SRui Ueyama } 1128ad882ba8SRui Ueyama 1129437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>> 113048af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1131db4ed0bdSRafael Espindola std::error_code EC; 113248af1c2aSRafael Espindola std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1133692410efSRafael Espindola if (EC) 1134692410efSRafael Espindola return EC; 1135437b0d58SRafael Espindola return std::move(Ret); 1136686738e2SRui Ueyama } 1137