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 @@ -188,7 +188,10 @@ } StringRef XCOFFObjectFile::getStringTable() const { - return StringRef(StringTable.Data, StringTable.Size); + // If the size is less than or equal to 4, then the string table contains no + // string data. + return StringRef(StringTable.Data, + StringTable.Size <= 4 ? 0 : StringTable.Size); } Expected diff --git a/llvm/test/tools/llvm-readobj/XCOFF/string-table.yaml b/llvm/test/tools/llvm-readobj/XCOFF/string-table.yaml --- a/llvm/test/tools/llvm-readobj/XCOFF/string-table.yaml +++ b/llvm/test/tools/llvm-readobj/XCOFF/string-table.yaml @@ -0,0 +1,57 @@ +## Test that the string table is dumped correctly. + +## The string table just contains a single-byte sized string entry. +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: llvm-readobj --string-table %t1 | FileCheck %s --check-prefix=SINGLE-BYTE + +# SINGLE-BYTE: StringTable { +# SINGLE-BYTE-NEXT: [ 4] n +# SINGLE-BYTE-NEXT: } + +--- !XCOFF +FileHeader: + MagicNumber: 0x01F7 +Symbols: + - Name: n + +## There is no string table. +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: llvm-readobj --string-table %t2 | FileCheck %s --check-prefix=NO-STRTBL + +# NO-STRTBL: StringTable { +# NO-STRTBL-NEXT: } + +--- !XCOFF +FileHeader: + MagicNumber: 0x01F7 + +## There is an empty string table with just the length field. +## TODO: Print the string table size to check the length field. +# RUN: yaml2obj --docnum=3 %s -o %t3 +# RUN: llvm-readobj --string-table %t3 | FileCheck %s --check-prefix=EMPTY-TBL + +# EMPTY-TBL: StringTable { +# EMPTY-TBL-NEXT: } + +--- !XCOFF +FileHeader: + MagicNumber: 0x1DF +Symbols: + - Name: asymname + +## The string table contians more than one entry. +# RUN: yaml2obj --docnum=4 %s -o %t4 +# RUN: llvm-readobj --string-table %t4 | FileCheck %s --check-prefix=BASIC + +# BASIC: StringTable { +# BASIC-NEXT: [ 4] longname2 +# BASIC-NEXT: [ e] longname1 +# BASIC-NEXT: } + +--- !XCOFF +FileHeader: + MagicNumber: 0x1DF +Symbols: + - Name: asymname + - Name: longname1 + - Name: longname2 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 @@ -2,8 +2,6 @@ # RUN: yaml2obj %s -o %t # 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 [ # CHECK-NEXT: Symbol { @@ -26,7 +24,7 @@ # CHECK-NEXT: } # CHECK-NEXT: ] # CHECK-NEXT: StringTable { -# CHECK-NEXT: [ 3] ..longname +# CHECK-NEXT: [ 4] .longname # CHECK-NEXT: } --- !XCOFF 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 @@ -110,7 +110,7 @@ virtual void printStackMap() const = 0; - void printAsStringList(StringRef StringContent); + void printAsStringList(StringRef StringContent, size_t StringDataOffset = 0); void printSectionsAsString(const object::ObjectFile &Obj, ArrayRef Sections); 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 @@ -53,9 +53,13 @@ W << (isPrint(Start[i]) ? static_cast(Start[i]) : '.'); } -void ObjDumper::printAsStringList(StringRef StringContent) { +void ObjDumper::printAsStringList(StringRef StringContent, + size_t StringDataOffset) { const uint8_t *StrContent = StringContent.bytes_begin(); - const uint8_t *CurrentWord = StrContent; + // Some formats contain additional metadata at the start which should not be + // interpreted as strings. Skip these bytes, but account for them in the + // string offsets. + const uint8_t *CurrentWord = StrContent + StringDataOffset; const uint8_t *StrEnd = StringContent.bytes_end(); while (CurrentWord <= StrEnd) { 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 @@ -460,7 +460,9 @@ void XCOFFDumper::printStringTable() { DictScope DS(W, "StringTable"); StringRef StrTable = Obj.getStringTable(); - printAsStringList(StrTable); + // Print strings from byte 4, since the first three bytes contain the length + // (in bytes) of the string table (including the length field). + printAsStringList(StrTable, 4); } void XCOFFDumper::printDynamicSymbols() {