diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -97,6 +97,33 @@ char Padding[4]; }; +struct LoaderSectionHeader32 { + support::ubig32_t Version; + support::ubig32_t NumberOfSymTabEnt; + support::ubig32_t NumberOfRelTabEnt; + support::ubig32_t LengthOfImpidStrTbl; + support::ubig32_t NumberOfImpid; + support::big32_t OffsetToImpid; + support::ubig32_t LengthOfStrTbl; + support::big32_t OffsetToStrTbl; + char Padding[4]; + support::big32_t OffsetToRelEnt; +}; + +struct LoaderSectionHeader64 { + support::ubig32_t Version; + support::ubig32_t NumberOfSymTabEnt; + support::ubig32_t NumberOfRelTabEnt; + support::ubig32_t LengthOfImpidStrTbl; + support::ubig32_t NumberOfImpid; + support::ubig32_t LengthOfStrTbl; + support::big64_t OffsetToImpid; + support::big64_t OffsetToStrTbl; + support::big64_t OffsetToSymTbl; + char Padding[16]; + support::big32_t OffsetToRelEnt; +}; + struct XCOFFStringTable { uint32_t Size; const char *Data; @@ -283,6 +310,7 @@ const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const; uintptr_t getSectionHeaderTableAddress() const; uintptr_t getEndOfSymbolTableAddress() const; + Expected getLoaderSectionAddress() const; // This returns a pointer to the start of the storage for the name field of // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily @@ -421,6 +449,9 @@ Expected> relocations(const XCOFFSectionHeader32 &) const; + // Loader section related interfaces. + Expected getImportFileTable() const; + // This function returns string table entry. Expected getStringTableEntry(uint32_t Offset) const; diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -300,6 +300,38 @@ return Result; } +Expected XCOFFObjectFile::getLoaderSectionAddress() const { + uint64_t OffsetToLoaderSection = 0; + uint64_t SizeOfLoaderSection = 0; + + if (is64Bit()) { + for (const auto &Sec64 : sections64()) + if (Sec64.getSectionType() == XCOFF::STYP_LOADER) { + OffsetToLoaderSection = Sec64.FileOffsetToRawData; + SizeOfLoaderSection = Sec64.SectionSize; + break; + } + } else { + for (const auto &Sec32 : sections32()) + if (Sec32.getSectionType() == XCOFF::STYP_LOADER) { + OffsetToLoaderSection = Sec32.FileOffsetToRawData; + SizeOfLoaderSection = Sec32.SectionSize; + break; + } + } + + // No loader section is not an error. + if (!SizeOfLoaderSection) + return 0; + + uintptr_t LoderSectionStart = + reinterpret_cast(base() + OffsetToLoaderSection); + if (Error E = + Binary::checkOffset(Data, LoderSectionStart, SizeOfLoaderSection)) + return std::move(E); + return LoderSectionStart; +} + bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { return false; } @@ -729,6 +761,47 @@ return XCOFFStringTable{Size, StringTablePtr}; } +// This function returns the import file table. Each entry in the import file +// table consists of: "path_name\0base_name\0archive_member_name\0". +Expected XCOFFObjectFile::getImportFileTable() const { + Expected LoaderSectionAddrOrError = getLoaderSectionAddress(); + if (!LoaderSectionAddrOrError) + return LoaderSectionAddrOrError.takeError(); + + uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get(); + if (!LoaderSectionAddr) + return StringRef(); + + uint64_t OffsetToImportFileTable = 0; + uint64_t LengthOfImportFileTable = 0; + if (is64Bit()) { + const LoaderSectionHeader64 *LoaderSec64 = + viewAs(LoaderSectionAddr); + OffsetToImportFileTable = LoaderSec64->OffsetToImpid; + LengthOfImportFileTable = LoaderSec64->LengthOfImpidStrTbl; + } else { + const LoaderSectionHeader32 *LoaderSec32 = + viewAs(LoaderSectionAddr); + OffsetToImportFileTable = LoaderSec32->OffsetToImpid; + LengthOfImportFileTable = LoaderSec32->LengthOfImpidStrTbl; + } + + auto ImportTableOrErr = getObject( + Data, + reinterpret_cast(LoaderSectionAddr + OffsetToImportFileTable), + LengthOfImportFileTable); + if (Error E = ImportTableOrErr.takeError()) + return std::move(E); + + const char *ImportTablePtr = ImportTableOrErr.get(); + if (ImportTablePtr[LengthOfImportFileTable - 1] != '\0') + return createStringError( + object_error::parse_failed, + "the import file table must end with a null terminator"); + + return StringRef(ImportTablePtr, LengthOfImportFileTable); +} + Expected> XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { // Can't use std::make_unique because of the private constructor. diff --git a/llvm/test/tools/llvm-readobj/XCOFF/Inputs/needed-libs-32.o b/llvm/test/tools/llvm-readobj/XCOFF/Inputs/needed-libs-32.o index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@(W.startLine()); + // Each entry consists of 3 strings: the path_name, base_name and + // archive_member_name. + OS << left_justify("PATH", 15) << left_justify("BASE", 15) + << left_justify("MEMBER", 15) << "\n"; + for (size_t StrIndex = 0; CurrentStr < TableEnd; + ++StrIndex, CurrentStr += strlen(CurrentStr) + 1) + // The first import file ID is a default LIBPATH value to be used by the + // system loader. Do not dump it here. + if (StrIndex >= 3) { + if (StrIndex % 3 == 0) + OS << " "; + OS << left_justify(CurrentStr, 15); + if (StrIndex % 3 == 2) + OS << "\n"; + } } static const EnumEntry SectionTypeFlagsNames[] = {