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 @@ -15,6 +15,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/BinaryFormat/XCOFF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Endian.h" @@ -424,6 +425,9 @@ // This function returns string table entry. Expected getStringTableEntry(uint32_t Offset) const; + // This function returns the string table. + Expected> getStringTable() const; + const XCOFF::SymbolAuxType *getSymbolAuxType(uintptr_t AuxEntryAddress) const; static uintptr_t getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress, 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 @@ -187,6 +187,35 @@ object_error::parse_failed); } +Expected> +XCOFFObjectFile::getStringTable() const { + DenseMap StringTableMap; + for (uint32_t I = 0, NumberOfSymbols = getNumberOfSymbolTableEntries(); + I < NumberOfSymbols; ++I) { + uintptr_t SymbolEntryAddress = getSymbolEntryAddressByIndex(I); + uint64_t StringTableEntryOffset = 0; + if (is64Bit()) { + const XCOFFSymbolEntry64 *SymbolEntry64 = + reinterpret_cast(SymbolEntryAddress); + StringTableEntryOffset = SymbolEntry64->Offset; + } else { + const XCOFFSymbolEntry32 *SymbolEntry32 = + reinterpret_cast(SymbolEntryAddress); + if (SymbolEntry32->NameInStrTbl.Magic == + XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) + StringTableEntryOffset = SymbolEntry32->NameInStrTbl.Offset; + } + if (StringTableEntryOffset) { + Expected StringTableEntry = + getStringTableEntry(StringTableEntryOffset); + if (!StringTableEntry) + return StringTableEntry.takeError(); + StringTableMap[StringTableEntryOffset] = StringTableEntry.get(); + } + } + return StringTableMap; +} + Expected XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const { if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) diff --git a/llvm/test/tools/yaml2obj/XCOFF/basic-doc64.yaml b/llvm/test/tools/yaml2obj/XCOFF/basic-doc64.yaml --- a/llvm/test/tools/yaml2obj/XCOFF/basic-doc64.yaml +++ b/llvm/test/tools/yaml2obj/XCOFF/basic-doc64.yaml @@ -1,5 +1,6 @@ # RUN: yaml2obj %s -o %t -# RUN: llvm-readobj --headers --symbols %t | FileCheck %s --check-prefix=CHECK64 +# RUN: llvm-readobj --headers --symbols --string-table %t | \ +# RUN: FileCheck %s --check-prefix=CHECK64 --- !XCOFF FileHeader: @@ -132,3 +133,9 @@ # CHECK64-NEXT: NumberOfAuxEntries: 0 # CHECK64-NEXT: } # CHECK64-NEXT: ] +# CHECK64-NEXT: StringTable { +# CHECK64-NEXT: [ 4] .text +# CHECK64-NEXT: [ f] .undef +# CHECK64-NEXT: [ 16] .file +# CHECK64-NEXT: [ a] .abs +# CHECK64-NEXT: } diff --git a/llvm/test/tools/yaml2obj/XCOFF/long-symbol-name.yaml b/llvm/test/tools/yaml2obj/XCOFF/long-symbol-name.yaml --- a/llvm/test/tools/yaml2obj/XCOFF/long-symbol-name.yaml +++ b/llvm/test/tools/yaml2obj/XCOFF/long-symbol-name.yaml @@ -1,7 +1,6 @@ ## Test that the string table works well for long symbol names. -## TODO: Dump the raw string table and check the contents. # RUN: yaml2obj %s -o %t -# RUN: llvm-readobj --symbols %t | FileCheck %s +# RUN: llvm-readobj --symbols --string-table %t | FileCheck %s # CHECK: AddressSize: 32bit # CHECK-NEXT: Symbols [ @@ -24,6 +23,9 @@ # CHECK-NEXT: NumberOfAuxEntries: 0 # CHECK-NEXT: } # CHECK-NEXT: ] +# CHECK-NEXT: StringTable { +# CHECK-NEXT: [ 4] .longname +# CHECK-NEXT: } --- !XCOFF FileHeader: diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h --- a/llvm/tools/llvm-readobj/ObjDumper.h +++ b/llvm/tools/llvm-readobj/ObjDumper.h @@ -105,6 +105,9 @@ virtual void printMachOIndirectSymbols() { } virtual void printMachOLinkerOptions() { } + // Currently only implemented for XCOFF. + virtual void printStringTable() { } + virtual void printStackMap() const = 0; void printSectionsAsString(const object::ObjectFile &Obj, diff --git a/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/llvm/tools/llvm-readobj/XCOFFDumper.cpp --- a/llvm/tools/llvm-readobj/XCOFFDumper.cpp +++ b/llvm/tools/llvm-readobj/XCOFFDumper.cpp @@ -34,6 +34,7 @@ void printUnwindInfo() override; void printStackMap() const override; void printNeededLibraries() override; + void printStringTable() override; private: template void printSectionHeaders(ArrayRef Sections); @@ -456,6 +457,18 @@ printSymbol(S); } +void XCOFFDumper::printStringTable() { + DictScope DS(W, "StringTable"); + Expected> StringTableMap = Obj.getStringTable(); + if (!StringTableMap) + reportWarning(StringTableMap.takeError(), Obj.getFileName()); + for (const auto &EntryPair : StringTableMap.get()) { + W.startLine() << format("[%6tx] ", EntryPair.first); + W.startLine() << EntryPair.second; + W.startLine() << '\n'; + } +} + void XCOFFDumper::printDynamicSymbols() { llvm_unreachable("Unimplemented functionality for XCOFFDumper"); } diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -199,6 +199,11 @@ cl::aliasopt(StringDump), cl::Prefix, cl::NotHidden); + // --string-table + cl::opt + StringTable("string-table", + cl::desc("Display the string table (only for XCOFF now)")); + // --hex-dump, -x cl::list HexDump("hex-dump", cl::value_desc("number|name"), @@ -534,6 +539,8 @@ Dumper->printGnuHashTable(); if (opts::VersionInfo) Dumper->printVersionInfo(); + if (opts::StringTable) + Dumper->printStringTable(); if (Obj.isELF()) { if (opts::DependentLibraries) Dumper->printDependentLibs();