summaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp198
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");
- }
-}