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,31 @@ 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; +}; + +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; @@ -290,6 +315,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 @@ -429,6 +455,9 @@ template Expected> relocations(const Shdr &Sec) 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 @@ -307,6 +307,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; } @@ -794,6 +826,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 new file mode 100755 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. The first entry is a default LIBPATH value and other + // entries have no path_name. We just dump the base_name and + // archive_member_name here. + OS << left_justify("BASE", BaseWidth) << " MEMBER\n"; + CurrentStr = ImportFileTable.data(); + for (size_t StrIndex = 0; CurrentStr < TableEnd; + ++StrIndex, CurrentStr += strlen(CurrentStr) + 1) { + if (StrIndex >= 3 && StrIndex % 3 != 0) { + if (StrIndex % 3 == 1) + OS << " " << left_justify(CurrentStr, BaseWidth) << " "; + else + OS << CurrentStr << "\n"; + } + } } static const EnumEntry SectionTypeFlagsNames[] = {