35#include <system_error>
47 if (M.getBufferSize() <
Size) {
48 EC = object_error::unexpected_eof;
62 Obj =
reinterpret_cast<const T *
>(Addr);
69 assert(Str.size() <= 6 &&
"String too long, possible overflow.");
74 while (!Str.empty()) {
76 if (Str[0] >=
'A' && Str[0] <=
'Z')
77 CharVal = Str[0] -
'A';
78 else if (Str[0] >=
'a' && Str[0] <=
'z')
79 CharVal = Str[0] -
'a' + 26;
80 else if (Str[0] >=
'0' && Str[0] <=
'9')
81 CharVal = Str[0] -
'0' + 52;
82 else if (Str[0] ==
'+')
84 else if (Str[0] ==
'/')
93 if (
Value > std::numeric_limits<uint32_t>::max())
100template <
typename coff_symbol_type>
101const coff_symbol_type *COFFObjectFile::toSymb(
DataRefImpl Ref)
const {
102 const coff_symbol_type *Addr =
103 reinterpret_cast<const coff_symbol_type *
>(
Ref.p);
109 reinterpret_cast<uintptr_t
>(Addr) -
reinterpret_cast<uintptr_t
>(
base());
112 "Symbol did not point to the beginning of a symbol");
119 const coff_section *Addr =
reinterpret_cast<const coff_section*
>(
Ref.p);
126 uintptr_t
Offset =
reinterpret_cast<uintptr_t
>(Addr) -
127 reinterpret_cast<uintptr_t
>(SectionTable);
129 "Section did not point to the beginning of a section");
136 auto End =
reinterpret_cast<uintptr_t>(StringTable);
140 Ref.p = std::min(
reinterpret_cast<uintptr_t>(Symb), End);
141 }
else if (SymbolTable32) {
144 Ref.p = std::min(
reinterpret_cast<uintptr_t>(Symb), End);
176 return Section.takeError();
177 Result += (*Section)->VirtualAddress;
285 return toSec(Sec) - SectionTable;
332 if (!SectionNameOrErr) {
416Error COFFObjectFile::initSymbolTablePtr() {
423 if (COFFBigObjHeader)
435 const ulittle32_t *StringTableSizePtr;
438 StringTableSize = *StringTableSizePtr;
444 if (StringTableSize < 4)
448 if (StringTableSize > 4 &&
StringTable[StringTableSize - 1] != 0)
450 "string table missing null terminator");
456 return PE32Header->ImageBase;
457 else if (PE32PlusHeader)
458 return PE32PlusHeader->ImageBase;
467 assert(Rva <= UINT32_MAX);
473 const char *ErrorContext)
const {
476 uint32_t SectionStart = Section->VirtualAddress;
477 uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
478 if (SectionStart <= Addr && Addr < SectionEnd) {
488 if (Section->SizeOfRawData < Section->VirtualSize &&
489 Addr >= SectionStart + Section->SizeOfRawData) {
493 Res =
reinterpret_cast<uintptr_t>(
base()) + Section->PointerToRawData +
500 "RVA 0x%" PRIx32
" for %s not found", Addr,
503 "RVA 0x%" PRIx32
" not found", Addr);
508 const char *ErrorContext)
const {
511 uint32_t SectionStart = Section->VirtualAddress;
514 uint32_t OffsetIntoSection = RVA - SectionStart;
515 if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
518 Section->PointerToRawData + OffsetIntoSection;
526 "RVA 0x%" PRIx32
" for %s not found", RVA,
529 "RVA 0x%" PRIx32
" not found", RVA);
540 Hint = *
reinterpret_cast<const ulittle16_t *
>(Ptr);
541 Name =
StringRef(
reinterpret_cast<const char *
>(Ptr + 2));
551 InfoBytes,
"PDB info"))
553 if (InfoBytes.
size() <
sizeof(*PDBInfo) + 1)
556 InfoBytes = InfoBytes.
drop_front(
sizeof(*PDBInfo));
557 PDBFileName =
StringRef(
reinterpret_cast<const char *
>(InfoBytes.
data()),
560 PDBFileName = PDBFileName.
split(
'\0').first;
576Error COFFObjectFile::initImportTablePtr() {
596 ImportDirectory =
reinterpret_cast<
602Error COFFObjectFile::initDelayImportTablePtr() {
611 NumberOfDelayImportDirectory = DataEntry->
Size /
620 DelayImportDirectory =
reinterpret_cast<
626Error COFFObjectFile::initExportTablePtr() {
649Error COFFObjectFile::initBaseRelocPtr() {
650 const data_directory *DataEntry =
657 uintptr_t IntPtr = 0;
664 BaseRelocHeader =
reinterpret_cast<const coff_base_reloc_block_header *
>(
666 BaseRelocEnd =
reinterpret_cast<coff_base_reloc_block_header *
>(
667 IntPtr + DataEntry->
Size);
673Error COFFObjectFile::initDebugDirectoryPtr() {
684 if (DataEntry->
Size %
sizeof(debug_directory) != 0)
686 "debug directory has uneven size");
688 uintptr_t IntPtr = 0;
695 DebugDirectoryBegin =
reinterpret_cast<const debug_directory *
>(IntPtr);
696 DebugDirectoryEnd =
reinterpret_cast<const debug_directory *
>(
697 IntPtr + DataEntry->
Size);
703Error COFFObjectFile::initTLSDirectoryPtr() {
717 if (DataEntry->
Size != DirSize)
720 "TLS Directory size (%u) is not the expected size (%" PRIu64
").",
721 static_cast<uint32_t
>(DataEntry->
Size), DirSize);
723 uintptr_t IntPtr = 0;
738Error COFFObjectFile::initLoadConfigPtr() {
747 uintptr_t IntPtr = 0;
749 "load config table"))
754 LoadConfig = (
const void *)IntPtr;
759 offsetof(coff_load_configuration64, CHPEMetadataPointer) +
760 sizeof(Config->CHPEMetadataPointer) &&
761 Config->CHPEMetadataPointer) {
762 uint64_t ChpeOff = Config->CHPEMetadataPointer;
769 CHPEMetadata =
reinterpret_cast<const chpe_metadata *
>(IntPtr);
772 if (CHPEMetadata->CodeMapCount) {
773 if (
Error E =
getRvaPtr(CHPEMetadata->CodeMap, IntPtr,
"CHPE code map"))
776 CHPEMetadata->CodeMapCount *
777 sizeof(chpe_range_entry)))
781 if (CHPEMetadata->CodeRangesToEntryPointsCount) {
783 "CHPE entry point ranges"))
786 CHPEMetadata->CodeRangesToEntryPointsCount *
787 sizeof(chpe_code_range_entry)))
791 if (CHPEMetadata->RedirectionMetadataCount) {
793 "CHPE redirection metadata"))
796 CHPEMetadata->RedirectionMetadataCount *
797 sizeof(chpe_redirection_entry)))
803 offsetof(coff_load_configuration64, DynamicValueRelocTableSection) +
804 sizeof(Config->DynamicValueRelocTableSection))
805 if (
Error E = initDynamicRelocPtr(Config->DynamicValueRelocTableSection,
806 Config->DynamicValueRelocTableOffset))
811 offsetof(coff_load_configuration32, DynamicValueRelocTableSection) +
812 sizeof(Config->DynamicValueRelocTableSection)) {
813 if (
Error E = initDynamicRelocPtr(Config->DynamicValueRelocTableSection,
814 Config->DynamicValueRelocTableOffset))
821Error COFFObjectFile::initDynamicRelocPtr(uint32_t SectionIndex,
822 uint32_t SectionOffset) {
830 ArrayRef<uint8_t> Contents;
834 Contents = Contents.
drop_front(SectionOffset);
835 if (Contents.
size() <
sizeof(coff_dynamic_reloc_table))
837 "Too large DynamicValueRelocTableOffset (" +
838 Twine(SectionOffset) +
")");
841 reinterpret_cast<const coff_dynamic_reloc_table *
>(Contents.
data());
843 if (DynamicRelocTable->Version != 1 && DynamicRelocTable->Version != 2)
845 "Unsupported dynamic relocations table version (" +
846 Twine(DynamicRelocTable->Version) +
")");
847 if (DynamicRelocTable->Size > Contents.
size() -
sizeof(*DynamicRelocTable))
849 "Indvalid dynamic relocations directory size (" +
850 Twine(DynamicRelocTable->Size) +
")");
853 if (
Error e = DynReloc.validate())
860Expected<std::unique_ptr<COFFObjectFile>>
862 std::unique_ptr<COFFObjectFile> Obj(
new COFFObjectFile(std::move(Object)));
863 if (
Error E = Obj->initialize())
865 return std::move(Obj);
870 COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
871 DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
872 SymbolTable32(nullptr),
StringTable(nullptr), StringTableSize(0),
873 ImportDirectory(nullptr), DelayImportDirectory(nullptr),
874 NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
875 BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
876 DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
877 TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
887Error COFFObjectFile::initialize() {
898 bool HasPEHeader =
false;
904 const auto *DH =
reinterpret_cast<const dos_header *
>(
base());
905 if (DH->Magic[0] ==
'M' && DH->Magic[1] ==
'Z') {
906 CurPtr = DH->AddressOfNewExeHeader;
910 "incorrect PE magic");
923 COFFHeader->NumberOfSections == uint16_t(0xffff) &&
932 COFFHeader =
nullptr;
933 CurPtr +=
sizeof(coff_bigobj_file_header);
936 COFFBigObjHeader =
nullptr;
942 EC = std::error_code();
943 CurPtr +=
sizeof(coff_file_header);
945 if (COFFHeader->isImportLibrary())
950 const pe32_header *Header;
954 const uint8_t *DataDirAddr;
955 uint64_t DataDirSize;
958 DataDirAddr =
base() + CurPtr +
sizeof(pe32_header);
959 DataDirSize =
sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
961 PE32PlusHeader =
reinterpret_cast<const pe32plus_header *
>(Header);
962 DataDirAddr =
base() + CurPtr +
sizeof(pe32plus_header);
963 DataDirSize =
sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
967 "incorrect PE magic");
974 CurPtr += COFFHeader->SizeOfOptionalHeader;
976 assert(COFFHeader || COFFBigObjHeader);
985 if (
Error E = initSymbolTablePtr()) {
988 SymbolTable16 =
nullptr;
989 SymbolTable32 =
nullptr;
990 StringTable =
nullptr;
997 "symbol table missing");
1038 Ret.
p =
reinterpret_cast<uintptr_t>(StringTable);
1043 if (!ImportDirectory)
1045 if (ImportDirectory->isNull())
1066 DelayImportDirectory, NumberOfDelayImportDirectory,
this));
1075 if (!ExportDirectory)
1078 ExportDirectory->AddressTableEntries,
this);
1084 Ret.
p =
reinterpret_cast<uintptr_t>(SectionTable);
1092 Ret.
p =
reinterpret_cast<uintptr_t>(SectionTable + NumSections);
1105 const void *Header = DynamicRelocTable ? DynamicRelocTable + 1 :
nullptr;
1110 const void *Header =
nullptr;
1111 if (DynamicRelocTable)
1112 Header =
reinterpret_cast<const uint8_t *
>(DynamicRelocTable + 1) +
1113 DynamicRelocTable->Size;
1126 return "COFF-x86-64";
1130 return "COFF-ARM64";
1132 return "COFF-ARM64EC";
1134 return "COFF-ARM64X";
1138 return "COFF-<unknown arch>";
1148 return PE32Header->AddressOfEntryPoint;
1179 assert(PE32Header || PE32PlusHeader);
1180 uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
1181 : PE32PlusHeader->NumberOfRvaAndSize;
1182 if (Index >= NumEnt)
1184 return &DataDirectory[Index];
1194 return SectionTable + (Index - 1);
1197 "section index out of bounds");
1201 if (StringTableSize <= 4)
1204 if (
Offset >= StringTableSize)
1216 if (Symbol->Name.Offset.Zeroes == 0)
1217 return getString(Symbol->Name.Offset.Offset);
1221 return StringRef(Symbol->Name.ShortName);
1232 if (Symbol.getNumberOfAuxSymbols() > 0) {
1234 Aux =
reinterpret_cast<const uint8_t *
>(Symbol.getRawPtr()) + SymbolSize;
1244 "Aux Symbol data did not point to the beginning of a symbol");
1247 return ArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
1254 "Symbol did not point to the beginning of a symbol");
1265 if (Name.starts_with(
"/")) {
1267 if (Name.starts_with(
"//")) {
1270 "invalid section name");
1272 if (Name.substr(1).getAsInteger(10,
Offset))
1274 "invalid section name");
1276 return getString(
Offset);
1312 Res =
ArrayRef(
reinterpret_cast<const uint8_t *
>(ConStart), SectionSize);
1327 return R->VirtualAddress;
1336 Ref.p =
reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
1337 else if (SymbolTable32)
1338 Ref.p =
reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
1351 return toSec(Section.getRawDataRefImpl());
1356 return toSymb<coff_symbol16>(
Ref);
1358 return toSymb<coff_symbol32>(
Ref);
1368 return toRel(
Reloc.getRawDataRefImpl());
1377#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \
1378 case COFF::reloc_type: \
1496#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1502 Result.append(Res.
begin(), Res.
end());
1506 return !DataDirectory;
1511 .
Case(
"eh_fram",
"eh_frame")
1519 std::unique_ptr<WritableMemoryBuffer> HybridView;
1525 for (
auto reloc : DynReloc.arm64x_relocs()) {
1529 memcpy(HybridView->getBufferStart(),
Data.getBufferStart(),
1530 Data.getBufferSize());
1538 Ptr = HybridView->getBufferStart() + IntPtr -
1542 Ptr = HybridView->getBufferStart() + RVA;
1545 switch (reloc.getType()) {
1547 memset(Ptr, 0, reloc.getSize());
1550 auto Value =
static_cast<ulittle64_t
>(reloc.getValue());
1551 memcpy(Ptr, &
Value, reloc.getSize());
1555 *
reinterpret_cast<ulittle32_t *
>(Ptr) += reloc.getValue();
1565 return std::nullopt;
1580 return std::nullopt;
1585 return ImportTable ==
Other.ImportTable && Index ==
Other.Index;
1590 if (ImportTable[Index].isNull()) {
1592 ImportTable =
nullptr;
1598 return getObject(Result, OwningObject->Data, ImportTable + Index);
1604 if (Object->getBytesInAddress() == 4) {
1616 cantFail(Object->getRvaPtr(RVA, IntPtr));
1624 cantFail(Object->getRvaPtr(RVA, IntPtr));
1627 if (Object->getBytesInAddress() == 4) {
1628 auto *Entry =
reinterpret_cast<ulittle32_t *
>(IntPtr);
1632 auto *Entry =
reinterpret_cast<ulittle64_t *
>(IntPtr);
1673 if (
Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr,
1674 "import directory name"))
1676 Result =
StringRef(
reinterpret_cast<const char *
>(IntPtr));
1682 Result = ImportTable[Index].ImportLookupTableRVA;
1688 Result = ImportTable[Index].ImportAddressTableRVA;
1694 return Table ==
Other.Table && Index ==
Other.Index;
1720 if (
Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr,
1721 "delay import directory name"))
1723 Result =
StringRef(
reinterpret_cast<const char *
>(IntPtr));
1729 Result = &Table[Index];
1735 uint32_t RVA = Table[Index].DelayImportAddressTable +
1736 AddrIndex * (OwningObject->is64() ? 8 : 4);
1738 if (
Error E = OwningObject->getRvaPtr(RVA, IntPtr,
"import address"))
1740 if (OwningObject->is64())
1741 Result = *
reinterpret_cast<const ulittle64_t *
>(IntPtr);
1743 Result = *
reinterpret_cast<const ulittle32_t *
>(IntPtr);
1749 return ExportTable ==
Other.ExportTable && Index ==
Other.Index;
1761 OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr,
"dll name"))
1763 Result =
StringRef(
reinterpret_cast<const char *
>(IntPtr));
1769 Result = ExportTable->OrdinalBase;
1775 Result = ExportTable->OrdinalBase + Index;
1782 if (
Error EC = OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA,
1783 IntPtr,
"export address"))
1796 if (
Error EC = OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr,
1797 "export ordinal table"))
1799 const ulittle16_t *Start =
reinterpret_cast<const ulittle16_t *
>(IntPtr);
1801 uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1803 for (
const ulittle16_t *
I = Start, *E = Start + NumEntries;
1807 if (
Error EC = OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr,
1808 "export table entry"))
1810 const ulittle32_t *NamePtr =
reinterpret_cast<const ulittle32_t *
>(IntPtr);
1811 if (
Error EC = OwningObject->getRvaPtr(NamePtr[
Offset], IntPtr,
1812 "export symbol name"))
1814 Result =
StringRef(
reinterpret_cast<const char *
>(IntPtr));
1826 "export table missing");
1832 Result = (Begin <= RVA && RVA < End);
1841 if (
auto EC = OwningObject->getRvaPtr(RVA, IntPtr,
"export forward target"))
1843 Result =
StringRef(
reinterpret_cast<const char *
>(IntPtr));
1849 return Entry32 ==
Other.Entry32 && Entry64 ==
Other.Entry64
1850 && Index ==
Other.Index;
1863 RVA = Entry32[Index].getHintNameRVA();
1867 RVA = Entry64[Index].getHintNameRVA();
1870 if (
Error EC = OwningObject->getRvaPtr(RVA, IntPtr,
"import symbol name"))
1873 Result =
StringRef(
reinterpret_cast<const char *
>(IntPtr + 2));
1879 Result = Entry32[Index].isOrdinal();
1881 Result = Entry64[Index].isOrdinal();
1887 Result = Entry32[Index].getHintNameRVA();
1889 Result = Entry64[Index].getHintNameRVA();
1897 Result = Entry32[Index].getOrdinal();
1900 RVA = Entry32[Index].getHintNameRVA();
1903 Result = Entry64[Index].getOrdinal();
1906 RVA = Entry64[Index].getHintNameRVA();
1909 if (
Error EC = OwningObject->getRvaPtr(RVA, IntPtr,
"import symbol ordinal"))
1911 Result = *
reinterpret_cast<const ulittle16_t *
>(IntPtr);
1921 return Header ==
Other.Header && Index ==
Other.Index;
1929 if (
Size == Header->BlockSize) {
1935 reinterpret_cast<const uint8_t *
>(Header) +
Size);
1944 Type = Entry[Index].getType();
1950 Result = Header->PageRVA + Entry[Index].getOffset();
1955 return Header ==
Other.Header;
1959 switch (Obj->getDynamicRelocTable()->Version) {
1963 Header +=
sizeof(*H) +
H->BaseRelocSize;
1966 Header +=
sizeof(*H) +
H->BaseRelocSize;
1972 Header +=
H->HeaderSize +
H->FixupInfoSize;
1975 Header +=
H->HeaderSize +
H->FixupInfoSize;
1982 switch (Obj->getDynamicRelocTable()->Version) {
2007 switch (Obj->getDynamicRelocTable()->Version) {
2029Error DynamicRelocRef::validate()
const {
2031 size_t ContentsSize =
2032 reinterpret_cast<const uint8_t *
>(Table + 1) + Table->
Size - Header;
2040 if (HeaderSize > ContentsSize)
2042 "Unexpected end of dynamic relocations data");
2047 ? reinterpret_cast<const coff_dynamic_relocation64_v2 *>(Header)
2049 : reinterpret_cast<const coff_dynamic_relocation32_v2 *>(Header)
2051 if (Size < HeaderSize || Size > ContentsSize)
2052 return createStringError(object_error::parse_failed,
2053 "Invalid dynamic relocation header size (" +
2060 if (Contents.
size() > ContentsSize - HeaderSize)
2062 "Too large dynamic relocation size (" +
2100 return Header ==
Other.Header && Index ==
Other.Index;
2103uint8_t Arm64XRelocRef::getEntrySize()
const {
2106 return (1ull << getArg()) /
sizeof(
uint16_t) + 1;
2115 Index += getEntrySize();
2116 if (
sizeof(*Header) + Index *
sizeof(
uint16_t) < Header->BlockSize &&
2119 if (
sizeof(*Header) + Index *
sizeof(
uint16_t) == Header->BlockSize) {
2131 return 1 << getArg();
2139 auto Ptr =
reinterpret_cast<const ulittle16_t *
>(Header + 1) + Index + 1;
2143 ulittle64_t
Value(0);
2153 delta *= (arg & 2) ? 8 : 4;
2164 size_t ContentsSize =
reinterpret_cast<const uint8_t *
>(Table + 1) +
2166 reinterpret_cast<const uint8_t *
>(Header);
2169 "Unexpected end of ARM64X relocations data");
2170 if (Header->BlockSize <=
sizeof(*Header))
2172 "ARM64X relocations block size (" +
2173 Twine(Header->BlockSize) +
") is too small");
2174 if (Header->BlockSize %
sizeof(
uint32_t))
2176 "Unaligned ARM64X relocations block size (" +
2177 Twine(Header->BlockSize) +
")");
2178 if (Header->BlockSize > ContentsSize)
2180 "ARM64X relocations block size (" +
2181 Twine(Header->BlockSize) +
") is too large");
2182 if (Header->PageRVA & 0xfff)
2184 "Unaligned ARM64X relocations page RVA (" +
2185 Twine(Header->PageRVA) +
")");
2188 switch ((getReloc() >> 12) & 3) {
2195 "Invalid ARM64X relocation value size (0)");
2199 "Invalid relocation type");
2203 (Header->BlockSize -
sizeof(*Header)) /
sizeof(
uint16_t);
2204 uint16_t EntrySize = getEntrySize();
2206 (Index + EntrySize + 1 < RelocsSize && !getReloc(EntrySize)))
2208 "Unexpected ARM64X relocations terminator");
2209 if (Index + EntrySize > RelocsSize)
2211 "Unexpected end of ARM64X relocations");
2214 "Unaligned ARM64X relocation RVA (" +
2216 if (Header->PageRVA) {
2218 return Obj->getRvaPtr(
getRVA() +
getSize(), IntPtr,
"ARM64X reloc");
2223#define RETURN_IF_ERROR(Expr) \
2227 return std::move(E); \
2238 return RawDirString;
2241Expected<ArrayRef<UTF16>>
2243 return getDirStringAtOffset(Entry.Identifier.getNameOffset());
2251 Reader.setOffset(
Offset);
2253 assert(Table !=
nullptr);
2262 Reader.setOffset(
Offset);
2264 assert(Entry !=
nullptr);
2273 Reader.setOffset(
Offset);
2275 assert(Entry !=
nullptr);
2279Expected<const coff_resource_dir_table &>
2281 assert(Entry.Offset.isSubDir());
2282 return getTableAtOffset(Entry.Offset.value());
2287 assert(!Entry.Offset.isSubDir());
2288 return getDataEntryAtOffset(Entry.Offset.value());
2292 return getTableAtOffset(0);
2300 const uint8_t *TablePtr =
reinterpret_cast<const uint8_t *
>(&Table);
2301 ptrdiff_t TableOffset = TablePtr - BBS.data().data();
2302 return getTableEntryAtOffset(TableOffset +
sizeof(Table) +
2310 return Name.takeError();
2312 if (*Name ==
".rsrc" || *Name ==
".rsrc$01")
2316 "no resource section found");
2326 const coff_section *COFFSect = Obj->getCOFFSection(Section);
2328 Relocs.reserve(OrigRelocs.
size());
2330 Relocs.push_back(&R);
2332 return A->VirtualAddress <
B->VirtualAddress;
2344 const uint8_t *EntryPtr =
reinterpret_cast<const uint8_t *
>(&Entry);
2345 ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
2348 auto RelocsForOffset =
2349 std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
2351 return A->VirtualAddress < B->VirtualAddress;
2354 if (RelocsForOffset.first != RelocsForOffset.second) {
2359 switch (Obj->getArch()) {
2377 "unsupported architecture");
2379 if (R.Type != RVAReloc)
2381 "unexpected relocation type");
2388 Obj->getSection(Sym->getSectionNumber());
2395 if (
Error E = Obj->getSectionContents(*Section, Contents))
2397 if (
Offset + Entry.DataSize > Contents.
size())
2399 "data outside of section");
2405 if (Obj->isRelocatableObject())
2407 "no relocation found for DataRVA");
2410 uint64_t VA = Entry.DataRVA + Obj->getImageBase();
2411 for (
const SectionRef &S : Obj->sections()) {
2412 if (VA >= S.getAddress() &&
2413 VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
2418 return Contents->substr(
Offset, Entry.DataSize);
2422 "address not found in image");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Mark last scratch load
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static imported_symbol_iterator importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object)
static uint32_t getNumberOfRelocations(const coff_section *Sec, MemoryBufferRef M, const uint8_t *base)
static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr, const uint64_t Size=sizeof(T))
static imported_symbol_iterator makeImportedSymbolIterator(const COFFObjectFile *Object, uintptr_t Ptr, int Index)
#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)
static const coff_relocation * getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base)
static imported_symbol_iterator importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object)
static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size)
#define RETURN_IF_ERROR(Expr)
static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result)
static Error ignoreStrippedErrors(Error E)
#define offsetof(TYPE, MEMBER)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
Get the array size.
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer.
Provides read only access to a subclass of BinaryStream.
Error readInteger(T &Dest)
Read an integer of the specified endianness into Dest and update the stream's offset.
void setOffset(uint64_t Off)
Error readArray(ArrayRef< T > &Array, uint32_t NumElements)
Get a reference to a NumElements element array of objects of type T from the underlying stream as if ...
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
A table of densely packed, null-terminated strings indexed by offset.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
static LLVM_ABI std::unique_ptr< WritableMemoryBuffer > getNewUninitMemBuffer(size_t Size, const Twine &BufferName="", std::optional< Align > Alignment=std::nullopt)
Allocate a new MemoryBuffer of the specified size that is not initialized.
A range adaptor for a pair of iterators.
LLVM_ABI bool operator==(const Arm64XRelocRef &Other) const
COFF::Arm64XFixupType getType() const
LLVM_ABI uint8_t getSize() const
LLVM_ABI uint64_t getValue() const
LLVM_ABI Error getType(uint8_t &Type) const
LLVM_ABI bool operator==(const BaseRelocRef &Other) const
LLVM_ABI Error getRVA(uint32_t &Result) const
DataRefImpl getRawDataRefImpl() const
StringRef getFileName() const
static Error checkOffset(MemoryBufferRef M, uintptr_t Addr, const uint64_t Size)
const dos_header * getDOSHeader() const
uint64_t getSectionSize(DataRefImpl Sec) const override
Expected< StringRef > getSectionName(DataRefImpl Sec) const override
uint64_t getSectionIndex(DataRefImpl Sec) const override
dynamic_reloc_iterator dynamic_reloc_begin() const
std::unique_ptr< MemoryBuffer > getHybridObjectView() const
uint32_t getSymbolAlignment(DataRefImpl Symb) const override
bool isSectionCompressed(DataRefImpl Sec) const override
void moveRelocationNext(DataRefImpl &Rel) const override
Expected< section_iterator > getSymbolSection(DataRefImpl Symb) const override
uint8_t getBytesInAddress() const override
The number of bytes used to represent an address in this object file format.
export_directory_iterator export_directory_begin() const
delay_import_directory_iterator delay_import_directory_end() const
base_reloc_iterator base_reloc_begin() const
section_iterator section_end() const override
Error getVaPtr(uint64_t VA, uintptr_t &Res) const
uint64_t getRelocationType(DataRefImpl Rel) const override
void moveSymbolNext(DataRefImpl &Symb) const override
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override
iterator_range< delay_import_directory_iterator > delay_import_directories() const
import_directory_iterator import_directory_end() const
uint32_t getPointerToSymbolTable() const
const coff_relocation * getCOFFRelocation(const RelocationRef &Reloc) const
Expected< StringRef > getSymbolName(DataRefImpl Symb) const override
bool isDebugSection(DataRefImpl Sec) const override
iterator_range< const debug_directory * > debug_directories() const
StringRef getRelocationTypeName(uint16_t Type) const
bool isSectionBSS(DataRefImpl Sec) const override
base_reloc_iterator base_reloc_end() const
uint64_t getSectionAddress(DataRefImpl Sec) const override
Expected< uint64_t > getSymbolAddress(DataRefImpl Symb) const override
uint32_t getNumberOfSymbols() const
section_iterator section_begin() const override
Expected< SymbolRef::Type > getSymbolType(DataRefImpl Symb) const override
size_t getSymbolTableEntrySize() const
friend class ImportDirectoryEntryRef
export_directory_iterator export_directory_end() const
Error getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const
uintptr_t getSymbolTable() const
static Expected< std::unique_ptr< COFFObjectFile > > create(MemoryBufferRef Object)
bool isSectionVirtual(DataRefImpl Sec) const override
unsigned getSectionID(SectionRef Sec) const
relocation_iterator section_rel_begin(DataRefImpl Sec) const override
iterator_range< import_directory_iterator > import_directories() const
delay_import_directory_iterator delay_import_directory_begin() const
basic_symbol_iterator symbol_end() const override
Error getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, ArrayRef< uint8_t > &Contents, const char *ErrorContext=nullptr) const
Given an RVA base and size, returns a valid array of bytes or an error code if the RVA and size is no...
const coff_load_configuration64 * getLoadConfig64() const
iterator_range< export_directory_iterator > export_directories() const
uint32_t getNumberOfSections() const
uint64_t getRelocationOffset(DataRefImpl Rel) const override
basic_symbol_iterator symbol_begin() const override
std::optional< MemoryBufferRef > findHybridObjectSection() const
Triple::ArchType getArch() const override
bool isRelocatableObject() const override
True if this is a relocatable object (.o/.obj).
Expected< uint32_t > getSymbolFlags(DataRefImpl Symb) const override
Expected< const coff_section * > getSection(int32_t index) const
bool isSectionText(DataRefImpl Sec) const override
Expected< ArrayRef< uint8_t > > getSectionContents(DataRefImpl Sec) const override
const data_directory * getDataDirectory(uint32_t index) const
StringRef mapDebugSectionName(StringRef Name) const override
Maps a debug section name to a standard DWARF section name.
ArrayRef< uint8_t > getSymbolAuxData(COFFSymbolRef Symbol) const
uint64_t getImageBase() const
const coff_load_configuration32 * getLoadConfig32() const
const coff_section * getCOFFSection(const SectionRef &Section) const
import_directory_iterator import_directory_begin() const
void moveSectionNext(DataRefImpl &Sec) const override
relocation_iterator section_rel_end(DataRefImpl Sec) const override
dynamic_reloc_iterator dynamic_reloc_end() const
ArrayRef< coff_relocation > getRelocations(const coff_section *Sec) const
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override
Error getRvaPtr(uint32_t Rva, uintptr_t &Res, const char *ErrorContext=nullptr) const
iterator_range< dynamic_reloc_iterator > dynamic_relocs() const
unsigned getSymbolSectionID(SymbolRef Sym) const
Error getDebugPDBInfo(const debug_directory *DebugDir, const codeview::DebugInfo *&Info, StringRef &PDBFileName) const
Get PDB information out of a codeview debug directory entry.
friend class ExportDirectoryEntryRef
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override
uint64_t getSectionAlignment(DataRefImpl Sec) const override
uint32_t getSymbolIndex(COFFSymbolRef Symbol) const
uint16_t getMachine() const
COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const
Expected< uint64_t > getStartAddress() const override
iterator_range< base_reloc_iterator > base_relocs() const
bool isSectionData(DataRefImpl Sec) const override
StringRef getFileFormatName() const override
bool isAnyUndefined() const
bool isFileRecord() const
const coff_aux_weak_external * getWeakExternal() const
bool isSectionDefinition() const
uint8_t getComplexType() const
uint32_t getValue() const
bool isWeakExternal() const
int32_t getSectionNumber() const
LLVM_ABI bool operator==(const DelayImportDirectoryEntryRef &Other) const
LLVM_ABI imported_symbol_iterator imported_symbol_begin() const
LLVM_ABI Error getImportAddress(int AddrIndex, uint64_t &Result) const
LLVM_ABI iterator_range< imported_symbol_iterator > imported_symbols() const
DelayImportDirectoryEntryRef()=default
LLVM_ABI imported_symbol_iterator imported_symbol_end() const
LLVM_ABI Error getDelayImportTable(const delay_import_directory_table_entry *&Result) const
LLVM_ABI Error getName(StringRef &Result) const
LLVM_ABI bool operator==(const DynamicRelocRef &Other) const
LLVM_ABI arm64x_reloc_iterator arm64x_reloc_begin() const
LLVM_ABI void getContents(ArrayRef< uint8_t > &Ref) const
DynamicRelocRef()=default
LLVM_ABI uint32_t getType() const
LLVM_ABI arm64x_reloc_iterator arm64x_reloc_end() const
LLVM_ABI iterator_range< arm64x_reloc_iterator > arm64x_relocs() const
LLVM_ABI bool operator==(const ExportDirectoryEntryRef &Other) const
LLVM_ABI Error getDllName(StringRef &Result) const
LLVM_ABI Error getExportRVA(uint32_t &Result) const
LLVM_ABI Error getOrdinalBase(uint32_t &Result) const
LLVM_ABI Error getOrdinal(uint32_t &Result) const
LLVM_ABI Error isForwarder(bool &Result) const
LLVM_ABI Error getForwardTo(StringRef &Result) const
LLVM_ABI Error getSymbolName(StringRef &Result) const
ExportDirectoryEntryRef()=default
LLVM_ABI bool operator==(const ImportDirectoryEntryRef &Other) const
LLVM_ABI imported_symbol_iterator imported_symbol_end() const
LLVM_ABI imported_symbol_iterator imported_symbol_begin() const
LLVM_ABI Error getImportLookupTableRVA(uint32_t &Result) const
LLVM_ABI Error getImportTableEntry(const coff_import_directory_table_entry *&Result) const
LLVM_ABI imported_symbol_iterator lookup_table_end() const
ImportDirectoryEntryRef()=default
LLVM_ABI iterator_range< imported_symbol_iterator > lookup_table_symbols() const
LLVM_ABI iterator_range< imported_symbol_iterator > imported_symbols() const
LLVM_ABI imported_symbol_iterator lookup_table_begin() const
LLVM_ABI Error getImportAddressTableRVA(uint32_t &Result) const
LLVM_ABI Error getName(StringRef &Result) const
LLVM_ABI bool operator==(const ImportedSymbolRef &Other) const
LLVM_ABI Error getHintNameRVA(uint32_t &Result) const
LLVM_ABI Error getOrdinal(uint16_t &Result) const
ImportedSymbolRef()=default
LLVM_ABI Error getSymbolName(StringRef &Result) const
LLVM_ABI Error isOrdinal(bool &Result) const
This class is the base class for all object file types.
friend class RelocationRef
static Expected< std::unique_ptr< COFFObjectFile > > createCOFFObjectFile(MemoryBufferRef Object)
section_iterator_range sections() const
Expected< uint64_t > getSymbolValue(DataRefImpl Symb) const
const uint8_t * base() const
LLVM_ABI Expected< const coff_resource_dir_table & > getBaseTable()
LLVM_ABI Expected< const coff_resource_dir_table & > getEntrySubDir(const coff_resource_dir_entry &Entry)
LLVM_ABI Expected< const coff_resource_data_entry & > getEntryData(const coff_resource_dir_entry &Entry)
LLVM_ABI Error load(const COFFObjectFile *O)
LLVM_ABI Expected< ArrayRef< UTF16 > > getEntryNameString(const coff_resource_dir_entry &Entry)
LLVM_ABI Expected< StringRef > getContents(const coff_resource_data_entry &Entry)
LLVM_ABI Expected< const coff_resource_dir_entry & > getTableEntry(const coff_resource_dir_table &Table, uint32_t Index)
This is a value type class that represents a single section in the list of sections in the object fil...
DataRefImpl getRawDataRefImpl() const
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ IMAGE_REL_MIPS_REFWORDNB
@ IMAGE_DYNAMIC_RELOCATION_ARM64X
@ IMAGE_FILE_MACHINE_ARM64
@ IMAGE_FILE_MACHINE_UNKNOWN
@ IMAGE_FILE_MACHINE_AMD64
@ IMAGE_FILE_MACHINE_ARM64EC
@ IMAGE_FILE_MACHINE_R4000
@ IMAGE_FILE_MACHINE_I386
@ IMAGE_FILE_MACHINE_ARM64X
@ IMAGE_FILE_MACHINE_ARMNT
@ IMAGE_SCN_CNT_UNINITIALIZED_DATA
@ IMAGE_SCN_CNT_INITIALIZED_DATA
@ IMAGE_DEBUG_TYPE_CODEVIEW
@ IMAGE_REL_ARM64_ADDR32NB
@ IMAGE_REL_AMD64_ADDR32NB
@ DELAY_IMPORT_DESCRIPTOR
@ IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE
@ IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA
@ IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL
@ IMAGE_WEAK_EXTERN_SEARCH_ALIAS
bool isReservedSectionNumber(int32_t SectionNumber)
static const char BigObjMagic[]
static const char PEMagic[]
@ IMAGE_SYM_DTYPE_FUNCTION
A function that returns a base type.
static Expected< const T * > getObject(MemoryBufferRef M, const void *Ptr, const uint64_t Size=sizeof(T))
content_iterator< SectionRef > section_iterator
coff_tls_directory< support::little64_t > coff_tls_directory64
content_iterator< BaseRelocRef > base_reloc_iterator
static constexpr StringLiteral kArm64ECSectionName
content_iterator< ExportDirectoryEntryRef > export_directory_iterator
content_iterator< BasicSymbolRef > basic_symbol_iterator
content_iterator< ImportedSymbolRef > imported_symbol_iterator
content_iterator< ImportDirectoryEntryRef > import_directory_iterator
coff_tls_directory< support::little32_t > coff_tls_directory32
import_lookup_table_entry< support::little32_t > import_lookup_table_entry32
coff_symbol< support::ulittle16_t > coff_symbol16
import_lookup_table_entry< support::little64_t > import_lookup_table_entry64
coff_symbol< support::ulittle32_t > coff_symbol32
content_iterator< RelocationRef > relocation_iterator
content_iterator< DynamicRelocRef > dynamic_reloc_iterator
content_iterator< Arm64XRelocRef > arm64x_reloc_iterator
content_iterator< DelayImportDirectoryEntryRef > delay_import_directory_iterator
detail::packed_endian_specific_integral< uint64_t, llvm::endianness::little, unaligned > ulittle64_t
detail::packed_endian_specific_integral< int16_t, llvm::endianness::little, unaligned > little16_t
detail::packed_endian_specific_integral< uint32_t, llvm::endianness::little, unaligned > ulittle32_t
detail::packed_endian_specific_integral< uint16_t, llvm::endianness::little, unaligned > ulittle16_t
This is an optimization pass for GlobalISel generic memory operations.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Triple::ArchType getMachineArchType(T machine)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
@ Ref
The access may reference the value stored in memory.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
void consumeError(Error Err)
Consume a Error without doing anything.
support::ulittle32_t Version
support::ulittle32_t Size
support::ulittle32_t VirtualAddress
support::ulittle16_t NumberOfNameEntries
support::ulittle16_t NumberOfIDEntries
support::ulittle32_t PointerToRawData
char Name[COFF::NameSize]
support::ulittle32_t VirtualSize
bool hasExtendedRelocations() const
uint32_t getAlignment() const
support::ulittle32_t Characteristics
support::ulittle32_t SizeOfRawData
support::ulittle32_t VirtualAddress
support::ulittle32_t PointerToRelocations
support::ulittle16_t NumberOfRelocations
uint8_t NumberOfAuxSymbols
support::ulittle32_t RelativeVirtualAddress
support::ulittle32_t Size
support::ulittle32_t SizeOfData
support::ulittle32_t AddressOfRawData
support::ulittle32_t ExportRVA