diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst --- a/llvm/docs/CommandGuide/llvm-readobj.rst +++ b/llvm/docs/CommandGuide/llvm-readobj.rst @@ -123,6 +123,10 @@ Display the specified section(s) as a list of strings. ``section`` may be a section index or section name. +.. option:: --string-table + + Display contents of the string table. + .. option:: --symbols, --syms, -s Display the symbol table. 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. + StringRef 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,10 @@ object_error::parse_failed); } +StringRef XCOFFObjectFile::getStringTable() const { + return StringRef(StringTable.Data, StringTable.Size); +} + 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/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,8 @@ ## 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 + +## FIXME: The first item of StringTable should be `[ 4] .longname`. # CHECK: AddressSize: 32bit # CHECK-NEXT: Symbols [ @@ -24,6 +25,9 @@ # CHECK-NEXT: NumberOfAuxEntries: 0 # CHECK-NEXT: } # CHECK-NEXT: ] +# CHECK-NEXT: StringTable { +# CHECK-NEXT: [ 3] ..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,8 +105,13 @@ virtual void printMachOIndirectSymbols() { } virtual void printMachOLinkerOptions() { } + // Currently only implemented for XCOFF. + virtual void printStringTable() { } + virtual void printStackMap() const = 0; + void printAsStringList(StringRef StringContent); + void printSectionsAsString(const object::ObjectFile &Obj, ArrayRef Sections); void printSectionsAsHex(const object::ObjectFile &Obj, diff --git a/llvm/tools/llvm-readobj/ObjDumper.cpp b/llvm/tools/llvm-readobj/ObjDumper.cpp --- a/llvm/tools/llvm-readobj/ObjDumper.cpp +++ b/llvm/tools/llvm-readobj/ObjDumper.cpp @@ -52,6 +52,25 @@ W << (isPrint(Start[i]) ? static_cast(Start[i]) : '.'); } +void ObjDumper::printAsStringList(StringRef StringContent) { + const uint8_t *StrContent = StringContent.bytes_begin(); + const uint8_t *CurrentWord = StrContent; + const uint8_t *StrEnd = StringContent.bytes_end(); + + while (CurrentWord <= StrEnd) { + size_t WordSize = strnlen(reinterpret_cast(CurrentWord), + StrEnd - CurrentWord); + if (!WordSize) { + CurrentWord++; + continue; + } + W.startLine() << format("[%6tx] ", CurrentWord - StrContent); + printAsPrintable(W.startLine(), CurrentWord, WordSize); + W.startLine() << '\n'; + CurrentWord += WordSize + 1; + } +} + static std::vector getSectionRefsByNameOrIndex(const object::ObjectFile &Obj, ArrayRef Sections) { @@ -109,23 +128,7 @@ StringRef SectionContent = unwrapOrError(Obj.getFileName(), Section.getContents()); - - const uint8_t *SecContent = SectionContent.bytes_begin(); - const uint8_t *CurrentWord = SecContent; - const uint8_t *SecEnd = SectionContent.bytes_end(); - - while (CurrentWord <= SecEnd) { - size_t WordSize = strnlen(reinterpret_cast(CurrentWord), - SecEnd - CurrentWord); - if (!WordSize) { - CurrentWord++; - continue; - } - W.startLine() << format("[%6tx] ", CurrentWord - SecContent); - printAsPrintable(W.startLine(), CurrentWord, WordSize); - W.startLine() << '\n'; - CurrentWord += WordSize + 1; - } + printAsStringList(SectionContent); } } 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,12 @@ printSymbol(S); } +void XCOFFDumper::printStringTable() { + DictScope DS(W, "StringTable"); + StringRef StrTable = Obj.getStringTable(); + printAsStringList(StrTable); +} + 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 @@ -206,6 +206,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"), @@ -541,6 +546,8 @@ Dumper->printGnuHashTable(); if (opts::VersionInfo) Dumper->printVersionInfo(); + if (opts::StringTable) + Dumper->printStringTable(); if (Obj.isELF()) { if (opts::DependentLibraries) Dumper->printDependentLibs();