xref: /src/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1d99dafe2SDimitry Andric //===- COFFObjectFile.cpp - COFF object file implementation ---------------===//
2cf099d11SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cf099d11SDimitry Andric //
7cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
8cf099d11SDimitry Andric //
9cf099d11SDimitry Andric // This file declares the COFFObjectFile class.
10cf099d11SDimitry Andric //
11cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
12cf099d11SDimitry Andric 
1363faed5bSDimitry Andric #include "llvm/ADT/ArrayRef.h"
14d99dafe2SDimitry Andric #include "llvm/ADT/StringRef.h"
15cfca06d7SDimitry Andric #include "llvm/ADT/StringSwitch.h"
161a82d4c0SDimitry Andric #include "llvm/ADT/iterator_range.h"
17d99dafe2SDimitry Andric #include "llvm/Object/Binary.h"
18d99dafe2SDimitry Andric #include "llvm/Object/COFF.h"
19d99dafe2SDimitry Andric #include "llvm/Object/Error.h"
20d99dafe2SDimitry Andric #include "llvm/Object/ObjectFile.h"
21ac9a064cSDimitry Andric #include "llvm/Object/WindowsMachineFlag.h"
22c46e6a59SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
23d99dafe2SDimitry Andric #include "llvm/Support/Endian.h"
24d99dafe2SDimitry Andric #include "llvm/Support/Error.h"
25d99dafe2SDimitry Andric #include "llvm/Support/ErrorHandling.h"
26d99dafe2SDimitry Andric #include "llvm/Support/MathExtras.h"
27145449b1SDimitry Andric #include "llvm/Support/MemoryBufferRef.h"
28d99dafe2SDimitry Andric #include <algorithm>
29d99dafe2SDimitry Andric #include <cassert>
30b60736ecSDimitry Andric #include <cinttypes>
31d99dafe2SDimitry Andric #include <cstddef>
32d99dafe2SDimitry Andric #include <cstring>
335ca98fd9SDimitry Andric #include <limits>
34d99dafe2SDimitry Andric #include <memory>
35d99dafe2SDimitry Andric #include <system_error>
36cf099d11SDimitry Andric 
37cf099d11SDimitry Andric using namespace llvm;
38cf099d11SDimitry Andric using namespace object;
39cf099d11SDimitry Andric 
40cf099d11SDimitry Andric using support::ulittle16_t;
41cf099d11SDimitry Andric using support::ulittle32_t;
4267c32a98SDimitry Andric using support::ulittle64_t;
43cf099d11SDimitry Andric using support::little16_t;
44cf099d11SDimitry Andric 
45411bd29eSDimitry Andric // Returns false if size is greater than the buffer size. And sets ec.
checkSize(MemoryBufferRef M,std::error_code & EC,uint64_t Size)4667c32a98SDimitry Andric static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
475ca98fd9SDimitry Andric   if (M.getBufferSize() < Size) {
485ca98fd9SDimitry Andric     EC = object_error::unexpected_eof;
49411bd29eSDimitry Andric     return false;
50411bd29eSDimitry Andric   }
51411bd29eSDimitry Andric   return true;
52cf099d11SDimitry Andric }
53cf099d11SDimitry Andric 
54f8af5cf6SDimitry Andric // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
55f8af5cf6SDimitry Andric // Returns unexpected_eof if error.
56f8af5cf6SDimitry Andric template <typename T>
getObject(const T * & Obj,MemoryBufferRef M,const void * Ptr,const uint64_t Size=sizeof (T))57cfca06d7SDimitry Andric static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr,
5867c32a98SDimitry Andric                        const uint64_t Size = sizeof(T)) {
59b60736ecSDimitry Andric   uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr);
60cfca06d7SDimitry Andric   if (Error E = Binary::checkOffset(M, Addr, Size))
61cfca06d7SDimitry Andric     return E;
62f8af5cf6SDimitry Andric   Obj = reinterpret_cast<const T *>(Addr);
63cfca06d7SDimitry Andric   return Error::success();
64411bd29eSDimitry Andric }
655ca98fd9SDimitry Andric 
665ca98fd9SDimitry Andric // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
675ca98fd9SDimitry Andric // prefixed slashes.
decodeBase64StringEntry(StringRef Str,uint32_t & Result)685ca98fd9SDimitry Andric static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
695ca98fd9SDimitry Andric   assert(Str.size() <= 6 && "String too long, possible overflow.");
705ca98fd9SDimitry Andric   if (Str.size() > 6)
715ca98fd9SDimitry Andric     return true;
725ca98fd9SDimitry Andric 
735ca98fd9SDimitry Andric   uint64_t Value = 0;
745ca98fd9SDimitry Andric   while (!Str.empty()) {
755ca98fd9SDimitry Andric     unsigned CharVal;
765ca98fd9SDimitry Andric     if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
775ca98fd9SDimitry Andric       CharVal = Str[0] - 'A';
785ca98fd9SDimitry Andric     else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
795ca98fd9SDimitry Andric       CharVal = Str[0] - 'a' + 26;
805ca98fd9SDimitry Andric     else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
815ca98fd9SDimitry Andric       CharVal = Str[0] - '0' + 52;
825ca98fd9SDimitry Andric     else if (Str[0] == '+') // 62
835ca98fd9SDimitry Andric       CharVal = 62;
845ca98fd9SDimitry Andric     else if (Str[0] == '/') // 63
855ca98fd9SDimitry Andric       CharVal = 63;
865ca98fd9SDimitry Andric     else
875ca98fd9SDimitry Andric       return true;
885ca98fd9SDimitry Andric 
895ca98fd9SDimitry Andric     Value = (Value * 64) + CharVal;
905ca98fd9SDimitry Andric     Str = Str.substr(1);
91cf099d11SDimitry Andric   }
92cf099d11SDimitry Andric 
935ca98fd9SDimitry Andric   if (Value > std::numeric_limits<uint32_t>::max())
945ca98fd9SDimitry Andric     return true;
955ca98fd9SDimitry Andric 
965ca98fd9SDimitry Andric   Result = static_cast<uint32_t>(Value);
975ca98fd9SDimitry Andric   return false;
985ca98fd9SDimitry Andric }
995ca98fd9SDimitry Andric 
10067c32a98SDimitry Andric template <typename coff_symbol_type>
toSymb(DataRefImpl Ref) const10167c32a98SDimitry Andric const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
10267c32a98SDimitry Andric   const coff_symbol_type *Addr =
10367c32a98SDimitry Andric       reinterpret_cast<const coff_symbol_type *>(Ref.p);
104cf099d11SDimitry Andric 
105b60736ecSDimitry Andric   assert(!checkOffset(Data, reinterpret_cast<uintptr_t>(Addr), sizeof(*Addr)));
106411bd29eSDimitry Andric #ifndef NDEBUG
107411bd29eSDimitry Andric   // Verify that the symbol points to a valid entry in the symbol table.
108b60736ecSDimitry Andric   uintptr_t Offset =
109b60736ecSDimitry Andric       reinterpret_cast<uintptr_t>(Addr) - reinterpret_cast<uintptr_t>(base());
110411bd29eSDimitry Andric 
11167c32a98SDimitry Andric   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
11267c32a98SDimitry Andric          "Symbol did not point to the beginning of a symbol");
113411bd29eSDimitry Andric #endif
114411bd29eSDimitry Andric 
1155ca98fd9SDimitry Andric   return Addr;
116cf099d11SDimitry Andric }
117cf099d11SDimitry Andric 
toSec(DataRefImpl Ref) const1185ca98fd9SDimitry Andric const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
1195ca98fd9SDimitry Andric   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
120cf099d11SDimitry Andric 
121411bd29eSDimitry Andric #ifndef NDEBUG
122411bd29eSDimitry Andric   // Verify that the section points to a valid entry in the section table.
12367c32a98SDimitry Andric   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
124411bd29eSDimitry Andric     report_fatal_error("Section was outside of section table.");
125cf099d11SDimitry Andric 
126b60736ecSDimitry Andric   uintptr_t Offset = reinterpret_cast<uintptr_t>(Addr) -
127b60736ecSDimitry Andric                      reinterpret_cast<uintptr_t>(SectionTable);
1285ca98fd9SDimitry Andric   assert(Offset % sizeof(coff_section) == 0 &&
129411bd29eSDimitry Andric          "Section did not point to the beginning of a section");
130411bd29eSDimitry Andric #endif
131cf099d11SDimitry Andric 
1325ca98fd9SDimitry Andric   return Addr;
133411bd29eSDimitry Andric }
134cf099d11SDimitry Andric 
moveSymbolNext(DataRefImpl & Ref) const1355ca98fd9SDimitry Andric void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
13667c32a98SDimitry Andric   auto End = reinterpret_cast<uintptr_t>(StringTable);
13767c32a98SDimitry Andric   if (SymbolTable16) {
13867c32a98SDimitry Andric     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1395ca98fd9SDimitry Andric     Symb += 1 + Symb->NumberOfAuxSymbols;
14067c32a98SDimitry Andric     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14167c32a98SDimitry Andric   } else if (SymbolTable32) {
14267c32a98SDimitry Andric     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
14367c32a98SDimitry Andric     Symb += 1 + Symb->NumberOfAuxSymbols;
14467c32a98SDimitry Andric     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14567c32a98SDimitry Andric   } else {
14667c32a98SDimitry Andric     llvm_unreachable("no symbol table pointer!");
14767c32a98SDimitry Andric   }
148cf099d11SDimitry Andric }
149cf099d11SDimitry Andric 
getSymbolName(DataRefImpl Ref) const15001095a5dSDimitry Andric Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
151cfca06d7SDimitry Andric   return getSymbolName(getCOFFSymbol(Ref));
1521a82d4c0SDimitry Andric }
1531a82d4c0SDimitry Andric 
getSymbolValueImpl(DataRefImpl Ref) const154ee8648bdSDimitry Andric uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
155ee8648bdSDimitry Andric   return getCOFFSymbol(Ref).getValue();
156cf099d11SDimitry Andric }
157cf099d11SDimitry Andric 
getSymbolAlignment(DataRefImpl Ref) const158b915e9e0SDimitry Andric uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
159b915e9e0SDimitry Andric   // MSVC/link.exe seems to align symbols to the next-power-of-2
160b915e9e0SDimitry Andric   // up to 32 bytes.
161b915e9e0SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
162b915e9e0SDimitry Andric   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
163b915e9e0SDimitry Andric }
164b915e9e0SDimitry Andric 
getSymbolAddress(DataRefImpl Ref) const16501095a5dSDimitry Andric Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
166cfca06d7SDimitry Andric   uint64_t Result = cantFail(getSymbolValue(Ref));
16767c32a98SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
16867c32a98SDimitry Andric   int32_t SectionNumber = Symb.getSectionNumber();
1691a82d4c0SDimitry Andric 
1701a82d4c0SDimitry Andric   if (Symb.isAnyUndefined() || Symb.isCommon() ||
1711a82d4c0SDimitry Andric       COFF::isReservedSectionNumber(SectionNumber))
172ee8648bdSDimitry Andric     return Result;
1731a82d4c0SDimitry Andric 
174cfca06d7SDimitry Andric   Expected<const coff_section *> Section = getSection(SectionNumber);
175cfca06d7SDimitry Andric   if (!Section)
176cfca06d7SDimitry Andric     return Section.takeError();
177cfca06d7SDimitry Andric   Result += (*Section)->VirtualAddress;
178dd58ef01SDimitry Andric 
179dd58ef01SDimitry Andric   // The section VirtualAddress does not include ImageBase, and we want to
180dd58ef01SDimitry Andric   // return virtual addresses.
181dd58ef01SDimitry Andric   Result += getImageBase();
182dd58ef01SDimitry Andric 
183ee8648bdSDimitry Andric   return Result;
18467c32a98SDimitry Andric }
18567c32a98SDimitry Andric 
getSymbolType(DataRefImpl Ref) const18601095a5dSDimitry Andric Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
18767c32a98SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
18867c32a98SDimitry Andric   int32_t SectionNumber = Symb.getSectionNumber();
18967c32a98SDimitry Andric 
190dd58ef01SDimitry Andric   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
191dd58ef01SDimitry Andric     return SymbolRef::ST_Function;
1921a82d4c0SDimitry Andric   if (Symb.isAnyUndefined())
1931a82d4c0SDimitry Andric     return SymbolRef::ST_Unknown;
1941a82d4c0SDimitry Andric   if (Symb.isCommon())
1951a82d4c0SDimitry Andric     return SymbolRef::ST_Data;
1961a82d4c0SDimitry Andric   if (Symb.isFileRecord())
1971a82d4c0SDimitry Andric     return SymbolRef::ST_File;
1981a82d4c0SDimitry Andric 
1995a5ac124SDimitry Andric   // TODO: perhaps we need a new symbol type ST_Section.
2001a82d4c0SDimitry Andric   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2011a82d4c0SDimitry Andric     return SymbolRef::ST_Debug;
2021a82d4c0SDimitry Andric 
2031a82d4c0SDimitry Andric   if (!COFF::isReservedSectionNumber(SectionNumber))
2041a82d4c0SDimitry Andric     return SymbolRef::ST_Data;
2051a82d4c0SDimitry Andric 
2061a82d4c0SDimitry Andric   return SymbolRef::ST_Other;
20730815c53SDimitry Andric }
20830815c53SDimitry Andric 
getSymbolFlags(DataRefImpl Ref) const209cfca06d7SDimitry Andric Expected<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
21067c32a98SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2115ca98fd9SDimitry Andric   uint32_t Result = SymbolRef::SF_None;
21263faed5bSDimitry Andric 
21367c32a98SDimitry Andric   if (Symb.isExternal() || Symb.isWeakExternal())
21463faed5bSDimitry Andric     Result |= SymbolRef::SF_Global;
21563faed5bSDimitry Andric 
216eb11fae6SDimitry Andric   if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
21763faed5bSDimitry Andric     Result |= SymbolRef::SF_Weak;
218eb11fae6SDimitry Andric     if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
219eb11fae6SDimitry Andric       Result |= SymbolRef::SF_Undefined;
22093c91e39SDimitry Andric   }
22163faed5bSDimitry Andric 
22267c32a98SDimitry Andric   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
22363faed5bSDimitry Andric     Result |= SymbolRef::SF_Absolute;
22463faed5bSDimitry Andric 
22567c32a98SDimitry Andric   if (Symb.isFileRecord())
22667c32a98SDimitry Andric     Result |= SymbolRef::SF_FormatSpecific;
22767c32a98SDimitry Andric 
22867c32a98SDimitry Andric   if (Symb.isSectionDefinition())
22967c32a98SDimitry Andric     Result |= SymbolRef::SF_FormatSpecific;
23067c32a98SDimitry Andric 
23167c32a98SDimitry Andric   if (Symb.isCommon())
23267c32a98SDimitry Andric     Result |= SymbolRef::SF_Common;
23367c32a98SDimitry Andric 
234eb11fae6SDimitry Andric   if (Symb.isUndefined())
23567c32a98SDimitry Andric     Result |= SymbolRef::SF_Undefined;
23667c32a98SDimitry Andric 
2375ca98fd9SDimitry Andric   return Result;
23830815c53SDimitry Andric }
23930815c53SDimitry Andric 
getCommonSymbolSizeImpl(DataRefImpl Ref) const2401a82d4c0SDimitry Andric uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
24167c32a98SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
24285d8b2bbSDimitry Andric   return Symb.getValue();
24367c32a98SDimitry Andric }
244cf099d11SDimitry Andric 
24501095a5dSDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Ref) const246dd58ef01SDimitry Andric COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
24767c32a98SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
248dd58ef01SDimitry Andric   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
249dd58ef01SDimitry Andric     return section_end();
250cfca06d7SDimitry Andric   Expected<const coff_section *> Sec = getSection(Symb.getSectionNumber());
251cfca06d7SDimitry Andric   if (!Sec)
252cfca06d7SDimitry Andric     return Sec.takeError();
253dd58ef01SDimitry Andric   DataRefImpl Ret;
254cfca06d7SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(*Sec);
255dd58ef01SDimitry Andric   return section_iterator(SectionRef(Ret, this));
256cf099d11SDimitry Andric }
257cf099d11SDimitry Andric 
getSymbolSectionID(SymbolRef Sym) const2581a82d4c0SDimitry Andric unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2591a82d4c0SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2601a82d4c0SDimitry Andric   return Symb.getSectionNumber();
2611a82d4c0SDimitry Andric }
2621a82d4c0SDimitry Andric 
moveSectionNext(DataRefImpl & Ref) const2635ca98fd9SDimitry Andric void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2645ca98fd9SDimitry Andric   const coff_section *Sec = toSec(Ref);
2655ca98fd9SDimitry Andric   Sec += 1;
2665ca98fd9SDimitry Andric   Ref.p = reinterpret_cast<uintptr_t>(Sec);
267522600a2SDimitry Andric }
268522600a2SDimitry Andric 
getSectionName(DataRefImpl Ref) const269e6d15924SDimitry Andric Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const {
2705ca98fd9SDimitry Andric   const coff_section *Sec = toSec(Ref);
271e6d15924SDimitry Andric   return getSectionName(Sec);
272cf099d11SDimitry Andric }
273cf099d11SDimitry Andric 
getSectionAddress(DataRefImpl Ref) const27467c32a98SDimitry Andric uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2755ca98fd9SDimitry Andric   const coff_section *Sec = toSec(Ref);
276dd58ef01SDimitry Andric   uint64_t Result = Sec->VirtualAddress;
277dd58ef01SDimitry Andric 
278dd58ef01SDimitry Andric   // The section VirtualAddress does not include ImageBase, and we want to
279dd58ef01SDimitry Andric   // return virtual addresses.
280dd58ef01SDimitry Andric   Result += getImageBase();
281dd58ef01SDimitry Andric   return Result;
282cf099d11SDimitry Andric }
283cf099d11SDimitry Andric 
getSectionIndex(DataRefImpl Sec) const284ab44ce3dSDimitry Andric uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
285ab44ce3dSDimitry Andric   return toSec(Sec) - SectionTable;
286ab44ce3dSDimitry Andric }
287ab44ce3dSDimitry Andric 
getSectionSize(DataRefImpl Ref) const28867c32a98SDimitry Andric uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
28967c32a98SDimitry Andric   return getSectionSize(toSec(Ref));
290cf099d11SDimitry Andric }
291cf099d11SDimitry Andric 
292e6d15924SDimitry Andric Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Ref) const293e6d15924SDimitry Andric COFFObjectFile::getSectionContents(DataRefImpl Ref) const {
2945ca98fd9SDimitry Andric   const coff_section *Sec = toSec(Ref);
29563faed5bSDimitry Andric   ArrayRef<uint8_t> Res;
296e6d15924SDimitry Andric   if (Error E = getSectionContents(Sec, Res))
297ac9a064cSDimitry Andric     return E;
298e6d15924SDimitry Andric   return Res;
299cf099d11SDimitry Andric }
300cf099d11SDimitry Andric 
getSectionAlignment(DataRefImpl Ref) const30167c32a98SDimitry Andric uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3025ca98fd9SDimitry Andric   const coff_section *Sec = toSec(Ref);
30301095a5dSDimitry Andric   return Sec->getAlignment();
30401095a5dSDimitry Andric }
30501095a5dSDimitry Andric 
isSectionCompressed(DataRefImpl Sec) const30601095a5dSDimitry Andric bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
30701095a5dSDimitry Andric   return false;
30830815c53SDimitry Andric }
30930815c53SDimitry Andric 
isSectionText(DataRefImpl Ref) const31067c32a98SDimitry Andric bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3115ca98fd9SDimitry Andric   const coff_section *Sec = toSec(Ref);
31267c32a98SDimitry Andric   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
313cf099d11SDimitry Andric }
314cf099d11SDimitry Andric 
isSectionData(DataRefImpl Ref) const31567c32a98SDimitry Andric bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3165ca98fd9SDimitry Andric   const coff_section *Sec = toSec(Ref);
31767c32a98SDimitry Andric   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
31830815c53SDimitry Andric }
31930815c53SDimitry Andric 
isSectionBSS(DataRefImpl Ref) const32067c32a98SDimitry Andric bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3215ca98fd9SDimitry Andric   const coff_section *Sec = toSec(Ref);
3225a5ac124SDimitry Andric   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3235a5ac124SDimitry Andric                             COFF::IMAGE_SCN_MEM_READ |
3245a5ac124SDimitry Andric                             COFF::IMAGE_SCN_MEM_WRITE;
3255a5ac124SDimitry Andric   return (Sec->Characteristics & BssFlags) == BssFlags;
32630815c53SDimitry Andric }
32730815c53SDimitry Andric 
328cfca06d7SDimitry Andric // The .debug sections are the only debug sections for COFF
329cfca06d7SDimitry Andric // (\see MCObjectFileInfo.cpp).
isDebugSection(DataRefImpl Ref) const330344a3780SDimitry Andric bool COFFObjectFile::isDebugSection(DataRefImpl Ref) const {
331344a3780SDimitry Andric   Expected<StringRef> SectionNameOrErr = getSectionName(Ref);
332344a3780SDimitry Andric   if (!SectionNameOrErr) {
333344a3780SDimitry Andric     // TODO: Report the error message properly.
334344a3780SDimitry Andric     consumeError(SectionNameOrErr.takeError());
335344a3780SDimitry Andric     return false;
336344a3780SDimitry Andric   }
337344a3780SDimitry Andric   StringRef SectionName = SectionNameOrErr.get();
338312c0ed1SDimitry Andric   return SectionName.starts_with(".debug");
339cfca06d7SDimitry Andric }
340cfca06d7SDimitry Andric 
getSectionID(SectionRef Sec) const3411a82d4c0SDimitry Andric unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3421a82d4c0SDimitry Andric   uintptr_t Offset =
343b60736ecSDimitry Andric       Sec.getRawDataRefImpl().p - reinterpret_cast<uintptr_t>(SectionTable);
3441a82d4c0SDimitry Andric   assert((Offset % sizeof(coff_section)) == 0);
3451a82d4c0SDimitry Andric   return (Offset / sizeof(coff_section)) + 1;
3461a82d4c0SDimitry Andric }
3471a82d4c0SDimitry Andric 
isSectionVirtual(DataRefImpl Ref) const34867c32a98SDimitry Andric bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3495ca98fd9SDimitry Andric   const coff_section *Sec = toSec(Ref);
3505a5ac124SDimitry Andric   // In COFF, a virtual section won't have any in-file
3515a5ac124SDimitry Andric   // content, so the file pointer to the content will be zero.
3525a5ac124SDimitry Andric   return Sec->PointerToRawData == 0;
35363faed5bSDimitry Andric }
35463faed5bSDimitry Andric 
getNumberOfRelocations(const coff_section * Sec,MemoryBufferRef M,const uint8_t * base)3555ca98fd9SDimitry Andric static uint32_t getNumberOfRelocations(const coff_section *Sec,
35667c32a98SDimitry Andric                                        MemoryBufferRef M, const uint8_t *base) {
3575ca98fd9SDimitry Andric   // The field for the number of relocations in COFF section table is only
3585ca98fd9SDimitry Andric   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
3595ca98fd9SDimitry Andric   // NumberOfRelocations field, and the actual relocation count is stored in the
3605ca98fd9SDimitry Andric   // VirtualAddress field in the first relocation entry.
3615ca98fd9SDimitry Andric   if (Sec->hasExtendedRelocations()) {
36267c32a98SDimitry Andric     const coff_relocation *FirstReloc;
363cfca06d7SDimitry Andric     if (Error E = getObject(FirstReloc, M,
364cfca06d7SDimitry Andric                             reinterpret_cast<const coff_relocation *>(
365cfca06d7SDimitry Andric                                 base + Sec->PointerToRelocations))) {
366cfca06d7SDimitry Andric       consumeError(std::move(E));
36767c32a98SDimitry Andric       return 0;
368cfca06d7SDimitry Andric     }
36967c32a98SDimitry Andric     // -1 to exclude this first relocation entry.
37067c32a98SDimitry Andric     return FirstReloc->VirtualAddress - 1;
3715ca98fd9SDimitry Andric   }
3725ca98fd9SDimitry Andric   return Sec->NumberOfRelocations;
3735ca98fd9SDimitry Andric }
37430815c53SDimitry Andric 
37567c32a98SDimitry Andric static const coff_relocation *
getFirstReloc(const coff_section * Sec,MemoryBufferRef M,const uint8_t * Base)37667c32a98SDimitry Andric getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
37767c32a98SDimitry Andric   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
37867c32a98SDimitry Andric   if (!NumRelocs)
37967c32a98SDimitry Andric     return nullptr;
38067c32a98SDimitry Andric   auto begin = reinterpret_cast<const coff_relocation *>(
38167c32a98SDimitry Andric       Base + Sec->PointerToRelocations);
38267c32a98SDimitry Andric   if (Sec->hasExtendedRelocations()) {
38367c32a98SDimitry Andric     // Skip the first relocation entry repurposed to store the number of
38467c32a98SDimitry Andric     // relocations.
38567c32a98SDimitry Andric     begin++;
38667c32a98SDimitry Andric   }
387b60736ecSDimitry Andric   if (auto E = Binary::checkOffset(M, reinterpret_cast<uintptr_t>(begin),
388cfca06d7SDimitry Andric                                    sizeof(coff_relocation) * NumRelocs)) {
389cfca06d7SDimitry Andric     consumeError(std::move(E));
39067c32a98SDimitry Andric     return nullptr;
391cfca06d7SDimitry Andric   }
39267c32a98SDimitry Andric   return begin;
39367c32a98SDimitry Andric }
39467c32a98SDimitry Andric 
section_rel_begin(DataRefImpl Ref) const39567c32a98SDimitry Andric relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
39667c32a98SDimitry Andric   const coff_section *Sec = toSec(Ref);
39767c32a98SDimitry Andric   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
398ee8648bdSDimitry Andric   if (begin && Sec->VirtualAddress != 0)
399ee8648bdSDimitry Andric     report_fatal_error("Sections with relocations should have an address of 0");
40067c32a98SDimitry Andric   DataRefImpl Ret;
40167c32a98SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(begin);
40267c32a98SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
40367c32a98SDimitry Andric }
40467c32a98SDimitry Andric 
section_rel_end(DataRefImpl Ref) const4055ca98fd9SDimitry Andric relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
4065ca98fd9SDimitry Andric   const coff_section *Sec = toSec(Ref);
40767c32a98SDimitry Andric   const coff_relocation *I = getFirstReloc(Sec, Data, base());
40867c32a98SDimitry Andric   if (I)
40967c32a98SDimitry Andric     I += getNumberOfRelocations(Sec, Data, base());
4105ca98fd9SDimitry Andric   DataRefImpl Ret;
41167c32a98SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(I);
4125ca98fd9SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
41330815c53SDimitry Andric }
41430815c53SDimitry Andric 
415f8af5cf6SDimitry Andric // Initialize the pointer to the symbol table.
initSymbolTablePtr()416cfca06d7SDimitry Andric Error COFFObjectFile::initSymbolTablePtr() {
41767c32a98SDimitry Andric   if (COFFHeader)
418cfca06d7SDimitry Andric     if (Error E = getObject(
41967c32a98SDimitry Andric             SymbolTable16, Data, base() + getPointerToSymbolTable(),
42067c32a98SDimitry Andric             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
421cfca06d7SDimitry Andric       return E;
42267c32a98SDimitry Andric 
42367c32a98SDimitry Andric   if (COFFBigObjHeader)
424cfca06d7SDimitry Andric     if (Error E = getObject(
42567c32a98SDimitry Andric             SymbolTable32, Data, base() + getPointerToSymbolTable(),
42667c32a98SDimitry Andric             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
427cfca06d7SDimitry Andric       return E;
428f8af5cf6SDimitry Andric 
429f8af5cf6SDimitry Andric   // Find string table. The first four byte of the string table contains the
430f8af5cf6SDimitry Andric   // total size of the string table, including the size field itself. If the
431f8af5cf6SDimitry Andric   // string table is empty, the value of the first four byte would be 4.
43267c32a98SDimitry Andric   uint32_t StringTableOffset = getPointerToSymbolTable() +
43367c32a98SDimitry Andric                                getNumberOfSymbols() * getSymbolTableEntrySize();
43467c32a98SDimitry Andric   const uint8_t *StringTableAddr = base() + StringTableOffset;
435f8af5cf6SDimitry Andric   const ulittle32_t *StringTableSizePtr;
436cfca06d7SDimitry Andric   if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr))
437cfca06d7SDimitry Andric     return E;
438f8af5cf6SDimitry Andric   StringTableSize = *StringTableSizePtr;
439cfca06d7SDimitry Andric   if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize))
440cfca06d7SDimitry Andric     return E;
4415ca98fd9SDimitry Andric 
4425ca98fd9SDimitry Andric   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
4435ca98fd9SDimitry Andric   // tools like cvtres write a size of 0 for an empty table instead of 4.
4445ca98fd9SDimitry Andric   if (StringTableSize < 4)
4455ca98fd9SDimitry Andric     StringTableSize = 4;
446f8af5cf6SDimitry Andric 
447f8af5cf6SDimitry Andric   // Check that the string table is null terminated if has any in it.
4485ca98fd9SDimitry Andric   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
449145449b1SDimitry Andric     return createStringError(object_error::parse_failed,
450145449b1SDimitry Andric                              "string table missing null terminator");
451cfca06d7SDimitry Andric   return Error::success();
452f8af5cf6SDimitry Andric }
453f8af5cf6SDimitry Andric 
getImageBase() const454dd58ef01SDimitry Andric uint64_t COFFObjectFile::getImageBase() const {
455dd58ef01SDimitry Andric   if (PE32Header)
456dd58ef01SDimitry Andric     return PE32Header->ImageBase;
457dd58ef01SDimitry Andric   else if (PE32PlusHeader)
458dd58ef01SDimitry Andric     return PE32PlusHeader->ImageBase;
459dd58ef01SDimitry Andric   // This actually comes up in practice.
460dd58ef01SDimitry Andric   return 0;
461dd58ef01SDimitry Andric }
462dd58ef01SDimitry Andric 
4635ca98fd9SDimitry Andric // Returns the file offset for the given VA.
getVaPtr(uint64_t Addr,uintptr_t & Res) const464cfca06d7SDimitry Andric Error COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
465dd58ef01SDimitry Andric   uint64_t ImageBase = getImageBase();
4665ca98fd9SDimitry Andric   uint64_t Rva = Addr - ImageBase;
4675ca98fd9SDimitry Andric   assert(Rva <= UINT32_MAX);
4685ca98fd9SDimitry Andric   return getRvaPtr((uint32_t)Rva, Res);
4695ca98fd9SDimitry Andric }
4705ca98fd9SDimitry Andric 
471f8af5cf6SDimitry Andric // Returns the file offset for the given RVA.
getRvaPtr(uint32_t Addr,uintptr_t & Res,const char * ErrorContext) const472145449b1SDimitry Andric Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res,
473145449b1SDimitry Andric                                 const char *ErrorContext) const {
4745ca98fd9SDimitry Andric   for (const SectionRef &S : sections()) {
4755ca98fd9SDimitry Andric     const coff_section *Section = getCOFFSection(S);
476f8af5cf6SDimitry Andric     uint32_t SectionStart = Section->VirtualAddress;
477f8af5cf6SDimitry Andric     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
4785ca98fd9SDimitry Andric     if (SectionStart <= Addr && Addr < SectionEnd) {
479145449b1SDimitry Andric       // A table/directory entry can be pointing to somewhere in a stripped
480145449b1SDimitry Andric       // section, in an object that went through `objcopy --only-keep-debug`.
481145449b1SDimitry Andric       // In this case we don't want to cause the parsing of the object file to
482145449b1SDimitry Andric       // fail, otherwise it will be impossible to use this object as debug info
483145449b1SDimitry Andric       // in LLDB. Return SectionStrippedError here so that
484145449b1SDimitry Andric       // COFFObjectFile::initialize can ignore the error.
485145449b1SDimitry Andric       // Somewhat common binaries may have RVAs pointing outside of the
486145449b1SDimitry Andric       // provided raw data. Instead of rejecting the binaries, just
487145449b1SDimitry Andric       // treat the section as stripped for these purposes.
488145449b1SDimitry Andric       if (Section->SizeOfRawData < Section->VirtualSize &&
489145449b1SDimitry Andric           Addr >= SectionStart + Section->SizeOfRawData) {
490145449b1SDimitry Andric         return make_error<SectionStrippedError>();
491145449b1SDimitry Andric       }
4925ca98fd9SDimitry Andric       uint32_t Offset = Addr - SectionStart;
493b60736ecSDimitry Andric       Res = reinterpret_cast<uintptr_t>(base()) + Section->PointerToRawData +
494b60736ecSDimitry Andric             Offset;
495cfca06d7SDimitry Andric       return Error::success();
496f8af5cf6SDimitry Andric     }
497f8af5cf6SDimitry Andric   }
498145449b1SDimitry Andric   if (ErrorContext)
499145449b1SDimitry Andric     return createStringError(object_error::parse_failed,
500145449b1SDimitry Andric                              "RVA 0x%" PRIx32 " for %s not found", Addr,
501145449b1SDimitry Andric                              ErrorContext);
502145449b1SDimitry Andric   return createStringError(object_error::parse_failed,
503145449b1SDimitry Andric                            "RVA 0x%" PRIx32 " not found", Addr);
504f8af5cf6SDimitry Andric }
505f8af5cf6SDimitry Andric 
getRvaAndSizeAsBytes(uint32_t RVA,uint32_t Size,ArrayRef<uint8_t> & Contents,const char * ErrorContext) const506cfca06d7SDimitry Andric Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
507145449b1SDimitry Andric                                            ArrayRef<uint8_t> &Contents,
508145449b1SDimitry Andric                                            const char *ErrorContext) const {
50901095a5dSDimitry Andric   for (const SectionRef &S : sections()) {
51001095a5dSDimitry Andric     const coff_section *Section = getCOFFSection(S);
51101095a5dSDimitry Andric     uint32_t SectionStart = Section->VirtualAddress;
51201095a5dSDimitry Andric     // Check if this RVA is within the section bounds. Be careful about integer
51301095a5dSDimitry Andric     // overflow.
51401095a5dSDimitry Andric     uint32_t OffsetIntoSection = RVA - SectionStart;
51501095a5dSDimitry Andric     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
51601095a5dSDimitry Andric         Size <= Section->VirtualSize - OffsetIntoSection) {
517b60736ecSDimitry Andric       uintptr_t Begin = reinterpret_cast<uintptr_t>(base()) +
518b60736ecSDimitry Andric                         Section->PointerToRawData + OffsetIntoSection;
51901095a5dSDimitry Andric       Contents =
52001095a5dSDimitry Andric           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
521cfca06d7SDimitry Andric       return Error::success();
52201095a5dSDimitry Andric     }
52301095a5dSDimitry Andric   }
524145449b1SDimitry Andric   if (ErrorContext)
525145449b1SDimitry Andric     return createStringError(object_error::parse_failed,
526145449b1SDimitry Andric                              "RVA 0x%" PRIx32 " for %s not found", RVA,
527145449b1SDimitry Andric                              ErrorContext);
528145449b1SDimitry Andric   return createStringError(object_error::parse_failed,
529145449b1SDimitry Andric                            "RVA 0x%" PRIx32 " not found", RVA);
53001095a5dSDimitry Andric }
53101095a5dSDimitry Andric 
532f8af5cf6SDimitry Andric // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
533f8af5cf6SDimitry Andric // table entry.
getHintName(uint32_t Rva,uint16_t & Hint,StringRef & Name) const534cfca06d7SDimitry Andric Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
5355ca98fd9SDimitry Andric                                   StringRef &Name) const {
536f8af5cf6SDimitry Andric   uintptr_t IntPtr = 0;
537cfca06d7SDimitry Andric   if (Error E = getRvaPtr(Rva, IntPtr))
538cfca06d7SDimitry Andric     return E;
539f8af5cf6SDimitry Andric   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
540f8af5cf6SDimitry Andric   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
541f8af5cf6SDimitry Andric   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
542cfca06d7SDimitry Andric   return Error::success();
543f8af5cf6SDimitry Andric }
544f8af5cf6SDimitry Andric 
getDebugPDBInfo(const debug_directory * DebugDir,const codeview::DebugInfo * & PDBInfo,StringRef & PDBFileName) const545cfca06d7SDimitry Andric Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
546b915e9e0SDimitry Andric                                       const codeview::DebugInfo *&PDBInfo,
54701095a5dSDimitry Andric                                       StringRef &PDBFileName) const {
54801095a5dSDimitry Andric   ArrayRef<uint8_t> InfoBytes;
549145449b1SDimitry Andric   if (Error E =
550145449b1SDimitry Andric           getRvaAndSizeAsBytes(DebugDir->AddressOfRawData, DebugDir->SizeOfData,
551145449b1SDimitry Andric                                InfoBytes, "PDB info"))
552cfca06d7SDimitry Andric     return E;
553b915e9e0SDimitry Andric   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
554145449b1SDimitry Andric     return createStringError(object_error::parse_failed, "PDB info too small");
555b915e9e0SDimitry Andric   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
556b915e9e0SDimitry Andric   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
55701095a5dSDimitry Andric   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
55801095a5dSDimitry Andric                           InfoBytes.size());
55901095a5dSDimitry Andric   // Truncate the name at the first null byte. Ignore any padding.
56001095a5dSDimitry Andric   PDBFileName = PDBFileName.split('\0').first;
561cfca06d7SDimitry Andric   return Error::success();
56201095a5dSDimitry Andric }
56301095a5dSDimitry Andric 
getDebugPDBInfo(const codeview::DebugInfo * & PDBInfo,StringRef & PDBFileName) const564cfca06d7SDimitry Andric Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
56501095a5dSDimitry Andric                                       StringRef &PDBFileName) const {
56601095a5dSDimitry Andric   for (const debug_directory &D : debug_directories())
56701095a5dSDimitry Andric     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
56801095a5dSDimitry Andric       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
56901095a5dSDimitry Andric   // If we get here, there is no PDB info to return.
57001095a5dSDimitry Andric   PDBInfo = nullptr;
57101095a5dSDimitry Andric   PDBFileName = StringRef();
572cfca06d7SDimitry Andric   return Error::success();
57301095a5dSDimitry Andric }
57401095a5dSDimitry Andric 
575f8af5cf6SDimitry Andric // Find the import table.
initImportTablePtr()576cfca06d7SDimitry Andric Error COFFObjectFile::initImportTablePtr() {
577f8af5cf6SDimitry Andric   // First, we get the RVA of the import table. If the file lacks a pointer to
578f8af5cf6SDimitry Andric   // the import table, do nothing.
579cfca06d7SDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE);
580cfca06d7SDimitry Andric   if (!DataEntry)
581cfca06d7SDimitry Andric     return Error::success();
582f8af5cf6SDimitry Andric 
583f8af5cf6SDimitry Andric   // Do nothing if the pointer to import table is NULL.
584f8af5cf6SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
585cfca06d7SDimitry Andric     return Error::success();
586f8af5cf6SDimitry Andric 
587f8af5cf6SDimitry Andric   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
588f8af5cf6SDimitry Andric 
589f8af5cf6SDimitry Andric   // Find the section that contains the RVA. This is needed because the RVA is
590f8af5cf6SDimitry Andric   // the import table's memory address which is different from its file offset.
591f8af5cf6SDimitry Andric   uintptr_t IntPtr = 0;
592145449b1SDimitry Andric   if (Error E = getRvaPtr(ImportTableRva, IntPtr, "import table"))
593cfca06d7SDimitry Andric     return E;
594cfca06d7SDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
595cfca06d7SDimitry Andric     return E;
596f8af5cf6SDimitry Andric   ImportDirectory = reinterpret_cast<
597b915e9e0SDimitry Andric       const coff_import_directory_table_entry *>(IntPtr);
598cfca06d7SDimitry Andric   return Error::success();
599f8af5cf6SDimitry Andric }
600f8af5cf6SDimitry Andric 
60167c32a98SDimitry Andric // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
initDelayImportTablePtr()602cfca06d7SDimitry Andric Error COFFObjectFile::initDelayImportTablePtr() {
603cfca06d7SDimitry Andric   const data_directory *DataEntry =
604cfca06d7SDimitry Andric       getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR);
605cfca06d7SDimitry Andric   if (!DataEntry)
606cfca06d7SDimitry Andric     return Error::success();
60767c32a98SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
608cfca06d7SDimitry Andric     return Error::success();
60967c32a98SDimitry Andric 
61067c32a98SDimitry Andric   uint32_t RVA = DataEntry->RelativeVirtualAddress;
61167c32a98SDimitry Andric   NumberOfDelayImportDirectory = DataEntry->Size /
61267c32a98SDimitry Andric       sizeof(delay_import_directory_table_entry) - 1;
61367c32a98SDimitry Andric 
61467c32a98SDimitry Andric   uintptr_t IntPtr = 0;
615145449b1SDimitry Andric   if (Error E = getRvaPtr(RVA, IntPtr, "delay import table"))
616cfca06d7SDimitry Andric     return E;
617145449b1SDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
618145449b1SDimitry Andric     return E;
619145449b1SDimitry Andric 
62067c32a98SDimitry Andric   DelayImportDirectory = reinterpret_cast<
62167c32a98SDimitry Andric       const delay_import_directory_table_entry *>(IntPtr);
622cfca06d7SDimitry Andric   return Error::success();
62367c32a98SDimitry Andric }
62467c32a98SDimitry Andric 
6255ca98fd9SDimitry Andric // Find the export table.
initExportTablePtr()626cfca06d7SDimitry Andric Error COFFObjectFile::initExportTablePtr() {
6275ca98fd9SDimitry Andric   // First, we get the RVA of the export table. If the file lacks a pointer to
6285ca98fd9SDimitry Andric   // the export table, do nothing.
629cfca06d7SDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE);
630cfca06d7SDimitry Andric   if (!DataEntry)
631cfca06d7SDimitry Andric     return Error::success();
6325ca98fd9SDimitry Andric 
6335ca98fd9SDimitry Andric   // Do nothing if the pointer to export table is NULL.
6345ca98fd9SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
635cfca06d7SDimitry Andric     return Error::success();
6365ca98fd9SDimitry Andric 
6375ca98fd9SDimitry Andric   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
6385ca98fd9SDimitry Andric   uintptr_t IntPtr = 0;
639145449b1SDimitry Andric   if (Error E = getRvaPtr(ExportTableRva, IntPtr, "export table"))
640cfca06d7SDimitry Andric     return E;
641145449b1SDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
642145449b1SDimitry Andric     return E;
643145449b1SDimitry Andric 
6445ca98fd9SDimitry Andric   ExportDirectory =
6455ca98fd9SDimitry Andric       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
646cfca06d7SDimitry Andric   return Error::success();
6475ca98fd9SDimitry Andric }
6485ca98fd9SDimitry Andric 
initBaseRelocPtr()649cfca06d7SDimitry Andric Error COFFObjectFile::initBaseRelocPtr() {
650cfca06d7SDimitry Andric   const data_directory *DataEntry =
651cfca06d7SDimitry Andric       getDataDirectory(COFF::BASE_RELOCATION_TABLE);
652cfca06d7SDimitry Andric   if (!DataEntry)
653cfca06d7SDimitry Andric     return Error::success();
65467c32a98SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
655cfca06d7SDimitry Andric     return Error::success();
65667c32a98SDimitry Andric 
65767c32a98SDimitry Andric   uintptr_t IntPtr = 0;
658145449b1SDimitry Andric   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
659145449b1SDimitry Andric                           "base reloc table"))
660cfca06d7SDimitry Andric     return E;
661145449b1SDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
662145449b1SDimitry Andric     return E;
663145449b1SDimitry Andric 
66467c32a98SDimitry Andric   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
66567c32a98SDimitry Andric       IntPtr);
66667c32a98SDimitry Andric   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
66767c32a98SDimitry Andric       IntPtr + DataEntry->Size);
668d8e91e46SDimitry Andric   // FIXME: Verify the section containing BaseRelocHeader has at least
669d8e91e46SDimitry Andric   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
670cfca06d7SDimitry Andric   return Error::success();
67167c32a98SDimitry Andric }
67267c32a98SDimitry Andric 
initDebugDirectoryPtr()673cfca06d7SDimitry Andric Error COFFObjectFile::initDebugDirectoryPtr() {
67401095a5dSDimitry Andric   // Get the RVA of the debug directory. Do nothing if it does not exist.
675cfca06d7SDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY);
676cfca06d7SDimitry Andric   if (!DataEntry)
677cfca06d7SDimitry Andric     return Error::success();
67801095a5dSDimitry Andric 
67901095a5dSDimitry Andric   // Do nothing if the RVA is NULL.
68001095a5dSDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
681cfca06d7SDimitry Andric     return Error::success();
68201095a5dSDimitry Andric 
68301095a5dSDimitry Andric   // Check that the size is a multiple of the entry size.
68401095a5dSDimitry Andric   if (DataEntry->Size % sizeof(debug_directory) != 0)
685145449b1SDimitry Andric     return createStringError(object_error::parse_failed,
686145449b1SDimitry Andric                              "debug directory has uneven size");
68701095a5dSDimitry Andric 
68801095a5dSDimitry Andric   uintptr_t IntPtr = 0;
689145449b1SDimitry Andric   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
690145449b1SDimitry Andric                           "debug directory"))
691cfca06d7SDimitry Andric     return E;
692145449b1SDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
693145449b1SDimitry Andric     return E;
694145449b1SDimitry Andric 
69501095a5dSDimitry Andric   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
696d8e91e46SDimitry Andric   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
697d8e91e46SDimitry Andric       IntPtr + DataEntry->Size);
698d8e91e46SDimitry Andric   // FIXME: Verify the section containing DebugDirectoryBegin has at least
699d8e91e46SDimitry Andric   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
700cfca06d7SDimitry Andric   return Error::success();
70101095a5dSDimitry Andric }
70201095a5dSDimitry Andric 
initTLSDirectoryPtr()703b60736ecSDimitry Andric Error COFFObjectFile::initTLSDirectoryPtr() {
704b60736ecSDimitry Andric   // Get the RVA of the TLS directory. Do nothing if it does not exist.
705b60736ecSDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE);
706b60736ecSDimitry Andric   if (!DataEntry)
707b60736ecSDimitry Andric     return Error::success();
708b60736ecSDimitry Andric 
709b60736ecSDimitry Andric   // Do nothing if the RVA is NULL.
710b60736ecSDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
711b60736ecSDimitry Andric     return Error::success();
712b60736ecSDimitry Andric 
713b60736ecSDimitry Andric   uint64_t DirSize =
714b60736ecSDimitry Andric       is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32);
715b60736ecSDimitry Andric 
716b60736ecSDimitry Andric   // Check that the size is correct.
717b60736ecSDimitry Andric   if (DataEntry->Size != DirSize)
718b60736ecSDimitry Andric     return createStringError(
719b60736ecSDimitry Andric         object_error::parse_failed,
720b60736ecSDimitry Andric         "TLS Directory size (%u) is not the expected size (%" PRIu64 ").",
721b60736ecSDimitry Andric         static_cast<uint32_t>(DataEntry->Size), DirSize);
722b60736ecSDimitry Andric 
723b60736ecSDimitry Andric   uintptr_t IntPtr = 0;
724145449b1SDimitry Andric   if (Error E =
725145449b1SDimitry Andric           getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr, "TLS directory"))
726145449b1SDimitry Andric     return E;
727145449b1SDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
728b60736ecSDimitry Andric     return E;
729b60736ecSDimitry Andric 
730b60736ecSDimitry Andric   if (is64())
731b60736ecSDimitry Andric     TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);
732b60736ecSDimitry Andric   else
733b60736ecSDimitry Andric     TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr);
734b60736ecSDimitry Andric 
735b60736ecSDimitry Andric   return Error::success();
736b60736ecSDimitry Andric }
737b60736ecSDimitry Andric 
initLoadConfigPtr()738cfca06d7SDimitry Andric Error COFFObjectFile::initLoadConfigPtr() {
73908bbd35aSDimitry Andric   // Get the RVA of the debug directory. Do nothing if it does not exist.
740cfca06d7SDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE);
741cfca06d7SDimitry Andric   if (!DataEntry)
742cfca06d7SDimitry Andric     return Error::success();
74308bbd35aSDimitry Andric 
74408bbd35aSDimitry Andric   // Do nothing if the RVA is NULL.
74508bbd35aSDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
746cfca06d7SDimitry Andric     return Error::success();
74708bbd35aSDimitry Andric   uintptr_t IntPtr = 0;
748145449b1SDimitry Andric   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
749145449b1SDimitry Andric                           "load config table"))
750145449b1SDimitry Andric     return E;
751145449b1SDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
752cfca06d7SDimitry Andric     return E;
75308bbd35aSDimitry Andric 
75408bbd35aSDimitry Andric   LoadConfig = (const void *)IntPtr;
7557fa27ce4SDimitry Andric 
7567fa27ce4SDimitry Andric   if (is64()) {
7577fa27ce4SDimitry Andric     auto Config = getLoadConfig64();
7587fa27ce4SDimitry Andric     if (Config->Size >=
7597fa27ce4SDimitry Andric             offsetof(coff_load_configuration64, CHPEMetadataPointer) +
7607fa27ce4SDimitry Andric                 sizeof(Config->CHPEMetadataPointer) &&
7617fa27ce4SDimitry Andric         Config->CHPEMetadataPointer) {
7627fa27ce4SDimitry Andric       uint64_t ChpeOff = Config->CHPEMetadataPointer;
7637fa27ce4SDimitry Andric       if (Error E =
7647fa27ce4SDimitry Andric               getRvaPtr(ChpeOff - getImageBase(), IntPtr, "CHPE metadata"))
7657fa27ce4SDimitry Andric         return E;
7667fa27ce4SDimitry Andric       if (Error E = checkOffset(Data, IntPtr, sizeof(CHPEMetadata)))
7677fa27ce4SDimitry Andric         return E;
7687fa27ce4SDimitry Andric 
7697fa27ce4SDimitry Andric       CHPEMetadata = reinterpret_cast<const chpe_metadata *>(IntPtr);
7707fa27ce4SDimitry Andric 
7717fa27ce4SDimitry Andric       // Validate CHPE metadata
7727fa27ce4SDimitry Andric       if (CHPEMetadata->CodeMapCount) {
7737fa27ce4SDimitry Andric         if (Error E = getRvaPtr(CHPEMetadata->CodeMap, IntPtr, "CHPE code map"))
7747fa27ce4SDimitry Andric           return E;
7757fa27ce4SDimitry Andric         if (Error E = checkOffset(Data, IntPtr,
7767fa27ce4SDimitry Andric                                   CHPEMetadata->CodeMapCount *
7777fa27ce4SDimitry Andric                                       sizeof(chpe_range_entry)))
7787fa27ce4SDimitry Andric           return E;
7797fa27ce4SDimitry Andric       }
7807fa27ce4SDimitry Andric 
7817fa27ce4SDimitry Andric       if (CHPEMetadata->CodeRangesToEntryPointsCount) {
7827fa27ce4SDimitry Andric         if (Error E = getRvaPtr(CHPEMetadata->CodeRangesToEntryPoints, IntPtr,
7837fa27ce4SDimitry Andric                                 "CHPE entry point ranges"))
7847fa27ce4SDimitry Andric           return E;
7857fa27ce4SDimitry Andric         if (Error E = checkOffset(Data, IntPtr,
7867fa27ce4SDimitry Andric                                   CHPEMetadata->CodeRangesToEntryPointsCount *
7877fa27ce4SDimitry Andric                                       sizeof(chpe_code_range_entry)))
7887fa27ce4SDimitry Andric           return E;
7897fa27ce4SDimitry Andric       }
7907fa27ce4SDimitry Andric 
7917fa27ce4SDimitry Andric       if (CHPEMetadata->RedirectionMetadataCount) {
7927fa27ce4SDimitry Andric         if (Error E = getRvaPtr(CHPEMetadata->RedirectionMetadata, IntPtr,
7937fa27ce4SDimitry Andric                                 "CHPE redirection metadata"))
7947fa27ce4SDimitry Andric           return E;
7957fa27ce4SDimitry Andric         if (Error E = checkOffset(Data, IntPtr,
7967fa27ce4SDimitry Andric                                   CHPEMetadata->RedirectionMetadataCount *
7977fa27ce4SDimitry Andric                                       sizeof(chpe_redirection_entry)))
7987fa27ce4SDimitry Andric           return E;
7997fa27ce4SDimitry Andric       }
8007fa27ce4SDimitry Andric     }
8017fa27ce4SDimitry Andric   }
8027fa27ce4SDimitry Andric 
803cfca06d7SDimitry Andric   return Error::success();
80408bbd35aSDimitry Andric }
80508bbd35aSDimitry Andric 
806cfca06d7SDimitry Andric Expected<std::unique_ptr<COFFObjectFile>>
create(MemoryBufferRef Object)807cfca06d7SDimitry Andric COFFObjectFile::create(MemoryBufferRef Object) {
808cfca06d7SDimitry Andric   std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object)));
809cfca06d7SDimitry Andric   if (Error E = Obj->initialize())
810ac9a064cSDimitry Andric     return E;
811cfca06d7SDimitry Andric   return std::move(Obj);
812cfca06d7SDimitry Andric }
813cfca06d7SDimitry Andric 
COFFObjectFile(MemoryBufferRef Object)814cfca06d7SDimitry Andric COFFObjectFile::COFFObjectFile(MemoryBufferRef Object)
81567c32a98SDimitry Andric     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
81667c32a98SDimitry Andric       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
81767c32a98SDimitry Andric       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
81867c32a98SDimitry Andric       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
819cfca06d7SDimitry Andric       ImportDirectory(nullptr), DelayImportDirectory(nullptr),
820cfca06d7SDimitry Andric       NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
821cfca06d7SDimitry Andric       BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
822b60736ecSDimitry Andric       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
823b60736ecSDimitry Andric       TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
824cfca06d7SDimitry Andric 
ignoreStrippedErrors(Error E)825145449b1SDimitry Andric static Error ignoreStrippedErrors(Error E) {
826145449b1SDimitry Andric   if (E.isA<SectionStrippedError>()) {
827145449b1SDimitry Andric     consumeError(std::move(E));
828145449b1SDimitry Andric     return Error::success();
829145449b1SDimitry Andric   }
830145449b1SDimitry Andric   return E;
831145449b1SDimitry Andric }
832145449b1SDimitry Andric 
initialize()833cfca06d7SDimitry Andric Error COFFObjectFile::initialize() {
834411bd29eSDimitry Andric   // Check that we at least have enough room for a header.
835cfca06d7SDimitry Andric   std::error_code EC;
83667c32a98SDimitry Andric   if (!checkSize(Data, EC, sizeof(coff_file_header)))
837cfca06d7SDimitry Andric     return errorCodeToError(EC);
8386b943ff3SDimitry Andric 
839f8af5cf6SDimitry Andric   // The current location in the file where we are looking at.
840f8af5cf6SDimitry Andric   uint64_t CurPtr = 0;
841f8af5cf6SDimitry Andric 
842f8af5cf6SDimitry Andric   // PE header is optional and is present only in executables. If it exists,
843f8af5cf6SDimitry Andric   // it is placed right after COFF header.
8445ca98fd9SDimitry Andric   bool HasPEHeader = false;
845411bd29eSDimitry Andric 
846411bd29eSDimitry Andric   // Check if this is a PE/COFF file.
84767c32a98SDimitry Andric   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
8486b943ff3SDimitry Andric     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
8496b943ff3SDimitry Andric     // PE signature to find 'normal' COFF header.
85067c32a98SDimitry Andric     const auto *DH = reinterpret_cast<const dos_header *>(base());
85167c32a98SDimitry Andric     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
85267c32a98SDimitry Andric       CurPtr = DH->AddressOfNewExeHeader;
853f8af5cf6SDimitry Andric       // Check the PE magic bytes. ("PE\0\0")
85467c32a98SDimitry Andric       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
855145449b1SDimitry Andric         return createStringError(object_error::parse_failed,
856145449b1SDimitry Andric                                  "incorrect PE magic");
857411bd29eSDimitry Andric       }
85867c32a98SDimitry Andric       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
8595ca98fd9SDimitry Andric       HasPEHeader = true;
8606b943ff3SDimitry Andric     }
86167c32a98SDimitry Andric   }
8626b943ff3SDimitry Andric 
863cfca06d7SDimitry Andric   if (Error E = getObject(COFFHeader, Data, base() + CurPtr))
864cfca06d7SDimitry Andric     return E;
86567c32a98SDimitry Andric 
86667c32a98SDimitry Andric   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
86767c32a98SDimitry Andric   // import libraries share a common prefix but bigobj is more restrictive.
86867c32a98SDimitry Andric   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
86967c32a98SDimitry Andric       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
87067c32a98SDimitry Andric       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
871cfca06d7SDimitry Andric     if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr))
872cfca06d7SDimitry Andric       return E;
87367c32a98SDimitry Andric 
87467c32a98SDimitry Andric     // Verify that we are dealing with bigobj.
87567c32a98SDimitry Andric     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
87667c32a98SDimitry Andric         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
87767c32a98SDimitry Andric                     sizeof(COFF::BigObjMagic)) == 0) {
87867c32a98SDimitry Andric       COFFHeader = nullptr;
87967c32a98SDimitry Andric       CurPtr += sizeof(coff_bigobj_file_header);
88067c32a98SDimitry Andric     } else {
88167c32a98SDimitry Andric       // It's not a bigobj.
88267c32a98SDimitry Andric       COFFBigObjHeader = nullptr;
88367c32a98SDimitry Andric     }
88467c32a98SDimitry Andric   }
88567c32a98SDimitry Andric   if (COFFHeader) {
88667c32a98SDimitry Andric     // The prior checkSize call may have failed.  This isn't a hard error
88767c32a98SDimitry Andric     // because we were just trying to sniff out bigobj.
88885d8b2bbSDimitry Andric     EC = std::error_code();
889f8af5cf6SDimitry Andric     CurPtr += sizeof(coff_file_header);
890411bd29eSDimitry Andric 
89167c32a98SDimitry Andric     if (COFFHeader->isImportLibrary())
892cfca06d7SDimitry Andric       return errorCodeToError(EC);
89367c32a98SDimitry Andric   }
89467c32a98SDimitry Andric 
8955ca98fd9SDimitry Andric   if (HasPEHeader) {
8965ca98fd9SDimitry Andric     const pe32_header *Header;
897cfca06d7SDimitry Andric     if (Error E = getObject(Header, Data, base() + CurPtr))
898cfca06d7SDimitry Andric       return E;
8995ca98fd9SDimitry Andric 
9005ca98fd9SDimitry Andric     const uint8_t *DataDirAddr;
9015ca98fd9SDimitry Andric     uint64_t DataDirSize;
90267c32a98SDimitry Andric     if (Header->Magic == COFF::PE32Header::PE32) {
9035ca98fd9SDimitry Andric       PE32Header = Header;
9045ca98fd9SDimitry Andric       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
9055ca98fd9SDimitry Andric       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
90667c32a98SDimitry Andric     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
9075ca98fd9SDimitry Andric       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
9085ca98fd9SDimitry Andric       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
9095ca98fd9SDimitry Andric       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
9105ca98fd9SDimitry Andric     } else {
9115ca98fd9SDimitry Andric       // It's neither PE32 nor PE32+.
912145449b1SDimitry Andric       return createStringError(object_error::parse_failed,
913145449b1SDimitry Andric                                "incorrect PE magic");
914411bd29eSDimitry Andric     }
915cfca06d7SDimitry Andric     if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))
916cfca06d7SDimitry Andric       return E;
91763faed5bSDimitry Andric   }
918411bd29eSDimitry Andric 
919b915e9e0SDimitry Andric   if (COFFHeader)
920b915e9e0SDimitry Andric     CurPtr += COFFHeader->SizeOfOptionalHeader;
921b915e9e0SDimitry Andric 
922cfca06d7SDimitry Andric   assert(COFFHeader || COFFBigObjHeader);
923cfca06d7SDimitry Andric 
924cfca06d7SDimitry Andric   if (Error E =
925cfca06d7SDimitry Andric           getObject(SectionTable, Data, base() + CurPtr,
926cfca06d7SDimitry Andric                     (uint64_t)getNumberOfSections() * sizeof(coff_section)))
927cfca06d7SDimitry Andric     return E;
928f8af5cf6SDimitry Andric 
929f8af5cf6SDimitry Andric   // Initialize the pointer to the symbol table.
93067c32a98SDimitry Andric   if (getPointerToSymbolTable() != 0) {
931cfca06d7SDimitry Andric     if (Error E = initSymbolTablePtr()) {
932cfca06d7SDimitry Andric       // Recover from errors reading the symbol table.
933cfca06d7SDimitry Andric       consumeError(std::move(E));
934b915e9e0SDimitry Andric       SymbolTable16 = nullptr;
935b915e9e0SDimitry Andric       SymbolTable32 = nullptr;
936b915e9e0SDimitry Andric       StringTable = nullptr;
937b915e9e0SDimitry Andric       StringTableSize = 0;
938b915e9e0SDimitry Andric     }
93967c32a98SDimitry Andric   } else {
94067c32a98SDimitry Andric     // We had better not have any symbols if we don't have a symbol table.
94167c32a98SDimitry Andric     if (getNumberOfSymbols() != 0) {
942145449b1SDimitry Andric       return createStringError(object_error::parse_failed,
943145449b1SDimitry Andric                                "symbol table missing");
94467c32a98SDimitry Andric     }
94567c32a98SDimitry Andric   }
946f8af5cf6SDimitry Andric 
947f8af5cf6SDimitry Andric   // Initialize the pointer to the beginning of the import table.
948145449b1SDimitry Andric   if (Error E = ignoreStrippedErrors(initImportTablePtr()))
949cfca06d7SDimitry Andric     return E;
950145449b1SDimitry Andric   if (Error E = ignoreStrippedErrors(initDelayImportTablePtr()))
951cfca06d7SDimitry Andric     return E;
952f8af5cf6SDimitry Andric 
9535ca98fd9SDimitry Andric   // Initialize the pointer to the export table.
954145449b1SDimitry Andric   if (Error E = ignoreStrippedErrors(initExportTablePtr()))
955cfca06d7SDimitry Andric     return E;
9565ca98fd9SDimitry Andric 
95767c32a98SDimitry Andric   // Initialize the pointer to the base relocation table.
958145449b1SDimitry Andric   if (Error E = ignoreStrippedErrors(initBaseRelocPtr()))
959cfca06d7SDimitry Andric     return E;
96067c32a98SDimitry Andric 
961b60736ecSDimitry Andric   // Initialize the pointer to the debug directory.
962145449b1SDimitry Andric   if (Error E = ignoreStrippedErrors(initDebugDirectoryPtr()))
963cfca06d7SDimitry Andric     return E;
96401095a5dSDimitry Andric 
965b60736ecSDimitry Andric   // Initialize the pointer to the TLS directory.
966145449b1SDimitry Andric   if (Error E = ignoreStrippedErrors(initTLSDirectoryPtr()))
967b60736ecSDimitry Andric     return E;
968b60736ecSDimitry Andric 
969145449b1SDimitry Andric   if (Error E = ignoreStrippedErrors(initLoadConfigPtr()))
970cfca06d7SDimitry Andric     return E;
97108bbd35aSDimitry Andric 
972cfca06d7SDimitry Andric   return Error::success();
973cf099d11SDimitry Andric }
974cf099d11SDimitry Andric 
symbol_begin() const975b915e9e0SDimitry Andric basic_symbol_iterator COFFObjectFile::symbol_begin() const {
9765ca98fd9SDimitry Andric   DataRefImpl Ret;
97767c32a98SDimitry Andric   Ret.p = getSymbolTable();
9785ca98fd9SDimitry Andric   return basic_symbol_iterator(SymbolRef(Ret, this));
979cf099d11SDimitry Andric }
980cf099d11SDimitry Andric 
symbol_end() const981b915e9e0SDimitry Andric basic_symbol_iterator COFFObjectFile::symbol_end() const {
982cf099d11SDimitry Andric   // The symbol table ends where the string table begins.
9835ca98fd9SDimitry Andric   DataRefImpl Ret;
9845ca98fd9SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
9855ca98fd9SDimitry Andric   return basic_symbol_iterator(SymbolRef(Ret, this));
986cf099d11SDimitry Andric }
987cf099d11SDimitry Andric 
import_directory_begin() const988f8af5cf6SDimitry Andric import_directory_iterator COFFObjectFile::import_directory_begin() const {
98901095a5dSDimitry Andric   if (!ImportDirectory)
99001095a5dSDimitry Andric     return import_directory_end();
991b915e9e0SDimitry Andric   if (ImportDirectory->isNull())
99201095a5dSDimitry Andric     return import_directory_end();
9935ca98fd9SDimitry Andric   return import_directory_iterator(
9945ca98fd9SDimitry Andric       ImportDirectoryEntryRef(ImportDirectory, 0, this));
995f8af5cf6SDimitry Andric }
996f8af5cf6SDimitry Andric 
import_directory_end() const997f8af5cf6SDimitry Andric import_directory_iterator COFFObjectFile::import_directory_end() const {
9985ca98fd9SDimitry Andric   return import_directory_iterator(
99901095a5dSDimitry Andric       ImportDirectoryEntryRef(nullptr, -1, this));
1000f8af5cf6SDimitry Andric }
100163faed5bSDimitry Andric 
100267c32a98SDimitry Andric delay_import_directory_iterator
delay_import_directory_begin() const100367c32a98SDimitry Andric COFFObjectFile::delay_import_directory_begin() const {
100467c32a98SDimitry Andric   return delay_import_directory_iterator(
100567c32a98SDimitry Andric       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
100667c32a98SDimitry Andric }
100767c32a98SDimitry Andric 
100867c32a98SDimitry Andric delay_import_directory_iterator
delay_import_directory_end() const100967c32a98SDimitry Andric COFFObjectFile::delay_import_directory_end() const {
101067c32a98SDimitry Andric   return delay_import_directory_iterator(
101167c32a98SDimitry Andric       DelayImportDirectoryEntryRef(
101267c32a98SDimitry Andric           DelayImportDirectory, NumberOfDelayImportDirectory, this));
101367c32a98SDimitry Andric }
101467c32a98SDimitry Andric 
export_directory_begin() const10155ca98fd9SDimitry Andric export_directory_iterator COFFObjectFile::export_directory_begin() const {
10165ca98fd9SDimitry Andric   return export_directory_iterator(
10175ca98fd9SDimitry Andric       ExportDirectoryEntryRef(ExportDirectory, 0, this));
1018cf099d11SDimitry Andric }
1019cf099d11SDimitry Andric 
export_directory_end() const10205ca98fd9SDimitry Andric export_directory_iterator COFFObjectFile::export_directory_end() const {
10215ca98fd9SDimitry Andric   if (!ExportDirectory)
10225ca98fd9SDimitry Andric     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
10235ca98fd9SDimitry Andric   ExportDirectoryEntryRef Ref(ExportDirectory,
10245ca98fd9SDimitry Andric                               ExportDirectory->AddressTableEntries, this);
10255ca98fd9SDimitry Andric   return export_directory_iterator(Ref);
10265ca98fd9SDimitry Andric }
10275ca98fd9SDimitry Andric 
section_begin() const10285ca98fd9SDimitry Andric section_iterator COFFObjectFile::section_begin() const {
10295ca98fd9SDimitry Andric   DataRefImpl Ret;
10305ca98fd9SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
10315ca98fd9SDimitry Andric   return section_iterator(SectionRef(Ret, this));
10325ca98fd9SDimitry Andric }
10335ca98fd9SDimitry Andric 
section_end() const10345ca98fd9SDimitry Andric section_iterator COFFObjectFile::section_end() const {
10355ca98fd9SDimitry Andric   DataRefImpl Ret;
103667c32a98SDimitry Andric   int NumSections =
103767c32a98SDimitry Andric       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
10385ca98fd9SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
10395ca98fd9SDimitry Andric   return section_iterator(SectionRef(Ret, this));
1040cf099d11SDimitry Andric }
1041cf099d11SDimitry Andric 
base_reloc_begin() const104267c32a98SDimitry Andric base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
104367c32a98SDimitry Andric   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
104467c32a98SDimitry Andric }
104567c32a98SDimitry Andric 
base_reloc_end() const104667c32a98SDimitry Andric base_reloc_iterator COFFObjectFile::base_reloc_end() const {
104767c32a98SDimitry Andric   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
104867c32a98SDimitry Andric }
104967c32a98SDimitry Andric 
getBytesInAddress() const1050cf099d11SDimitry Andric uint8_t COFFObjectFile::getBytesInAddress() const {
10519df3605dSDimitry Andric   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
1052cf099d11SDimitry Andric }
1053cf099d11SDimitry Andric 
getFileFormatName() const1054cf099d11SDimitry Andric StringRef COFFObjectFile::getFileFormatName() const {
105567c32a98SDimitry Andric   switch(getMachine()) {
1056cf099d11SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_I386:
1057cf099d11SDimitry Andric     return "COFF-i386";
1058cf099d11SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_AMD64:
1059cf099d11SDimitry Andric     return "COFF-x86-64";
10605ca98fd9SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARMNT:
10615ca98fd9SDimitry Andric     return "COFF-ARM";
1062dd58ef01SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARM64:
1063dd58ef01SDimitry Andric     return "COFF-ARM64";
1064e3b55780SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARM64EC:
1065e3b55780SDimitry Andric     return "COFF-ARM64EC";
10667fa27ce4SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARM64X:
10677fa27ce4SDimitry Andric     return "COFF-ARM64X";
1068cf099d11SDimitry Andric   default:
1069cf099d11SDimitry Andric     return "COFF-<unknown arch>";
1070cf099d11SDimitry Andric   }
1071cf099d11SDimitry Andric }
1072cf099d11SDimitry Andric 
getArch() const1073044eb2f6SDimitry Andric Triple::ArchType COFFObjectFile::getArch() const {
1074ac9a064cSDimitry Andric   return getMachineArchType(getMachine());
1075cf099d11SDimitry Andric }
1076cf099d11SDimitry Andric 
getStartAddress() const1077eb11fae6SDimitry Andric Expected<uint64_t> COFFObjectFile::getStartAddress() const {
1078eb11fae6SDimitry Andric   if (PE32Header)
1079eb11fae6SDimitry Andric     return PE32Header->AddressOfEntryPoint;
1080eb11fae6SDimitry Andric   return 0;
1081eb11fae6SDimitry Andric }
1082eb11fae6SDimitry Andric 
108367c32a98SDimitry Andric iterator_range<import_directory_iterator>
import_directories() const108467c32a98SDimitry Andric COFFObjectFile::import_directories() const {
108567c32a98SDimitry Andric   return make_range(import_directory_begin(), import_directory_end());
1086f8af5cf6SDimitry Andric }
1087f8af5cf6SDimitry Andric 
108867c32a98SDimitry Andric iterator_range<delay_import_directory_iterator>
delay_import_directories() const108967c32a98SDimitry Andric COFFObjectFile::delay_import_directories() const {
109067c32a98SDimitry Andric   return make_range(delay_import_directory_begin(),
109167c32a98SDimitry Andric                     delay_import_directory_end());
109267c32a98SDimitry Andric }
109367c32a98SDimitry Andric 
109467c32a98SDimitry Andric iterator_range<export_directory_iterator>
export_directories() const109567c32a98SDimitry Andric COFFObjectFile::export_directories() const {
109667c32a98SDimitry Andric   return make_range(export_directory_begin(), export_directory_end());
109767c32a98SDimitry Andric }
109867c32a98SDimitry Andric 
base_relocs() const109967c32a98SDimitry Andric iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
110067c32a98SDimitry Andric   return make_range(base_reloc_begin(), base_reloc_end());
1101f8af5cf6SDimitry Andric }
1102f8af5cf6SDimitry Andric 
getDataDirectory(uint32_t Index) const1103cfca06d7SDimitry Andric const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const {
1104cfca06d7SDimitry Andric   if (!DataDirectory)
1105cfca06d7SDimitry Andric     return nullptr;
11065ca98fd9SDimitry Andric   assert(PE32Header || PE32PlusHeader);
11075ca98fd9SDimitry Andric   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
11085ca98fd9SDimitry Andric                                : PE32PlusHeader->NumberOfRvaAndSize;
1109cfca06d7SDimitry Andric   if (Index >= NumEnt)
1110cfca06d7SDimitry Andric     return nullptr;
1111cfca06d7SDimitry Andric   return &DataDirectory[Index];
11125ca98fd9SDimitry Andric }
11135ca98fd9SDimitry Andric 
getSection(int32_t Index) const1114cfca06d7SDimitry Andric Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const {
1115cfca06d7SDimitry Andric   // Perhaps getting the section of a reserved section index should be an error,
1116cfca06d7SDimitry Andric   // but callers rely on this to return null.
111767c32a98SDimitry Andric   if (COFF::isReservedSectionNumber(Index))
1118cfca06d7SDimitry Andric     return (const coff_section *)nullptr;
111967c32a98SDimitry Andric   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
1120411bd29eSDimitry Andric     // We already verified the section table data, so no need to check again.
1121cfca06d7SDimitry Andric     return SectionTable + (Index - 1);
1122cf099d11SDimitry Andric   }
1123145449b1SDimitry Andric   return createStringError(object_error::parse_failed,
1124145449b1SDimitry Andric                            "section index out of bounds");
112567c32a98SDimitry Andric }
1126cf099d11SDimitry Andric 
getString(uint32_t Offset) const1127cfca06d7SDimitry Andric Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const {
1128411bd29eSDimitry Andric   if (StringTableSize <= 4)
1129411bd29eSDimitry Andric     // Tried to get a string from an empty string table.
1130145449b1SDimitry Andric     return createStringError(object_error::parse_failed, "string table empty");
11315ca98fd9SDimitry Andric   if (Offset >= StringTableSize)
1132cfca06d7SDimitry Andric     return errorCodeToError(object_error::unexpected_eof);
1133cfca06d7SDimitry Andric   return StringRef(StringTable + Offset);
1134cf099d11SDimitry Andric }
1135cf099d11SDimitry Andric 
getSymbolName(COFFSymbolRef Symbol) const1136cfca06d7SDimitry Andric Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const {
1137cfca06d7SDimitry Andric   return getSymbolName(Symbol.getGeneric());
11381a82d4c0SDimitry Andric }
11391a82d4c0SDimitry Andric 
1140cfca06d7SDimitry Andric Expected<StringRef>
getSymbolName(const coff_symbol_generic * Symbol) const1141cfca06d7SDimitry Andric COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const {
114263faed5bSDimitry Andric   // Check for string table entry. First 4 bytes are 0.
1143cfca06d7SDimitry Andric   if (Symbol->Name.Offset.Zeroes == 0)
1144cfca06d7SDimitry Andric     return getString(Symbol->Name.Offset.Offset);
114563faed5bSDimitry Andric 
114663faed5bSDimitry Andric   // Null terminated, let ::strlen figure out the length.
1147cfca06d7SDimitry Andric   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
1148cfca06d7SDimitry Andric     return StringRef(Symbol->Name.ShortName);
1149cfca06d7SDimitry Andric 
115063faed5bSDimitry Andric   // Not null terminated, use all 8 bytes.
1151cfca06d7SDimitry Andric   return StringRef(Symbol->Name.ShortName, COFF::NameSize);
115263faed5bSDimitry Andric }
115363faed5bSDimitry Andric 
115467c32a98SDimitry Andric ArrayRef<uint8_t>
getSymbolAuxData(COFFSymbolRef Symbol) const115567c32a98SDimitry Andric COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
11565ca98fd9SDimitry Andric   const uint8_t *Aux = nullptr;
115758b69754SDimitry Andric 
115867c32a98SDimitry Andric   size_t SymbolSize = getSymbolTableEntrySize();
115967c32a98SDimitry Andric   if (Symbol.getNumberOfAuxSymbols() > 0) {
116058b69754SDimitry Andric     // AUX data comes immediately after the symbol in COFF
116167c32a98SDimitry Andric     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
116258b69754SDimitry Andric #ifndef NDEBUG
11635ca98fd9SDimitry Andric     // Verify that the Aux symbol points to a valid entry in the symbol table.
11645ca98fd9SDimitry Andric     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
116567c32a98SDimitry Andric     if (Offset < getPointerToSymbolTable() ||
116667c32a98SDimitry Andric         Offset >=
116767c32a98SDimitry Andric             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
116858b69754SDimitry Andric       report_fatal_error("Aux Symbol data was outside of symbol table.");
116958b69754SDimitry Andric 
117067c32a98SDimitry Andric     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
117167c32a98SDimitry Andric            "Aux Symbol data did not point to the beginning of a symbol");
117258b69754SDimitry Andric #endif
117358b69754SDimitry Andric   }
1174e3b55780SDimitry Andric   return ArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
117558b69754SDimitry Andric }
117658b69754SDimitry Andric 
getSymbolIndex(COFFSymbolRef Symbol) const1177d8e91e46SDimitry Andric uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
1178d8e91e46SDimitry Andric   uintptr_t Offset =
1179d8e91e46SDimitry Andric       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
1180d8e91e46SDimitry Andric   assert(Offset % getSymbolTableEntrySize() == 0 &&
1181d8e91e46SDimitry Andric          "Symbol did not point to the beginning of a symbol");
1182d8e91e46SDimitry Andric   size_t Index = Offset / getSymbolTableEntrySize();
1183d8e91e46SDimitry Andric   assert(Index < getNumberOfSymbols());
1184d8e91e46SDimitry Andric   return Index;
1185d8e91e46SDimitry Andric }
1186d8e91e46SDimitry Andric 
1187e6d15924SDimitry Andric Expected<StringRef>
getSectionName(const coff_section * Sec) const1188e6d15924SDimitry Andric COFFObjectFile::getSectionName(const coff_section *Sec) const {
1189145449b1SDimitry Andric   StringRef Name = StringRef(Sec->Name, COFF::NameSize).split('\0').first;
119063faed5bSDimitry Andric 
119163faed5bSDimitry Andric   // Check for string table entry. First byte is '/'.
1192312c0ed1SDimitry Andric   if (Name.starts_with("/")) {
119363faed5bSDimitry Andric     uint32_t Offset;
1194312c0ed1SDimitry Andric     if (Name.starts_with("//")) {
11955ca98fd9SDimitry Andric       if (decodeBase64StringEntry(Name.substr(2), Offset))
1196e6d15924SDimitry Andric         return createStringError(object_error::parse_failed,
1197cfca06d7SDimitry Andric                                  "invalid section name");
11985ca98fd9SDimitry Andric     } else {
119963faed5bSDimitry Andric       if (Name.substr(1).getAsInteger(10, Offset))
1200e6d15924SDimitry Andric         return createStringError(object_error::parse_failed,
1201e6d15924SDimitry Andric                                  "invalid section name");
12025ca98fd9SDimitry Andric     }
1203cfca06d7SDimitry Andric     return getString(Offset);
120463faed5bSDimitry Andric   }
120563faed5bSDimitry Andric 
1206e6d15924SDimitry Andric   return Name;
120763faed5bSDimitry Andric }
120863faed5bSDimitry Andric 
getSectionSize(const coff_section * Sec) const120967c32a98SDimitry Andric uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
121067c32a98SDimitry Andric   // SizeOfRawData and VirtualSize change what they represent depending on
121167c32a98SDimitry Andric   // whether or not we have an executable image.
121267c32a98SDimitry Andric   //
121367c32a98SDimitry Andric   // For object files, SizeOfRawData contains the size of section's data;
1214ee8648bdSDimitry Andric   // VirtualSize should be zero but isn't due to buggy COFF writers.
121567c32a98SDimitry Andric   //
121667c32a98SDimitry Andric   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
121767c32a98SDimitry Andric   // actual section size is in VirtualSize.  It is possible for VirtualSize to
121867c32a98SDimitry Andric   // be greater than SizeOfRawData; the contents past that point should be
121967c32a98SDimitry Andric   // considered to be zero.
1220ee8648bdSDimitry Andric   if (getDOSHeader())
1221ee8648bdSDimitry Andric     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1222ee8648bdSDimitry Andric   return Sec->SizeOfRawData;
122367c32a98SDimitry Andric }
122467c32a98SDimitry Andric 
getSectionContents(const coff_section * Sec,ArrayRef<uint8_t> & Res) const1225e6d15924SDimitry Andric Error COFFObjectFile::getSectionContents(const coff_section *Sec,
122663faed5bSDimitry Andric                                          ArrayRef<uint8_t> &Res) const {
122701095a5dSDimitry Andric   // In COFF, a virtual section won't have any in-file
122801095a5dSDimitry Andric   // content, so the file pointer to the content will be zero.
122901095a5dSDimitry Andric   if (Sec->PointerToRawData == 0)
1230e6d15924SDimitry Andric     return Error::success();
123163faed5bSDimitry Andric   // The only thing that we need to verify is that the contents is contained
123263faed5bSDimitry Andric   // within the file bounds. We don't need to make sure it doesn't cover other
123363faed5bSDimitry Andric   // data, as there's nothing that says that is not allowed.
1234b60736ecSDimitry Andric   uintptr_t ConStart =
1235b60736ecSDimitry Andric       reinterpret_cast<uintptr_t>(base()) + Sec->PointerToRawData;
123667c32a98SDimitry Andric   uint32_t SectionSize = getSectionSize(Sec);
1237cfca06d7SDimitry Andric   if (Error E = checkOffset(Data, ConStart, SectionSize))
1238cfca06d7SDimitry Andric     return E;
1239e3b55780SDimitry Andric   Res = ArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
1240e6d15924SDimitry Andric   return Error::success();
124163faed5bSDimitry Andric }
124263faed5bSDimitry Andric 
toRel(DataRefImpl Rel) const124330815c53SDimitry Andric const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
124430815c53SDimitry Andric   return reinterpret_cast<const coff_relocation*>(Rel.p);
124530815c53SDimitry Andric }
12465ca98fd9SDimitry Andric 
moveRelocationNext(DataRefImpl & Rel) const12475ca98fd9SDimitry Andric void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
124830815c53SDimitry Andric   Rel.p = reinterpret_cast<uintptr_t>(
124930815c53SDimitry Andric             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
125030815c53SDimitry Andric }
12515ca98fd9SDimitry Andric 
getRelocationOffset(DataRefImpl Rel) const12521a82d4c0SDimitry Andric uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
125367c32a98SDimitry Andric   const coff_relocation *R = toRel(Rel);
12541a82d4c0SDimitry Andric   return R->VirtualAddress;
125563faed5bSDimitry Andric }
12565ca98fd9SDimitry Andric 
getRelocationSymbol(DataRefImpl Rel) const1257f8af5cf6SDimitry Andric symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
125830815c53SDimitry Andric   const coff_relocation *R = toRel(Rel);
12595ca98fd9SDimitry Andric   DataRefImpl Ref;
126067c32a98SDimitry Andric   if (R->SymbolTableIndex >= getNumberOfSymbols())
126167c32a98SDimitry Andric     return symbol_end();
126267c32a98SDimitry Andric   if (SymbolTable16)
126367c32a98SDimitry Andric     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
126467c32a98SDimitry Andric   else if (SymbolTable32)
126567c32a98SDimitry Andric     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
126667c32a98SDimitry Andric   else
126767c32a98SDimitry Andric     llvm_unreachable("no symbol table pointer!");
12685ca98fd9SDimitry Andric   return symbol_iterator(SymbolRef(Ref, this));
126930815c53SDimitry Andric }
12705ca98fd9SDimitry Andric 
getRelocationType(DataRefImpl Rel) const12711a82d4c0SDimitry Andric uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
127230815c53SDimitry Andric   const coff_relocation* R = toRel(Rel);
12731a82d4c0SDimitry Andric   return R->Type;
127430815c53SDimitry Andric }
127530815c53SDimitry Andric 
12765ca98fd9SDimitry Andric const coff_section *
getCOFFSection(const SectionRef & Section) const12775ca98fd9SDimitry Andric COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
12785ca98fd9SDimitry Andric   return toSec(Section.getRawDataRefImpl());
127958b69754SDimitry Andric }
128058b69754SDimitry Andric 
getCOFFSymbol(const DataRefImpl & Ref) const128167c32a98SDimitry Andric COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
128267c32a98SDimitry Andric   if (SymbolTable16)
128367c32a98SDimitry Andric     return toSymb<coff_symbol16>(Ref);
128467c32a98SDimitry Andric   if (SymbolTable32)
128567c32a98SDimitry Andric     return toSymb<coff_symbol32>(Ref);
128667c32a98SDimitry Andric   llvm_unreachable("no symbol table pointer!");
128767c32a98SDimitry Andric }
128867c32a98SDimitry Andric 
getCOFFSymbol(const SymbolRef & Symbol) const128967c32a98SDimitry Andric COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
129067c32a98SDimitry Andric   return getCOFFSymbol(Symbol.getRawDataRefImpl());
129158b69754SDimitry Andric }
129258b69754SDimitry Andric 
12935ca98fd9SDimitry Andric const coff_relocation *
getCOFFRelocation(const RelocationRef & Reloc) const12945ca98fd9SDimitry Andric COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
12955ca98fd9SDimitry Andric   return toRel(Reloc.getRawDataRefImpl());
129658b69754SDimitry Andric }
129758b69754SDimitry Andric 
1298eb11fae6SDimitry Andric ArrayRef<coff_relocation>
getRelocations(const coff_section * Sec) const12991a82d4c0SDimitry Andric COFFObjectFile::getRelocations(const coff_section *Sec) const {
1300eb11fae6SDimitry Andric   return {getFirstReloc(Sec, Data, base()),
1301eb11fae6SDimitry Andric           getNumberOfRelocations(Sec, Data, base())};
13021a82d4c0SDimitry Andric }
13031a82d4c0SDimitry Andric 
13045ca98fd9SDimitry Andric #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
13055ca98fd9SDimitry Andric   case COFF::reloc_type:                                                       \
1306d8e91e46SDimitry Andric     return #reloc_type;
130730815c53SDimitry Andric 
getRelocationTypeName(uint16_t Type) const1308d8e91e46SDimitry Andric StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
1309ac9a064cSDimitry Andric   switch (getArch()) {
1310ac9a064cSDimitry Andric   case Triple::x86_64:
1311d8e91e46SDimitry Andric     switch (Type) {
131230815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
131330815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
131430815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
131530815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
131630815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
131730815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
131830815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
131930815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
132030815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
132130815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
132230815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
132330815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
132430815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
132530815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
132630815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
132730815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
132830815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
132930815c53SDimitry Andric     default:
1330d8e91e46SDimitry Andric       return "Unknown";
13315ca98fd9SDimitry Andric     }
13325ca98fd9SDimitry Andric     break;
1333ac9a064cSDimitry Andric   case Triple::thumb:
1334d8e91e46SDimitry Andric     switch (Type) {
13355ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
13365ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
13375ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
13385ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
13395ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
13405ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
13415ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
13425ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1343e6d15924SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
13445ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
13455ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
13465ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
13475ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
13485ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
13495ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
13505ca98fd9SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
1351e6d15924SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
13525ca98fd9SDimitry Andric     default:
1353d8e91e46SDimitry Andric       return "Unknown";
135430815c53SDimitry Andric     }
135530815c53SDimitry Andric     break;
1356ac9a064cSDimitry Andric   case Triple::aarch64:
1357d8e91e46SDimitry Andric     switch (Type) {
13589df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
13599df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
13609df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
13619df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
13629df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
13639df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
13649df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
13659df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
13669df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
13679df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
13689df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
13699df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
13709df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
13719df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
13729df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
13739df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
13749df3605dSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
1375e6d15924SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
13769df3605dSDimitry Andric     default:
1377d8e91e46SDimitry Andric       return "Unknown";
13789df3605dSDimitry Andric     }
13799df3605dSDimitry Andric     break;
1380ac9a064cSDimitry Andric   case Triple::x86:
1381d8e91e46SDimitry Andric     switch (Type) {
138230815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
138330815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
138430815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
138530815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
138630815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
138730815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
138830815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
138930815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
139030815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
139130815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
139230815c53SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
139330815c53SDimitry Andric     default:
1394d8e91e46SDimitry Andric       return "Unknown";
139530815c53SDimitry Andric     }
139630815c53SDimitry Andric     break;
139730815c53SDimitry Andric   default:
1398d8e91e46SDimitry Andric     return "Unknown";
139930815c53SDimitry Andric   }
140030815c53SDimitry Andric }
140130815c53SDimitry Andric 
140230815c53SDimitry Andric #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
140330815c53SDimitry Andric 
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const1404d8e91e46SDimitry Andric void COFFObjectFile::getRelocationTypeName(
1405d8e91e46SDimitry Andric     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1406d8e91e46SDimitry Andric   const coff_relocation *Reloc = toRel(Rel);
1407d8e91e46SDimitry Andric   StringRef Res = getRelocationTypeName(Reloc->Type);
1408d8e91e46SDimitry Andric   Result.append(Res.begin(), Res.end());
1409d8e91e46SDimitry Andric }
1410d8e91e46SDimitry Andric 
isRelocatableObject() const141167c32a98SDimitry Andric bool COFFObjectFile::isRelocatableObject() const {
141267c32a98SDimitry Andric   return !DataDirectory;
141363faed5bSDimitry Andric }
141463faed5bSDimitry Andric 
mapDebugSectionName(StringRef Name) const1415d8e91e46SDimitry Andric StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
1416d8e91e46SDimitry Andric   return StringSwitch<StringRef>(Name)
1417d8e91e46SDimitry Andric       .Case("eh_fram", "eh_frame")
1418d8e91e46SDimitry Andric       .Default(Name);
1419d8e91e46SDimitry Andric }
1420d8e91e46SDimitry Andric 
1421f8af5cf6SDimitry Andric bool ImportDirectoryEntryRef::
operator ==(const ImportDirectoryEntryRef & Other) const1422f8af5cf6SDimitry Andric operator==(const ImportDirectoryEntryRef &Other) const {
14235ca98fd9SDimitry Andric   return ImportTable == Other.ImportTable && Index == Other.Index;
1424f8af5cf6SDimitry Andric }
1425f8af5cf6SDimitry Andric 
moveNext()14265ca98fd9SDimitry Andric void ImportDirectoryEntryRef::moveNext() {
14275ca98fd9SDimitry Andric   ++Index;
1428b915e9e0SDimitry Andric   if (ImportTable[Index].isNull()) {
142901095a5dSDimitry Andric     Index = -1;
143001095a5dSDimitry Andric     ImportTable = nullptr;
143101095a5dSDimitry Andric   }
1432f8af5cf6SDimitry Andric }
1433f8af5cf6SDimitry Andric 
getImportTableEntry(const coff_import_directory_table_entry * & Result) const1434cfca06d7SDimitry Andric Error ImportDirectoryEntryRef::getImportTableEntry(
1435b915e9e0SDimitry Andric     const coff_import_directory_table_entry *&Result) const {
143601095a5dSDimitry Andric   return getObject(Result, OwningObject->Data, ImportTable + Index);
1437f8af5cf6SDimitry Andric }
1438f8af5cf6SDimitry Andric 
143967c32a98SDimitry Andric static imported_symbol_iterator
makeImportedSymbolIterator(const COFFObjectFile * Object,uintptr_t Ptr,int Index)144067c32a98SDimitry Andric makeImportedSymbolIterator(const COFFObjectFile *Object,
144167c32a98SDimitry Andric                            uintptr_t Ptr, int Index) {
144267c32a98SDimitry Andric   if (Object->getBytesInAddress() == 4) {
144367c32a98SDimitry Andric     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
144467c32a98SDimitry Andric     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
144567c32a98SDimitry Andric   }
144667c32a98SDimitry Andric   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
144767c32a98SDimitry Andric   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
144867c32a98SDimitry Andric }
144967c32a98SDimitry Andric 
145067c32a98SDimitry Andric static imported_symbol_iterator
importedSymbolBegin(uint32_t RVA,const COFFObjectFile * Object)145167c32a98SDimitry Andric importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
145267c32a98SDimitry Andric   uintptr_t IntPtr = 0;
1453cfca06d7SDimitry Andric   // FIXME: Handle errors.
1454cfca06d7SDimitry Andric   cantFail(Object->getRvaPtr(RVA, IntPtr));
145567c32a98SDimitry Andric   return makeImportedSymbolIterator(Object, IntPtr, 0);
145667c32a98SDimitry Andric }
145767c32a98SDimitry Andric 
145867c32a98SDimitry Andric static imported_symbol_iterator
importedSymbolEnd(uint32_t RVA,const COFFObjectFile * Object)145967c32a98SDimitry Andric importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
146067c32a98SDimitry Andric   uintptr_t IntPtr = 0;
1461cfca06d7SDimitry Andric   // FIXME: Handle errors.
1462cfca06d7SDimitry Andric   cantFail(Object->getRvaPtr(RVA, IntPtr));
146367c32a98SDimitry Andric   // Forward the pointer to the last entry which is null.
146467c32a98SDimitry Andric   int Index = 0;
146567c32a98SDimitry Andric   if (Object->getBytesInAddress() == 4) {
146667c32a98SDimitry Andric     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
146767c32a98SDimitry Andric     while (*Entry++)
146867c32a98SDimitry Andric       ++Index;
146967c32a98SDimitry Andric   } else {
147067c32a98SDimitry Andric     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
147167c32a98SDimitry Andric     while (*Entry++)
147267c32a98SDimitry Andric       ++Index;
147367c32a98SDimitry Andric   }
147467c32a98SDimitry Andric   return makeImportedSymbolIterator(Object, IntPtr, Index);
147567c32a98SDimitry Andric }
147667c32a98SDimitry Andric 
147767c32a98SDimitry Andric imported_symbol_iterator
imported_symbol_begin() const147867c32a98SDimitry Andric ImportDirectoryEntryRef::imported_symbol_begin() const {
1479b915e9e0SDimitry Andric   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
148067c32a98SDimitry Andric                              OwningObject);
148167c32a98SDimitry Andric }
148267c32a98SDimitry Andric 
148367c32a98SDimitry Andric imported_symbol_iterator
imported_symbol_end() const148467c32a98SDimitry Andric ImportDirectoryEntryRef::imported_symbol_end() const {
1485b915e9e0SDimitry Andric   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
148667c32a98SDimitry Andric                            OwningObject);
148767c32a98SDimitry Andric }
148867c32a98SDimitry Andric 
148967c32a98SDimitry Andric iterator_range<imported_symbol_iterator>
imported_symbols() const149067c32a98SDimitry Andric ImportDirectoryEntryRef::imported_symbols() const {
149167c32a98SDimitry Andric   return make_range(imported_symbol_begin(), imported_symbol_end());
149267c32a98SDimitry Andric }
149367c32a98SDimitry Andric 
lookup_table_begin() const1494b915e9e0SDimitry Andric imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
1495b915e9e0SDimitry Andric   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
1496b915e9e0SDimitry Andric                              OwningObject);
1497b915e9e0SDimitry Andric }
1498b915e9e0SDimitry Andric 
lookup_table_end() const1499b915e9e0SDimitry Andric imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
1500b915e9e0SDimitry Andric   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
1501b915e9e0SDimitry Andric                            OwningObject);
1502b915e9e0SDimitry Andric }
1503b915e9e0SDimitry Andric 
1504b915e9e0SDimitry Andric iterator_range<imported_symbol_iterator>
lookup_table_symbols() const1505b915e9e0SDimitry Andric ImportDirectoryEntryRef::lookup_table_symbols() const {
1506b915e9e0SDimitry Andric   return make_range(lookup_table_begin(), lookup_table_end());
1507b915e9e0SDimitry Andric }
1508b915e9e0SDimitry Andric 
getName(StringRef & Result) const1509cfca06d7SDimitry Andric Error ImportDirectoryEntryRef::getName(StringRef &Result) const {
1510f8af5cf6SDimitry Andric   uintptr_t IntPtr = 0;
1511145449b1SDimitry Andric   if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr,
1512145449b1SDimitry Andric                                         "import directory name"))
1513cfca06d7SDimitry Andric     return E;
15145ca98fd9SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1515cfca06d7SDimitry Andric   return Error::success();
1516f8af5cf6SDimitry Andric }
1517f8af5cf6SDimitry Andric 
1518cfca06d7SDimitry Andric Error
getImportLookupTableRVA(uint32_t & Result) const151967c32a98SDimitry Andric ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
152067c32a98SDimitry Andric   Result = ImportTable[Index].ImportLookupTableRVA;
1521cfca06d7SDimitry Andric   return Error::success();
152267c32a98SDimitry Andric }
152367c32a98SDimitry Andric 
getImportAddressTableRVA(uint32_t & Result) const1524cfca06d7SDimitry Andric Error ImportDirectoryEntryRef::getImportAddressTableRVA(
1525cfca06d7SDimitry Andric     uint32_t &Result) const {
152667c32a98SDimitry Andric   Result = ImportTable[Index].ImportAddressTableRVA;
1527cfca06d7SDimitry Andric   return Error::success();
152867c32a98SDimitry Andric }
152967c32a98SDimitry Andric 
153067c32a98SDimitry Andric bool DelayImportDirectoryEntryRef::
operator ==(const DelayImportDirectoryEntryRef & Other) const153167c32a98SDimitry Andric operator==(const DelayImportDirectoryEntryRef &Other) const {
153267c32a98SDimitry Andric   return Table == Other.Table && Index == Other.Index;
153367c32a98SDimitry Andric }
153467c32a98SDimitry Andric 
moveNext()153567c32a98SDimitry Andric void DelayImportDirectoryEntryRef::moveNext() {
153667c32a98SDimitry Andric   ++Index;
153767c32a98SDimitry Andric }
153867c32a98SDimitry Andric 
153967c32a98SDimitry Andric imported_symbol_iterator
imported_symbol_begin() const154067c32a98SDimitry Andric DelayImportDirectoryEntryRef::imported_symbol_begin() const {
154167c32a98SDimitry Andric   return importedSymbolBegin(Table[Index].DelayImportNameTable,
154267c32a98SDimitry Andric                              OwningObject);
154367c32a98SDimitry Andric }
154467c32a98SDimitry Andric 
154567c32a98SDimitry Andric imported_symbol_iterator
imported_symbol_end() const154667c32a98SDimitry Andric DelayImportDirectoryEntryRef::imported_symbol_end() const {
154767c32a98SDimitry Andric   return importedSymbolEnd(Table[Index].DelayImportNameTable,
154867c32a98SDimitry Andric                            OwningObject);
154967c32a98SDimitry Andric }
155067c32a98SDimitry Andric 
155167c32a98SDimitry Andric iterator_range<imported_symbol_iterator>
imported_symbols() const155267c32a98SDimitry Andric DelayImportDirectoryEntryRef::imported_symbols() const {
155367c32a98SDimitry Andric   return make_range(imported_symbol_begin(), imported_symbol_end());
155467c32a98SDimitry Andric }
155567c32a98SDimitry Andric 
getName(StringRef & Result) const1556cfca06d7SDimitry Andric Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
155767c32a98SDimitry Andric   uintptr_t IntPtr = 0;
1558145449b1SDimitry Andric   if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr,
1559145449b1SDimitry Andric                                         "delay import directory name"))
1560cfca06d7SDimitry Andric     return E;
156167c32a98SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1562cfca06d7SDimitry Andric   return Error::success();
156367c32a98SDimitry Andric }
156467c32a98SDimitry Andric 
getDelayImportTable(const delay_import_directory_table_entry * & Result) const1565cfca06d7SDimitry Andric Error DelayImportDirectoryEntryRef::getDelayImportTable(
1566cfca06d7SDimitry Andric     const delay_import_directory_table_entry *&Result) const {
1567e6d15924SDimitry Andric   Result = &Table[Index];
1568cfca06d7SDimitry Andric   return Error::success();
156967c32a98SDimitry Andric }
157067c32a98SDimitry Andric 
getImportAddress(int AddrIndex,uint64_t & Result) const1571cfca06d7SDimitry Andric Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex,
1572cfca06d7SDimitry Andric                                                      uint64_t &Result) const {
157367c32a98SDimitry Andric   uint32_t RVA = Table[Index].DelayImportAddressTable +
157467c32a98SDimitry Andric       AddrIndex * (OwningObject->is64() ? 8 : 4);
157567c32a98SDimitry Andric   uintptr_t IntPtr = 0;
1576145449b1SDimitry Andric   if (Error E = OwningObject->getRvaPtr(RVA, IntPtr, "import address"))
1577cfca06d7SDimitry Andric     return E;
157867c32a98SDimitry Andric   if (OwningObject->is64())
157967c32a98SDimitry Andric     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
158067c32a98SDimitry Andric   else
158167c32a98SDimitry Andric     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
1582cfca06d7SDimitry Andric   return Error::success();
158367c32a98SDimitry Andric }
158467c32a98SDimitry Andric 
15855ca98fd9SDimitry Andric bool ExportDirectoryEntryRef::
operator ==(const ExportDirectoryEntryRef & Other) const15865ca98fd9SDimitry Andric operator==(const ExportDirectoryEntryRef &Other) const {
15875ca98fd9SDimitry Andric   return ExportTable == Other.ExportTable && Index == Other.Index;
1588cf099d11SDimitry Andric }
1589cf099d11SDimitry Andric 
moveNext()15905ca98fd9SDimitry Andric void ExportDirectoryEntryRef::moveNext() {
15915ca98fd9SDimitry Andric   ++Index;
15925ca98fd9SDimitry Andric }
15935ca98fd9SDimitry Andric 
15945ca98fd9SDimitry Andric // Returns the name of the current export symbol. If the symbol is exported only
15955ca98fd9SDimitry Andric // by ordinal, the empty string is set as a result.
getDllName(StringRef & Result) const1596cfca06d7SDimitry Andric Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
15975ca98fd9SDimitry Andric   uintptr_t IntPtr = 0;
1598145449b1SDimitry Andric   if (Error E =
1599145449b1SDimitry Andric           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr, "dll name"))
1600cfca06d7SDimitry Andric     return E;
16015ca98fd9SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1602cfca06d7SDimitry Andric   return Error::success();
16035ca98fd9SDimitry Andric }
16045ca98fd9SDimitry Andric 
16055ca98fd9SDimitry Andric // Returns the starting ordinal number.
getOrdinalBase(uint32_t & Result) const1606cfca06d7SDimitry Andric Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
16075ca98fd9SDimitry Andric   Result = ExportTable->OrdinalBase;
1608cfca06d7SDimitry Andric   return Error::success();
16095ca98fd9SDimitry Andric }
16105ca98fd9SDimitry Andric 
16115ca98fd9SDimitry Andric // Returns the export ordinal of the current export symbol.
getOrdinal(uint32_t & Result) const1612cfca06d7SDimitry Andric Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
16135ca98fd9SDimitry Andric   Result = ExportTable->OrdinalBase + Index;
1614cfca06d7SDimitry Andric   return Error::success();
16155ca98fd9SDimitry Andric }
16165ca98fd9SDimitry Andric 
16175ca98fd9SDimitry Andric // Returns the address of the current export symbol.
getExportRVA(uint32_t & Result) const1618cfca06d7SDimitry Andric Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
16195ca98fd9SDimitry Andric   uintptr_t IntPtr = 0;
1620145449b1SDimitry Andric   if (Error EC = OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA,
1621145449b1SDimitry Andric                                          IntPtr, "export address"))
16225ca98fd9SDimitry Andric     return EC;
16235ca98fd9SDimitry Andric   const export_address_table_entry *entry =
16245ca98fd9SDimitry Andric       reinterpret_cast<const export_address_table_entry *>(IntPtr);
16255ca98fd9SDimitry Andric   Result = entry[Index].ExportRVA;
1626cfca06d7SDimitry Andric   return Error::success();
16275ca98fd9SDimitry Andric }
16285ca98fd9SDimitry Andric 
16295ca98fd9SDimitry Andric // Returns the name of the current export symbol. If the symbol is exported only
16305ca98fd9SDimitry Andric // by ordinal, the empty string is set as a result.
1631cfca06d7SDimitry Andric Error
getSymbolName(StringRef & Result) const16325ca98fd9SDimitry Andric ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
16335ca98fd9SDimitry Andric   uintptr_t IntPtr = 0;
1634145449b1SDimitry Andric   if (Error EC = OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr,
1635145449b1SDimitry Andric                                          "export ordinal table"))
16365ca98fd9SDimitry Andric     return EC;
16375ca98fd9SDimitry Andric   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
16385ca98fd9SDimitry Andric 
16395ca98fd9SDimitry Andric   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
16405ca98fd9SDimitry Andric   int Offset = 0;
16415ca98fd9SDimitry Andric   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
16425ca98fd9SDimitry Andric        I < E; ++I, ++Offset) {
16435ca98fd9SDimitry Andric     if (*I != Index)
16445ca98fd9SDimitry Andric       continue;
1645145449b1SDimitry Andric     if (Error EC = OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr,
1646145449b1SDimitry Andric                                            "export table entry"))
16475ca98fd9SDimitry Andric       return EC;
16485ca98fd9SDimitry Andric     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1649145449b1SDimitry Andric     if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr,
1650145449b1SDimitry Andric                                            "export symbol name"))
16515ca98fd9SDimitry Andric       return EC;
16525ca98fd9SDimitry Andric     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1653cfca06d7SDimitry Andric     return Error::success();
16545ca98fd9SDimitry Andric   }
16555ca98fd9SDimitry Andric   Result = "";
1656cfca06d7SDimitry Andric   return Error::success();
16575ca98fd9SDimitry Andric }
16585ca98fd9SDimitry Andric 
isForwarder(bool & Result) const1659cfca06d7SDimitry Andric Error ExportDirectoryEntryRef::isForwarder(bool &Result) const {
1660cfca06d7SDimitry Andric   const data_directory *DataEntry =
1661cfca06d7SDimitry Andric       OwningObject->getDataDirectory(COFF::EXPORT_TABLE);
1662cfca06d7SDimitry Andric   if (!DataEntry)
1663145449b1SDimitry Andric     return createStringError(object_error::parse_failed,
1664145449b1SDimitry Andric                              "export table missing");
1665050e163aSDimitry Andric   uint32_t RVA;
1666050e163aSDimitry Andric   if (auto EC = getExportRVA(RVA))
1667050e163aSDimitry Andric     return EC;
1668050e163aSDimitry Andric   uint32_t Begin = DataEntry->RelativeVirtualAddress;
1669050e163aSDimitry Andric   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
1670050e163aSDimitry Andric   Result = (Begin <= RVA && RVA < End);
1671cfca06d7SDimitry Andric   return Error::success();
1672050e163aSDimitry Andric }
1673050e163aSDimitry Andric 
getForwardTo(StringRef & Result) const1674cfca06d7SDimitry Andric Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
1675050e163aSDimitry Andric   uint32_t RVA;
1676050e163aSDimitry Andric   if (auto EC = getExportRVA(RVA))
1677050e163aSDimitry Andric     return EC;
1678050e163aSDimitry Andric   uintptr_t IntPtr = 0;
1679145449b1SDimitry Andric   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr, "export forward target"))
1680050e163aSDimitry Andric     return EC;
1681050e163aSDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1682cfca06d7SDimitry Andric   return Error::success();
1683050e163aSDimitry Andric }
1684050e163aSDimitry Andric 
168567c32a98SDimitry Andric bool ImportedSymbolRef::
operator ==(const ImportedSymbolRef & Other) const168667c32a98SDimitry Andric operator==(const ImportedSymbolRef &Other) const {
168767c32a98SDimitry Andric   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
168867c32a98SDimitry Andric       && Index == Other.Index;
168967c32a98SDimitry Andric }
169067c32a98SDimitry Andric 
moveNext()169167c32a98SDimitry Andric void ImportedSymbolRef::moveNext() {
169267c32a98SDimitry Andric   ++Index;
169367c32a98SDimitry Andric }
169467c32a98SDimitry Andric 
getSymbolName(StringRef & Result) const1695cfca06d7SDimitry Andric Error ImportedSymbolRef::getSymbolName(StringRef &Result) const {
169667c32a98SDimitry Andric   uint32_t RVA;
169767c32a98SDimitry Andric   if (Entry32) {
169867c32a98SDimitry Andric     // If a symbol is imported only by ordinal, it has no name.
169967c32a98SDimitry Andric     if (Entry32[Index].isOrdinal())
1700cfca06d7SDimitry Andric       return Error::success();
170167c32a98SDimitry Andric     RVA = Entry32[Index].getHintNameRVA();
170267c32a98SDimitry Andric   } else {
170367c32a98SDimitry Andric     if (Entry64[Index].isOrdinal())
1704cfca06d7SDimitry Andric       return Error::success();
170567c32a98SDimitry Andric     RVA = Entry64[Index].getHintNameRVA();
170667c32a98SDimitry Andric   }
170767c32a98SDimitry Andric   uintptr_t IntPtr = 0;
1708145449b1SDimitry Andric   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol name"))
170967c32a98SDimitry Andric     return EC;
171067c32a98SDimitry Andric   // +2 because the first two bytes is hint.
171167c32a98SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
1712cfca06d7SDimitry Andric   return Error::success();
171367c32a98SDimitry Andric }
171467c32a98SDimitry Andric 
isOrdinal(bool & Result) const1715cfca06d7SDimitry Andric Error ImportedSymbolRef::isOrdinal(bool &Result) const {
171601095a5dSDimitry Andric   if (Entry32)
171701095a5dSDimitry Andric     Result = Entry32[Index].isOrdinal();
171801095a5dSDimitry Andric   else
171901095a5dSDimitry Andric     Result = Entry64[Index].isOrdinal();
1720cfca06d7SDimitry Andric   return Error::success();
172101095a5dSDimitry Andric }
172201095a5dSDimitry Andric 
getHintNameRVA(uint32_t & Result) const1723cfca06d7SDimitry Andric Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
172401095a5dSDimitry Andric   if (Entry32)
172501095a5dSDimitry Andric     Result = Entry32[Index].getHintNameRVA();
172601095a5dSDimitry Andric   else
172701095a5dSDimitry Andric     Result = Entry64[Index].getHintNameRVA();
1728cfca06d7SDimitry Andric   return Error::success();
172901095a5dSDimitry Andric }
173001095a5dSDimitry Andric 
getOrdinal(uint16_t & Result) const1731cfca06d7SDimitry Andric Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
173267c32a98SDimitry Andric   uint32_t RVA;
173367c32a98SDimitry Andric   if (Entry32) {
173467c32a98SDimitry Andric     if (Entry32[Index].isOrdinal()) {
173567c32a98SDimitry Andric       Result = Entry32[Index].getOrdinal();
1736cfca06d7SDimitry Andric       return Error::success();
173767c32a98SDimitry Andric     }
173867c32a98SDimitry Andric     RVA = Entry32[Index].getHintNameRVA();
173967c32a98SDimitry Andric   } else {
174067c32a98SDimitry Andric     if (Entry64[Index].isOrdinal()) {
174167c32a98SDimitry Andric       Result = Entry64[Index].getOrdinal();
1742cfca06d7SDimitry Andric       return Error::success();
174367c32a98SDimitry Andric     }
174467c32a98SDimitry Andric     RVA = Entry64[Index].getHintNameRVA();
174567c32a98SDimitry Andric   }
174667c32a98SDimitry Andric   uintptr_t IntPtr = 0;
1747145449b1SDimitry Andric   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol ordinal"))
174867c32a98SDimitry Andric     return EC;
174967c32a98SDimitry Andric   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
1750cfca06d7SDimitry Andric   return Error::success();
175167c32a98SDimitry Andric }
175267c32a98SDimitry Andric 
1753044eb2f6SDimitry Andric Expected<std::unique_ptr<COFFObjectFile>>
createCOFFObjectFile(MemoryBufferRef Object)175467c32a98SDimitry Andric ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1755cfca06d7SDimitry Andric   return COFFObjectFile::create(Object);
175667c32a98SDimitry Andric }
175767c32a98SDimitry Andric 
operator ==(const BaseRelocRef & Other) const175867c32a98SDimitry Andric bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
175967c32a98SDimitry Andric   return Header == Other.Header && Index == Other.Index;
176067c32a98SDimitry Andric }
176167c32a98SDimitry Andric 
moveNext()176267c32a98SDimitry Andric void BaseRelocRef::moveNext() {
176367c32a98SDimitry Andric   // Header->BlockSize is the size of the current block, including the
176467c32a98SDimitry Andric   // size of the header itself.
176567c32a98SDimitry Andric   uint32_t Size = sizeof(*Header) +
176667c32a98SDimitry Andric       sizeof(coff_base_reloc_block_entry) * (Index + 1);
176767c32a98SDimitry Andric   if (Size == Header->BlockSize) {
176867c32a98SDimitry Andric     // .reloc contains a list of base relocation blocks. Each block
176967c32a98SDimitry Andric     // consists of the header followed by entries. The header contains
177067c32a98SDimitry Andric     // how many entories will follow. When we reach the end of the
177167c32a98SDimitry Andric     // current block, proceed to the next block.
177267c32a98SDimitry Andric     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
177367c32a98SDimitry Andric         reinterpret_cast<const uint8_t *>(Header) + Size);
177467c32a98SDimitry Andric     Index = 0;
177567c32a98SDimitry Andric   } else {
177667c32a98SDimitry Andric     ++Index;
177767c32a98SDimitry Andric   }
177867c32a98SDimitry Andric }
177967c32a98SDimitry Andric 
getType(uint8_t & Type) const1780cfca06d7SDimitry Andric Error BaseRelocRef::getType(uint8_t &Type) const {
178167c32a98SDimitry Andric   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
178267c32a98SDimitry Andric   Type = Entry[Index].getType();
1783cfca06d7SDimitry Andric   return Error::success();
178467c32a98SDimitry Andric }
178567c32a98SDimitry Andric 
getRVA(uint32_t & Result) const1786cfca06d7SDimitry Andric Error BaseRelocRef::getRVA(uint32_t &Result) const {
178767c32a98SDimitry Andric   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
178867c32a98SDimitry Andric   Result = Header->PageRVA + Entry[Index].getOffset();
1789cfca06d7SDimitry Andric   return Error::success();
17905ca98fd9SDimitry Andric }
1791c46e6a59SDimitry Andric 
17921d5ae102SDimitry Andric #define RETURN_IF_ERROR(Expr)                                                  \
17931d5ae102SDimitry Andric   do {                                                                         \
17941d5ae102SDimitry Andric     Error E = (Expr);                                                          \
1795044eb2f6SDimitry Andric     if (E)                                                                     \
17961d5ae102SDimitry Andric       return std::move(E);                                                     \
17971d5ae102SDimitry Andric   } while (0)
1798c46e6a59SDimitry Andric 
1799044eb2f6SDimitry Andric Expected<ArrayRef<UTF16>>
getDirStringAtOffset(uint32_t Offset)1800044eb2f6SDimitry Andric ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1801c46e6a59SDimitry Andric   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1802c46e6a59SDimitry Andric   Reader.setOffset(Offset);
1803c46e6a59SDimitry Andric   uint16_t Length;
1804c46e6a59SDimitry Andric   RETURN_IF_ERROR(Reader.readInteger(Length));
1805c46e6a59SDimitry Andric   ArrayRef<UTF16> RawDirString;
1806c46e6a59SDimitry Andric   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1807c46e6a59SDimitry Andric   return RawDirString;
1808c46e6a59SDimitry Andric }
1809c46e6a59SDimitry Andric 
1810044eb2f6SDimitry Andric Expected<ArrayRef<UTF16>>
getEntryNameString(const coff_resource_dir_entry & Entry)1811c46e6a59SDimitry Andric ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1812c46e6a59SDimitry Andric   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1813c46e6a59SDimitry Andric }
1814c46e6a59SDimitry Andric 
1815044eb2f6SDimitry Andric Expected<const coff_resource_dir_table &>
getTableAtOffset(uint32_t Offset)1816c46e6a59SDimitry Andric ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1817c46e6a59SDimitry Andric   const coff_resource_dir_table *Table = nullptr;
1818c46e6a59SDimitry Andric 
1819c46e6a59SDimitry Andric   BinaryStreamReader Reader(BBS);
1820c46e6a59SDimitry Andric   Reader.setOffset(Offset);
1821c46e6a59SDimitry Andric   RETURN_IF_ERROR(Reader.readObject(Table));
1822c46e6a59SDimitry Andric   assert(Table != nullptr);
1823c46e6a59SDimitry Andric   return *Table;
1824c46e6a59SDimitry Andric }
1825c46e6a59SDimitry Andric 
18261d5ae102SDimitry Andric Expected<const coff_resource_dir_entry &>
getTableEntryAtOffset(uint32_t Offset)18271d5ae102SDimitry Andric ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {
18281d5ae102SDimitry Andric   const coff_resource_dir_entry *Entry = nullptr;
18291d5ae102SDimitry Andric 
18301d5ae102SDimitry Andric   BinaryStreamReader Reader(BBS);
18311d5ae102SDimitry Andric   Reader.setOffset(Offset);
18321d5ae102SDimitry Andric   RETURN_IF_ERROR(Reader.readObject(Entry));
18331d5ae102SDimitry Andric   assert(Entry != nullptr);
18341d5ae102SDimitry Andric   return *Entry;
18351d5ae102SDimitry Andric }
18361d5ae102SDimitry Andric 
18371d5ae102SDimitry Andric Expected<const coff_resource_data_entry &>
getDataEntryAtOffset(uint32_t Offset)18381d5ae102SDimitry Andric ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) {
18391d5ae102SDimitry Andric   const coff_resource_data_entry *Entry = nullptr;
18401d5ae102SDimitry Andric 
18411d5ae102SDimitry Andric   BinaryStreamReader Reader(BBS);
18421d5ae102SDimitry Andric   Reader.setOffset(Offset);
18431d5ae102SDimitry Andric   RETURN_IF_ERROR(Reader.readObject(Entry));
18441d5ae102SDimitry Andric   assert(Entry != nullptr);
18451d5ae102SDimitry Andric   return *Entry;
18461d5ae102SDimitry Andric }
18471d5ae102SDimitry Andric 
1848044eb2f6SDimitry Andric Expected<const coff_resource_dir_table &>
getEntrySubDir(const coff_resource_dir_entry & Entry)1849c46e6a59SDimitry Andric ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
18501d5ae102SDimitry Andric   assert(Entry.Offset.isSubDir());
1851c46e6a59SDimitry Andric   return getTableAtOffset(Entry.Offset.value());
1852c46e6a59SDimitry Andric }
1853c46e6a59SDimitry Andric 
18541d5ae102SDimitry Andric Expected<const coff_resource_data_entry &>
getEntryData(const coff_resource_dir_entry & Entry)18551d5ae102SDimitry Andric ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) {
18561d5ae102SDimitry Andric   assert(!Entry.Offset.isSubDir());
18571d5ae102SDimitry Andric   return getDataEntryAtOffset(Entry.Offset.value());
18581d5ae102SDimitry Andric }
18591d5ae102SDimitry Andric 
getBaseTable()1860044eb2f6SDimitry Andric Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1861c46e6a59SDimitry Andric   return getTableAtOffset(0);
1862c46e6a59SDimitry Andric }
18631d5ae102SDimitry Andric 
18641d5ae102SDimitry Andric Expected<const coff_resource_dir_entry &>
getTableEntry(const coff_resource_dir_table & Table,uint32_t Index)18651d5ae102SDimitry Andric ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,
18661d5ae102SDimitry Andric                                   uint32_t Index) {
18671d5ae102SDimitry Andric   if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
18681d5ae102SDimitry Andric     return createStringError(object_error::parse_failed, "index out of range");
18691d5ae102SDimitry Andric   const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);
18701d5ae102SDimitry Andric   ptrdiff_t TableOffset = TablePtr - BBS.data().data();
18711d5ae102SDimitry Andric   return getTableEntryAtOffset(TableOffset + sizeof(Table) +
18721d5ae102SDimitry Andric                                Index * sizeof(coff_resource_dir_entry));
18731d5ae102SDimitry Andric }
18741d5ae102SDimitry Andric 
load(const COFFObjectFile * O)18751d5ae102SDimitry Andric Error ResourceSectionRef::load(const COFFObjectFile *O) {
18761d5ae102SDimitry Andric   for (const SectionRef &S : O->sections()) {
18771d5ae102SDimitry Andric     Expected<StringRef> Name = S.getName();
18781d5ae102SDimitry Andric     if (!Name)
18791d5ae102SDimitry Andric       return Name.takeError();
18801d5ae102SDimitry Andric 
18811d5ae102SDimitry Andric     if (*Name == ".rsrc" || *Name == ".rsrc$01")
18821d5ae102SDimitry Andric       return load(O, S);
18831d5ae102SDimitry Andric   }
18841d5ae102SDimitry Andric   return createStringError(object_error::parse_failed,
18851d5ae102SDimitry Andric                            "no resource section found");
18861d5ae102SDimitry Andric }
18871d5ae102SDimitry Andric 
load(const COFFObjectFile * O,const SectionRef & S)18881d5ae102SDimitry Andric Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {
18891d5ae102SDimitry Andric   Obj = O;
18901d5ae102SDimitry Andric   Section = S;
18911d5ae102SDimitry Andric   Expected<StringRef> Contents = Section.getContents();
18921d5ae102SDimitry Andric   if (!Contents)
18931d5ae102SDimitry Andric     return Contents.takeError();
1894b1c73532SDimitry Andric   BBS = BinaryByteStream(*Contents, llvm::endianness::little);
18951d5ae102SDimitry Andric   const coff_section *COFFSect = Obj->getCOFFSection(Section);
18961d5ae102SDimitry Andric   ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);
18971d5ae102SDimitry Andric   Relocs.reserve(OrigRelocs.size());
18981d5ae102SDimitry Andric   for (const coff_relocation &R : OrigRelocs)
18991d5ae102SDimitry Andric     Relocs.push_back(&R);
1900b60736ecSDimitry Andric   llvm::sort(Relocs, [](const coff_relocation *A, const coff_relocation *B) {
19011d5ae102SDimitry Andric     return A->VirtualAddress < B->VirtualAddress;
19021d5ae102SDimitry Andric   });
19031d5ae102SDimitry Andric   return Error::success();
19041d5ae102SDimitry Andric }
19051d5ae102SDimitry Andric 
19061d5ae102SDimitry Andric Expected<StringRef>
getContents(const coff_resource_data_entry & Entry)19071d5ae102SDimitry Andric ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
19081d5ae102SDimitry Andric   if (!Obj)
19091d5ae102SDimitry Andric     return createStringError(object_error::parse_failed, "no object provided");
19101d5ae102SDimitry Andric 
19111d5ae102SDimitry Andric   // Find a potential relocation at the DataRVA field (first member of
19121d5ae102SDimitry Andric   // the coff_resource_data_entry struct).
19131d5ae102SDimitry Andric   const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);
19141d5ae102SDimitry Andric   ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
19151d5ae102SDimitry Andric   coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),
19161d5ae102SDimitry Andric                               ulittle16_t(0)};
19171d5ae102SDimitry Andric   auto RelocsForOffset =
19181d5ae102SDimitry Andric       std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
19191d5ae102SDimitry Andric                        [](const coff_relocation *A, const coff_relocation *B) {
19201d5ae102SDimitry Andric                          return A->VirtualAddress < B->VirtualAddress;
19211d5ae102SDimitry Andric                        });
19221d5ae102SDimitry Andric 
19231d5ae102SDimitry Andric   if (RelocsForOffset.first != RelocsForOffset.second) {
19241d5ae102SDimitry Andric     // We found a relocation with the right offset. Check that it does have
19251d5ae102SDimitry Andric     // the expected type.
19261d5ae102SDimitry Andric     const coff_relocation &R = **RelocsForOffset.first;
19271d5ae102SDimitry Andric     uint16_t RVAReloc;
1928ac9a064cSDimitry Andric     switch (Obj->getArch()) {
1929ac9a064cSDimitry Andric     case Triple::x86:
19301d5ae102SDimitry Andric       RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
19311d5ae102SDimitry Andric       break;
1932ac9a064cSDimitry Andric     case Triple::x86_64:
19331d5ae102SDimitry Andric       RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
19341d5ae102SDimitry Andric       break;
1935ac9a064cSDimitry Andric     case Triple::thumb:
19361d5ae102SDimitry Andric       RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
19371d5ae102SDimitry Andric       break;
1938ac9a064cSDimitry Andric     case Triple::aarch64:
19391d5ae102SDimitry Andric       RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
19401d5ae102SDimitry Andric       break;
19411d5ae102SDimitry Andric     default:
19421d5ae102SDimitry Andric       return createStringError(object_error::parse_failed,
19431d5ae102SDimitry Andric                                "unsupported architecture");
19441d5ae102SDimitry Andric     }
19451d5ae102SDimitry Andric     if (R.Type != RVAReloc)
19461d5ae102SDimitry Andric       return createStringError(object_error::parse_failed,
19471d5ae102SDimitry Andric                                "unexpected relocation type");
19481d5ae102SDimitry Andric     // Get the relocation's symbol
19491d5ae102SDimitry Andric     Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);
19501d5ae102SDimitry Andric     if (!Sym)
19511d5ae102SDimitry Andric       return Sym.takeError();
19521d5ae102SDimitry Andric     // And the symbol's section
1953cfca06d7SDimitry Andric     Expected<const coff_section *> Section =
1954cfca06d7SDimitry Andric         Obj->getSection(Sym->getSectionNumber());
1955cfca06d7SDimitry Andric     if (!Section)
1956cfca06d7SDimitry Andric       return Section.takeError();
19571d5ae102SDimitry Andric     // Add the initial value of DataRVA to the symbol's offset to find the
19581d5ae102SDimitry Andric     // data it points at.
19591d5ae102SDimitry Andric     uint64_t Offset = Entry.DataRVA + Sym->getValue();
19601d5ae102SDimitry Andric     ArrayRef<uint8_t> Contents;
1961cfca06d7SDimitry Andric     if (Error E = Obj->getSectionContents(*Section, Contents))
1962ac9a064cSDimitry Andric       return E;
19631d5ae102SDimitry Andric     if (Offset + Entry.DataSize > Contents.size())
19641d5ae102SDimitry Andric       return createStringError(object_error::parse_failed,
19651d5ae102SDimitry Andric                                "data outside of section");
19661d5ae102SDimitry Andric     // Return a reference to the data inside the section.
19671d5ae102SDimitry Andric     return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,
19681d5ae102SDimitry Andric                      Entry.DataSize);
19691d5ae102SDimitry Andric   } else {
19701d5ae102SDimitry Andric     // Relocatable objects need a relocation for the DataRVA field.
19711d5ae102SDimitry Andric     if (Obj->isRelocatableObject())
19721d5ae102SDimitry Andric       return createStringError(object_error::parse_failed,
19731d5ae102SDimitry Andric                                "no relocation found for DataRVA");
19741d5ae102SDimitry Andric 
19751d5ae102SDimitry Andric     // Locate the section that contains the address that DataRVA points at.
19761d5ae102SDimitry Andric     uint64_t VA = Entry.DataRVA + Obj->getImageBase();
19771d5ae102SDimitry Andric     for (const SectionRef &S : Obj->sections()) {
19781d5ae102SDimitry Andric       if (VA >= S.getAddress() &&
19791d5ae102SDimitry Andric           VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
19801d5ae102SDimitry Andric         uint64_t Offset = VA - S.getAddress();
19811d5ae102SDimitry Andric         Expected<StringRef> Contents = S.getContents();
19821d5ae102SDimitry Andric         if (!Contents)
19831d5ae102SDimitry Andric           return Contents.takeError();
19841d5ae102SDimitry Andric         return Contents->slice(Offset, Offset + Entry.DataSize);
19851d5ae102SDimitry Andric       }
19861d5ae102SDimitry Andric     }
19871d5ae102SDimitry Andric     return createStringError(object_error::parse_failed,
19881d5ae102SDimitry Andric                              "address not found in image");
19891d5ae102SDimitry Andric   }
19901d5ae102SDimitry Andric }
1991