diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp | 198 |
1 files changed, 30 insertions, 168 deletions
diff --git a/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp index 2c0f6dc2b1e9..854664e679df 100644 --- a/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp @@ -937,6 +937,29 @@ iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { } std::error_code +COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const { + Res = COFFHeader; + return std::error_code(); +} + +std::error_code +COFFObjectFile::getCOFFBigObjHeader(const coff_bigobj_file_header *&Res) const { + Res = COFFBigObjHeader; + return std::error_code(); +} + +std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { + Res = PE32Header; + return std::error_code(); +} + +std::error_code +COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { + Res = PE32PlusHeader; + return std::error_code(); +} + +std::error_code COFFObjectFile::getDataDirectory(uint32_t Index, const data_directory *&Res) const { // Error if there's no data directory or the index is out of range. @@ -971,12 +994,11 @@ std::error_code COFFObjectFile::getSection(int32_t Index, std::error_code COFFObjectFile::getSection(StringRef SectionName, const coff_section *&Result) const { Result = nullptr; + StringRef SecName; for (const SectionRef &Section : sections()) { - auto NameOrErr = Section.getName(); - if (!NameOrErr) - return errorToErrorCode(NameOrErr.takeError()); - - if (*NameOrErr == SectionName) { + if (std::error_code E = Section.getName(SecName)) + return E; + if (SecName == SectionName) { Result = getCOFFSection(Section); return std::error_code(); } @@ -1662,12 +1684,9 @@ std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { return std::error_code(); } -#define RETURN_IF_ERROR(Expr) \ - do { \ - Error E = (Expr); \ - if (E) \ - return std::move(E); \ - } while (0) +#define RETURN_IF_ERROR(E) \ + if (E) \ + return E; Expected<ArrayRef<UTF16>> ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) { @@ -1696,168 +1715,11 @@ ResourceSectionRef::getTableAtOffset(uint32_t Offset) { return *Table; } -Expected<const coff_resource_dir_entry &> -ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) { - const coff_resource_dir_entry *Entry = nullptr; - - BinaryStreamReader Reader(BBS); - Reader.setOffset(Offset); - RETURN_IF_ERROR(Reader.readObject(Entry)); - assert(Entry != nullptr); - return *Entry; -} - -Expected<const coff_resource_data_entry &> -ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) { - const coff_resource_data_entry *Entry = nullptr; - - BinaryStreamReader Reader(BBS); - Reader.setOffset(Offset); - RETURN_IF_ERROR(Reader.readObject(Entry)); - assert(Entry != nullptr); - return *Entry; -} - Expected<const coff_resource_dir_table &> ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) { - assert(Entry.Offset.isSubDir()); return getTableAtOffset(Entry.Offset.value()); } -Expected<const coff_resource_data_entry &> -ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) { - assert(!Entry.Offset.isSubDir()); - return getDataEntryAtOffset(Entry.Offset.value()); -} - Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() { return getTableAtOffset(0); } - -Expected<const coff_resource_dir_entry &> -ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table, - uint32_t Index) { - if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries)) - return createStringError(object_error::parse_failed, "index out of range"); - const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table); - ptrdiff_t TableOffset = TablePtr - BBS.data().data(); - return getTableEntryAtOffset(TableOffset + sizeof(Table) + - Index * sizeof(coff_resource_dir_entry)); -} - -Error ResourceSectionRef::load(const COFFObjectFile *O) { - for (const SectionRef &S : O->sections()) { - Expected<StringRef> Name = S.getName(); - if (!Name) - return Name.takeError(); - - if (*Name == ".rsrc" || *Name == ".rsrc$01") - return load(O, S); - } - return createStringError(object_error::parse_failed, - "no resource section found"); -} - -Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) { - Obj = O; - Section = S; - Expected<StringRef> Contents = Section.getContents(); - if (!Contents) - return Contents.takeError(); - BBS = BinaryByteStream(*Contents, support::little); - const coff_section *COFFSect = Obj->getCOFFSection(Section); - ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect); - Relocs.reserve(OrigRelocs.size()); - for (const coff_relocation &R : OrigRelocs) - Relocs.push_back(&R); - std::sort(Relocs.begin(), Relocs.end(), - [](const coff_relocation *A, const coff_relocation *B) { - return A->VirtualAddress < B->VirtualAddress; - }); - return Error::success(); -} - -Expected<StringRef> -ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) { - if (!Obj) - return createStringError(object_error::parse_failed, "no object provided"); - - // Find a potential relocation at the DataRVA field (first member of - // the coff_resource_data_entry struct). - const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry); - ptrdiff_t EntryOffset = EntryPtr - BBS.data().data(); - coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0), - ulittle16_t(0)}; - auto RelocsForOffset = - std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget, - [](const coff_relocation *A, const coff_relocation *B) { - return A->VirtualAddress < B->VirtualAddress; - }); - - if (RelocsForOffset.first != RelocsForOffset.second) { - // We found a relocation with the right offset. Check that it does have - // the expected type. - const coff_relocation &R = **RelocsForOffset.first; - uint16_t RVAReloc; - switch (Obj->getMachine()) { - case COFF::IMAGE_FILE_MACHINE_I386: - RVAReloc = COFF::IMAGE_REL_I386_DIR32NB; - break; - case COFF::IMAGE_FILE_MACHINE_AMD64: - RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB; - break; - case COFF::IMAGE_FILE_MACHINE_ARMNT: - RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB; - break; - case COFF::IMAGE_FILE_MACHINE_ARM64: - RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB; - break; - default: - return createStringError(object_error::parse_failed, - "unsupported architecture"); - } - if (R.Type != RVAReloc) - return createStringError(object_error::parse_failed, - "unexpected relocation type"); - // Get the relocation's symbol - Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex); - if (!Sym) - return Sym.takeError(); - const coff_section *Section = nullptr; - // And the symbol's section - if (std::error_code EC = Obj->getSection(Sym->getSectionNumber(), Section)) - return errorCodeToError(EC); - // Add the initial value of DataRVA to the symbol's offset to find the - // data it points at. - uint64_t Offset = Entry.DataRVA + Sym->getValue(); - ArrayRef<uint8_t> Contents; - if (Error E = Obj->getSectionContents(Section, Contents)) - return std::move(E); - if (Offset + Entry.DataSize > Contents.size()) - return createStringError(object_error::parse_failed, - "data outside of section"); - // Return a reference to the data inside the section. - return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset, - Entry.DataSize); - } else { - // Relocatable objects need a relocation for the DataRVA field. - if (Obj->isRelocatableObject()) - return createStringError(object_error::parse_failed, - "no relocation found for DataRVA"); - - // Locate the section that contains the address that DataRVA points at. - uint64_t VA = Entry.DataRVA + Obj->getImageBase(); - for (const SectionRef &S : Obj->sections()) { - if (VA >= S.getAddress() && - VA + Entry.DataSize <= S.getAddress() + S.getSize()) { - uint64_t Offset = VA - S.getAddress(); - Expected<StringRef> Contents = S.getContents(); - if (!Contents) - return Contents.takeError(); - return Contents->slice(Offset, Offset + Entry.DataSize); - } - } - return createStringError(object_error::parse_failed, - "address not found in image"); - } -} |
