diff --git a/docs/CommandGuide/llvm-readobj.rst b/docs/CommandGuide/llvm-readobj.rst index 84f0aa42351..8c4546bbcef 100644 --- a/docs/CommandGuide/llvm-readobj.rst +++ b/docs/CommandGuide/llvm-readobj.rst @@ -123,6 +123,10 @@ file formats. 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/include/llvm/Object/XCOFFObjectFile.h b/include/llvm/Object/XCOFFObjectFile.h index fce555bffd9..7d024fbc3ea 100644 --- a/include/llvm/Object/XCOFFObjectFile.h +++ b/include/llvm/Object/XCOFFObjectFile.h @@ -424,6 +424,9 @@ public: // 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/lib/Object/XCOFFObjectFile.cpp b/lib/Object/XCOFFObjectFile.cpp index a03627f2097..53447d0c97b 100644 --- a/lib/Object/XCOFFObjectFile.cpp +++ b/lib/Object/XCOFFObjectFile.cpp @@ -187,6 +187,10 @@ XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const { 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/test/tools/yaml2obj/XCOFF/long-symbol-name.yaml b/test/tools/yaml2obj/XCOFF/long-symbol-name.yaml index d800f6cd73f..86cedd0fa79 100644 --- a/test/tools/yaml2obj/XCOFF/long-symbol-name.yaml +++ b/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/tools/llvm-readobj/ObjDumper.cpp b/tools/llvm-readobj/ObjDumper.cpp index fc91d81f078..87c229356e2 100644 --- a/tools/llvm-readobj/ObjDumper.cpp +++ b/tools/llvm-readobj/ObjDumper.cpp @@ -52,6 +52,25 @@ static void printAsPrintable(raw_ostream &W, const uint8_t *Start, size_t Len) { 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 @@ void ObjDumper::printSectionsAsString(const object::ObjectFile &Obj, 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/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h index e707c36713d..7e1c0ca3512 100644 --- a/tools/llvm-readobj/ObjDumper.h +++ b/tools/llvm-readobj/ObjDumper.h @@ -105,8 +105,13 @@ public: 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/tools/llvm-readobj/XCOFFDumper.cpp b/tools/llvm-readobj/XCOFFDumper.cpp index bff2fecfb5d..94ef96e447c 100644 --- a/tools/llvm-readobj/XCOFFDumper.cpp +++ b/tools/llvm-readobj/XCOFFDumper.cpp @@ -34,6 +34,7 @@ public: void printUnwindInfo() override; void printStackMap() const override; void printNeededLibraries() override; + void printStringTable() override; private: template void printSectionHeaders(ArrayRef Sections); @@ -456,6 +457,12 @@ void XCOFFDumper::printSymbols() { 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/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index 8d07688dd07..1608e0238d9 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -206,6 +206,11 @@ namespace opts { 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 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer, Dumper->printGnuHashTable(); if (opts::VersionInfo) Dumper->printVersionInfo(); + if (opts::StringTable) + Dumper->printStringTable(); if (Obj.isELF()) { if (opts::DependentLibraries) Dumper->printDependentLibs();