[llvm] [llvm-objdump] Add inlined function display support (PR #142246)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 9 07:34:31 PDT 2025
https://github.com/gulfemsavrun updated https://github.com/llvm/llvm-project/pull/142246
>From 8ea0679e22237a5d37ecdc77789a54b083815835 Mon Sep 17 00:00:00 2001
From: Gulfem Savrun Yeniceri <gulfem at google.com>
Date: Fri, 30 May 2025 18:19:41 -0700
Subject: [PATCH 1/2] [llvm-objdump] Add inlined function display support
This patch adds the support for displaying inlined functions
into llvm-objdump.
1) It extends the source variable display
support for inlined functions both for ascii and unicode
formats.
2) It also introduces a new format called line that only
prints a line for the start and end of an inlined function
without line-drawing characters.
---
llvm/docs/CommandGuide/llvm-objdump.rst | 18 +-
llvm/docs/ReleaseNotes.md | 4 +
.../llvm-objdump/ELF/ARM/debug-vars-dwarf4.s | 4 +-
.../X86/Inputs/debug-inlined-functions.c | 10 +
.../llvm-objdump/X86/debug-inlined-function.s | 650 ++++++++++++++++++
llvm/tools/llvm-objdump/ObjdumpOpts.td | 8 +-
llvm/tools/llvm-objdump/SourcePrinter.cpp | 190 ++++-
llvm/tools/llvm-objdump/SourcePrinter.h | 95 ++-
llvm/tools/llvm-objdump/llvm-objdump.cpp | 34 +-
llvm/tools/llvm-objdump/llvm-objdump.h | 5 +-
10 files changed, 944 insertions(+), 74 deletions(-)
create mode 100644 llvm/test/tools/llvm-objdump/X86/Inputs/debug-inlined-functions.c
create mode 100644 llvm/test/tools/llvm-objdump/X86/debug-inlined-function.s
diff --git a/llvm/docs/CommandGuide/llvm-objdump.rst b/llvm/docs/CommandGuide/llvm-objdump.rst
index 5e5eaccecd2b7..e49cd197034c3 100644
--- a/llvm/docs/CommandGuide/llvm-objdump.rst
+++ b/llvm/docs/CommandGuide/llvm-objdump.rst
@@ -147,17 +147,23 @@ OPTIONS
and at least one server URL was provided by the environment variable
``DEBUGINFOD_URLS``.
-.. option:: --debug-vars=<format>
+.. option:: --debug-indent=<width>
+
+ Distance to indent the source-level variable or inlined function display,
+ relative to the start of the disassembly. Defaults to 52 characters.
+
+.. option:: --debug-inlined-funcs[=<format>]
+
+ Print the locations of inlined functions alongside disassembly.
+ ``format`` may be ``unicode``, ``ascii`` or ``line``, defaulting to
+ ``unicode`` if omitted.
+
+.. option:: --debug-vars[=<format>]
Print the locations (in registers or memory) of source-level variables
alongside disassembly. ``format`` may be ``unicode`` or ``ascii``, defaulting
to ``unicode`` if omitted.
-.. option:: --debug-vars-indent=<width>
-
- Distance to indent the source-level variable display, relative to the start
- of the disassembly. Defaults to 52 characters.
-
.. option:: -j, --section=<section1[,section2,...]>
Perform commands on the specified sections only. For Mach-O use
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 5c9ed181af59e..2d236a9d12397 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -267,6 +267,10 @@ Changes to the LLVM tools
* In llvm-objcopy/llvm-strip's ELF port, `--discard-locals` and `--discard-all` now allow and preserve symbols referenced by relocations.
([#47468](https://github.com/llvm/llvm-project/issues/47468))
* llvm-addr2line now supports a `+` prefix when specifying an address.
+* llvm-objdump now supports the `--debug-inlined-funcs` flag that prints the
+ locations of inlined functions alongside disassembly. It also renames
+ `--debug-vars-indent` flag to `--debug-indent`.
+
Changes to LLDB
---------------------------------
diff --git a/llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-dwarf4.s b/llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-dwarf4.s
index 69b7489e7e62e..085f258edfa57 100644
--- a/llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-dwarf4.s
+++ b/llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-dwarf4.s
@@ -15,10 +15,10 @@
## Check that passing the default value for --debug-vars-indent (52) makes no
## change to the output.
-# RUN: llvm-objdump %t.o -d --debug-vars --debug-vars-indent=52 | \
+# RUN: llvm-objdump %t.o -d --debug-vars --debug-indent=52 | \
# RUN: FileCheck %s --check-prefix=RAW --strict-whitespace
-# RUN: llvm-objdump %t.o -d --debug-vars --debug-vars-indent=30 | \
+# RUN: llvm-objdump %t.o -d --debug-vars --debug-indent=30 | \
# RUN: FileCheck %s --check-prefix=INDENT --strict-whitespace
# RUN: llvm-objdump %t.o -d --debug-vars --no-show-raw-insn | \
diff --git a/llvm/test/tools/llvm-objdump/X86/Inputs/debug-inlined-functions.c b/llvm/test/tools/llvm-objdump/X86/Inputs/debug-inlined-functions.c
new file mode 100644
index 0000000000000..a708bc0cae604
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/X86/Inputs/debug-inlined-functions.c
@@ -0,0 +1,10 @@
+int bar(int x, int y) {
+ int sum = x + y;
+ int mul = x * y;
+ return sum + mul;
+}
+
+int foo(int a, int b) {
+ int result = bar(a, b);
+ return result;
+}
diff --git a/llvm/test/tools/llvm-objdump/X86/debug-inlined-function.s b/llvm/test/tools/llvm-objdump/X86/debug-inlined-function.s
new file mode 100644
index 0000000000000..a88b23baab810
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/X86/debug-inlined-function.s
@@ -0,0 +1,650 @@
+## Generated with this compile command, with the source code in Inputs/debug-inlined-functions.c:
+## clang -g -c debug-inlined-function.c -O1 -S -o -
+
+# RUN: llvm-mc -triple=x86_64 %s -filetype=obj -o %t.o
+
+# RUN: llvm-objdump %t.o -d --debug-inlined-funcs=line | \
+# RUN: FileCheck %s --check-prefix=LINE
+
+# RUN: llvm-objdump %t.o -d --debug-inlined-funcs=unicode | \
+# RUN: FileCheck %s --check-prefix=UNICODE --strict-whitespace
+
+# RUN: llvm-objdump %t.o -d --debug-inlined-funcs=unicode --debug-indent=30 | \
+# RUN: FileCheck %s --check-prefix=INDENT --strict-whitespace
+
+# RUN: llvm-objdump %t.o -d --debug-inlined-funcs=ascii | \
+# RUN: FileCheck %s --check-prefix=ASCII --strict-whitespace
+
+# RUN: llvm-objdump %t.o -d --debug-inlined-funcs=unicode --debug-vars=unicode | \
+# RUN: FileCheck %s --check-prefix=DEBUG-ALL --strict-whitespace
+
+# LINE: 0000000000000000 <bar>:
+# LINE-NEXT: 0: 8d 04 3e leal (%rsi,%rdi), %eax
+# LINE-NEXT: 3: 0f af f7 imull %edi, %esi
+# LINE-NEXT: 6: 01 f0 addl %esi, %eax
+# LINE-NEXT: 8: c3 retq
+# LINE-NEXT: 9: 0f 1f 80 00 00 00 00 nopl (%rax)
+# LINE-EMPTY:
+# LINE-NEXT: 0000000000000010 <foo>:
+# LINE-NEXT: debug-inlined-functions.c:8:16: bar inlined into foo
+# LINE-NEXT: 10: 8d 04 3e leal (%rsi,%rdi), %eax
+# LINE-NEXT: 13: 0f af f7 imull %edi, %esi
+# LINE-NEXT: 16: 01 f0 addl %esi, %eax
+# LINE-NEXT: debug-inlined-functions.c:8:16: end of bar inlined into foo
+# LINE-NEXT: 18: c3 retq
+
+# UNICODE: 0000000000000000 <bar>:
+# UNICODE-NEXT: 0: 8d 04 3e leal (%rsi,%rdi), %eax
+# UNICODE-NEXT: 3: 0f af f7 imull %edi, %esi
+# UNICODE-NEXT: 6: 01 f0 addl %esi, %eax
+# UNICODE-NEXT: 8: c3 retq
+# UNICODE-NEXT: 9: 0f 1f 80 00 00 00 00 nopl (%rax)
+# UNICODE-EMPTY:
+# UNICODE-NEXT: 0000000000000010 <foo>:
+# UNICODE-NEXT: ┠─ bar = inlined into foo
+# UNICODE-NEXT: 10: 8d 04 3e leal (%rsi,%rdi), %eax ┃
+# UNICODE-NEXT: 13: 0f af f7 imull %edi, %esi ┃
+# UNICODE-NEXT: 16: 01 f0 addl %esi, %eax ┻
+# UNICODE-NEXT: 18: c3 retq
+
+# INDENT: 0000000000000000 <bar>:
+# INDENT-NEXT: 0: 8d 04 3e leal (%rsi,%rdi), %eax
+# INDENT-NEXT: 3: 0f af f7 imull %edi, %esi
+# INDENT-NEXT: 6: 01 f0 addl %esi, %eax
+# INDENT-NEXT: 8: c3 retq
+# INDENT-NEXT: 9: 0f 1f 80 00 00 00 00 nopl (%rax)
+# INDENT-EMPTY:
+# INDENT-NEXT: 0000000000000010 <foo>:
+# INDENT-NEXT: ┠─ bar = inlined into foo
+# INDENT-NEXT: 10: 8d 04 3e leal (%rsi,%rdi), %eax ┃
+# INDENT-NEXT: 13: 0f af f7 imull %edi, %esi ┃
+# INDENT-NEXT: 16: 01 f0 addl %esi, %eax ┻
+# INDENT-NEXT: 18: c3 retq
+
+# ASCII: 0000000000000000 <bar>:
+# ASCII-NEXT: 0: 8d 04 3e leal (%rsi,%rdi), %eax
+# ASCII-NEXT: 3: 0f af f7 imull %edi, %esi
+# ASCII-NEXT: 6: 01 f0 addl %esi, %eax
+# ASCII-NEXT: 8: c3 retq
+# ASCII-NEXT: 9: 0f 1f 80 00 00 00 00 nopl (%rax)
+# ASCII-EMPTY:
+# ASCII-NEXT: 0000000000000010 <foo>:
+# ASCII-NEXT: |- bar = inlined into foo
+# ASCII-NEXT: 10: 8d 04 3e leal (%rsi,%rdi), %eax |
+# ASCII-NEXT: 13: 0f af f7 imull %edi, %esi |
+# ASCII-NEXT: 16: 01 f0 addl %esi, %eax v
+# ASCII-NEXT: 18: c3 retq
+
+# DEBUG-ALL: 0000000000000010 <foo>:
+# DEBUG-ALL-NEXT: ┠─ a = RDI
+# DEBUG-ALL-NEXT: ┃ ┠─ b = RSI
+# DEBUG-ALL-NEXT: ┃ ┃ ┠─ bar = inlined into foo
+# DEBUG-ALL-NEXT: ┃ ┃ ┃ ┠─ x = RDI
+# DEBUG-ALL-NEXT: ┃ ┃ ┃ ┃ ┠─ y = RSI
+# DEBUG-ALL-NEXT: ┃ ┃ ┃ ┃ ┃ ┌─ sum = RAX
+# DEBUG-ALL-NEXT: 10: 8d 04 3e leal (%rsi,%rdi), %eax ┃ ┃ ┃ ┃ ┃ ╈
+# DEBUG-ALL-NEXT: ┃ ┃ ┃ ┃ ┃ ┃ ┌─ b = entry(RSI)
+# DEBUG-ALL-NEXT: ┃ ┃ ┃ ┃ ┃ ┃ │ ┌─ mul = RSI
+# DEBUG-ALL-NEXT: 13: 0f af f7 imull %edi, %esi ┃ ┻ ┃ ┃ ┻ ┃ ╈ ╈
+# DEBUG-ALL-NEXT: ┃ ┌─ result = RAX
+# DEBUG-ALL-NEXT: 16: 01 f0 addl %esi, %eax ┃ ╈ ┻ ┻ ┻ ┃ ┃
+# DEBUG-ALL-NEXT: 18: c3 retq ┻ ┻ ┻ ┻
+
+ .file "debug-inlined-functions.c"
+ .text
+ .globl bar # -- Begin function bar
+ .p2align 4
+ .type bar, at function
+bar: # @bar
+.Lfunc_begin0:
+ .file 0 "" "debug-inlined-function.c"
+ .cfi_startproc
+# %bb.0:
+ #DEBUG_VALUE: bar:x <- $edi
+ #DEBUG_VALUE: bar:y <- $esi
+ # kill: def $esi killed $esi def $rsi
+ # kill: def $edi killed $edi def $rdi
+ .file 1 "" "debug-inlined-functions.c"
+ .loc 1 2 15 prologue_end
+ leal (%rsi,%rdi), %eax
+.Ltmp0:
+ #DEBUG_VALUE: bar:sum <- $eax
+ .loc 1 3 15
+ imull %edi, %esi
+.Ltmp1:
+ #DEBUG_VALUE: bar:y <- [DW_OP_LLVM_entry_value 1] $esi
+ #DEBUG_VALUE: bar:mul <- $esi
+ .loc 1 4 14
+ addl %esi, %eax
+.Ltmp2:
+ .loc 1 4 3 is_stmt 0
+ retq
+.Ltmp3:
+.Lfunc_end0:
+ .size bar, .Lfunc_end0-bar
+ .cfi_endproc
+ # -- End function
+ .globl foo # -- Begin function foo
+ .p2align 4
+ .type foo, at function
+foo: # @foo
+.Lfunc_begin1:
+ .cfi_startproc
+# %bb.0:
+ #DEBUG_VALUE: foo:a <- $edi
+ #DEBUG_VALUE: foo:b <- $esi
+ #DEBUG_VALUE: bar:x <- $edi
+ #DEBUG_VALUE: bar:y <- $esi
+ # kill: def $esi killed $esi def $rsi
+ # kill: def $edi killed $edi def $rdi
+ .loc 1 2 15 prologue_end is_stmt 1
+ leal (%rsi,%rdi), %eax
+.Ltmp4:
+ #DEBUG_VALUE: bar:sum <- $eax
+ .loc 1 3 15
+ imull %edi, %esi
+.Ltmp5:
+ #DEBUG_VALUE: foo:b <- [DW_OP_LLVM_entry_value 1] $esi
+ #DEBUG_VALUE: bar:mul <- $esi
+ .loc 1 4 14
+ addl %esi, %eax
+.Ltmp6:
+ #DEBUG_VALUE: foo:result <- $eax
+ .loc 1 9 3
+ retq
+.Ltmp7:
+.Lfunc_end1:
+ .size foo, .Lfunc_end1-foo
+ .cfi_endproc
+ # -- End function
+ .section .debug_loclists,"", at progbits
+ .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length
+.Ldebug_list_header_start0:
+ .short 5 # Version
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+ .long 8 # Offset entry count
+.Lloclists_table_base0:
+ .long .Ldebug_loc0-.Lloclists_table_base0
+ .long .Ldebug_loc1-.Lloclists_table_base0
+ .long .Ldebug_loc2-.Lloclists_table_base0
+ .long .Ldebug_loc3-.Lloclists_table_base0
+ .long .Ldebug_loc4-.Lloclists_table_base0
+ .long .Ldebug_loc5-.Lloclists_table_base0
+ .long .Ldebug_loc6-.Lloclists_table_base0
+ .long .Ldebug_loc7-.Lloclists_table_base0
+.Ldebug_loc0:
+ .byte 4 # DW_LLE_offset_pair
+ .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset
+ .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset
+ .byte 1 # Loc expr size
+ .byte 84 # super-register DW_OP_reg4
+ .byte 4 # DW_LLE_offset_pair
+ .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset
+ .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset
+ .byte 4 # Loc expr size
+ .byte 163 # DW_OP_entry_value
+ .byte 1 # 1
+ .byte 84 # super-register DW_OP_reg4
+ .byte 159 # DW_OP_stack_value
+ .byte 0 # DW_LLE_end_of_list
+.Ldebug_loc1:
+ .byte 4 # DW_LLE_offset_pair
+ .uleb128 .Ltmp0-.Lfunc_begin0 # starting offset
+ .uleb128 .Ltmp2-.Lfunc_begin0 # ending offset
+ .byte 1 # Loc expr size
+ .byte 80 # super-register DW_OP_reg0
+ .byte 0 # DW_LLE_end_of_list
+.Ldebug_loc2:
+ .byte 4 # DW_LLE_offset_pair
+ .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset
+ .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset
+ .byte 1 # Loc expr size
+ .byte 84 # super-register DW_OP_reg4
+ .byte 0 # DW_LLE_end_of_list
+.Ldebug_loc3:
+ .byte 4 # DW_LLE_offset_pair
+ .uleb128 .Lfunc_begin1-.Lfunc_begin0 # starting offset
+ .uleb128 .Ltmp5-.Lfunc_begin0 # ending offset
+ .byte 1 # Loc expr size
+ .byte 84 # super-register DW_OP_reg4
+ .byte 4 # DW_LLE_offset_pair
+ .uleb128 .Ltmp5-.Lfunc_begin0 # starting offset
+ .uleb128 .Lfunc_end1-.Lfunc_begin0 # ending offset
+ .byte 4 # Loc expr size
+ .byte 163 # DW_OP_entry_value
+ .byte 1 # 1
+ .byte 84 # super-register DW_OP_reg4
+ .byte 159 # DW_OP_stack_value
+ .byte 0 # DW_LLE_end_of_list
+.Ldebug_loc4:
+ .byte 4 # DW_LLE_offset_pair
+ .uleb128 .Lfunc_begin1-.Lfunc_begin0 # starting offset
+ .uleb128 .Ltmp5-.Lfunc_begin0 # ending offset
+ .byte 1 # Loc expr size
+ .byte 84 # super-register DW_OP_reg4
+ .byte 0 # DW_LLE_end_of_list
+.Ldebug_loc5:
+ .byte 4 # DW_LLE_offset_pair
+ .uleb128 .Ltmp4-.Lfunc_begin0 # starting offset
+ .uleb128 .Ltmp6-.Lfunc_begin0 # ending offset
+ .byte 1 # Loc expr size
+ .byte 80 # super-register DW_OP_reg0
+ .byte 0 # DW_LLE_end_of_list
+.Ldebug_loc6:
+ .byte 4 # DW_LLE_offset_pair
+ .uleb128 .Ltmp5-.Lfunc_begin0 # starting offset
+ .uleb128 .Lfunc_end1-.Lfunc_begin0 # ending offset
+ .byte 1 # Loc expr size
+ .byte 84 # super-register DW_OP_reg4
+ .byte 0 # DW_LLE_end_of_list
+.Ldebug_loc7:
+ .byte 4 # DW_LLE_offset_pair
+ .uleb128 .Ltmp6-.Lfunc_begin0 # starting offset
+ .uleb128 .Lfunc_end1-.Lfunc_begin0 # ending offset
+ .byte 1 # Loc expr size
+ .byte 80 # super-register DW_OP_reg0
+ .byte 0 # DW_LLE_end_of_list
+.Ldebug_list_header_end0:
+ .section .debug_abbrev,"", at progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .ascii "\214\001" # DW_AT_loclists_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 122 # DW_AT_call_all_calls
+ .byte 25 # DW_FORM_flag_present
+ .byte 49 # DW_AT_abstract_origin
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 5 # DW_TAG_formal_parameter
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 49 # DW_AT_abstract_origin
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 5 # DW_TAG_formal_parameter
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 34 # DW_FORM_loclistx
+ .byte 49 # DW_AT_abstract_origin
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 34 # DW_FORM_loclistx
+ .byte 49 # DW_AT_abstract_origin
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 39 # DW_AT_prototyped
+ .byte 25 # DW_FORM_flag_present
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 32 # DW_AT_inline
+ .byte 33 # DW_FORM_implicit_const
+ .byte 1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 5 # DW_TAG_formal_parameter
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 9 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 10 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 122 # DW_AT_call_all_calls
+ .byte 25 # DW_FORM_flag_present
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 39 # DW_AT_prototyped
+ .byte 25 # DW_FORM_flag_present
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 11 # Abbreviation Code
+ .byte 5 # DW_TAG_formal_parameter
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 12 # Abbreviation Code
+ .byte 5 # DW_TAG_formal_parameter
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 34 # DW_FORM_loclistx
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 13 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 34 # DW_FORM_loclistx
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 14 # Abbreviation Code
+ .byte 29 # DW_TAG_inlined_subroutine
+ .byte 1 # DW_CHILDREN_yes
+ .byte 49 # DW_AT_abstract_origin
+ .byte 19 # DW_FORM_ref4
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 88 # DW_AT_call_file
+ .byte 11 # DW_FORM_data1
+ .byte 89 # DW_AT_call_line
+ .byte 11 # DW_FORM_data1
+ .byte 87 # DW_AT_call_column
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] 0xc:0xc2 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 29 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .long .Lloclists_table_base0 # DW_AT_loclists_base
+ .byte 2 # Abbrev [2] 0x27:0x26 DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 87
+ # DW_AT_call_all_calls
+ .long 77 # DW_AT_abstract_origin
+ .byte 3 # Abbrev [3] 0x33:0x7 DW_TAG_formal_parameter
+ .byte 1 # DW_AT_location
+ .byte 85
+ .long 85 # DW_AT_abstract_origin
+ .byte 4 # Abbrev [4] 0x3a:0x6 DW_TAG_formal_parameter
+ .byte 0 # DW_AT_location
+ .long 93 # DW_AT_abstract_origin
+ .byte 5 # Abbrev [5] 0x40:0x6 DW_TAG_variable
+ .byte 1 # DW_AT_location
+ .long 101 # DW_AT_abstract_origin
+ .byte 5 # Abbrev [5] 0x46:0x6 DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .long 109 # DW_AT_abstract_origin
+ .byte 0 # End Of Children Mark
+ .byte 6 # Abbrev [6] 0x4d:0x29 DW_TAG_subprogram
+ .byte 3 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ # DW_AT_prototyped
+ .long 118 # DW_AT_type
+ # DW_AT_external
+ # DW_AT_inline
+ .byte 7 # Abbrev [7] 0x55:0x8 DW_TAG_formal_parameter
+ .byte 5 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .long 118 # DW_AT_type
+ .byte 7 # Abbrev [7] 0x5d:0x8 DW_TAG_formal_parameter
+ .byte 6 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .long 118 # DW_AT_type
+ .byte 8 # Abbrev [8] 0x65:0x8 DW_TAG_variable
+ .byte 7 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 118 # DW_AT_type
+ .byte 8 # Abbrev [8] 0x6d:0x8 DW_TAG_variable
+ .byte 8 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .long 118 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 9 # Abbrev [9] 0x76:0x4 DW_TAG_base_type
+ .byte 4 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 10 # Abbrev [10] 0x7a:0x53 DW_TAG_subprogram
+ .byte 1 # DW_AT_low_pc
+ .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 87
+ # DW_AT_call_all_calls
+ .byte 9 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 7 # DW_AT_decl_line
+ # DW_AT_prototyped
+ .long 118 # DW_AT_type
+ # DW_AT_external
+ .byte 11 # Abbrev [11] 0x89:0xa DW_TAG_formal_parameter
+ .byte 1 # DW_AT_location
+ .byte 85
+ .byte 10 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 7 # DW_AT_decl_line
+ .long 118 # DW_AT_type
+ .byte 12 # Abbrev [12] 0x93:0x9 DW_TAG_formal_parameter
+ .byte 3 # DW_AT_location
+ .byte 11 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 7 # DW_AT_decl_line
+ .long 118 # DW_AT_type
+ .byte 13 # Abbrev [13] 0x9c:0x9 DW_TAG_variable
+ .byte 7 # DW_AT_location
+ .byte 12 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 8 # DW_AT_decl_line
+ .long 118 # DW_AT_type
+ .byte 14 # Abbrev [14] 0xa5:0x27 DW_TAG_inlined_subroutine
+ .long 77 # DW_AT_abstract_origin
+ .byte 1 # DW_AT_low_pc
+ .long .Ltmp6-.Lfunc_begin1 # DW_AT_high_pc
+ .byte 1 # DW_AT_call_file
+ .byte 8 # DW_AT_call_line
+ .byte 16 # DW_AT_call_column
+ .byte 3 # Abbrev [3] 0xb2:0x7 DW_TAG_formal_parameter
+ .byte 1 # DW_AT_location
+ .byte 85
+ .long 85 # DW_AT_abstract_origin
+ .byte 4 # Abbrev [4] 0xb9:0x6 DW_TAG_formal_parameter
+ .byte 4 # DW_AT_location
+ .long 93 # DW_AT_abstract_origin
+ .byte 5 # Abbrev [5] 0xbf:0x6 DW_TAG_variable
+ .byte 5 # DW_AT_location
+ .long 101 # DW_AT_abstract_origin
+ .byte 5 # Abbrev [5] 0xc5:0x6 DW_TAG_variable
+ .byte 6 # DW_AT_location
+ .long 109 # DW_AT_abstract_origin
+ .byte 0 # End Of Children Mark
+ .byte 0 # End Of Children Mark
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"", at progbits
+ .long 56 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 21.0.0git (git at github.com:llvm/llvm-project.git a97f73405f8e074263a0ed2dd2b8c87c014f46d9)" # string offset=0
+.Linfo_string1:
+ .asciz "SRC_COMPDIR/debug.c" # string offset=108
+.Linfo_string2:
+ .asciz "build" # string offset=224
+.Linfo_string3:
+ .asciz "bar" # string offset=273
+.Linfo_string4:
+ .asciz "int" # string offset=277
+.Linfo_string5:
+ .asciz "x" # string offset=281
+.Linfo_string6:
+ .asciz "y" # string offset=283
+.Linfo_string7:
+ .asciz "sum" # string offset=285
+.Linfo_string8:
+ .asciz "mul" # string offset=289
+.Linfo_string9:
+ .asciz "foo" # string offset=293
+.Linfo_string10:
+ .asciz "a" # string offset=297
+.Linfo_string11:
+ .asciz "b" # string offset=299
+.Linfo_string12:
+ .asciz "result" # string offset=301
+ .section .debug_str_offsets,"", at progbits
+ .long .Linfo_string0
+ .long .Linfo_string1
+ .long .Linfo_string2
+ .long .Linfo_string3
+ .long .Linfo_string4
+ .long .Linfo_string5
+ .long .Linfo_string6
+ .long .Linfo_string7
+ .long .Linfo_string8
+ .long .Linfo_string9
+ .long .Linfo_string10
+ .long .Linfo_string11
+ .long .Linfo_string12
+ .section .debug_addr,"", at progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+ .quad .Lfunc_begin1
+.Ldebug_addr_end0:
+ .ident "clang version 21.0.0git (git at github.com:llvm/llvm-project.git a97f73405f8e074263a0ed2dd2b8c87c014f46d9)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/llvm/tools/llvm-objdump/ObjdumpOpts.td b/llvm/tools/llvm-objdump/ObjdumpOpts.td
index c3764c6e97534..526e6896821bd 100644
--- a/llvm/tools/llvm-objdump/ObjdumpOpts.td
+++ b/llvm/tools/llvm-objdump/ObjdumpOpts.td
@@ -248,7 +248,13 @@ def debug_vars_EQ : Joined<["--"], "debug-vars=">,
Values<"unicode,ascii">;
def : Flag<["--"], "debug-vars">, Alias<debug_vars_EQ>, AliasArgs<["unicode"]>;
-def debug_vars_indent_EQ : Joined<["--"], "debug-vars-indent=">,
+def debug_inlined_funcs_EQ : Joined<["--"], "debug-inlined-funcs=">,
+ HelpText<"Print the locations of inlined functions alongside disassembly. "
+ "Supported formats: ascii, unicode (default) and line">,
+ Values<"unicode,ascii,line">;
+def : Flag<["--"], "debug-inlined-funcs">, Alias<debug_inlined_funcs_EQ>, AliasArgs<["unicode"]>;
+
+def debug_indent_EQ : Joined<["--"], "debug-indent=">,
HelpText<"Distance to indent the source-level variable display, "
"relative to the start of the disassembly">;
diff --git a/llvm/tools/llvm-objdump/SourcePrinter.cpp b/llvm/tools/llvm-objdump/SourcePrinter.cpp
index 33d494bfd1ac7..97f50fbb50806 100644
--- a/llvm/tools/llvm-objdump/SourcePrinter.cpp
+++ b/llvm/tools/llvm-objdump/SourcePrinter.cpp
@@ -8,7 +8,7 @@
//
// This file implements the LiveVariablePrinter and SourcePrinter classes to
// keep track of DWARF info as the current address is updated, and print out the
-// source file line and variable liveness as needed.
+// source file line and variable or inlined function liveness as needed.
//
//===----------------------------------------------------------------------===//
@@ -16,6 +16,7 @@
#include "llvm-objdump.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/FormatVariadic.h"
#define DEBUG_TYPE "objdump"
@@ -23,6 +24,69 @@
namespace llvm {
namespace objdump {
+bool InlinedFunction::liveAtAddress(object::SectionedAddress Addr) {
+ if (!Range.valid())
+ return false;
+
+ return Range.LowPC <= Addr.Address && Range.HighPC > Addr.Address;
+}
+
+void InlinedFunction::print(raw_ostream &OS, const MCRegisterInfo &MRI) const {
+ const char *MangledCallerName = FuncDie.getName(DINameKind::LinkageName);
+ if (!MangledCallerName)
+ return;
+
+ if (Demangle)
+ OS << "inlined into " << demangle(MangledCallerName);
+ else
+ OS << "inlined into " << MangledCallerName;
+}
+
+void InlinedFunction::dump(raw_ostream &OS) const {
+ OS << Name << " @ " << Range << ": ";
+}
+
+void InlinedFunction::printElementLine(raw_ostream &OS,
+ object::SectionedAddress Addr,
+ bool IsEnd) const {
+ bool LiveIn = !IsEnd && Range.LowPC == Addr.Address;
+ bool LiveOut = IsEnd && Range.HighPC == Addr.Address;
+ if (!(LiveIn || LiveOut))
+ return;
+
+ uint32_t CallFile, CallLine, CallColumn, CallDiscriminator;
+ InlinedFuncDie.getCallerFrame(CallFile, CallLine, CallColumn,
+ CallDiscriminator);
+ const DWARFDebugLine::LineTable *LineTable =
+ Unit->getContext().getLineTableForUnit(Unit);
+ std::string FileName;
+ if (!LineTable->hasFileAtIndex(CallFile))
+ return;
+ if (!LineTable->getFileNameByIndex(
+ CallFile, Unit->getCompilationDir(),
+ DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FileName))
+ return;
+
+ if (FileName.empty())
+ return;
+
+ const char *MangledCallerName = FuncDie.getName(DINameKind::LinkageName);
+ if (!MangledCallerName)
+ return;
+
+ std::string CallerName = MangledCallerName;
+ std::string CalleeName = Name;
+ if (Demangle) {
+ CallerName = demangle(MangledCallerName);
+ CalleeName = demangle(Name);
+ }
+
+ OS << "; " << FileName << ":" << CallLine << ":" << CallColumn << ": ";
+ if (IsEnd)
+ OS << "end of ";
+ OS << CalleeName << " inlined into " << CallerName << "\n";
+}
+
bool LiveVariable::liveAtAddress(object::SectionedAddress Addr) {
if (LocExpr.Range == std::nullopt)
return false;
@@ -48,6 +112,23 @@ void LiveVariable::print(raw_ostream &OS, const MCRegisterInfo &MRI) const {
Expression.printCompact(OS, GetRegName);
}
+void LiveVariable::dump(raw_ostream &OS) const {
+ OS << Name << " @ " << LocExpr.Range << ": ";
+}
+
+void LiveVariablePrinter::addInlinedFunction(DWARFDie FuncDie,
+ DWARFDie InlinedFuncDie) {
+ uint64_t FuncLowPC, FuncHighPC, SectionIndex;
+ if (!InlinedFuncDie.getLowAndHighPC(FuncLowPC, FuncHighPC, SectionIndex))
+ return;
+
+ DWARFUnit *U = InlinedFuncDie.getDwarfUnit();
+ const char *InlinedFuncName = InlinedFuncDie.getName(DINameKind::LinkageName);
+ DWARFAddressRange Range{FuncLowPC, FuncHighPC, SectionIndex};
+ LiveElements.emplace_back(std::make_unique<InlinedFunction>(
+ InlinedFuncName, U, FuncDie, InlinedFuncDie, Range));
+}
+
void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
uint64_t FuncLowPC, FuncHighPC, SectionIndex;
FuncDie.getLowAndHighPC(FuncLowPC, FuncHighPC, SectionIndex);
@@ -66,7 +147,8 @@ void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
for (const DWARFLocationExpression &LocExpr : *Locs) {
if (LocExpr.Range) {
- LiveVariables.emplace_back(LocExpr, VarName, U, FuncDie);
+ LiveElements.emplace_back(
+ std::make_unique<LiveVariable>(LocExpr, VarName, U, FuncDie));
} else {
// If the LocExpr does not have an associated range, it is valid for
// the whole of the function.
@@ -74,22 +156,28 @@ void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
// LocExpr, does that happen in reality?
DWARFLocationExpression WholeFuncExpr{
DWARFAddressRange(FuncLowPC, FuncHighPC, SectionIndex), LocExpr.Expr};
- LiveVariables.emplace_back(WholeFuncExpr, VarName, U, FuncDie);
+ LiveElements.emplace_back(
+ std::make_unique<LiveVariable>(WholeFuncExpr, VarName, U, FuncDie));
}
}
}
void LiveVariablePrinter::addFunction(DWARFDie D) {
for (const DWARFDie &Child : D.children()) {
- if (Child.getTag() == dwarf::DW_TAG_variable ||
- Child.getTag() == dwarf::DW_TAG_formal_parameter)
+ if (DbgVariables != DVDisabled &&
+ (Child.getTag() == dwarf::DW_TAG_variable ||
+ Child.getTag() == dwarf::DW_TAG_formal_parameter))
addVariable(D, Child);
- else
+ else if (DbgInlinedFunctions != DVDisabled &&
+ Child.getTag() == dwarf::DW_TAG_inlined_subroutine) {
+ addInlinedFunction(D, Child);
+ addFunction(Child);
+ } else
addFunction(Child);
}
}
-// Get the column number (in characters) at which the first live variable
+// Get the column number (in characters) at which the first live element
// line should be printed.
unsigned LiveVariablePrinter::getIndentLevel() const {
return DbgIndent + getInstStartColumn(STI);
@@ -99,7 +187,7 @@ unsigned LiveVariablePrinter::getIndentLevel() const {
// printed line, and return the index of that column.
// TODO: formatted_raw_ostream uses "column" to mean a number of characters
// since the last \n, and we use it to mean the number of slots in which we
-// put live variable lines. Pick a less overloaded word.
+// put live element lines. Pick a less overloaded word.
unsigned LiveVariablePrinter::moveToFirstVarColumn(formatted_raw_ostream &OS) {
// Logical column number: column zero is the first column we print in, each
// logical column is 2 physical columns wide.
@@ -127,9 +215,9 @@ unsigned LiveVariablePrinter::findFreeColumn() {
}
void LiveVariablePrinter::dump() const {
- for (const LiveVariable &LV : LiveVariables) {
- dbgs() << LV.VarName << " @ " << LV.LocExpr.Range << ": ";
- LV.print(dbgs(), MRI);
+ for (const std::unique_ptr<LiveElement> &LE : LiveElements) {
+ LE->dump(dbgs());
+ LE->print(dbgs(), MRI);
dbgs() << "\n";
}
}
@@ -150,44 +238,54 @@ void LiveVariablePrinter::addCompileUnit(DWARFDie D) {
void LiveVariablePrinter::update(object::SectionedAddress ThisAddr,
object::SectionedAddress NextAddr,
bool IncludeDefinedVars) {
+ // Do not create live ranges when debug-inlined-funcs option is provided with
+ // line format option.
+ if (DbgInlinedFunctions == DVLine)
+ return;
+
// First, check variables which have already been assigned a column, so
// that we don't change their order.
- SmallSet<unsigned, 8> CheckedVarIdxs;
+ SmallSet<unsigned, 8> CheckedElementIdxs;
for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) {
if (!ActiveCols[ColIdx].isActive())
continue;
- CheckedVarIdxs.insert(ActiveCols[ColIdx].VarIdx);
- LiveVariable &LV = LiveVariables[ActiveCols[ColIdx].VarIdx];
- ActiveCols[ColIdx].LiveIn = LV.liveAtAddress(ThisAddr);
- ActiveCols[ColIdx].LiveOut = LV.liveAtAddress(NextAddr);
+
+ CheckedElementIdxs.insert(ActiveCols[ColIdx].ElementIdx);
+ const std::unique_ptr<LiveElement> &LE =
+ LiveElements[ActiveCols[ColIdx].ElementIdx];
+ ActiveCols[ColIdx].LiveIn = LE->liveAtAddress(ThisAddr);
+ ActiveCols[ColIdx].LiveOut = LE->liveAtAddress(NextAddr);
+ std::string Name = Demangle ? demangle(LE->getName()) : LE->getName();
LLVM_DEBUG(dbgs() << "pass 1, " << ThisAddr.Address << "-"
- << NextAddr.Address << ", " << LV.VarName << ", Col "
- << ColIdx << ": LiveIn=" << ActiveCols[ColIdx].LiveIn
+ << NextAddr.Address << ", " << Name << ", Col " << ColIdx
+ << ": LiveIn=" << ActiveCols[ColIdx].LiveIn
<< ", LiveOut=" << ActiveCols[ColIdx].LiveOut << "\n");
if (!ActiveCols[ColIdx].LiveIn && !ActiveCols[ColIdx].LiveOut)
- ActiveCols[ColIdx].VarIdx = Column::NullVarIdx;
+ ActiveCols[ColIdx].ElementIdx = Column::NullElementIdx;
}
// Next, look for variables which don't already have a column, but which
// are now live.
if (IncludeDefinedVars) {
- for (unsigned VarIdx = 0, End = LiveVariables.size(); VarIdx < End;
- ++VarIdx) {
- if (CheckedVarIdxs.count(VarIdx))
+ for (unsigned ElementIdx = 0, End = LiveElements.size(); ElementIdx < End;
+ ++ElementIdx) {
+ if (CheckedElementIdxs.count(ElementIdx))
continue;
- LiveVariable &LV = LiveVariables[VarIdx];
- bool LiveIn = LV.liveAtAddress(ThisAddr);
- bool LiveOut = LV.liveAtAddress(NextAddr);
+
+ const std::unique_ptr<LiveElement> &LE = LiveElements[ElementIdx];
+ bool LiveIn = LE->liveAtAddress(ThisAddr);
+ bool LiveOut = LE->liveAtAddress(NextAddr);
if (!LiveIn && !LiveOut)
continue;
unsigned ColIdx = findFreeColumn();
+ std::string Name = Demangle ? demangle(LE->getName()) : LE->getName();
LLVM_DEBUG(dbgs() << "pass 2, " << ThisAddr.Address << "-"
- << NextAddr.Address << ", " << LV.VarName << ", Col "
+ << NextAddr.Address << ", " << Name << ", Col "
<< ColIdx << ": LiveIn=" << LiveIn
<< ", LiveOut=" << LiveOut << "\n");
- ActiveCols[ColIdx].VarIdx = VarIdx;
+ ActiveCols[ColIdx].ElementIdx = ElementIdx;
ActiveCols[ColIdx].LiveIn = LiveIn;
ActiveCols[ColIdx].LiveOut = LiveOut;
ActiveCols[ColIdx].MustDrawLabel = true;
@@ -205,7 +303,7 @@ enum class LineChar {
LabelHoriz,
};
const char *LiveVariablePrinter::getLineChar(LineChar C) const {
- bool IsASCII = DbgVariables == DVASCII;
+ bool IsASCII = DbgVariables == DVASCII || DbgInlinedFunctions == DVASCII;
switch (C) {
case LineChar::RangeStart:
return IsASCII ? "^" : (const char *)u8"\u2548";
@@ -251,8 +349,8 @@ void LiveVariablePrinter::printAfterOtherLine(formatted_raw_ostream &OS,
OS << "\n";
}
-/// Print any live variable range info needed to the right of a
-/// non-instruction line of disassembly. This is where we print the variable
+/// Print any live element range info needed to the right of a
+/// non-instruction line of disassembly. This is where we print the element
/// names and expressions, with thin line-drawing characters connecting them
/// to the live range which starts at the next instruction. If MustPrint is
/// true, we have to print at least one line (with the continuation of any
@@ -276,17 +374,20 @@ void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream &OS,
OS << " ";
}
+ const std::unique_ptr<LiveElement> &LE =
+ LiveElements[ActiveCols[ColIdx].ElementIdx];
// Then print the variable name and location of the new live range,
// with box drawing characters joining it to the live range line.
OS << getLineChar(ActiveCols[ColIdx].LiveIn ? LineChar::LabelCornerActive
: LineChar::LabelCornerNew)
<< getLineChar(LineChar::LabelHoriz) << " ";
- WithColor(OS, raw_ostream::GREEN)
- << LiveVariables[ActiveCols[ColIdx].VarIdx].VarName;
+
+ std::string Name = Demangle ? demangle(LE->getName()) : LE->getName();
+ WithColor(OS, raw_ostream::GREEN) << Name;
OS << " = ";
{
WithColor ExprColor(OS, raw_ostream::CYAN);
- LiveVariables[ActiveCols[ColIdx].VarIdx].print(OS, MRI);
+ LE->print(OS, MRI);
}
// If there are any columns to the right of the expression we just
@@ -316,7 +417,7 @@ void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream &OS,
printAfterOtherLine(OS, false);
}
-/// Print the live variable ranges to the right of a disassembled instruction.
+/// Print the live element ranges to the right of a disassembled instruction.
void LiveVariablePrinter::printAfterInst(formatted_raw_ostream &OS) {
if (!ActiveCols.size())
return;
@@ -336,6 +437,24 @@ void LiveVariablePrinter::printAfterInst(formatted_raw_ostream &OS) {
}
}
+void LiveVariablePrinter::printStartLine(formatted_raw_ostream &OS,
+ object::SectionedAddress Addr) {
+ // Print a line to idenfity the start of an inlined function if line format
+ // is specified.
+ if (DbgInlinedFunctions == DVLine)
+ for (const std::unique_ptr<LiveElement> &LE : LiveElements)
+ LE->printElementLine(OS, Addr, false);
+}
+
+void LiveVariablePrinter::printEndLine(formatted_raw_ostream &OS,
+ object::SectionedAddress Addr) {
+ // Print a line to idenfity the end of an inlined function if line format is
+ // specified.
+ if (DbgInlinedFunctions == DVLine)
+ for (const std::unique_ptr<LiveElement> &LE : LiveElements)
+ LE->printElementLine(OS, Addr, true);
+}
+
bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) {
std::unique_ptr<MemoryBuffer> Buffer;
if (LineInfo.Source) {
@@ -418,13 +537,14 @@ void SourcePrinter::printSourceLine(formatted_raw_ostream &OS,
}
if (PrintLines)
- printLines(OS, LineInfo, Delimiter, LVP);
+ printLines(OS, Address, LineInfo, Delimiter, LVP);
if (PrintSource)
printSources(OS, LineInfo, ObjectFilename, Delimiter, LVP);
OldLineInfo = LineInfo;
}
void SourcePrinter::printLines(formatted_raw_ostream &OS,
+ object::SectionedAddress Address,
const DILineInfo &LineInfo, StringRef Delimiter,
LiveVariablePrinter &LVP) {
bool PrintFunctionName = LineInfo.FunctionName != DILineInfo::BadString &&
diff --git a/llvm/tools/llvm-objdump/SourcePrinter.h b/llvm/tools/llvm-objdump/SourcePrinter.h
index fc67fc6507444..167fd544c419f 100644
--- a/llvm/tools/llvm-objdump/SourcePrinter.h
+++ b/llvm/tools/llvm-objdump/SourcePrinter.h
@@ -22,40 +22,84 @@
namespace llvm {
namespace objdump {
+/// Base class for representing the location of a source-level variable or
+/// an inlined function.
+class LiveElement {
+protected:
+ const char *Name;
+ DWARFUnit *Unit;
+ const DWARFDie FuncDie;
+
+public:
+ LiveElement(const char *Name, DWARFUnit *Unit, const DWARFDie FuncDie)
+ : Name(Name), Unit(Unit), FuncDie(FuncDie) {}
+
+ virtual ~LiveElement() {};
+ const char *getName() const { return Name; }
+ DWARFUnit *getDwarfUnit() const { return Unit; }
+ const DWARFDie getFuncDie() const { return FuncDie; }
+
+ virtual bool liveAtAddress(object::SectionedAddress Addr) = 0;
+ virtual void print(raw_ostream &OS, const MCRegisterInfo &MRI) const = 0;
+ virtual void dump(raw_ostream &OS) const = 0;
+ virtual void printElementLine(raw_ostream &OS,
+ object::SectionedAddress Address,
+ bool IsEnd) const {}
+};
+
+class InlinedFunction : public LiveElement {
+ DWARFDie InlinedFuncDie;
+ DWARFAddressRange Range;
+
+public:
+ InlinedFunction(const char *FunctionName, DWARFUnit *Unit,
+ const DWARFDie FuncDie, const DWARFDie InlinedFuncDie,
+ DWARFAddressRange &Range)
+ : LiveElement(FunctionName, Unit, FuncDie),
+ InlinedFuncDie(InlinedFuncDie), Range(Range) {}
+
+ bool liveAtAddress(object::SectionedAddress Addr) override;
+ void print(raw_ostream &OS, const MCRegisterInfo &MRI) const override;
+ void dump(raw_ostream &OS) const override;
+ void printElementLine(raw_ostream &OS, object::SectionedAddress Address,
+ bool IsEnd) const override;
+};
+
/// Stores a single expression representing the location of a source-level
/// variable, along with the PC range for which that expression is valid.
-struct LiveVariable {
+class LiveVariable : public LiveElement {
DWARFLocationExpression LocExpr;
- const char *VarName;
- DWARFUnit *Unit;
- const DWARFDie FuncDie;
+public:
LiveVariable(const DWARFLocationExpression &LocExpr, const char *VarName,
DWARFUnit *Unit, const DWARFDie FuncDie)
- : LocExpr(LocExpr), VarName(VarName), Unit(Unit), FuncDie(FuncDie) {}
+ : LiveElement(VarName, Unit, FuncDie), LocExpr(LocExpr) {}
- bool liveAtAddress(object::SectionedAddress Addr);
-
- void print(raw_ostream &OS, const MCRegisterInfo &MRI) const;
+ DWARFLocationExpression getLocationExpression() const { return LocExpr; };
+ bool liveAtAddress(object::SectionedAddress Addr) override;
+ void print(raw_ostream &OS, const MCRegisterInfo &MRI) const override;
+ void dump(raw_ostream &OS) const override;
};
-/// Helper class for printing source variable locations alongside disassembly.
+/// Helper class for printing source locations for variables and inlines
+/// subroutines alongside disassembly.
class LiveVariablePrinter {
- // Information we want to track about one column in which we are printing a
- // variable live range.
+ // Information we want to track about one column in which we are printing an
+ // element live range.
struct Column {
- unsigned VarIdx = NullVarIdx;
+ unsigned ElementIdx = NullElementIdx;
bool LiveIn = false;
bool LiveOut = false;
bool MustDrawLabel = false;
- bool isActive() const { return VarIdx != NullVarIdx; }
+ bool isActive() const { return ElementIdx != NullElementIdx; }
- static constexpr unsigned NullVarIdx = std::numeric_limits<unsigned>::max();
+ static constexpr unsigned NullElementIdx =
+ std::numeric_limits<unsigned>::max();
};
- // All live variables we know about in the object/image file.
- std::vector<LiveVariable> LiveVariables;
+ // All live elements we know about in the object/image file.
+ std::vector<std::unique_ptr<LiveElement>> LiveElements;
// The columns we are currently drawing.
IndexedMap<Column> ActiveCols;
@@ -63,11 +107,12 @@ class LiveVariablePrinter {
const MCRegisterInfo &MRI;
const MCSubtargetInfo &STI;
+ void addInlinedFunction(DWARFDie FuncDie, DWARFDie InlinedFuncDie);
void addVariable(DWARFDie FuncDie, DWARFDie VarDie);
void addFunction(DWARFDie D);
- // Get the column number (in characters) at which the first live variable
+ // Get the column number (in characters) at which the first live element
// line should be printed.
unsigned getIndentLevel() const;
@@ -75,7 +120,7 @@ class LiveVariablePrinter {
// printed line, and return the index of that column.
// TODO: formatted_raw_ostream uses "column" to mean a number of characters
// since the last \n, and we use it to mean the number of slots in which we
- // put live variable lines. Pick a less overloaded word.
+ // put live element lines. Pick a less overloaded word.
unsigned moveToFirstVarColumn(formatted_raw_ostream &OS);
unsigned findFreeColumn();
@@ -114,7 +159,7 @@ class LiveVariablePrinter {
/// otherwise this is being printed before it.
void printAfterOtherLine(formatted_raw_ostream &OS, bool AfterInst);
- /// Print any live variable range info needed to the right of a
+ /// Print any live element range info needed to the right of a
/// non-instruction line of disassembly. This is where we print the variable
/// names and expressions, with thin line-drawing characters connecting them
/// to the live range which starts at the next instruction. If MustPrint is
@@ -123,8 +168,13 @@ class LiveVariablePrinter {
/// earlier on this line.
void printBetweenInsts(formatted_raw_ostream &OS, bool MustPrint);
- /// Print the live variable ranges to the right of a disassembled instruction.
+ /// Print the live element ranges to the right of a disassembled instruction.
void printAfterInst(formatted_raw_ostream &OS);
+
+ /// Print a line to idenfity the start of a live element.
+ void printStartLine(formatted_raw_ostream &OS, object::SectionedAddress Addr);
+ /// Print a line to idenfity the end of a live element.
+ void printEndLine(formatted_raw_ostream &OS, object::SectionedAddress Addr);
};
class SourcePrinter {
@@ -144,8 +194,9 @@ class SourcePrinter {
private:
bool cacheSource(const DILineInfo &LineInfoFile);
- void printLines(formatted_raw_ostream &OS, const DILineInfo &LineInfo,
- StringRef Delimiter, LiveVariablePrinter &LVP);
+ void printLines(formatted_raw_ostream &OS, object::SectionedAddress Address,
+ const DILineInfo &LineInfo, StringRef Delimiter,
+ LiveVariablePrinter &LVP);
void printSources(formatted_raw_ostream &OS, const DILineInfo &LineInfo,
StringRef ObjectFilename, StringRef Delimiter,
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 5ecb33375943f..0767e73082cd1 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -348,7 +348,8 @@ static bool Wide;
std::string objdump::Prefix;
uint32_t objdump::PrefixStrip;
-DebugVarsFormat objdump::DbgVariables = DVDisabled;
+DebugFormat objdump::DbgVariables = DVDisabled;
+DebugFormat objdump::DbgInlinedFunctions = DVDisabled;
int objdump::DbgIndent = 52;
@@ -678,6 +679,7 @@ class PrettyPrinter {
LiveVariablePrinter &LVP) {
if (SP && (PrintSource || PrintLines))
SP->printSourceLine(OS, Address, ObjectFilename, LVP);
+ LVP.printStartLine(OS, Address);
LVP.printBetweenInsts(OS, false);
printRawData(Bytes, Address.Address, OS, STI);
@@ -867,6 +869,7 @@ class ARMPrettyPrinter : public PrettyPrinter {
LiveVariablePrinter &LVP) override {
if (SP && (PrintSource || PrintLines))
SP->printSourceLine(OS, Address, ObjectFilename, LVP);
+ LVP.printStartLine(OS, Address);
LVP.printBetweenInsts(OS, false);
size_t Start = OS.tell();
@@ -921,6 +924,7 @@ class AArch64PrettyPrinter : public PrettyPrinter {
LiveVariablePrinter &LVP) override {
if (SP && (PrintSource || PrintLines))
SP->printSourceLine(OS, Address, ObjectFilename, LVP);
+ LVP.printStartLine(OS, Address);
LVP.printBetweenInsts(OS, false);
size_t Start = OS.tell();
@@ -959,6 +963,7 @@ class RISCVPrettyPrinter : public PrettyPrinter {
LiveVariablePrinter &LVP) override {
if (SP && (PrintSource || PrintLines))
SP->printSourceLine(OS, Address, ObjectFilename, LVP);
+ LVP.printStartLine(OS, Address);
LVP.printBetweenInsts(OS, false);
size_t Start = OS.tell();
@@ -1859,7 +1864,7 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
std::unique_ptr<DWARFContext> DICtx;
LiveVariablePrinter LVP(*DT->Context->getRegisterInfo(), *DT->SubtargetInfo);
- if (DbgVariables != DVDisabled) {
+ if (DbgVariables != DVDisabled || DbgInlinedFunctions != DVDisabled) {
DICtx = DWARFContext::create(DbgObj);
for (const std::unique_ptr<DWARFUnit> &CU : DICtx->compile_units())
LVP.addCompileUnit(CU->getUnitDIE(false));
@@ -2333,8 +2338,9 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
ThisBytes.size(),
DT->DisAsm->suggestBytesToSkip(ThisBytes, ThisAddr));
- LVP.update({Index, Section.getIndex()},
- {Index + Size, Section.getIndex()}, Index + Size != End);
+ LVP.update({ThisAddr, Section.getIndex()},
+ {ThisAddr + Size, Section.getIndex()},
+ Index + Size != End);
DT->InstPrinter->setCommentStream(CommentStream);
@@ -2543,6 +2549,10 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
}
}
+ object::SectionedAddress NextAddr = {
+ SectionAddr + Index + VMAAdjustment + Size, Section.getIndex()};
+ LVP.printEndLine(FOS, NextAddr);
+
Index += Size;
}
}
@@ -3582,13 +3592,25 @@ static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
Prefix = InputArgs.getLastArgValue(OBJDUMP_prefix).str();
parseIntArg(InputArgs, OBJDUMP_prefix_strip, PrefixStrip);
if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_debug_vars_EQ)) {
- DbgVariables = StringSwitch<DebugVarsFormat>(A->getValue())
+ DbgVariables = StringSwitch<DebugFormat>(A->getValue())
.Case("ascii", DVASCII)
.Case("unicode", DVUnicode)
.Default(DVInvalid);
if (DbgVariables == DVInvalid)
invalidArgValue(A);
}
+
+ if (const opt::Arg *A =
+ InputArgs.getLastArg(OBJDUMP_debug_inlined_funcs_EQ)) {
+ DbgInlinedFunctions = StringSwitch<DebugFormat>(A->getValue())
+ .Case("ascii", DVASCII)
+ .Case("unicode", DVUnicode)
+ .Case("line", DVLine)
+ .Default(DVInvalid);
+ if (DbgInlinedFunctions == DVInvalid)
+ invalidArgValue(A);
+ }
+
if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_disassembler_color_EQ)) {
DisassemblyColor = StringSwitch<ColorOutput>(A->getValue())
.Case("on", ColorOutput::Enable)
@@ -3599,7 +3621,7 @@ static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
invalidArgValue(A);
}
- parseIntArg(InputArgs, OBJDUMP_debug_vars_indent_EQ, DbgIndent);
+ parseIntArg(InputArgs, OBJDUMP_debug_indent_EQ, DbgIndent);
parseMachOOptions(InputArgs);
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h
index 25d9c1e106a6c..70a4d3975c24d 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -40,11 +40,12 @@ class XCOFFObjectFile;
namespace objdump {
-enum DebugVarsFormat { DVDisabled, DVUnicode, DVASCII, DVInvalid };
+enum DebugFormat { DVDisabled, DVUnicode, DVASCII, DVLine, DVInvalid };
extern bool ArchiveHeaders;
extern int DbgIndent;
-extern DebugVarsFormat DbgVariables;
+extern DebugFormat DbgVariables;
+extern DebugFormat DbgInlinedFunctions;
extern bool Demangle;
extern bool Disassemble;
extern bool DisassembleAll;
>From f53b1fc7d636fb1713a5c987674deeaa83fc2d11 Mon Sep 17 00:00:00 2001
From: Gulfem Savrun Yeniceri <gulfem at google.com>
Date: Wed, 9 Jul 2025 14:31:41 +0000
Subject: [PATCH 2/2] [llvm-objdump] Address reviewer feedback
---
llvm/docs/CommandGuide/llvm-objdump.rst | 14 +-
llvm/docs/ReleaseNotes.md | 7 +-
.../llvm-objdump/X86/debug-inlined-function.s | 17 +++
llvm/tools/llvm-objdump/ObjdumpOpts.td | 20 +--
llvm/tools/llvm-objdump/SourcePrinter.cpp | 80 +++++------
llvm/tools/llvm-objdump/SourcePrinter.h | 23 ++-
llvm/tools/llvm-objdump/llvm-objdump.cpp | 136 +++++++++---------
llvm/tools/llvm-objdump/llvm-objdump.h | 4 +-
8 files changed, 156 insertions(+), 145 deletions(-)
diff --git a/llvm/docs/CommandGuide/llvm-objdump.rst b/llvm/docs/CommandGuide/llvm-objdump.rst
index e49cd197034c3..05451ea5fe7ff 100644
--- a/llvm/docs/CommandGuide/llvm-objdump.rst
+++ b/llvm/docs/CommandGuide/llvm-objdump.rst
@@ -140,13 +140,6 @@ OPTIONS
debug information for stripped binaries. Multiple instances of this argument
are searched in the order given.
-.. option:: --debuginfod, --no-debuginfod
-
- Whether or not to try debuginfod lookups for debug binaries. Unless specified,
- debuginfod is only enabled if libcurl was compiled in (``LLVM_ENABLE_CURL``)
- and at least one server URL was provided by the environment variable
- ``DEBUGINFOD_URLS``.
-
.. option:: --debug-indent=<width>
Distance to indent the source-level variable or inlined function display,
@@ -164,6 +157,13 @@ OPTIONS
alongside disassembly. ``format`` may be ``unicode`` or ``ascii``, defaulting
to ``unicode`` if omitted.
+.. option:: --debuginfod, --no-debuginfod
+
+ Whether or not to try debuginfod lookups for debug binaries. Unless specified,
+ debuginfod is only enabled if libcurl was compiled in (``LLVM_ENABLE_CURL``)
+ and at least one server URL was provided by the environment variable
+ ``DEBUGINFOD_URLS``.
+
.. option:: -j, --section=<section1[,section2,...]>
Perform commands on the specified sections only. For Mach-O use
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 2d236a9d12397..15870daf746c7 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -267,10 +267,9 @@ Changes to the LLVM tools
* In llvm-objcopy/llvm-strip's ELF port, `--discard-locals` and `--discard-all` now allow and preserve symbols referenced by relocations.
([#47468](https://github.com/llvm/llvm-project/issues/47468))
* llvm-addr2line now supports a `+` prefix when specifying an address.
-* llvm-objdump now supports the `--debug-inlined-funcs` flag that prints the
- locations of inlined functions alongside disassembly. It also renames
- `--debug-vars-indent` flag to `--debug-indent`.
-
+* llvm-objdump now supports the `--debug-inlined-funcs` flag, which prints the
+ locations of inlined functions alongside disassembly. The
+ `--debug-vars-indent` flag has also been renamed to `--debug-indent`.
Changes to LLDB
---------------------------------
diff --git a/llvm/test/tools/llvm-objdump/X86/debug-inlined-function.s b/llvm/test/tools/llvm-objdump/X86/debug-inlined-function.s
index a88b23baab810..c00bc544b4d5f 100644
--- a/llvm/test/tools/llvm-objdump/X86/debug-inlined-function.s
+++ b/llvm/test/tools/llvm-objdump/X86/debug-inlined-function.s
@@ -6,6 +6,9 @@
# RUN: llvm-objdump %t.o -d --debug-inlined-funcs=line | \
# RUN: FileCheck %s --check-prefix=LINE
+# RUN: llvm-objdump %t.o -d --debug-inlined-funcs | \
+# RUN: FileCheck %s --check-prefix=DEFAULT --strict-whitespace
+
# RUN: llvm-objdump %t.o -d --debug-inlined-funcs=unicode | \
# RUN: FileCheck %s --check-prefix=UNICODE --strict-whitespace
@@ -33,6 +36,20 @@
# LINE-NEXT: debug-inlined-functions.c:8:16: end of bar inlined into foo
# LINE-NEXT: 18: c3 retq
+# DEFAULT: 0000000000000000 <bar>:
+# DEFAULT-NEXT: 0: 8d 04 3e leal (%rsi,%rdi), %eax
+# DEFAULT-NEXT: 3: 0f af f7 imull %edi, %esi
+# DEFAULT-NEXT: 6: 01 f0 addl %esi, %eax
+# DEFAULT-NEXT: 8: c3 retq
+# DEFAULT-NEXT: 9: 0f 1f 80 00 00 00 00 nopl (%rax)
+# DEFAULT-EMPTY:
+# DEFAULT-NEXT: 0000000000000010 <foo>:
+# DEFAULT-NEXT: ┠─ bar = inlined into foo
+# DEFAULT-NEXT: 10: 8d 04 3e leal (%rsi,%rdi), %eax ┃
+# DEFAULT-NEXT: 13: 0f af f7 imull %edi, %esi ┃
+# DEFAULT-NEXT: 16: 01 f0 addl %esi, %eax ┻
+# DEFAULT-NEXT: 18: c3 retq
+
# UNICODE: 0000000000000000 <bar>:
# UNICODE-NEXT: 0: 8d 04 3e leal (%rsi,%rdi), %eax
# UNICODE-NEXT: 3: 0f af f7 imull %edi, %esi
diff --git a/llvm/tools/llvm-objdump/ObjdumpOpts.td b/llvm/tools/llvm-objdump/ObjdumpOpts.td
index 526e6896821bd..aa416ceb1e477 100644
--- a/llvm/tools/llvm-objdump/ObjdumpOpts.td
+++ b/llvm/tools/llvm-objdump/ObjdumpOpts.td
@@ -241,22 +241,22 @@ defm prefix_strip
"paths. No effect without --prefix">,
MetaVarName<"prefix">;
-def debug_vars_EQ : Joined<["--"], "debug-vars=">,
- HelpText<"Print the locations (in registers or memory) of "
- "source-level variables alongside disassembly. "
- "Supported formats: ascii, unicode (default)">,
- Values<"unicode,ascii">;
-def : Flag<["--"], "debug-vars">, Alias<debug_vars_EQ>, AliasArgs<["unicode"]>;
+def debug_indent_EQ : Joined<["--"], "debug-indent=">,
+ HelpText<"Distance to indent the source-level variable display, "
+ "relative to the start of the disassembly">;
def debug_inlined_funcs_EQ : Joined<["--"], "debug-inlined-funcs=">,
HelpText<"Print the locations of inlined functions alongside disassembly. "
- "Supported formats: ascii, unicode (default) and line">,
+ "Supported formats: ascii, line and unicode (default)">,
Values<"unicode,ascii,line">;
def : Flag<["--"], "debug-inlined-funcs">, Alias<debug_inlined_funcs_EQ>, AliasArgs<["unicode"]>;
-def debug_indent_EQ : Joined<["--"], "debug-indent=">,
- HelpText<"Distance to indent the source-level variable display, "
- "relative to the start of the disassembly">;
+def debug_vars_EQ : Joined<["--"], "debug-vars=">,
+ HelpText<"Print the locations (in registers or memory) of "
+ "source-level variables alongside disassembly. "
+ "Supported formats: ascii, unicode (default)">,
+ Values<"unicode,ascii">;
+def : Flag<["--"], "debug-vars">, Alias<debug_vars_EQ>, AliasArgs<["unicode"]>;
def x86_asm_syntax_att : Flag<["--"], "x86-asm-syntax=att">,
HelpText<"Emit AT&T-style disassembly">;
diff --git a/llvm/tools/llvm-objdump/SourcePrinter.cpp b/llvm/tools/llvm-objdump/SourcePrinter.cpp
index 97f50fbb50806..42fb22e794bbd 100644
--- a/llvm/tools/llvm-objdump/SourcePrinter.cpp
+++ b/llvm/tools/llvm-objdump/SourcePrinter.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the LiveVariablePrinter and SourcePrinter classes to
+// This file implements the LiveElementPrinter and SourcePrinter classes to
// keep track of DWARF info as the current address is updated, and print out the
// source file line and variable or inlined function liveness as needed.
//
@@ -24,7 +24,7 @@
namespace llvm {
namespace objdump {
-bool InlinedFunction::liveAtAddress(object::SectionedAddress Addr) {
+bool InlinedFunction::liveAtAddress(object::SectionedAddress Addr) const {
if (!Range.valid())
return false;
@@ -87,7 +87,7 @@ void InlinedFunction::printElementLine(raw_ostream &OS,
OS << CalleeName << " inlined into " << CallerName << "\n";
}
-bool LiveVariable::liveAtAddress(object::SectionedAddress Addr) {
+bool LiveVariable::liveAtAddress(object::SectionedAddress Addr) const {
if (LocExpr.Range == std::nullopt)
return false;
return LocExpr.Range->SectionIndex == Addr.SectionIndex &&
@@ -116,8 +116,8 @@ void LiveVariable::dump(raw_ostream &OS) const {
OS << Name << " @ " << LocExpr.Range << ": ";
}
-void LiveVariablePrinter::addInlinedFunction(DWARFDie FuncDie,
- DWARFDie InlinedFuncDie) {
+void LiveElementPrinter::addInlinedFunction(DWARFDie FuncDie,
+ DWARFDie InlinedFuncDie) {
uint64_t FuncLowPC, FuncHighPC, SectionIndex;
if (!InlinedFuncDie.getLowAndHighPC(FuncLowPC, FuncHighPC, SectionIndex))
return;
@@ -129,7 +129,7 @@ void LiveVariablePrinter::addInlinedFunction(DWARFDie FuncDie,
InlinedFuncName, U, FuncDie, InlinedFuncDie, Range));
}
-void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
+void LiveElementPrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
uint64_t FuncLowPC, FuncHighPC, SectionIndex;
FuncDie.getLowAndHighPC(FuncLowPC, FuncHighPC, SectionIndex);
const char *VarName = VarDie.getName(DINameKind::ShortName);
@@ -162,14 +162,14 @@ void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
}
}
-void LiveVariablePrinter::addFunction(DWARFDie D) {
+void LiveElementPrinter::addFunction(DWARFDie D) {
for (const DWARFDie &Child : D.children()) {
- if (DbgVariables != DVDisabled &&
+ if (DbgVariables != DFDisabled &&
(Child.getTag() == dwarf::DW_TAG_variable ||
- Child.getTag() == dwarf::DW_TAG_formal_parameter))
+ Child.getTag() == dwarf::DW_TAG_formal_parameter)) {
addVariable(D, Child);
- else if (DbgInlinedFunctions != DVDisabled &&
- Child.getTag() == dwarf::DW_TAG_inlined_subroutine) {
+ } else if (DbgInlinedFunctions != DFDisabled &&
+ Child.getTag() == dwarf::DW_TAG_inlined_subroutine) {
addInlinedFunction(D, Child);
addFunction(Child);
} else
@@ -179,7 +179,7 @@ void LiveVariablePrinter::addFunction(DWARFDie D) {
// Get the column number (in characters) at which the first live element
// line should be printed.
-unsigned LiveVariablePrinter::getIndentLevel() const {
+unsigned LiveElementPrinter::getIndentLevel() const {
return DbgIndent + getInstStartColumn(STI);
}
@@ -188,7 +188,7 @@ unsigned LiveVariablePrinter::getIndentLevel() const {
// TODO: formatted_raw_ostream uses "column" to mean a number of characters
// since the last \n, and we use it to mean the number of slots in which we
// put live element lines. Pick a less overloaded word.
-unsigned LiveVariablePrinter::moveToFirstVarColumn(formatted_raw_ostream &OS) {
+unsigned LiveElementPrinter::moveToFirstVarColumn(formatted_raw_ostream &OS) {
// Logical column number: column zero is the first column we print in, each
// logical column is 2 physical columns wide.
unsigned FirstUnprintedLogicalColumn =
@@ -204,7 +204,7 @@ unsigned LiveVariablePrinter::moveToFirstVarColumn(formatted_raw_ostream &OS) {
return FirstUnprintedLogicalColumn;
}
-unsigned LiveVariablePrinter::findFreeColumn() {
+unsigned LiveElementPrinter::findFreeColumn() {
for (unsigned ColIdx = 0; ColIdx < ActiveCols.size(); ++ColIdx)
if (!ActiveCols[ColIdx].isActive())
return ColIdx;
@@ -214,7 +214,7 @@ unsigned LiveVariablePrinter::findFreeColumn() {
return OldSize;
}
-void LiveVariablePrinter::dump() const {
+void LiveElementPrinter::dump() const {
for (const std::unique_ptr<LiveElement> &LE : LiveElements) {
LE->dump(dbgs());
LE->print(dbgs(), MRI);
@@ -222,7 +222,7 @@ void LiveVariablePrinter::dump() const {
}
}
-void LiveVariablePrinter::addCompileUnit(DWARFDie D) {
+void LiveElementPrinter::addCompileUnit(DWARFDie D) {
if (D.getTag() == dwarf::DW_TAG_subprogram)
addFunction(D);
else
@@ -235,12 +235,12 @@ void LiveVariablePrinter::addCompileUnit(DWARFDie D) {
/// live-in to the instruction, and any live range active at NextAddr is
/// live-out of the instruction. If IncludeDefinedVars is false, then live
/// ranges starting at NextAddr will be ignored.
-void LiveVariablePrinter::update(object::SectionedAddress ThisAddr,
- object::SectionedAddress NextAddr,
- bool IncludeDefinedVars) {
+void LiveElementPrinter::update(object::SectionedAddress ThisAddr,
+ object::SectionedAddress NextAddr,
+ bool IncludeDefinedVars) {
// Do not create live ranges when debug-inlined-funcs option is provided with
// line format option.
- if (DbgInlinedFunctions == DVLine)
+ if (DbgInlinedFunctions == DFLine)
return;
// First, check variables which have already been assigned a column, so
@@ -302,8 +302,8 @@ enum class LineChar {
LabelCornerActive,
LabelHoriz,
};
-const char *LiveVariablePrinter::getLineChar(LineChar C) const {
- bool IsASCII = DbgVariables == DVASCII || DbgInlinedFunctions == DVASCII;
+const char *LiveElementPrinter::getLineChar(LineChar C) const {
+ bool IsASCII = DbgVariables == DFASCII || DbgInlinedFunctions == DFASCII;
switch (C) {
case LineChar::RangeStart:
return IsASCII ? "^" : (const char *)u8"\u2548";
@@ -328,8 +328,8 @@ const char *LiveVariablePrinter::getLineChar(LineChar C) const {
/// we only need to print active ranges or empty columns. If AfterInst is
/// true, this is being printed after the last instruction fed to update(),
/// otherwise this is being printed before it.
-void LiveVariablePrinter::printAfterOtherLine(formatted_raw_ostream &OS,
- bool AfterInst) {
+void LiveElementPrinter::printAfterOtherLine(formatted_raw_ostream &OS,
+ bool AfterInst) {
if (ActiveCols.size()) {
unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS);
for (size_t ColIdx = FirstUnprintedColumn, End = ActiveCols.size();
@@ -356,8 +356,8 @@ void LiveVariablePrinter::printAfterOtherLine(formatted_raw_ostream &OS,
/// true, we have to print at least one line (with the continuation of any
/// already-active live ranges) because something has already been printed
/// earlier on this line.
-void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream &OS,
- bool MustPrint) {
+void LiveElementPrinter::printBetweenInsts(formatted_raw_ostream &OS,
+ bool MustPrint) {
bool PrintedSomething = false;
for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) {
if (ActiveCols[ColIdx].isActive() && ActiveCols[ColIdx].MustDrawLabel) {
@@ -418,7 +418,7 @@ void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream &OS,
}
/// Print the live element ranges to the right of a disassembled instruction.
-void LiveVariablePrinter::printAfterInst(formatted_raw_ostream &OS) {
+void LiveElementPrinter::printAfterInst(formatted_raw_ostream &OS) {
if (!ActiveCols.size())
return;
unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS);
@@ -437,20 +437,20 @@ void LiveVariablePrinter::printAfterInst(formatted_raw_ostream &OS) {
}
}
-void LiveVariablePrinter::printStartLine(formatted_raw_ostream &OS,
- object::SectionedAddress Addr) {
+void LiveElementPrinter::printStartLine(formatted_raw_ostream &OS,
+ object::SectionedAddress Addr) {
// Print a line to idenfity the start of an inlined function if line format
// is specified.
- if (DbgInlinedFunctions == DVLine)
+ if (DbgInlinedFunctions == DFLine)
for (const std::unique_ptr<LiveElement> &LE : LiveElements)
LE->printElementLine(OS, Addr, false);
}
-void LiveVariablePrinter::printEndLine(formatted_raw_ostream &OS,
- object::SectionedAddress Addr) {
+void LiveElementPrinter::printEndLine(formatted_raw_ostream &OS,
+ object::SectionedAddress Addr) {
// Print a line to idenfity the end of an inlined function if line format is
// specified.
- if (DbgInlinedFunctions == DVLine)
+ if (DbgInlinedFunctions == DFLine)
for (const std::unique_ptr<LiveElement> &LE : LiveElements)
LE->printElementLine(OS, Addr, true);
}
@@ -489,7 +489,7 @@ bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) {
void SourcePrinter::printSourceLine(formatted_raw_ostream &OS,
object::SectionedAddress Address,
StringRef ObjectFilename,
- LiveVariablePrinter &LVP,
+ LiveElementPrinter &LEP,
StringRef Delimiter) {
if (!Symbolizer)
return;
@@ -537,16 +537,16 @@ void SourcePrinter::printSourceLine(formatted_raw_ostream &OS,
}
if (PrintLines)
- printLines(OS, Address, LineInfo, Delimiter, LVP);
+ printLines(OS, Address, LineInfo, Delimiter, LEP);
if (PrintSource)
- printSources(OS, LineInfo, ObjectFilename, Delimiter, LVP);
+ printSources(OS, LineInfo, ObjectFilename, Delimiter, LEP);
OldLineInfo = LineInfo;
}
void SourcePrinter::printLines(formatted_raw_ostream &OS,
object::SectionedAddress Address,
const DILineInfo &LineInfo, StringRef Delimiter,
- LiveVariablePrinter &LVP) {
+ LiveElementPrinter &LEP) {
bool PrintFunctionName = LineInfo.FunctionName != DILineInfo::BadString &&
LineInfo.FunctionName != OldLineInfo.FunctionName;
if (PrintFunctionName) {
@@ -561,7 +561,7 @@ void SourcePrinter::printLines(formatted_raw_ostream &OS,
(OldLineInfo.Line != LineInfo.Line ||
OldLineInfo.FileName != LineInfo.FileName || PrintFunctionName)) {
OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line;
- LVP.printBetweenInsts(OS, true);
+ LEP.printBetweenInsts(OS, true);
}
}
@@ -596,7 +596,7 @@ StringRef SourcePrinter::getLine(const DILineInfo &LineInfo,
void SourcePrinter::printSources(formatted_raw_ostream &OS,
const DILineInfo &LineInfo,
StringRef ObjectFilename, StringRef Delimiter,
- LiveVariablePrinter &LVP) {
+ LiveElementPrinter &LEP) {
if (LineInfo.FileName == DILineInfo::BadString || LineInfo.Line == 0 ||
(OldLineInfo.Line == LineInfo.Line &&
OldLineInfo.FileName == LineInfo.FileName))
@@ -605,7 +605,7 @@ void SourcePrinter::printSources(formatted_raw_ostream &OS,
StringRef Line = getLine(LineInfo, ObjectFilename);
if (!Line.empty()) {
OS << Delimiter << Line;
- LVP.printBetweenInsts(OS, true);
+ LEP.printBetweenInsts(OS, true);
}
}
diff --git a/llvm/tools/llvm-objdump/SourcePrinter.h b/llvm/tools/llvm-objdump/SourcePrinter.h
index 167fd544c419f..98906293b89fb 100644
--- a/llvm/tools/llvm-objdump/SourcePrinter.h
+++ b/llvm/tools/llvm-objdump/SourcePrinter.h
@@ -36,10 +36,8 @@ class LiveElement {
virtual ~LiveElement() {};
const char *getName() const { return Name; }
- DWARFUnit *getDwarfUnit() const { return Unit; }
- const DWARFDie getFuncDie() const { return FuncDie; }
- virtual bool liveAtAddress(object::SectionedAddress Addr) = 0;
+ virtual bool liveAtAddress(object::SectionedAddress Addr) const = 0;
virtual void print(raw_ostream &OS, const MCRegisterInfo &MRI) const = 0;
virtual void dump(raw_ostream &OS) const = 0;
virtual void printElementLine(raw_ostream &OS,
@@ -48,6 +46,7 @@ class LiveElement {
};
class InlinedFunction : public LiveElement {
+private:
DWARFDie InlinedFuncDie;
DWARFAddressRange Range;
@@ -58,7 +57,7 @@ class InlinedFunction : public LiveElement {
: LiveElement(FunctionName, Unit, FuncDie),
InlinedFuncDie(InlinedFuncDie), Range(Range) {}
- bool liveAtAddress(object::SectionedAddress Addr) override;
+ bool liveAtAddress(object::SectionedAddress Addr) const override;
void print(raw_ostream &OS, const MCRegisterInfo &MRI) const override;
void dump(raw_ostream &OS) const override;
void printElementLine(raw_ostream &OS, object::SectionedAddress Address,
@@ -68,6 +67,7 @@ class InlinedFunction : public LiveElement {
/// Stores a single expression representing the location of a source-level
/// variable, along with the PC range for which that expression is valid.
class LiveVariable : public LiveElement {
+private:
DWARFLocationExpression LocExpr;
public:
@@ -75,15 +75,14 @@ class LiveVariable : public LiveElement {
DWARFUnit *Unit, const DWARFDie FuncDie)
: LiveElement(VarName, Unit, FuncDie), LocExpr(LocExpr) {}
- DWARFLocationExpression getLocationExpression() const { return LocExpr; };
- bool liveAtAddress(object::SectionedAddress Addr) override;
+ bool liveAtAddress(object::SectionedAddress Addr) const override;
void print(raw_ostream &OS, const MCRegisterInfo &MRI) const override;
void dump(raw_ostream &OS) const override;
};
-/// Helper class for printing source locations for variables and inlines
+/// Helper class for printing source locations for variables and inline
/// subroutines alongside disassembly.
-class LiveVariablePrinter {
+class LiveElementPrinter {
// Information we want to track about one column in which we are printing an
// element live range.
struct Column {
@@ -126,7 +125,7 @@ class LiveVariablePrinter {
unsigned findFreeColumn();
public:
- LiveVariablePrinter(const MCRegisterInfo &MRI, const MCSubtargetInfo &STI)
+ LiveElementPrinter(const MCRegisterInfo &MRI, const MCSubtargetInfo &STI)
: ActiveCols(Column()), MRI(MRI), STI(STI) {}
void dump() const;
@@ -196,11 +195,11 @@ class SourcePrinter {
void printLines(formatted_raw_ostream &OS, object::SectionedAddress Address,
const DILineInfo &LineInfo, StringRef Delimiter,
- LiveVariablePrinter &LVP);
+ LiveElementPrinter &LEP);
void printSources(formatted_raw_ostream &OS, const DILineInfo &LineInfo,
StringRef ObjectFilename, StringRef Delimiter,
- LiveVariablePrinter &LVP);
+ LiveElementPrinter &LEP);
// Returns line source code corresponding to `LineInfo`.
// Returns empty string if source code cannot be found.
@@ -213,7 +212,7 @@ class SourcePrinter {
virtual void printSourceLine(formatted_raw_ostream &OS,
object::SectionedAddress Address,
StringRef ObjectFilename,
- LiveVariablePrinter &LVP,
+ LiveElementPrinter &LEP,
StringRef Delimiter = "; ");
};
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 0767e73082cd1..1a59f39945624 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -348,8 +348,8 @@ static bool Wide;
std::string objdump::Prefix;
uint32_t objdump::PrefixStrip;
-DebugFormat objdump::DbgVariables = DVDisabled;
-DebugFormat objdump::DbgInlinedFunctions = DVDisabled;
+DebugFormat objdump::DbgVariables = DFDisabled;
+DebugFormat objdump::DbgInlinedFunctions = DFDisabled;
int objdump::DbgIndent = 52;
@@ -524,8 +524,8 @@ static const Target *getTarget(const ObjectFile *Obj) {
// Get the target specific parser.
std::string Error;
- const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple,
- Error);
+ const Target *TheTarget =
+ TargetRegistry::lookupTarget(ArchName, TheTriple, Error);
if (!TheTarget)
reportError(Obj->getFileName(), "can't find target: " + Error);
@@ -634,7 +634,7 @@ static bool isCSKYElf(const ObjectFile &Obj) {
}
static bool hasMappingSymbols(const ObjectFile &Obj) {
- return isArmElf(Obj) || isAArch64Elf(Obj) || isCSKYElf(Obj) ;
+ return isArmElf(Obj) || isAArch64Elf(Obj) || isCSKYElf(Obj);
}
static void printRelocation(formatted_raw_ostream &OS, StringRef FileName,
@@ -654,7 +654,7 @@ static void printRelocation(formatted_raw_ostream &OS, StringRef FileName,
static void printBTFRelocation(formatted_raw_ostream &FOS, llvm::BTFParser &BTF,
object::SectionedAddress Address,
- LiveVariablePrinter &LVP) {
+ LiveElementPrinter &LEP) {
const llvm::BTF::BPFFieldReloc *Reloc = BTF.findFieldReloc(Address);
if (!Reloc)
return;
@@ -665,7 +665,7 @@ static void printBTFRelocation(formatted_raw_ostream &FOS, llvm::BTFParser &BTF,
if (LeadingAddr)
FOS << format("%016" PRIx64 ": ", Address.Address + AdjustVMA);
FOS << "CO-RE " << Val;
- LVP.printAfterOtherLine(FOS, true);
+ LEP.printAfterOtherLine(FOS, true);
}
class PrettyPrinter {
@@ -676,11 +676,11 @@ class PrettyPrinter {
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) {
+ LiveElementPrinter &LEP) {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP);
- LVP.printStartLine(OS, Address);
- LVP.printBetweenInsts(OS, false);
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP);
+ LEP.printStartLine(OS, Address);
+ LEP.printBetweenInsts(OS, false);
printRawData(Bytes, Address.Address, OS, STI);
@@ -720,9 +720,9 @@ class HexagonPrettyPrinter : public PrettyPrinter {
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) override {
+ LiveElementPrinter &LEP) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP, "");
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP, "");
if (!MI) {
printLead(Bytes, Address.Address, OS);
OS << " <unknown>";
@@ -759,7 +759,7 @@ class HexagonPrettyPrinter : public PrettyPrinter {
OS << Separator;
Separator = "\n";
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP, "");
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP, "");
printLead(Bytes, Address.Address, OS);
OS << Preamble;
Preamble = " ";
@@ -769,8 +769,7 @@ class HexagonPrettyPrinter : public PrettyPrinter {
OS << Duplex.first;
OS << "; ";
Inst = Duplex.second;
- }
- else
+ } else
Inst = HeadTail.first;
OS << Inst;
HeadTail = HeadTail.second.split('\n');
@@ -790,9 +789,9 @@ class AMDGCNPrettyPrinter : public PrettyPrinter {
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) override {
+ LiveElementPrinter &LEP) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP);
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP);
if (MI) {
SmallString<40> InstStr;
@@ -811,10 +810,10 @@ class AMDGCNPrettyPrinter : public PrettyPrinter {
support::endian::read32<llvm::endianness::little>(Bytes.data()));
OS.indent(42);
} else {
- OS << format("\t.byte 0x%02" PRIx8, Bytes[0]);
- for (unsigned int i = 1; i < Bytes.size(); i++)
- OS << format(", 0x%02" PRIx8, Bytes[i]);
- OS.indent(55 - (6 * Bytes.size()));
+ OS << format("\t.byte 0x%02" PRIx8, Bytes[0]);
+ for (unsigned int i = 1; i < Bytes.size(); i++)
+ OS << format(", 0x%02" PRIx8, Bytes[i]);
+ OS.indent(55 - (6 * Bytes.size()));
}
}
@@ -825,7 +824,7 @@ class AMDGCNPrettyPrinter : public PrettyPrinter {
for (uint32_t D :
ArrayRef(reinterpret_cast<const support::little32_t *>(Bytes.data()),
Bytes.size() / 4))
- OS << format(" %08" PRIX32, D);
+ OS << format(" %08" PRIX32, D);
} else {
for (unsigned char B : Bytes)
OS << format(" %02" PRIX8, B);
@@ -843,9 +842,9 @@ class BPFPrettyPrinter : public PrettyPrinter {
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) override {
+ LiveElementPrinter &LEP) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP);
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP);
if (LeadingAddr)
OS << format("%8" PRId64 ":", Address.Address / 8);
if (ShowRawInsn) {
@@ -866,11 +865,11 @@ class ARMPrettyPrinter : public PrettyPrinter {
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) override {
+ LiveElementPrinter &LEP) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP);
- LVP.printStartLine(OS, Address);
- LVP.printBetweenInsts(OS, false);
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP);
+ LEP.printStartLine(OS, Address);
+ LEP.printBetweenInsts(OS, false);
size_t Start = OS.tell();
if (LeadingAddr)
@@ -921,11 +920,11 @@ class AArch64PrettyPrinter : public PrettyPrinter {
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) override {
+ LiveElementPrinter &LEP) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP);
- LVP.printStartLine(OS, Address);
- LVP.printBetweenInsts(OS, false);
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP);
+ LEP.printStartLine(OS, Address);
+ LEP.printBetweenInsts(OS, false);
size_t Start = OS.tell();
if (LeadingAddr)
@@ -960,11 +959,11 @@ class RISCVPrettyPrinter : public PrettyPrinter {
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) override {
+ LiveElementPrinter &LEP) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP);
- LVP.printStartLine(OS, Address);
- LVP.printBetweenInsts(OS, false);
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP);
+ LEP.printStartLine(OS, Address);
+ LEP.printBetweenInsts(OS, false);
size_t Start = OS.tell();
if (LeadingAddr)
@@ -1005,7 +1004,7 @@ class RISCVPrettyPrinter : public PrettyPrinter {
RISCVPrettyPrinter RISCVPrettyPrinterInst;
PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
- switch(Triple.getArch()) {
+ switch (Triple.getArch()) {
default:
return PrettyPrinterInst;
case Triple::hexagon:
@@ -1056,8 +1055,7 @@ class DisassemblerTarget {
DisassemblerTarget::DisassemblerTarget(const Target *TheTarget, ObjectFile &Obj,
StringRef TripleName, StringRef MCPU,
SubtargetFeatures &Features)
- : TheTarget(TheTarget),
- Printer(&selectPrettyPrinter(Triple(TripleName))),
+ : TheTarget(TheTarget), Printer(&selectPrettyPrinter(Triple(TripleName))),
RegisterInfo(TheTarget->createMCRegInfo(TripleName)) {
if (!RegisterInfo)
reportError(Obj.getFileName(), "no register info for target " + TripleName);
@@ -1336,7 +1334,6 @@ static bool shouldAdjustVA(const SectionRef &Section) {
return false;
}
-
typedef std::pair<uint64_t, char> MappingSymbolPair;
static char getMappingSymbolKind(ArrayRef<MappingSymbolPair> MappingSymbols,
uint64_t Address) {
@@ -1364,8 +1361,7 @@ static uint64_t dumpARMELFData(uint64_t SectionAddr, uint64_t Index,
dumpBytes(Bytes.slice(Index, 4), OS);
AlignToInstStartColumn(Start, STI, OS);
OS << "\t.word\t"
- << format_hex(support::endian::read32(Bytes.data() + Index, Endian),
- 10);
+ << format_hex(support::endian::read32(Bytes.data() + Index, Endian), 10);
return 4;
}
if (Index + 2 <= End) {
@@ -1618,7 +1614,7 @@ static void emitPostInstructionInfo(formatted_raw_ostream &FOS,
const MCAsmInfo &MAI,
const MCSubtargetInfo &STI,
StringRef Comments,
- LiveVariablePrinter &LVP) {
+ LiveElementPrinter &LEP) {
do {
if (!Comments.empty()) {
// Emit a line of comments.
@@ -1631,7 +1627,6 @@ static void emitPostInstructionInfo(formatted_raw_ostream &FOS,
FOS.PadToColumn(CommentColumn);
FOS << MAI.getCommentString() << ' ' << Comment;
}
- LVP.printAfterInst(FOS);
FOS << '\n';
} while (!Comments.empty());
FOS.flush();
@@ -1761,9 +1756,9 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
// STAB symbol's section field refers to a valid section index. Otherwise
// the symbol may error trying to load a section that does not exist.
DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
- uint8_t NType = (MachO->is64Bit() ?
- MachO->getSymbol64TableEntry(SymDRI).n_type:
- MachO->getSymbolTableEntry(SymDRI).n_type);
+ uint8_t NType =
+ (MachO->is64Bit() ? MachO->getSymbol64TableEntry(SymDRI).n_type
+ : MachO->getSymbolTableEntry(SymDRI).n_type);
if (NType & MachO::N_STAB)
continue;
}
@@ -1862,15 +1857,15 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
llvm::stable_sort(AbsoluteSymbols);
std::unique_ptr<DWARFContext> DICtx;
- LiveVariablePrinter LVP(*DT->Context->getRegisterInfo(), *DT->SubtargetInfo);
+ LiveElementPrinter LEP(*DT->Context->getRegisterInfo(), *DT->SubtargetInfo);
- if (DbgVariables != DVDisabled || DbgInlinedFunctions != DVDisabled) {
+ if (DbgVariables != DFDisabled || DbgInlinedFunctions != DFDisabled) {
DICtx = DWARFContext::create(DbgObj);
for (const std::unique_ptr<DWARFUnit> &CU : DICtx->compile_units())
- LVP.addCompileUnit(CU->getUnitDIE(false));
+ LEP.addCompileUnit(CU->getUnitDIE(false));
}
- LLVM_DEBUG(LVP.dump());
+ LLVM_DEBUG(LEP.dump());
BBAddrMapInfo FullAddrMap;
auto ReadBBAddrMap = [&](std::optional<unsigned> SectionIndex =
@@ -2338,7 +2333,7 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
ThisBytes.size(),
DT->DisAsm->suggestBytesToSkip(ThisBytes, ThisAddr));
- LVP.update({ThisAddr, Section.getIndex()},
+ LEP.update({ThisAddr, Section.getIndex()},
{ThisAddr + Size, Section.getIndex()},
Index + Size != End);
@@ -2348,7 +2343,7 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
*DT->InstPrinter, Disassembled ? &Inst : nullptr,
Bytes.slice(Index, Size),
{SectionAddr + Index + VMAAdjustment, Section.getIndex()}, FOS,
- "", *DT->SubtargetInfo, &SP, Obj.getFileName(), &Rels, LVP);
+ "", *DT->SubtargetInfo, &SP, Obj.getFileName(), &Rels, LEP);
DT->InstPrinter->setCommentStream(llvm::nulls());
@@ -2532,11 +2527,11 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
assert(DT->Context->getAsmInfo());
emitPostInstructionInfo(FOS, *DT->Context->getAsmInfo(),
- *DT->SubtargetInfo, CommentStream.str(), LVP);
+ *DT->SubtargetInfo, CommentStream.str(), LEP);
Comments.clear();
if (BTF)
- printBTFRelocation(FOS, *BTF, {Index, Section.getIndex()}, LVP);
+ printBTFRelocation(FOS, *BTF, {Index, Section.getIndex()}, LEP);
// Hexagon handles relocs in pretty printer
if (InlineRelocs && Obj.getArch() != Triple::hexagon) {
@@ -2544,14 +2539,14 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
// When --adjust-vma is used, update the address printed.
printRelocation(FOS, Obj.getFileName(), *RelCur,
SectionAddr + RelOffset + VMAAdjustment, Is64Bits);
- LVP.printAfterOtherLine(FOS, true);
+ LEP.printAfterOtherLine(FOS, true);
++RelCur;
}
}
object::SectionedAddress NextAddr = {
SectionAddr + Index + VMAAdjustment + Size, Section.getIndex()};
- LVP.printEndLine(FOS, NextAddr);
+ LEP.printEndLine(FOS, NextAddr);
Index += Size;
}
@@ -2844,7 +2839,8 @@ void objdump::printSectionContents(const ObjectFile *Obj) {
continue;
}
- StringRef Contents = unwrapOrError(Section.getContents(), Obj->getFileName());
+ StringRef Contents =
+ unwrapOrError(Section.getContents(), Obj->getFileName());
// Dump out the content as hex and printable ascii characters.
for (std::size_t Addr = 0, End = Contents.size(); Addr < End; Addr += 16) {
@@ -3268,8 +3264,8 @@ static bool shouldWarnForInvalidStartStopAddress(ObjectFile *Obj) {
return false;
}
-static void checkForInvalidStartStopAddress(ObjectFile *Obj,
- uint64_t Start, uint64_t Stop) {
+static void checkForInvalidStartStopAddress(ObjectFile *Obj, uint64_t Start,
+ uint64_t Stop) {
if (!shouldWarnForInvalidStartStopAddress(Obj))
return;
@@ -3593,21 +3589,21 @@ static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
parseIntArg(InputArgs, OBJDUMP_prefix_strip, PrefixStrip);
if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_debug_vars_EQ)) {
DbgVariables = StringSwitch<DebugFormat>(A->getValue())
- .Case("ascii", DVASCII)
- .Case("unicode", DVUnicode)
- .Default(DVInvalid);
- if (DbgVariables == DVInvalid)
+ .Case("ascii", DFASCII)
+ .Case("unicode", DFUnicode)
+ .Default(DFInvalid);
+ if (DbgVariables == DFInvalid)
invalidArgValue(A);
}
if (const opt::Arg *A =
InputArgs.getLastArg(OBJDUMP_debug_inlined_funcs_EQ)) {
DbgInlinedFunctions = StringSwitch<DebugFormat>(A->getValue())
- .Case("ascii", DVASCII)
- .Case("unicode", DVUnicode)
- .Case("line", DVLine)
- .Default(DVInvalid);
- if (DbgInlinedFunctions == DVInvalid)
+ .Case("ascii", DFASCII)
+ .Case("unicode", DFUnicode)
+ .Case("line", DFLine)
+ .Default(DFInvalid);
+ if (DbgInlinedFunctions == DFInvalid)
invalidArgValue(A);
}
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h
index 70a4d3975c24d..866e8300e6a2a 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -40,7 +40,7 @@ class XCOFFObjectFile;
namespace objdump {
-enum DebugFormat { DVDisabled, DVUnicode, DVASCII, DVLine, DVInvalid };
+enum DebugFormat { DFDisabled, DFUnicode, DFASCII, DFLine, DFInvalid };
extern bool ArchiveHeaders;
extern int DbgIndent;
@@ -127,7 +127,7 @@ void printSectionContents(const object::ObjectFile *O);
void reportWarning(const Twine &Message, StringRef File);
template <typename T, typename... Ts>
-T unwrapOrError(Expected<T> EO, Ts &&... Args) {
+T unwrapOrError(Expected<T> EO, Ts &&...Args) {
if (EO)
return std::move(*EO);
reportError(EO.takeError(), std::forward<Ts>(Args)...);
More information about the llvm-commits
mailing list