Skip to content

Commit c649f29

Browse files
committed
[llvm-nm] Add --line-numbers flag
This parallels the binutils/BSD flag of the same name. Debugging information is loaded to print line number information for symbols. Defined symbols are symbolized by their section addresses, and undefined symbols by their first text reloc with line info. Differential Revision: https://reviews.llvm.org/D150987
1 parent 86b32c4 commit c649f29

File tree

6 files changed

+339
-5
lines changed

6 files changed

+339
-5
lines changed

llvm/docs/CommandGuide/llvm-nm.rst

+6
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,12 @@ OPTIONS
190190

191191
Print just the symbol names. Alias for `--format=just-symbols``.
192192

193+
.. option:: --line-numbers, -l
194+
195+
Use debugging information to print the filenames and line numbers where
196+
symbols are defined. Undefined symbols have the location of their first
197+
relocation printed instead.
198+
193199
.. option:: -m
194200

195201
Use Darwin format. Alias for ``--format=darwin``.

llvm/docs/ReleaseNotes.rst

+3
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ Changes to the LLVM tools
177177
* llvm-readelf now supports ``--extra-sym-info`` (``-X``) to display extra
178178
information (section name) when showing symbols.
179179

180+
* ``llvm-nm`` now supports the ``--line-numbers`` (``-l``) option to use
181+
debugging information to print symbols' filenames and line numbers.
182+
180183
Changes to LLDB
181184
---------------------------------
182185

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
## Check that printing line numbers isn't attempted for files like bitcode,
2+
## which have symbols but limited/no section or debug info.
3+
# RUN: llvm-nm --line-numbers %p/Inputs/test.IRobj-x86_64 | FileCheck %s --check-prefix=BITCODE --match-full-lines --implicit-check-not={{.}}
4+
# BITCODE: ---------------- S _global_const
5+
# BITCODE-NEXT: ---------------- D _global_data
6+
# BITCODE-NEXT: ---------------- T _global_func
7+
# BITCODE-NEXT: ---------------- S _hidden_const
8+
# BITCODE-NEXT: ---------------- D _hidden_data
9+
# BITCODE-NEXT: ---------------- T _hidden_func
10+
# BITCODE-NEXT: ---------------- s _static_const
11+
# BITCODE-NEXT: ---------------- d _static_data
12+
# BITCODE-NEXT: ---------------- t _static_func
13+
14+
## Check that various symbol types can use debug information if available to
15+
## print line numbers, and if unavailable, don't print anything erroneous. The
16+
## specific cases checked are given by the symbol names below. Other test cases
17+
## place requirements on the contents of the whole file, so they are kept out
18+
## of main.o.
19+
# RUN: rm -rf %t
20+
# RUN: split-file %s %t
21+
# RUN: llvm-mc -g --filetype=obj %t/main.s -o %t/main.o
22+
# RUN: llvm-nm -l %t/main.o | FileCheck %s --match-full-lines --implicit-check-not={{.}}
23+
# RUN: llvm-nm --line-numbers %t/main.o | FileCheck %s --match-full-lines --implicit-check-not={{.}}
24+
25+
# CHECK: 0000000000001234 a absolute_symbol
26+
# CHECK-NEXT: 0000000000000000 d data_no_dwarf
27+
# CHECK-NEXT: 0000000000000000 T defined_global_function [[FILENAME:.*main.s]]:4
28+
# CHECK-NEXT: 0000000000000001 t defined_local_function [[FILENAME]]:7
29+
# CHECK-NEXT: 0000000000000000 t function_no_dwarf
30+
# CHECK-NEXT: U undef1 [[FILENAME]]:12
31+
# CHECK-NEXT: U undef2 [[FILENAME]]:14
32+
# CHECK-NEXT: U undef_no_reloc
33+
# CHECK-NEXT: 0000000000000002 t undefined_references [[FILENAME]]:12
34+
35+
## Check that in the absence of DWARF in the whole object, no line number
36+
## information is printed.
37+
# RUN: llvm-mc --filetype=obj %t/main.s -o %t/no-dwarf.o
38+
# RUN: llvm-nm -l %t/no-dwarf.o | FileCheck %s --check-prefix=NO-DWARF --match-full-lines --implicit-check-not={{.}}
39+
40+
# NO-DWARF: 0000000000001234 a absolute_symbol
41+
# NO-DWARF-NEXT: 0000000000000000 d data_no_dwarf
42+
# NO-DWARF-NEXT: 0000000000000000 T defined_global_function
43+
# NO-DWARF-NEXT: 0000000000000001 t defined_local_function
44+
# NO-DWARF-NEXT: 0000000000000000 t function_no_dwarf
45+
# NO-DWARF-NEXT: U undef1
46+
# NO-DWARF-NEXT: U undef2
47+
# NO-DWARF-NEXT: U undef_no_reloc
48+
# NO-DWARF-NEXT: 0000000000000002 t undefined_references
49+
50+
## Check that printing line numbers for undefined values is not attempted in
51+
## the absence of any relocation section.
52+
# RUN: llvm-mc --filetype=obj %t/undef-no-reloc-sections.s -o %t/undef-no-reloc-sections.o
53+
# RUN: llvm-nm --line-numbers %t/undef-no-reloc-sections.o | FileCheck %s --check-prefix=UNDEF-NO-RELOC-SECTIONS --match-full-lines --implicit-check-not={{.}}
54+
55+
# UNDEF-NO-RELOC-SECTIONS: U undef
56+
57+
## Check that printing line numbers for undefined values does not include
58+
## relocations for non-text sections. This is broken out of main.s to ensure
59+
## that the data relocation for undef comes first.
60+
# RUN: llvm-mc -g --filetype=obj %t/undef-data-reloc.s -o %t/undef-data-reloc.o
61+
# RUN: llvm-nm --line-numbers %t/undef-data-reloc.o | FileCheck %s --check-prefix=UNDEF-DATA-RELOC --match-full-lines --implicit-check-not={{.}}
62+
63+
# UNDEF-DATA-RELOC: 0000000000000000 r data_reloc
64+
# UNDEF-DATA-RELOC-NEXT: U undef
65+
66+
## Check that line numbers can be printed for data definitions. These are broken
67+
## out of main.s since their DWARF cannot be generated with llvm-mc -g.
68+
# RUN: llvm-mc -g --filetype=obj %t/data-dwarf.s -o %t/data-dwarf.o
69+
# RUN: llvm-nm --line-numbers %t/data-dwarf.o | FileCheck %s --check-prefix=DATA-DWARF --match-full-lines --implicit-check-not={{.}}
70+
71+
# DATA-DWARF: 0000000000000000 D defined_data /tmp/tmp.c:1
72+
73+
#--- main.s
74+
.text
75+
.globl defined_global_function
76+
defined_global_function:
77+
ret
78+
79+
defined_local_function:
80+
ret
81+
82+
absolute_symbol = 0x1234
83+
84+
undefined_references:
85+
nop
86+
.long undef1
87+
nop
88+
.long undef2
89+
ret
90+
91+
# Note: llvm-mc -g produces no DWARF for data.
92+
.data
93+
data_no_dwarf:
94+
.byte 0
95+
96+
.globl undef_no_reloc
97+
98+
# Note: llvm-mc -g does not produce DWARF for non-SHF_ALLOC sections.
99+
.section no_alloc_text,"x",@progbits
100+
function_no_dwarf:
101+
ret
102+
103+
#--- undef-no-reloc-sections.s
104+
.globl undef
105+
106+
#--- undef-data-reloc.s
107+
.globl undef
108+
.rodata
109+
data_reloc:
110+
.long undef
111+
112+
#--- data-dwarf.s
113+
# char defined_data = 42
114+
.text
115+
.file "tmp.c"
116+
.file 0 "/tmp" "/tmp/tmp.c" md5 0x39602a53b15a32d6a622ca86936e88d7
117+
.file 1 "tmp.c" md5 0x39602a53b15a32d6a622ca86936e88d7
118+
.type defined_data,@object # @defined_data
119+
.data
120+
.globl defined_data
121+
defined_data:
122+
.byte 42 # 0x2a
123+
.size defined_data, 1
124+
125+
.section .debug_abbrev,"",@progbits
126+
.byte 1 # Abbreviation Code
127+
.byte 17 # DW_TAG_compile_unit
128+
.byte 1 # DW_CHILDREN_yes
129+
.byte 37 # DW_AT_producer
130+
.byte 37 # DW_FORM_strx1
131+
.byte 19 # DW_AT_language
132+
.byte 5 # DW_FORM_data2
133+
.byte 3 # DW_AT_name
134+
.byte 37 # DW_FORM_strx1
135+
.byte 114 # DW_AT_str_offsets_base
136+
.byte 23 # DW_FORM_sec_offset
137+
.byte 16 # DW_AT_stmt_list
138+
.byte 23 # DW_FORM_sec_offset
139+
.byte 27 # DW_AT_comp_dir
140+
.byte 37 # DW_FORM_strx1
141+
.byte 115 # DW_AT_addr_base
142+
.byte 23 # DW_FORM_sec_offset
143+
.byte 0 # EOM(1)
144+
.byte 0 # EOM(2)
145+
.byte 2 # Abbreviation Code
146+
.byte 52 # DW_TAG_variable
147+
.byte 0 # DW_CHILDREN_no
148+
.byte 3 # DW_AT_name
149+
.byte 37 # DW_FORM_strx1
150+
.byte 73 # DW_AT_type
151+
.byte 19 # DW_FORM_ref4
152+
.byte 63 # DW_AT_external
153+
.byte 25 # DW_FORM_flag_present
154+
.byte 58 # DW_AT_decl_file
155+
.byte 11 # DW_FORM_data1
156+
.byte 59 # DW_AT_decl_line
157+
.byte 11 # DW_FORM_data1
158+
.byte 2 # DW_AT_location
159+
.byte 24 # DW_FORM_exprloc
160+
.byte 0 # EOM(1)
161+
.byte 0 # EOM(2)
162+
.byte 3 # Abbreviation Code
163+
.byte 36 # DW_TAG_base_type
164+
.byte 0 # DW_CHILDREN_no
165+
.byte 3 # DW_AT_name
166+
.byte 37 # DW_FORM_strx1
167+
.byte 62 # DW_AT_encoding
168+
.byte 11 # DW_FORM_data1
169+
.byte 11 # DW_AT_byte_size
170+
.byte 11 # DW_FORM_data1
171+
.byte 0 # EOM(1)
172+
.byte 0 # EOM(2)
173+
.byte 0 # EOM(3)
174+
.section .debug_info,"",@progbits
175+
.Lcu_begin0:
176+
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
177+
.Ldebug_info_start0:
178+
.short 5 # DWARF version number
179+
.byte 1 # DWARF Unit Type
180+
.byte 8 # Address Size (in bytes)
181+
.long .debug_abbrev # Offset Into Abbrev. Section
182+
.byte 1 # Abbrev [1] 0xc:0x22 DW_TAG_compile_unit
183+
.byte 0 # DW_AT_producer
184+
.short 12 # DW_AT_language
185+
.byte 1 # DW_AT_name
186+
.long .Lstr_offsets_base0 # DW_AT_str_offsets_base
187+
.long .Lline_table_start0 # DW_AT_stmt_list
188+
.byte 2 # DW_AT_comp_dir
189+
.long .Laddr_table_base0 # DW_AT_addr_base
190+
.byte 2 # Abbrev [2] 0x1e:0xb DW_TAG_variable
191+
.byte 3 # DW_AT_name
192+
.long 41 # DW_AT_type
193+
# DW_AT_external
194+
.byte 1 # DW_AT_decl_file
195+
.byte 1 # DW_AT_decl_line
196+
.byte 2 # DW_AT_location
197+
.byte 161
198+
.byte 0
199+
.byte 3 # Abbrev [3] 0x29:0x4 DW_TAG_base_type
200+
.byte 4 # DW_AT_name
201+
.byte 6 # DW_AT_encoding
202+
.byte 1 # DW_AT_byte_size
203+
.byte 0 # End Of Children Mark
204+
.Ldebug_info_end0:
205+
.section .debug_str_offsets,"",@progbits
206+
.long 24 # Length of String Offsets Set
207+
.short 5
208+
.short 0
209+
.Lstr_offsets_base0:
210+
.section .debug_str,"MS",@progbits,1
211+
.Linfo_string0:
212+
.asciz "Debian clang version 14.0.6" # string offset=0
213+
.Linfo_string1:
214+
.asciz "/tmp/tmp.c" # string offset=28
215+
.Linfo_string2:
216+
.asciz "/tmp" # string offset=39
217+
.Linfo_string3:
218+
.asciz "defined_data" # string offset=44
219+
.Linfo_string4:
220+
.asciz "char" # string offset=57
221+
.section .debug_str_offsets,"",@progbits
222+
.long .Linfo_string0
223+
.long .Linfo_string1
224+
.long .Linfo_string2
225+
.long .Linfo_string3
226+
.long .Linfo_string4
227+
.section .debug_addr,"",@progbits
228+
.long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
229+
.Ldebug_addr_start0:
230+
.short 5 # DWARF version number
231+
.byte 8 # Address size
232+
.byte 0 # Segment selector size
233+
.Laddr_table_base0:
234+
.quad defined_data
235+
.Ldebug_addr_end0:
236+
.ident "Debian clang version 14.0.6"
237+
.section ".note.GNU-stack","",@progbits
238+
.addrsig
239+
.section .debug_line,"",@progbits
240+
.Lline_table_start0:

llvm/tools/llvm-nm/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ set(LLVM_LINK_COMPONENTS
88
Object
99
Option
1010
Support
11+
Symbolize
1112
TargetParser
1213
TextAPI
1314
)

llvm/tools/llvm-nm/Opts.td

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def export_symbols : FF<"export-symbols", "Export symbol list for all inputs">;
2222
def extern_only : FF<"extern-only", "Show only external symbols">;
2323
defm format : Eq<"format", "Specify output format: bsd (default), posix, sysv, darwin, just-symbols">, MetaVarName<"<format>">;
2424
def help : FF<"help", "Display this help">;
25+
def line_numbers : FF<"line-numbers", "Use debugging information to print symbols' filenames and line numbers">;
2526
def no_llvm_bc : FF<"no-llvm-bc", "Disable LLVM bitcode reader">;
2627
def no_sort : FF<"no-sort", "Show symbols in order encountered">;
2728
def no_weak : FF<"no-weak", "Show only non-weak symbols">;
@@ -67,6 +68,7 @@ def : JoinedOrSeparate<["-"], "f">, HelpText<"Alias for --format">, Alias<format
6768
def : F<"h", "Alias for --help">, Alias<help>;
6869
def : F<"g", "Alias for --extern-only">, Alias<extern_only>;
6970
def : F<"j", "Alias for --format=just-symbols">, Alias<format_EQ>, AliasArgs<["just-symbols"]>;
71+
def : F<"l", "Alias for --line-numbers">, Alias<line_numbers>;
7072
def : F<"m", "Alias for --format=darwin">, Alias<format_EQ>, AliasArgs<["darwin"]>;
7173
def : F<"M", "Deprecated alias for --print-armap">, Alias<print_armap>, Flags<[HelpHidden]>;
7274
def : F<"n", "Alias for --numeric-sort">, Alias<numeric_sort>;

0 commit comments

Comments
 (0)