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 @@ -424,6 +424,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 { + std::vector StringTable; + uint32_t NumberOfSymbols = getNumberOfSymbolTableEntries(); + for (uint32_t I = 0; 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(); + StringTable.push_back(StringTableEntry.get()); + } + } + return StringTable; +} + 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 --xcoff-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: .file +# CHECK64-NEXT: .undef +# CHECK64-NEXT: .abs +# CHECK64-NEXT: .text +# 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 --xcoff-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: .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() { } + // Only implemented for XCOFF. + virtual void printXCOFFStringTable() { } + 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 printXCOFFStringTable() override; private: template void printSectionHeaders(ArrayRef Sections); @@ -456,6 +457,14 @@ printSymbol(S); } +void XCOFFDumper::printXCOFFStringTable() { + DictScope DS(W, "StringTable"); + std::vector StringTable = + unwrapOrError(Obj.getFileName(), Obj.getStringTable()); + for (const StringRef &Entry : StringTable) + W.printString(Entry); +} + 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 @@ -291,6 +291,11 @@ COFFLoadConfig("coff-load-config", cl::desc("Display the PE/COFF load config")); + // --xcoff-string-table + cl::opt + XCOFFStringTable("xcoff-string-table", + cl::desc("Display the XCOFF string table")); + // --elf-linker-options cl::opt ELFLinkerOptions("elf-linker-options", @@ -596,6 +601,10 @@ if (opts::MachODysymtab) Dumper->printMachODysymtab(); } + if (Obj.isXCOFF()) { + if (opts::XCOFFStringTable) + Dumper->printXCOFFStringTable(); + } if (opts::PrintStackMap) Dumper->printStackMap(); if (opts::PrintStackSizes)