[llvm] d6d7f7b - [AIX][XCOFF] print out the traceback info
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 6 08:49:00 PDT 2023
Author: zhijian
Date: 2023-07-06T11:47:08-04:00
New Revision: d6d7f7b1d2639a06002779aed5dccf53fee20c6e
URL: https://github.com/llvm/llvm-project/commit/d6d7f7b1d2639a06002779aed5dccf53fee20c6e
DIFF: https://github.com/llvm/llvm-project/commit/d6d7f7b1d2639a06002779aed5dccf53fee20c6e.diff
LOG: [AIX][XCOFF] print out the traceback info
Summary:
Adding a new option -traceback-table to print out the traceback info of xcoff ojbect file.
Reviewers: James Henderson, Fangrui Song, Stephen Peckham, Xing Xue
Differential Revision: https://reviews.llvm.org/D89049
Added:
llvm/test/tools/llvm-objdump/XCOFF/disassemble-invalid-traceback-table.test
llvm/test/tools/llvm-objdump/XCOFF/disassemble-traceback-table-warning.test
llvm/test/tools/llvm-objdump/XCOFF/disassemble-traceback-table.test
Modified:
llvm/docs/CommandGuide/llvm-objdump.rst
llvm/include/llvm/Object/XCOFFObjectFile.h
llvm/lib/Object/XCOFFObjectFile.cpp
llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-clobber-register.ll
llvm/test/tools/llvm-objdump/X86/elf-disassemble.test
llvm/tools/llvm-objdump/ObjdumpOpts.td
llvm/tools/llvm-objdump/SourcePrinter.cpp
llvm/tools/llvm-objdump/XCOFFDump.cpp
llvm/tools/llvm-objdump/XCOFFDump.h
llvm/tools/llvm-objdump/llvm-objdump.cpp
llvm/tools/llvm-objdump/llvm-objdump.h
llvm/unittests/Object/XCOFFObjectFileTest.cpp
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/llvm-objdump.rst b/llvm/docs/CommandGuide/llvm-objdump.rst
index 6fc60faac1f649..9023abfa526afd 100644
--- a/llvm/docs/CommandGuide/llvm-objdump.rst
+++ b/llvm/docs/CommandGuide/llvm-objdump.rst
@@ -440,6 +440,10 @@ XCOFF ONLY OPTIONS AND COMMANDS
Add symbol description to disassembly output.
+.. option:: --traceback-table
+
+ Decode traceback table in disassembly output. Implies :option:`--disassemble`.
+
BUGS
----
diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h
index 2377d17d59390f..1f8ba6f32634ee 100644
--- a/llvm/include/llvm/Object/XCOFFObjectFile.h
+++ b/llvm/include/llvm/Object/XCOFFObjectFile.h
@@ -846,6 +846,7 @@ class TBVectorExt {
class XCOFFTracebackTable {
const uint8_t *const TBPtr;
+ bool Is64BitObj;
std::optional<SmallString<32>> ParmsType;
std::optional<uint32_t> TraceBackTableOffset;
std::optional<uint32_t> HandlerMask;
@@ -855,8 +856,10 @@ class XCOFFTracebackTable {
std::optional<uint8_t> AllocaRegister;
std::optional<TBVectorExt> VecExt;
std::optional<uint8_t> ExtensionTable;
+ std::optional<uint64_t> EhInfoDisp;
- XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err);
+ XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err,
+ bool Is64Bit = false);
public:
/// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes.
@@ -872,8 +875,8 @@ class XCOFFTracebackTable {
/// If the XCOFF Traceback Table is not parsed successfully or there are
/// extra bytes that are not recognized, \a Size will be updated to be the
/// size up to the end of the last successfully parsed field of the table.
- static Expected<XCOFFTracebackTable> create(const uint8_t *Ptr,
- uint64_t &Size);
+ static Expected<XCOFFTracebackTable>
+ create(const uint8_t *Ptr, uint64_t &Size, bool Is64Bits = false);
uint8_t getVersion() const;
uint8_t getLanguageID() const;
@@ -930,6 +933,7 @@ class XCOFFTracebackTable {
const std::optional<uint8_t> &getExtensionTable() const {
return ExtensionTable;
}
+ const std::optional<uint64_t> &getEhInfoDisp() const { return EhInfoDisp; }
};
bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes);
diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp
index ef134ded780f67..b6d0180c47fb31 100644
--- a/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/llvm/lib/Object/XCOFFObjectFile.cpp
@@ -1394,18 +1394,18 @@ bool TBVectorExt::hasVMXInstruction() const {
#undef GETVALUEWITHMASK
#undef GETVALUEWITHMASKSHIFT
-Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr,
- uint64_t &Size) {
+Expected<XCOFFTracebackTable>
+XCOFFTracebackTable::create(const uint8_t *Ptr, uint64_t &Size, bool Is64Bit) {
Error Err = Error::success();
- XCOFFTracebackTable TBT(Ptr, Size, Err);
+ XCOFFTracebackTable TBT(Ptr, Size, Err, Is64Bit);
if (Err)
return std::move(Err);
return TBT;
}
XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
- Error &Err)
- : TBPtr(Ptr) {
+ Error &Err, bool Is64Bit)
+ : TBPtr(Ptr), Is64BitObj(Is64Bit) {
ErrorAsOutParameter EAO(&Err);
DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false,
/*AddressSize=*/0);
@@ -1460,6 +1460,8 @@ XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
}
VecExt = TBVecExtOrErr.get();
VectorParmsNum = VecExt->getNumberOfVectorParms();
+ // Skip two bytes of padding after vector info.
+ DE.skip(Cur, 2);
}
}
@@ -1480,9 +1482,15 @@ XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
ParmsType = ParmsTypeOrError.get();
}
- if (Cur && hasExtensionTable())
+ if (Cur && hasExtensionTable()) {
ExtensionTable = DE.getU8(Cur);
+ if (*ExtensionTable & ExtendedTBTableFlag::TB_EH_INFO) {
+ // eh_info displacement must be 4-byte aligned.
+ Cur.seek(alignTo(Cur.tell(), 4));
+ EhInfoDisp = Is64BitObj ? DE.getU64(Cur) : DE.getU32(Cur);
+ }
+ }
if (!Cur)
Err = Cur.takeError();
diff --git a/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-clobber-register.ll b/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-clobber-register.ll
index 2384ca3a74ace7..b36785a53fedde 100644
--- a/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-clobber-register.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-clobber-register.ll
@@ -6,6 +6,16 @@
; RUN: -mcpu=pwr4 -mattr=+altivec -vec-extabi < %s | \
; RUN: FileCheck --check-prefixes=CHECK-FUNC,COMMON %s
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN: -mattr=+altivec -vec-extabi -xcoff-traceback-table=true -filetype=obj -o %t.o < %s
+; RUN: llvm-objdump -d --traceback-table --symbol-description %t.o | \
+; RUN: FileCheck --match-full-lines --strict-whitespace --check-prefixes=OBJ-DIS,NO-FUNC-SEC %s
+
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN: -mattr=+altivec -vec-extabi -xcoff-traceback-table=true -function-sections -filetype=obj -o %t_func.o < %s
+; RUN: llvm-objdump -d --traceback-table --symbol-description %t_func.o | \
+; RUN: FileCheck --match-full-lines --strict-whitespace --check-prefixes=OBJ-DIS,FUNC-SEC %s
+
define float @bar() #0 {
entry:
%fvalue = alloca float, align 4
@@ -95,3 +105,53 @@ entry:
; COMMON: .toc
; COMMON: L..C2:
; COMMON-NEXT: .tc __ehinfo.1[TC],__ehinfo.1
+
+
+; OBJ-DIS: 9c: 00 00 00 00 # Traceback table start
+; OBJ-DIS-NEXT: a0: 00 # Version = 0
+; OBJ-DIS-NEXT: a1: 09 # Language = CPlusPlus
+; OBJ-DIS-NEXT: a2: 22 # -isGlobalLinkage, -isOutOfLineEpilogOrPrologue
+; OBJ-DIS-NEXT: +hasTraceBackTableOffset, -isInternalProcedure
+; OBJ-DIS-NEXT: -hasControlledStorage, -isTOCless
+; OBJ-DIS-NEXT: +isFloatingPointPresent
+; OBJ-DIS-NEXT: -isFloatingPointOperationLogOrAbortEnabled
+; OBJ-DIS-NEXT: a3: 40 # -isInterruptHandler, +isFuncNamePresent, -isAllocaUsed
+; OBJ-DIS-NEXT: OnConditionDirective = 0, -isCRSaved, -isLRSaved
+; OBJ-DIS-NEXT: a4: 05 # -isBackChainStored, -isFixup, NumOfFPRsSaved = 5
+; OBJ-DIS-NEXT: a5: 04 # -hasExtensionTable, -hasVectorInfo, NumOfGPRsSaved = 4
+; OBJ-DIS-NEXT: a6: 00 # NumberOfFixedParms = 0
+; OBJ-DIS-NEXT: a7: 01 # NumberOfFPParms = 0, +hasParmsOnStack
+; OBJ-DIS-NEXT: a8: 00 00 00 9c # TraceBackTableOffset = 156
+; OBJ-DIS-NEXT: ac: 00 03 # FunctionNameLen = 3
+; OBJ-DIS-NEXT: ae: 62 61 72 # FunctionName = bar
+; NO-FUNC-SEC-NEXT: b1: 60 00 00 # Padding
+; NO-FUNC-SEC-NEXT: b4: 00 60 00 00
+; NO-FUNC-SEC-NEXT: b8: 00 60 00 00
+; NO-FUNC-SEC-NEXT: bc: 00 00 00 00
+; FUNC-SEC-NEXT: b1: 00 00 00 # Padding
+; FUNC-SEC-NEXT: ...
+
+; OBJ-DIS: 11c: 00 00 00 00 # Traceback table start
+; OBJ-DIS-NEXT: 120: 00 # Version = 0
+; OBJ-DIS-NEXT: 121: 09 # Language = CPlusPlus
+; OBJ-DIS-NEXT: 122: 20 # -isGlobalLinkage, -isOutOfLineEpilogOrPrologue
+; OBJ-DIS-NEXT: +hasTraceBackTableOffset, -isInternalProcedure
+; OBJ-DIS-NEXT: -hasControlledStorage, -isTOCless
+; OBJ-DIS-NEXT: -isFloatingPointPresent
+; OBJ-DIS-NEXT: -isFloatingPointOperationLogOrAbortEnabled
+; OBJ-DIS-NEXT: 123: 40 # -isInterruptHandler, +isFuncNamePresent, -isAllocaUsed
+; OBJ-DIS-NEXT: OnConditionDirective = 0, -isCRSaved, -isLRSaved
+; OBJ-DIS-NEXT: 124: 00 # -isBackChainStored, -isFixup, NumOfFPRsSaved = 0
+; OBJ-DIS-NEXT: 125: c0 # +hasExtensionTable, +hasVectorInfo, NumOfGPRsSaved = 0
+; OBJ-DIS-NEXT: 126: 00 # NumberOfFixedParms = 0
+; OBJ-DIS-NEXT: 127: 01 # NumberOfFPParms = 0, +hasParmsOnStack
+; OBJ-DIS-NEXT: 128: 00 00 00 5c # TraceBackTableOffset = 92
+; OBJ-DIS-NEXT: 12c: 00 04 # FunctionNameLen = 4
+; OBJ-DIS-NEXT: 12e: 66 6f 6f 76 # FunctionName = foov
+; OBJ-DIS-NEXT: 132: 12 # NumberOfVRSaved = 4, +isVRSavedOnStack, -hasVarArgs
+; OBJ-DIS-NEXT: 133: 01 # NumberOfVectorParms = 0, +hasVMXInstruction
+; OBJ-DIS-NEXT: 134: 00 00 00 00 # VectorParmsInfoString =
+; OBJ-DIS-NEXT: 138: 00 00 # Padding
+; OBJ-DIS-NEXT: 13a: 08 # ExtensionTable = TB_EH_INFO
+; OBJ-DIS-NEXT: 13b: 00 # Alignment padding for eh info displacement
+; OBJ-DIS-NEXT: 13c: 00 00 00 08 # EH info displacement
diff --git a/llvm/test/tools/llvm-objdump/X86/elf-disassemble.test b/llvm/test/tools/llvm-objdump/X86/elf-disassemble.test
index 2028f7fefd758d..ae4cb5c8ee5ca3 100644
--- a/llvm/test/tools/llvm-objdump/X86/elf-disassemble.test
+++ b/llvm/test/tools/llvm-objdump/X86/elf-disassemble.test
@@ -3,6 +3,9 @@
# RUN: llvm-objdump %t.o -d | FileCheck %s --implicit-check-not=Disassembly
# RUN: llvm-objdump %t.o --disassemble-all | FileCheck %s --check-prefixes=CHECK,ALL
+## Show that disassembly is enabled by default for --traceback-table, even for non-XCOFF objects.
+# RUN: llvm-objdump %t.o --traceback-table | FileCheck %s --implicit-check-not=Disassembly
+
# CHECK: Disassembly of section .executable:
# CHECK-EMPTY:
# CHECK-NEXT: 0000000000001000 <.executable>:
diff --git a/llvm/test/tools/llvm-objdump/XCOFF/disassemble-invalid-traceback-table.test b/llvm/test/tools/llvm-objdump/XCOFF/disassemble-invalid-traceback-table.test
new file mode 100644
index 00000000000000..06020e9b55b148
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/XCOFF/disassemble-invalid-traceback-table.test
@@ -0,0 +1,36 @@
+## Test that parsing of an invalid XCOFF traceback table with a too
+## big function name length causes an out of range error.
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: llvm-objdump -d --traceback-table --symbol-description %t.o 2>&1 | \
+# RUN: FileCheck -DFILE=%t.o --implicit-check-not="warning:" --check-prefixes=WARN %s
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: 0x1DF
+Sections:
+ - Name: .text
+ Flags: [ STYP_TEXT ]
+ SectionData: "4e8000200000000000002240800102075a000000000000880073666f6f0000000000000000000000"
+Symbols:
+ - Name: .AddNum
+ Value: 0
+ Section: .text
+ Type: 0x20
+ StorageClass: C_EXT
+ AuxEntries:
+ - Type: AUX_CSECT
+ SectionOrLength: 0x28
+ SymbolAlignmentAndType: 0x21
+ StorageMappingClass: XMC_PR
+
+# WARN: warning: '[[FILE]]': failure parsing traceback table with address: 0x4
+# WARN-NEXT: >>> unexpected end of data at offset 0x24 while reading [0x12, 0x85)
+# WARN-NEXT: >>> Raw traceback table data is:
+# WARN-NEXT: 8: 00 00 22 40
+# WARN-NEXT: c: 80 01 02 07
+# WARN-NEXT: 10: 5a 00 00 00
+# WARN-NEXT: 14: 00 00 00 88
+# WARN-NEXT: 18: 00 73 66 6f
+# WARN-NEXT: 1c: 6f 00 00 00
+# WARN-NEXT: ...
diff --git a/llvm/test/tools/llvm-objdump/XCOFF/disassemble-traceback-table-warning.test b/llvm/test/tools/llvm-objdump/XCOFF/disassemble-traceback-table-warning.test
new file mode 100644
index 00000000000000..621d61513a8818
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/XCOFF/disassemble-traceback-table-warning.test
@@ -0,0 +1,26 @@
+## Test that "llvm-objdump --traceback-table" warn when a function name's length is 0.
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: llvm-objdump -d --traceback-table --symbol-description %t.o 2>&1 |\
+# RUN: FileCheck -DFILE=%t.o --implicit-check-not="warning:" --check-prefixes=WARN %s
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: 0x1DF
+Sections:
+ - Name: .text
+ Flags: [ STYP_TEXT ]
+ SectionData: "9421ffc0000000000000204080000201000000000000000400004164644e756d00000000"
+Symbols:
+ - Name: .AddNum
+ Value: 0
+ Section: .text
+ Type: 0x20
+ StorageClass: C_EXT
+ AuxEntries:
+ - Type: AUX_CSECT
+ SectionOrLength: 0x24
+ SymbolAlignmentAndType: 0x21
+ StorageMappingClass: XMC_PR
+
+# WARN: warning: '[[FILE]]': the length of the function name must be greater than zero if the isFuncNamePresent bit is set in the traceback table
diff --git a/llvm/test/tools/llvm-objdump/XCOFF/disassemble-traceback-table.test b/llvm/test/tools/llvm-objdump/XCOFF/disassemble-traceback-table.test
new file mode 100644
index 00000000000000..91354f5a951e0d
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/XCOFF/disassemble-traceback-table.test
@@ -0,0 +1,115 @@
+## Test that "llvm-objdump --traceback-table" decodes the ControlledStorageInfo,
+## AllocaRegister, and extension table of the traceback table.
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: llvm-objdump -d --traceback-table --symbol-description %t.o | \
+# RUN: FileCheck --match-full-lines --strict-whitespace %s
+
+## Show that --traceback-table implies --disassemble.
+# RUN: llvm-objdump --traceback-table --symbol-description %t.o | \
+# RUN: FileCheck --match-full-lines --strict-whitespace %s
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: 0x1DF
+Sections:
+ - Name: .text
+ Flags: [ STYP_TEXT ]
+ SectionData: "9421ffc0000000000000204080000201000000000000000400064164644e756d0000000093e1fffc0000000000002a6080c202072c90000000000004000000036f0000010000000a000001000003666f6f1f0203c000000000002000000000000000000000000000010000000000000100000000000000000000000000123400000000"
+Symbols:
+ - Name: .AddNum
+ Value: 0
+ Section: .text
+ Type: 0x20
+ StorageClass: C_EXT
+ AuxEntries:
+ - Type: AUX_CSECT
+ SectionOrLength: 0x24
+ SymbolAlignmentAndType: 0x21
+ StorageMappingClass: XMC_PR
+ - Name: .foo
+ Value: 0x24
+ Section: .text
+ Type: 0x20
+ StorageClass: C_EXT
+ AuxEntries:
+ - Type: AUX_CSECT
+ SectionOrLength: 0x5F
+ SymbolAlignmentAndType: 0x21
+ StorageMappingClass: XMC_PR
+
+## The above .text section data is generated using the compiler command:
+## xlc -o test.o -c test.c
+## We also modified the binary content of the traceback table in the object file to add vector information
+## for function "foo", including ControlledStorageInfo, AllocaRegister, and ExtensionTable.
+
+## test.c:
+## int AddNum(int i,intj) {
+## return i+j;
+## }
+
+## float foo(int i1,float f1,double d1,int i2, float f2) {
+## return i1+f1+d1+i2+f2;
+## }
+
+# CHECK:00000000 (idx: 0) .AddNum[PR]:
+# CHECK-NEXT: 0: 94 21 ff c0 stwu 1, -64(1)
+# CHECK-NEXT: 4: 00 00 00 00 # Traceback table start
+# CHECK-NEXT: 8: 00 # Version = 0
+# CHECK-NEXT: 9: 00 # Language = C
+# CHECK-NEXT: a: 20 # -isGlobalLinkage, -isOutOfLineEpilogOrPrologue
+# CHECK-NEXT: +hasTraceBackTableOffset, -isInternalProcedure
+# CHECK-NEXT: -hasControlledStorage, -isTOCless
+# CHECK-NEXT: -isFloatingPointPresent
+# CHECK-NEXT: -isFloatingPointOperationLogOrAbortEnabled
+# CHECK-NEXT: b: 40 # -isInterruptHandler, +isFuncNamePresent, -isAllocaUsed
+# CHECK-NEXT: OnConditionDirective = 0, -isCRSaved, -isLRSaved
+# CHECK-NEXT: c: 80 # +isBackChainStored, -isFixup, NumOfFPRsSaved = 0
+# CHECK-NEXT: d: 00 # -hasExtensionTable, -hasVectorInfo, NumOfGPRsSaved = 0
+# CHECK-NEXT: e: 02 # NumberOfFixedParms = 2
+# CHECK-NEXT: f: 01 # NumberOfFPParms = 0, +hasParmsOnStack
+# CHECK-NEXT: 10: 00 00 00 00 # ParmsType = i, i
+# CHECK-NEXT: 14: 00 00 00 04 # TraceBackTableOffset = 4
+# CHECK-NEXT: 18: 00 06 # FunctionNameLen = 6
+# CHECK-NEXT: 1a: 41 64 64 4e # FunctionName = AddNum
+# CHECK-NEXT: 1e: 75 6d
+# CHECK-NEXT: 20: 00 00 00 00 # Padding
+
+# CHECK:00000024 (idx: 2) .foo[PR]:
+# CHECK-NEXT: 24: 93 e1 ff fc stw 31, -4(1)
+# CHECK-NEXT: 28: 00 00 00 00 # Traceback table start
+# CHECK-NEXT: 2c: 00 # Version = 0
+# CHECK-NEXT: 2d: 00 # Language = C
+# CHECK-NEXT: 2e: 2a # -isGlobalLinkage, -isOutOfLineEpilogOrPrologue
+# CHECK-NEXT: +hasTraceBackTableOffset, -isInternalProcedure
+# CHECK-NEXT: +hasControlledStorage, -isTOCless
+# CHECK-NEXT: +isFloatingPointPresent
+# CHECK-NEXT: -isFloatingPointOperationLogOrAbortEnabled
+# CHECK-NEXT: 2f: 60 # -isInterruptHandler, +isFuncNamePresent, +isAllocaUsed
+# CHECK-NEXT: OnConditionDirective = 0, -isCRSaved, -isLRSaved
+# CHECK-NEXT: 30: 80 # +isBackChainStored, -isFixup, NumOfFPRsSaved = 0
+# CHECK-NEXT: 31: c2 # +hasExtensionTable, +hasVectorInfo, NumOfGPRsSaved = 2
+# CHECK-NEXT: 32: 02 # NumberOfFixedParms = 2
+# CHECK-NEXT: 33: 07 # NumberOfFPParms = 3, +hasParmsOnStack
+# CHECK-NEXT: 34: 2c 90 00 00 # ParmsType = i, f, d, i, f, v
+# CHECK-NEXT: 38: 00 00 00 04 # TraceBackTableOffset = 4
+# CHECK-NEXT: 3c: 00 00 00 03 # NumOfCtlAnchors = 3
+# CHECK-NEXT: 40: 6f 00 00 01 # ControlledStorageInfoDisp[0] = 1862270977
+# CHECK-NEXT: 44: 00 00 00 0a ControlledStorageInfoDisp[1] = 10
+# CHECK-NEXT: 48: 00 00 01 00 ControlledStorageInfoDisp[2] = 256
+# CHECK-NEXT: 4c: 00 03 # FunctionNameLen = 3
+# CHECK-NEXT: 4e: 66 6f 6f # FunctionName = foo
+# CHECK-NEXT: 51: 1f # AllocaRegister = 31
+# CHECK-NEXT: 52: 02 # NumberOfVRSaved = 0, +isVRSavedOnStack, -hasVarArgs
+# CHECK-NEXT: 53: 03 # NumberOfVectorParms = 1, +hasVMXInstruction
+# CHECK-NEXT: 54: c0 00 00 00 # VectorParmsInfoString = vf
+# CHECK-NEXT: 58: 00 00 # Padding
+# CHECK-NEXT: 5a: 20 # ExtensionTable = TB_SSP_CANARY
+# CHECK-NEXT: 5b: 00 # Padding
+# CHECK-NEXT: ...
+# CHECK-NEXT: 68: 01 00 00 00
+# CHECK-NEXT: 6c: 00 00 00 01
+# CHECK-NEXT: 70: 00 00 00 00
+# CHECK-NEXT: ...
+# CHECK-NEXT: 7c: 00 12 34 00
+# CHECK-NEXT: 80: 00 00 00 00
diff --git a/llvm/tools/llvm-objdump/ObjdumpOpts.td b/llvm/tools/llvm-objdump/ObjdumpOpts.td
index c6627c75157b8e..e3e74762420deb 100644
--- a/llvm/tools/llvm-objdump/ObjdumpOpts.td
+++ b/llvm/tools/llvm-objdump/ObjdumpOpts.td
@@ -65,7 +65,11 @@ def : Flag<["-"], "D">, Alias<disassemble_all>,
def symbol_description : Flag<["--"], "symbol-description">,
HelpText<"Add symbol description for disassembly. This "
- "option is for XCOFF files only.">;
+ "option is for XCOFF files only">;
+
+def traceback_table : Flag<["--"], "traceback-table">,
+ HelpText<"Decode traceback table in disassembly. Implies --disassemble. "
+ "This option is for XCOFF files only">;
def disassemble_symbols_EQ : Joined<["--"], "disassemble-symbols=">,
HelpText<"List of symbols to disassemble. "
diff --git a/llvm/tools/llvm-objdump/SourcePrinter.cpp b/llvm/tools/llvm-objdump/SourcePrinter.cpp
index 6736cbc9ad5f81..04c767680d55a3 100644
--- a/llvm/tools/llvm-objdump/SourcePrinter.cpp
+++ b/llvm/tools/llvm-objdump/SourcePrinter.cpp
@@ -26,10 +26,6 @@
namespace llvm {
namespace objdump {
-unsigned getInstStartColumn(const MCSubtargetInfo &STI) {
- return !ShowRawInsn ? 16 : STI.getTargetTriple().isX86() ? 40 : 24;
-}
-
bool LiveVariable::liveAtAddress(object::SectionedAddress Addr) {
if (LocExpr.Range == std::nullopt)
return false;
diff --git a/llvm/tools/llvm-objdump/XCOFFDump.cpp b/llvm/tools/llvm-objdump/XCOFFDump.cpp
index 4849b20f1166bb..91891e3138b2ce 100644
--- a/llvm/tools/llvm-objdump/XCOFFDump.cpp
+++ b/llvm/tools/llvm-objdump/XCOFFDump.cpp
@@ -15,9 +15,17 @@
#include "llvm-objdump.h"
#include "llvm/Demangle/Demangle.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/FormattedStream.h"
+#include <algorithm>
using namespace llvm;
using namespace llvm::object;
+using namespace llvm::XCOFF;
+using namespace llvm::support;
Error objdump::getXCOFFRelocationValueString(const XCOFFObjectFile &Obj,
const RelocationRef &Rel,
@@ -107,3 +115,299 @@ std::string objdump::getXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo,
return Result;
}
+
+#define PRINTBOOL(Prefix, Obj, Field) \
+ OS << Prefix << " " << ((Obj.Field()) ? "+" : "-") << #Field
+
+#define PRINTGET(Prefix, Obj, Field) \
+ OS << Prefix << " " << #Field << " = " \
+ << static_cast<unsigned>(Obj.get##Field())
+
+#define PRINTOPTIONAL(Field) \
+ if (TbTable.get##Field()) { \
+ OS << '\n'; \
+ printRawData(Bytes.slice(Index, 4), Address + Index, OS, STI); \
+ Index += 4; \
+ OS << "\t# " << #Field << " = " << *TbTable.get##Field(); \
+ }
+
+void objdump::dumpTracebackTable(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ formatted_raw_ostream &OS, uint64_t End,
+ const MCSubtargetInfo &STI,
+ const XCOFFObjectFile *Obj) {
+ uint64_t Index = 0;
+ unsigned TabStop = getInstStartColumn(STI) - 1;
+ // Print traceback table boundary.
+ printRawData(Bytes.slice(Index, 4), Address, OS, STI);
+ OS << "\t# Traceback table start\n";
+ Index += 4;
+
+ uint64_t Size = End - Address;
+ bool Is64Bit = Obj->is64Bit();
+
+ // XCOFFTracebackTable::create modifies the size parameter, so ensure Size
+ // isn't changed.
+ uint64_t SizeCopy = End - Address;
+ Expected<XCOFFTracebackTable> TTOrErr =
+ XCOFFTracebackTable::create(Bytes.data() + Index, SizeCopy, Is64Bit);
+
+ if (!TTOrErr) {
+ std::string WarningMsgStr;
+ raw_string_ostream WarningStream(WarningMsgStr);
+ WarningStream << "failure parsing traceback table with address: 0x"
+ << utohexstr(Address) + "\n>>> "
+ << toString(TTOrErr.takeError())
+ << "\n>>> Raw traceback table data is:\n";
+
+ uint64_t LastNonZero = Index;
+ for (uint64_t I = Index; I < Size; I += 4)
+ if (support::endian::read32be(Bytes.slice(I, 4).data()) != 0)
+ LastNonZero = I + 4 > Size ? Size : I + 4;
+
+ if (Size - LastNonZero <= 4)
+ LastNonZero = Size;
+
+ formatted_raw_ostream FOS(WarningStream);
+ while (Index < LastNonZero) {
+ printRawData(Bytes.slice(Index, 4), Address + Index, FOS, STI);
+ Index += 4;
+ WarningStream << '\n';
+ }
+
+ // Print all remaining zeroes as ...
+ if (Size - LastNonZero >= 8)
+ WarningStream << "\t\t...\n";
+
+ reportWarning(WarningMsgStr, Obj->getFileName());
+ return;
+ }
+
+ auto PrintBytes = [&](uint64_t N) {
+ printRawData(Bytes.slice(Index, N), Address + Index, OS, STI);
+ Index += N;
+ };
+
+ XCOFFTracebackTable TbTable = *TTOrErr;
+ // Print the first of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ OS << format("\t# Version = %i", TbTable.getVersion()) << '\n';
+
+ // Print the second of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ TracebackTable::LanguageID LangId =
+ static_cast<TracebackTable::LanguageID>(TbTable.getLanguageID());
+ OS << "\t# Language = " << getNameForTracebackTableLanguageId(LangId) << '\n';
+
+ auto Split = [&]() {
+ OS << '\n';
+ OS.indent(TabStop);
+ };
+
+ // Print the third of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ PRINTBOOL("\t#", TbTable, isGlobalLinkage);
+ PRINTBOOL(",", TbTable, isOutOfLineEpilogOrPrologue);
+ Split();
+ PRINTBOOL("\t ", TbTable, hasTraceBackTableOffset);
+ PRINTBOOL(",", TbTable, isInternalProcedure);
+ Split();
+ PRINTBOOL("\t ", TbTable, hasControlledStorage);
+ PRINTBOOL(",", TbTable, isTOCless);
+ Split();
+ PRINTBOOL("\t ", TbTable, isFloatingPointPresent);
+ Split();
+ PRINTBOOL("\t ", TbTable, isFloatingPointOperationLogOrAbortEnabled);
+ OS << '\n';
+
+ // Print the 4th of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ PRINTBOOL("\t#", TbTable, isInterruptHandler);
+ PRINTBOOL(",", TbTable, isFuncNamePresent);
+ PRINTBOOL(",", TbTable, isAllocaUsed);
+ Split();
+ PRINTGET("\t ", TbTable, OnConditionDirective);
+ PRINTBOOL(",", TbTable, isCRSaved);
+ PRINTBOOL(",", TbTable, isLRSaved);
+ OS << '\n';
+
+ // Print the 5th of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ PRINTBOOL("\t#", TbTable, isBackChainStored);
+ PRINTBOOL(",", TbTable, isFixup);
+ PRINTGET(",", TbTable, NumOfFPRsSaved);
+ OS << '\n';
+
+ // Print the 6th of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ PRINTBOOL("\t#", TbTable, hasExtensionTable);
+ PRINTBOOL(",", TbTable, hasVectorInfo);
+ PRINTGET(",", TbTable, NumOfGPRsSaved);
+ OS << '\n';
+
+ // Print the 7th of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ PRINTGET("\t#", TbTable, NumberOfFixedParms);
+ OS << '\n';
+
+ // Print the 8th of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ PRINTGET("\t#", TbTable, NumberOfFPParms);
+ PRINTBOOL(",", TbTable, hasParmsOnStack);
+
+ PRINTOPTIONAL(ParmsType);
+ PRINTOPTIONAL(TraceBackTableOffset);
+ PRINTOPTIONAL(HandlerMask);
+ PRINTOPTIONAL(NumOfCtlAnchors);
+
+ if (TbTable.getControlledStorageInfoDisp()) {
+ SmallVector<uint32_t, 8> Disp = *TbTable.getControlledStorageInfoDisp();
+ for (unsigned I = 0; I < Disp.size(); ++I) {
+ OS << '\n';
+ PrintBytes(4);
+ OS << "\t" << (I ? " " : "#") << " ControlledStorageInfoDisp[" << I
+ << "] = " << Disp[I];
+ }
+ }
+
+ // If there is a name, print the function name and function name length.
+ if (TbTable.isFuncNamePresent()) {
+ uint16_t FunctionNameLen = TbTable.getFunctionName()->size();
+ if (FunctionNameLen == 0) {
+ OS << '\n';
+ reportWarning(
+ "the length of the function name must be greater than zero if the "
+ "isFuncNamePresent bit is set in the traceback table",
+ Obj->getFileName());
+ return;
+ }
+
+ OS << '\n';
+ PrintBytes(2);
+ OS << "\t# FunctionNameLen = " << FunctionNameLen;
+
+ uint16_t RemainingBytes = FunctionNameLen;
+ bool HasPrinted = false;
+ while (RemainingBytes > 0) {
+ OS << '\n';
+ uint16_t PrintLen = RemainingBytes >= 4 ? 4 : RemainingBytes;
+ printRawData(Bytes.slice(Index, PrintLen), Address + Index, OS, STI);
+ Index += PrintLen;
+ RemainingBytes -= PrintLen;
+
+ if (!HasPrinted) {
+ OS << "\t# FunctionName = " << *TbTable.getFunctionName();
+ HasPrinted = true;
+ }
+ }
+ }
+
+ if (TbTable.isAllocaUsed()) {
+ OS << '\n';
+ PrintBytes(1);
+ OS << format("\t# AllocaRegister = %u", *TbTable.getAllocaRegister());
+ }
+
+ if (TbTable.getVectorExt()) {
+ OS << '\n';
+ TBVectorExt VecExt = *TbTable.getVectorExt();
+ // Print first byte of VectorExt.
+ PrintBytes(1);
+ PRINTGET("\t#", VecExt, NumberOfVRSaved);
+ PRINTBOOL(",", VecExt, isVRSavedOnStack);
+ PRINTBOOL(",", VecExt, hasVarArgs);
+ OS << '\n';
+
+ // Print the second byte of VectorExt.
+ PrintBytes(1);
+ PRINTGET("\t#", VecExt, NumberOfVectorParms);
+ PRINTBOOL(",", VecExt, hasVMXInstruction);
+ OS << '\n';
+
+ PrintBytes(4);
+ OS << "\t# VectorParmsInfoString = " << VecExt.getVectorParmsInfo();
+
+ // There are two bytes of padding after vector info.
+ OS << '\n';
+ PrintBytes(2);
+ OS << "\t# Padding";
+ }
+
+ if (TbTable.getExtensionTable()) {
+ OS << '\n';
+ PrintBytes(1);
+ ExtendedTBTableFlag Flag =
+ static_cast<ExtendedTBTableFlag>(*TbTable.getExtensionTable());
+ OS << "\t# ExtensionTable = " << getExtendedTBTableFlagString(Flag);
+ }
+
+ if (TbTable.getEhInfoDisp()) {
+ // There are 4 bytes alignment before eh info displacement.
+ if (Index % 4) {
+ OS << '\n';
+ PrintBytes(4 - Index % 4);
+ OS << "\t# Alignment padding for eh info displacement";
+ }
+ OS << '\n';
+ // The size of the displacement (address) is 4 bytes in 32-bit object files,
+ // and 8 bytes in 64-bit object files.
+ PrintBytes(4);
+ OS << "\t# EH info displacement";
+ if (Is64Bit) {
+ OS << '\n';
+ PrintBytes(4);
+ }
+ }
+
+ OS << '\n';
+ if (End == Address + Index)
+ return;
+
+ Size = End - Address;
+
+ const char *LineSuffix = "\t# Padding\n";
+ auto IsWordZero = [&](uint64_t WordPos) {
+ if (WordPos >= Size)
+ return false;
+ uint64_t LineLength = std::min(4 - WordPos % 4, Size - WordPos);
+ return std::all_of(Bytes.begin() + WordPos,
+ Bytes.begin() + WordPos + LineLength,
+ [](uint8_t Byte) { return Byte == 0; });
+ };
+
+ bool AreWordsZero[] = {IsWordZero(Index), IsWordZero(alignTo(Index, 4) + 4),
+ IsWordZero(alignTo(Index, 4) + 8)};
+ bool ShouldPrintLine = true;
+ while (true) {
+ // Determine the length of the line (4, except for the first line, which
+ // will be just enough to align to the word boundary, and the last line,
+ // which will be the remainder of the data).
+ uint64_t LineLength = std::min(4 - Index % 4, Size - Index);
+ if (ShouldPrintLine) {
+ // Print the line.
+ printRawData(Bytes.slice(Index, LineLength), Address + Index, OS, STI);
+ OS << LineSuffix;
+ LineSuffix = "\n";
+ }
+
+ Index += LineLength;
+ if (Index == Size)
+ return;
+
+ // For 3 or more consecutive lines of zeros, skip all but the first one, and
+ // replace them with "...".
+ if (AreWordsZero[0] && AreWordsZero[1] && AreWordsZero[2]) {
+ if (ShouldPrintLine)
+ OS << std::string(8, ' ') << "...\n";
+ ShouldPrintLine = false;
+ } else if (!AreWordsZero[1]) {
+ // We have reached the end of a skipped block of zeros.
+ ShouldPrintLine = true;
+ }
+ AreWordsZero[0] = AreWordsZero[1];
+ AreWordsZero[1] = AreWordsZero[2];
+ AreWordsZero[2] = IsWordZero(Index + 8);
+ }
+}
+#undef PRINTBOOL
+#undef PRINTGET
+#undef PRINTOPTIONAL
diff --git a/llvm/tools/llvm-objdump/XCOFFDump.h b/llvm/tools/llvm-objdump/XCOFFDump.h
index 35d1c0f1ebbe50..cf5b19f910ea84 100644
--- a/llvm/tools/llvm-objdump/XCOFFDump.h
+++ b/llvm/tools/llvm-objdump/XCOFFDump.h
@@ -13,6 +13,8 @@
namespace llvm {
+class formatted_raw_ostream;
+class MCSubtargetInfo;
struct SymbolInfoTy;
namespace objdump {
@@ -32,6 +34,11 @@ std::string getXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo,
Error getXCOFFRelocationValueString(const object::XCOFFObjectFile &Obj,
const object::RelocationRef &RelRef,
llvm::SmallVectorImpl<char> &Result);
+
+void dumpTracebackTable(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ formatted_raw_ostream &OS, uint64_t End,
+ const MCSubtargetInfo &STI,
+ const object::XCOFFObjectFile *Obj);
} // namespace objdump
} // namespace llvm
#endif
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 7b6edb3d05b657..d77b0006049e98 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -48,7 +48,6 @@
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/Archive.h"
@@ -196,6 +195,7 @@ bool objdump::Demangle;
bool objdump::Disassemble;
bool objdump::DisassembleAll;
bool objdump::SymbolDescription;
+bool objdump::TracebackTable;
static std::vector<std::string> DisassembleSymbols;
static bool DisassembleZeroes;
static std::vector<std::string> DisassemblerOptions;
@@ -442,14 +442,36 @@ static bool getHidden(RelocationRef RelRef) {
return false;
}
-namespace {
-
/// Get the column at which we want to start printing the instruction
/// disassembly, taking into account anything which appears to the left of it.
-unsigned getInstStartColumn(const MCSubtargetInfo &STI) {
+unsigned objdump::getInstStartColumn(const MCSubtargetInfo &STI) {
return !ShowRawInsn ? 16 : STI.getTargetTriple().isX86() ? 40 : 24;
}
+static void AlignToInstStartColumn(size_t Start, const MCSubtargetInfo &STI,
+ raw_ostream &OS) {
+ // The output of printInst starts with a tab. Print some spaces so that
+ // the tab has 1 column and advances to the target tab stop.
+ unsigned TabStop = getInstStartColumn(STI);
+ unsigned Column = OS.tell() - Start;
+ OS.indent(Column < TabStop - 1 ? TabStop - 1 - Column : 7 - Column % 8);
+}
+
+void objdump::printRawData(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ formatted_raw_ostream &OS,
+ MCSubtargetInfo const &STI) {
+ size_t Start = OS.tell();
+ if (LeadingAddr)
+ OS << format("%8" PRIx64 ":", Address);
+ if (ShowRawInsn) {
+ OS << ' ';
+ dumpBytes(Bytes, OS);
+ }
+ AlignToInstStartColumn(Start, STI, OS);
+}
+
+namespace {
+
static bool isAArch64Elf(const ObjectFile &Obj) {
const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj);
return Elf && Elf->getEMachine() == ELF::EM_AARCH64;
@@ -489,15 +511,6 @@ static void printRelocation(formatted_raw_ostream &OS, StringRef FileName,
OS << Name << "\t" << Val;
}
-static void AlignToInstStartColumn(size_t Start, const MCSubtargetInfo &STI,
- raw_ostream &OS) {
- // The output of printInst starts with a tab. Print some spaces so that
- // the tab has 1 column and advances to the target tab stop.
- unsigned TabStop = getInstStartColumn(STI);
- unsigned Column = OS.tell() - Start;
- OS.indent(Column < TabStop - 1 ? TabStop - 1 - Column : 7 - Column % 8);
-}
-
class PrettyPrinter {
public:
virtual ~PrettyPrinter() = default;
@@ -511,15 +524,7 @@ class PrettyPrinter {
SP->printSourceLine(OS, Address, ObjectFilename, LVP);
LVP.printBetweenInsts(OS, false);
- size_t Start = OS.tell();
- if (LeadingAddr)
- OS << format("%8" PRIx64 ":", Address.Address);
- if (ShowRawInsn) {
- OS << ' ';
- dumpBytes(Bytes, OS);
- }
-
- AlignToInstStartColumn(Start, STI, OS);
+ printRawData(Bytes, Address.Address, OS, STI);
if (MI) {
// See MCInstPrinter::printInst. On targets where a PC relative immediate
@@ -806,7 +811,7 @@ PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
return AArch64PrettyPrinterInst;
}
}
-}
+} // namespace
static uint8_t getElfSymbolType(const ObjectFile &Obj, const SymbolRef &Sym) {
assert(Obj.isELF());
@@ -1087,7 +1092,7 @@ SymbolInfoTy objdump::createSymbolInfo(const ObjectFile &Obj,
const uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName);
const StringRef Name = unwrapOrError(Symbol.getName(), FileName);
- if (Obj.isXCOFF() && SymbolDescription) {
+ if (Obj.isXCOFF() && (SymbolDescription || TracebackTable)) {
const auto &XCOFFObj = cast<XCOFFObjectFile>(Obj);
DataRefImpl SymbolDRI = Symbol.getRawDataRefImpl();
@@ -1108,7 +1113,7 @@ SymbolInfoTy objdump::createSymbolInfo(const ObjectFile &Obj,
static SymbolInfoTy createDummySymbolInfo(const ObjectFile &Obj,
const uint64_t Addr, StringRef &Name,
uint8_t Type) {
- if (Obj.isXCOFF() && SymbolDescription)
+ if (Obj.isXCOFF() && (SymbolDescription || TracebackTable))
return SymbolInfoTy(Addr, Name, std::nullopt, std::nullopt, false);
else
return SymbolInfoTy(Addr, Name, Type);
@@ -1735,6 +1740,11 @@ static void disassembleObject(const Target *TheTarget, ObjectFile &Obj,
}
bool DumpARMELFData = false;
+ bool DumpTracebackTableForXCOFFFunction =
+ Obj.isXCOFF() && Section.isText() && TracebackTable &&
+ Symbols[SI - 1].XCOFFSymInfo.StorageMappingClass &&
+ (*Symbols[SI - 1].XCOFFSymInfo.StorageMappingClass == XCOFF::XMC_PR);
+
formatted_raw_ostream FOS(outs());
std::unordered_map<uint64_t, std::string> AllLabels;
@@ -1787,6 +1797,16 @@ static void disassembleObject(const Target *TheTarget, ObjectFile &Obj,
}
}
+ if (DumpTracebackTableForXCOFFFunction &&
+ doesXCOFFTracebackTableBegin(Bytes.slice(Index, 4))) {
+ dumpTracebackTable(Bytes.slice(Index),
+ SectionAddr + Index + VMAAdjustment, FOS,
+ SectionAddr + End + VMAAdjustment, *STI,
+ cast<XCOFFObjectFile>(&Obj));
+ Index = End;
+ continue;
+ }
+
// Print local label if there's any.
auto Iter1 = BBAddrMapLabels.find(SectionAddr + Index);
if (Iter1 != BBAddrMapLabels.end()) {
@@ -3018,6 +3038,7 @@ static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
Disassemble = InputArgs.hasArg(OBJDUMP_disassemble);
DisassembleAll = InputArgs.hasArg(OBJDUMP_disassemble_all);
SymbolDescription = InputArgs.hasArg(OBJDUMP_symbol_description);
+ TracebackTable = InputArgs.hasArg(OBJDUMP_traceback_table);
DisassembleSymbols =
commaSeparatedValues(InputArgs, OBJDUMP_disassemble_symbols_EQ);
DisassembleZeroes = InputArgs.hasArg(OBJDUMP_disassemble_zeroes);
@@ -3218,7 +3239,7 @@ int main(int argc, char **argv) {
ArchiveHeaders = FileHeaders = PrivateHeaders = Relocations =
SectionHeaders = SymbolTable = true;
- if (DisassembleAll || PrintSource || PrintLines ||
+ if (DisassembleAll || PrintSource || PrintLines || TracebackTable ||
!DisassembleSymbols.empty())
Disassemble = true;
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h
index efb44519525958..51dd3aa918d132 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -12,9 +12,11 @@
#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
+#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Object/Archive.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/FormattedStream.h"
namespace llvm {
class StringRef;
@@ -55,6 +57,7 @@ extern bool SectionHeaders;
extern bool SectionContents;
extern bool ShowRawInsn;
extern bool SymbolDescription;
+extern bool TracebackTable;
extern bool SymbolTable;
extern std::string TripleName;
extern bool UnwindInfo;
@@ -156,6 +159,10 @@ std::string getFileNameForError(const object::Archive::Child &C,
unsigned Index);
SymbolInfoTy createSymbolInfo(const object::ObjectFile &Obj,
const object::SymbolRef &Symbol);
+unsigned getInstStartColumn(const MCSubtargetInfo &STI);
+void printRawData(llvm::ArrayRef<uint8_t> Bytes, uint64_t Address,
+ llvm::formatted_raw_ostream &OS,
+ llvm::MCSubtargetInfo const &STI);
} // namespace objdump
} // end namespace llvm
diff --git a/llvm/unittests/Object/XCOFFObjectFileTest.cpp b/llvm/unittests/Object/XCOFFObjectFileTest.cpp
index f00ae6cd070864..f696cde99e0ecc 100644
--- a/llvm/unittests/Object/XCOFFObjectFileTest.cpp
+++ b/llvm/unittests/Object/XCOFFObjectFileTest.cpp
@@ -158,10 +158,11 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIParmsType) {
}
const uint8_t TBTableData[] = {
- 0x00, 0x00, 0x2A, 0x60, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc4, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
- 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c,
- 0x6c, 0x1f, 0x02, 0x05, 0xf0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
+ 0x00, 0x00, 0x2A, 0x60, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02,
+ 0x05, 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07,
+ 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x1f, 0x02, 0x05,
+ 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIControlledStorageInfoDisp) {
uint64_t Size = sizeof(TBTableData);
@@ -180,7 +181,7 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIControlledStorageInfoDisp) {
ASSERT_EQ(Disp.size(), 2UL);
EXPECT_EQ(Disp[0], 0x05050000u);
EXPECT_EQ(Disp[1], 0x06060000u);
- EXPECT_EQ(Size, 45u);
+ EXPECT_EQ(Size, 47u);
}
TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIAllocaRegister) {
@@ -224,15 +225,16 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo) {
ASSERT_TRUE(TT.getExtensionTable());
EXPECT_EQ(*TT.getExtensionTable(), ExtendedTBTableFlag::TB_SSP_CANARY);
- EXPECT_EQ(Size, 45u);
+ EXPECT_EQ(Size, 47u);
}
TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo1) {
const uint8_t TBTableData[] = {
- 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc5, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
- 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c,
- 0x6c, 0x11, 0x07, 0x90, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
+ 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc5,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02,
+ 0x05, 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07,
+ 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x11, 0x07, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
uint64_t Size = sizeof(TBTableData);
Expected<XCOFFTracebackTable> TTOrErr =
XCOFFTracebackTable::create(TBTableData, Size);
@@ -257,7 +259,7 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo1) {
ASSERT_TRUE(TT.getExtensionTable());
EXPECT_EQ(*TT.getExtensionTable(), ExtendedTBTableFlag::TB_SSP_CANARY);
- EXPECT_EQ(Size, 44u);
+ EXPECT_EQ(Size, 46u);
}
TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtMandatory) {
@@ -386,15 +388,15 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtVectorInfoParmsInfo) {
}
TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtExtLongTBTable) {
- uint64_t Size = 44;
+ uint64_t Size = 46;
Expected<XCOFFTracebackTable> TTOrErr =
XCOFFTracebackTable::create(TBTableData, Size);
EXPECT_THAT_ERROR(
TTOrErr.takeError(),
FailedWithMessage(
- "unexpected end of data at offset 0x2c while reading [0x2c, 0x2d)"));
- EXPECT_EQ(Size, 44u);
+ "unexpected end of data at offset 0x2e while reading [0x2e, 0x2f)"));
+ EXPECT_EQ(Size, 46u);
}
TEST(XCOFFObjectFileTest, XCOFFGetCsectAuxRef32) {
@@ -528,11 +530,12 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableErrorAtParameterType) {
TEST(XCOFFObjectFileTest, XCOFFTracebackTableErrorAtParameterTypeWithVecInfo) {
const uint8_t TBTableData[] = {
- 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc0, 0x00, 0x10,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
- 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c,
- 0x6c, 0x11, 0x07, 0x90, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
- uint64_t Size = 44;
+ 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc0,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02,
+ 0x05, 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07,
+ 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x11, 0x07, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
+ uint64_t Size = 46;
Expected<XCOFFTracebackTable> TTOrErr =
XCOFFTracebackTable::create(TBTableData, Size);
@@ -544,11 +547,12 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableErrorAtParameterTypeWithVecInfo) {
TEST(XCOFFObjectFileTest, XCOFFTracebackTableErrorAtVecParameterType) {
const uint8_t TBTableData[] = {
- 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
- 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c,
- 0x6c, 0x11, 0x07, 0x90, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00};
- uint64_t Size = 44;
+ 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02,
+ 0x05, 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07,
+ 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x11, 0x07, 0x90,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
+ uint64_t Size = 46;
Expected<XCOFFTracebackTable> TTOrErr =
XCOFFTracebackTable::create(TBTableData, Size);
More information about the llvm-commits
mailing list