[lld] [llvm] [Symbolizer] Support for Missing Line Numbers. (PR #82240)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 13 23:04:41 PDT 2024


ampandey-1995 wrote:





> > I will _try_ to post up an improved test if I can.
> 
> @ampandey-1995 below is my attempt. I think that it contains the testcases from both the of current tests and IMO it is more readable/understandable.
> 
> ```
> $ cat skip-line-zero.s
> ## Test the --skip-line-zero option.
> ##
> ## This test uses hand written assembly to produce the following line table:
> ## Address            Line   Column File   ISA Discriminator Flags
> ## ------------------ ------ ------ ------ --- ------------- -------------
> ## 0x0000000000000000     10      0      1   0             0
> ## 0x0000000000000001      9      0      1   0             0
> ## 0x0000000000000002      0      0      1   0             0
> ## 0x0000000000000003      8      0      1   0             0  end_sequence
> ## 0x0000000000000006      0      0      1   0             0
> ## 0x0000000000000007      0      0      1   0             0
> ## 0x0000000000000016      5      0      1   0             0  end_sequence
> ##
> ## The first sequence is for symbol foo and the second is for symbol bar.
> 
> # REQUIRES: x86-registered-target
> 
> # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
> 
> ## Check that without --skip-line-zero line zero is displayed for a line with no source correspondence.
> # RUN: llvm-symbolizer --obj=%t.o 0x2 | \
> # RUN:   FileCheck --check-prefix=SKIP-DISABLED %s
> # SKIP-DISABLED:foo
> # SKIP-DISABLED-NEXT:two.c:0:0
> 
> ## Check that with --skip-line-zero the last line non-zero line in the current sequence is displayed.
> # RUN: llvm-symbolizer --obj=%t.o 0x2 --skip-line-zero | \
> # RUN:   FileCheck --check-prefix=SKIP-ENABLED %s
> # SKIP-ENABLED:foo
> # SKIP-ENABLED-NEXT:two.c:9:0 (approximate)
> 
> ## Check that that --skip-line-zero only affects line zero addresses when more than one address is specified.
> # RUN: llvm-symbolizer --obj=%t.o --skip-line-zero 0x2 0x1 | \
> # RUN:   FileCheck --check-prefixes=SKIP-ENABLED,NO-SKIP %s
> # NO-SKIP:foo
> # NO-SKIP-NEXT:two.c:9:0
> 
> ## Check --verbose output is correct with --skip-line-zero.
> # RUN: llvm-symbolizer --obj=%t.o --skip-line-zero --verbose 0x2 | \
> # RUN:   FileCheck --check-prefix=SKIP-VERBOSE %s
> # SKIP-VERBOSE:foo
> # SKIP-VERBOSE-NEXT:  Filename: {{.*}}two.c
> # SKIP-VERBOSE-NEXT:  Function start address: 0x0
> # SKIP-VERBOSE-NEXT:  Line: 9
> # SKIP-VERBOSE-NEXT:  Column: 0
> # SKIP-VERBOSE-NEXT:  Approximate: true
> 
> ## Check --output-style=JSON output is correct with --skip-line-zero.
> # RUN: llvm-symbolizer --obj=%t.o --skip-line-zero --output-style=JSON 0x2 | \
> # RUN:   FileCheck --check-prefix=SKIP-JSON %s
> # SKIP-JSON:[{"Address":"0x2","ModuleName":"{{.*}}skip-line-zero.s.tmp.o","Symbol":[{"Approximate":true,"Column":0,"Discriminator":0,"FileName":"{{.*}}two.c","FunctionName":"foo","Line":9,"StartAddress":"0x0","StartFileName":"","StartLine":0}]}]
> 
> ## Check that that --skip-line-zero does not cross sequence boundaries.
> # RUN: llvm-symbolizer --obj=%t.o --skip-line-zero 0x7 | \
> # RUN:   FileCheck --check-prefixes=SKIP-BOUNDARY %s
> # SKIP-BOUNDARY:bar
> # SKIP-BOUNDARY:two.c:0:0
> 
> 	.section	.text.foo,"ax", at progbits
> 	.globl	foo
> foo:
> .Lfunc_begin0:
> 	movl	$10, %eax
> 	retq
> .Lfunc_end0:
> 	.size	foo, .Lfunc_end0-foo
> 
> 	.globl	bar
> bar:
> .Lfunc_begin1:
> # %bb.0:
> 	pushq	%rbp
> 	movq	%rsp, %rbp
> 	callq	foo
> 	movl	$20, %eax
> 	popq	%rbp
> 	retq
> .Lfunc_end1:
> 	.size	bar, .Lfunc_end1-bar
> 
> 	.section	.debug_abbrev,"", at progbits
> 	.byte	1                               # Abbreviation Code
> 	.byte	17                              # DW_TAG_compile_unit
> 	.byte	0                               # DW_CHILDREN_no
> 	.byte	37                              # DW_AT_producer
> 	.byte	14                              # DW_FORM_strp
> 	.byte	19                              # DW_AT_language
> 	.byte	5                               # DW_FORM_data2
> 	.byte	3                               # DW_AT_name
> 	.byte	14                              # DW_FORM_strp
> 	.byte	16                              # DW_AT_stmt_list
> 	.byte	23                              # DW_FORM_sec_offset
> 	.byte	27                              # DW_AT_comp_dir
> 	.byte	14                              # DW_FORM_strp
> 	.byte	83                              # DW_AT_use_UTF8
> 	.byte	25                              # DW_FORM_flag_present
> 	.byte	17                              # DW_AT_low_pc
> 	.byte	1                               # DW_FORM_addr
> 	.byte	85                              # DW_AT_ranges
> 	.byte	23                              # DW_FORM_sec_offset
> 	.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	4                               # DWARF version number
> 	.long	.debug_abbrev                   # Offset Into Abbrev. Section
> 	.byte	8                               # Address Size (in bytes)
> 	.byte	1                               # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
> 	.long	.Linfo_string0                  # DW_AT_producer
> 	.short	29                              # DW_AT_language
> 	.long	.Linfo_string1                  # DW_AT_name
> 	.long	.Lline_table_start0             # DW_AT_stmt_list
> 	.long	.Linfo_string2                  # DW_AT_comp_dir
>                                         # DW_AT_use_UTF8
> 	.quad	0                               # DW_AT_low_pc
> 	.long	.Ldebug_ranges0                 # DW_AT_ranges
> .Ldebug_info_end0:
> 	.section	.debug_aranges,"", at progbits
> 	.section	.debug_ranges,"", at progbits
> .Ldebug_ranges0:
> 	.quad	.Lfunc_begin0
> 	.quad	.Lfunc_end0
> 	.quad	.Lfunc_begin1
> 	.quad	.Lfunc_end1
> 	.quad	0
> 	.quad	0
> 	.section	.debug_str,"MS", at progbits,1
> .Linfo_string0:
> 	.asciz	"clang version 16.0.5 ---------------------------------------" # string offset=0
> .Linfo_string1:
> 	.asciz	"two.c"                         # string offset=61
> .Linfo_string2:
> 	.asciz	"c:\\Temp\\dwarfline"           # string offset=67
> 	.ident	"clang version 16.0.5 ---------------------------------------"
> 	.section	".note.GNU-stack","", at progbits
> .function_and_data_sections
> 	.section	.debug_line,"", at progbits
> .Lline_table_start0:
>         .long .Lunit_end - .Lunit_start # unit length
> .Lunit_start:
>         .short 4   # version
>         .long .Lprologue_end - .Lprologue_start # header length
> .Lprologue_start:
> 	.byte 1                                # minimum_instruction_length
> 	.byte 1                                # maximum_operations_per_instruction
> 	.byte 0                                # default_is_stmt
> 	.byte -5                               # line_base
> 	.byte 14                               # line_range
> 	.byte 13                               # opcode_base
> 	.byte 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 # arguments in standard opcodes
> 	.asciz "dir0"                          # include directory
> 	.asciz "dir1"                          # include directory
> 	.byte 0                                # end of include directories
> 	.asciz "two.c"                         # filename
> 	.byte 0                                # reference to dir0
> 	.byte 0                                # modification time
> 	.byte 0                                # length of file (unavailable)
> 	.byte 0                                # end of filenames
> .Lprologue_end:
>         .byte 0, 9, 2        # DW_LNE_set_address
>         .quad 0x0            #  foo (to 0)
>         .byte 3              # DW_LNS_advance_line
>         .sleb128 9           #  by 9 (to 10)
>         .byte 1              # DW_LNS_copy
>         .byte 3              # DW_LNS_advance_line
>         .sleb128 -1          #  by -1 (to 9)
>         .byte 2              # DW_LNS_advance_pc
>         .byte 1              #  += (1 * min instruction length) (to 1)
>         .byte 1              # DW_LNS_copy
>         .byte 3              # DW_LNS_advance_line
>         .sleb128 -9          #  by -9 (to 0)
>         .byte 2              # DW_LNS_advance_pc
>         .byte 1              #  += (1 * min instruction length) (to 2)
>         .byte 1              # DW_LNS_copy
>         .byte 3              # DW_LNS_advance_line
>         .sleb128 8           #  by 8 (to 8)
>         .byte 2              # DW_LNS_advance_pc
>         .byte 1              #  += (1 * min instruction length) (to 3)
>         .byte 0, 1, 1        # DW_LNE_end_sequence
>         .byte 0, 9, 2        # DW_LNE_set_address
>         .quad .Lfunc_begin1 - .Lfunc_begin0 #  bar (to 6)
>         .byte 3              # DW_LNS_advance_line
>         .sleb128 -1          #  by -1 (to 0)
>         .byte 1              # DW_LNS_copy
>         .byte 2              # DW_LNS_advance_pc
>         .byte 1              #  += (1 * min instruction length) (to 7)
>         .byte 1              # DW_LNS_copy
>         .byte 3              # DW_LNS_advance_line
>         .sleb128 5           #  by 5 (to 5)
>         .byte 2              # DW_LNS_advance_pc
>         .byte 15             #  += (15 * min instruction length) (to 22)
>         .byte 0, 1, 1        # DW_LNE_end_sequence
> .Lunit_end:
> ```

This is failing at my side 

> > I will _try_ to post up an improved test if I can.
> 
> @ampandey-1995 below is my attempt. I think that it contains the testcases from both the of current tests and IMO it is more readable/understandable.
> 
> ```
> $ cat skip-line-zero.s
> ## Test the --skip-line-zero option.
> ##
> ## This test uses hand written assembly to produce the following line table:
> ## Address            Line   Column File   ISA Discriminator Flags
> ## ------------------ ------ ------ ------ --- ------------- -------------
> ## 0x0000000000000000     10      0      1   0             0
> ## 0x0000000000000001      9      0      1   0             0
> ## 0x0000000000000002      0      0      1   0             0
> ## 0x0000000000000003      8      0      1   0             0  end_sequence
> ## 0x0000000000000006      0      0      1   0             0
> ## 0x0000000000000007      0      0      1   0             0
> ## 0x0000000000000016      5      0      1   0             0  end_sequence
> ##
> ## The first sequence is for symbol foo and the second is for symbol bar.
> 
> # REQUIRES: x86-registered-target
> 
> # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
> 
> ## Check that without --skip-line-zero line zero is displayed for a line with no source correspondence.
> # RUN: llvm-symbolizer --obj=%t.o 0x2 | \
> # RUN:   FileCheck --check-prefix=SKIP-DISABLED %s
> # SKIP-DISABLED:foo
> # SKIP-DISABLED-NEXT:two.c:0:0
> 
> ## Check that with --skip-line-zero the last line non-zero line in the current sequence is displayed.
> # RUN: llvm-symbolizer --obj=%t.o 0x2 --skip-line-zero | \
> # RUN:   FileCheck --check-prefix=SKIP-ENABLED %s
> # SKIP-ENABLED:foo
> # SKIP-ENABLED-NEXT:two.c:9:0 (approximate)
> 
> ## Check that that --skip-line-zero only affects line zero addresses when more than one address is specified.
> # RUN: llvm-symbolizer --obj=%t.o --skip-line-zero 0x2 0x1 | \
> # RUN:   FileCheck --check-prefixes=SKIP-ENABLED,NO-SKIP %s
> # NO-SKIP:foo
> # NO-SKIP-NEXT:two.c:9:0
> 
> ## Check --verbose output is correct with --skip-line-zero.
> # RUN: llvm-symbolizer --obj=%t.o --skip-line-zero --verbose 0x2 | \
> # RUN:   FileCheck --check-prefix=SKIP-VERBOSE %s
> # SKIP-VERBOSE:foo
> # SKIP-VERBOSE-NEXT:  Filename: {{.*}}two.c
> # SKIP-VERBOSE-NEXT:  Function start address: 0x0
> # SKIP-VERBOSE-NEXT:  Line: 9
> # SKIP-VERBOSE-NEXT:  Column: 0
> # SKIP-VERBOSE-NEXT:  Approximate: true
> 
> ## Check --output-style=JSON output is correct with --skip-line-zero.
> # RUN: llvm-symbolizer --obj=%t.o --skip-line-zero --output-style=JSON 0x2 | \
> # RUN:   FileCheck --check-prefix=SKIP-JSON %s
> # SKIP-JSON:[{"Address":"0x2","ModuleName":"{{.*}}skip-line-zero.s.tmp.o","Symbol":[{"Approximate":true,"Column":0,"Discriminator":0,"FileName":"{{.*}}two.c","FunctionName":"foo","Line":9,"StartAddress":"0x0","StartFileName":"","StartLine":0}]}]
> 
> ## Check that that --skip-line-zero does not cross sequence boundaries.
> # RUN: llvm-symbolizer --obj=%t.o --skip-line-zero 0x7 | \
> # RUN:   FileCheck --check-prefixes=SKIP-BOUNDARY %s
> # SKIP-BOUNDARY:bar
> # SKIP-BOUNDARY:two.c:0:0
> 
> 	.section	.text.foo,"ax", at progbits
> 	.globl	foo
> foo:
> .Lfunc_begin0:
> 	movl	$10, %eax
> 	retq
> .Lfunc_end0:
> 	.size	foo, .Lfunc_end0-foo
> 
> 	.globl	bar
> bar:
> .Lfunc_begin1:
> # %bb.0:
> 	pushq	%rbp
> 	movq	%rsp, %rbp
> 	callq	foo
> 	movl	$20, %eax
> 	popq	%rbp
> 	retq
> .Lfunc_end1:
> 	.size	bar, .Lfunc_end1-bar
> 
> 	.section	.debug_abbrev,"", at progbits
> 	.byte	1                               # Abbreviation Code
> 	.byte	17                              # DW_TAG_compile_unit
> 	.byte	0                               # DW_CHILDREN_no
> 	.byte	37                              # DW_AT_producer
> 	.byte	14                              # DW_FORM_strp
> 	.byte	19                              # DW_AT_language
> 	.byte	5                               # DW_FORM_data2
> 	.byte	3                               # DW_AT_name
> 	.byte	14                              # DW_FORM_strp
> 	.byte	16                              # DW_AT_stmt_list
> 	.byte	23                              # DW_FORM_sec_offset
> 	.byte	27                              # DW_AT_comp_dir
> 	.byte	14                              # DW_FORM_strp
> 	.byte	83                              # DW_AT_use_UTF8
> 	.byte	25                              # DW_FORM_flag_present
> 	.byte	17                              # DW_AT_low_pc
> 	.byte	1                               # DW_FORM_addr
> 	.byte	85                              # DW_AT_ranges
> 	.byte	23                              # DW_FORM_sec_offset
> 	.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	4                               # DWARF version number
> 	.long	.debug_abbrev                   # Offset Into Abbrev. Section
> 	.byte	8                               # Address Size (in bytes)
> 	.byte	1                               # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
> 	.long	.Linfo_string0                  # DW_AT_producer
> 	.short	29                              # DW_AT_language
> 	.long	.Linfo_string1                  # DW_AT_name
> 	.long	.Lline_table_start0             # DW_AT_stmt_list
> 	.long	.Linfo_string2                  # DW_AT_comp_dir
>                                         # DW_AT_use_UTF8
> 	.quad	0                               # DW_AT_low_pc
> 	.long	.Ldebug_ranges0                 # DW_AT_ranges
> .Ldebug_info_end0:
> 	.section	.debug_aranges,"", at progbits
> 	.section	.debug_ranges,"", at progbits
> .Ldebug_ranges0:
> 	.quad	.Lfunc_begin0
> 	.quad	.Lfunc_end0
> 	.quad	.Lfunc_begin1
> 	.quad	.Lfunc_end1
> 	.quad	0
> 	.quad	0
> 	.section	.debug_str,"MS", at progbits,1
> .Linfo_string0:
> 	.asciz	"clang version 16.0.5 ---------------------------------------" # string offset=0
> .Linfo_string1:
> 	.asciz	"two.c"                         # string offset=61
> .Linfo_string2:
> 	.asciz	"c:\\Temp\\dwarfline"           # string offset=67
> 	.ident	"clang version 16.0.5 ---------------------------------------"
> 	.section	".note.GNU-stack","", at progbits
> .function_and_data_sections
> 	.section	.debug_line,"", at progbits
> .Lline_table_start0:
>         .long .Lunit_end - .Lunit_start # unit length
> .Lunit_start:
>         .short 4   # version
>         .long .Lprologue_end - .Lprologue_start # header length
> .Lprologue_start:
> 	.byte 1                                # minimum_instruction_length
> 	.byte 1                                # maximum_operations_per_instruction
> 	.byte 0                                # default_is_stmt
> 	.byte -5                               # line_base
> 	.byte 14                               # line_range
> 	.byte 13                               # opcode_base
> 	.byte 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 # arguments in standard opcodes
> 	.asciz "dir0"                          # include directory
> 	.asciz "dir1"                          # include directory
> 	.byte 0                                # end of include directories
> 	.asciz "two.c"                         # filename
> 	.byte 0                                # reference to dir0
> 	.byte 0                                # modification time
> 	.byte 0                                # length of file (unavailable)
> 	.byte 0                                # end of filenames
> .Lprologue_end:
>         .byte 0, 9, 2        # DW_LNE_set_address
>         .quad 0x0            #  foo (to 0)
>         .byte 3              # DW_LNS_advance_line
>         .sleb128 9           #  by 9 (to 10)
>         .byte 1              # DW_LNS_copy
>         .byte 3              # DW_LNS_advance_line
>         .sleb128 -1          #  by -1 (to 9)
>         .byte 2              # DW_LNS_advance_pc
>         .byte 1              #  += (1 * min instruction length) (to 1)
>         .byte 1              # DW_LNS_copy
>         .byte 3              # DW_LNS_advance_line
>         .sleb128 -9          #  by -9 (to 0)
>         .byte 2              # DW_LNS_advance_pc
>         .byte 1              #  += (1 * min instruction length) (to 2)
>         .byte 1              # DW_LNS_copy
>         .byte 3              # DW_LNS_advance_line
>         .sleb128 8           #  by 8 (to 8)
>         .byte 2              # DW_LNS_advance_pc
>         .byte 1              #  += (1 * min instruction length) (to 3)
>         .byte 0, 1, 1        # DW_LNE_end_sequence
>         .byte 0, 9, 2        # DW_LNE_set_address
>         .quad .Lfunc_begin1 - .Lfunc_begin0 #  bar (to 6)
>         .byte 3              # DW_LNS_advance_line
>         .sleb128 -1          #  by -1 (to 0)
>         .byte 1              # DW_LNS_copy
>         .byte 2              # DW_LNS_advance_pc
>         .byte 1              #  += (1 * min instruction length) (to 7)
>         .byte 1              # DW_LNS_copy
>         .byte 3              # DW_LNS_advance_line
>         .sleb128 5           #  by 5 (to 5)
>         .byte 2              # DW_LNS_advance_pc
>         .byte 15             #  += (15 * min instruction length) (to 22)
>         .byte 0, 1, 1        # DW_LNE_end_sequence
> .Lunit_end:
> ```

Copied your test-case on my machine. It fails.

![image](https://github.com/llvm/llvm-project/assets/137622562/147be21c-dbe5-4560-8122-0bdd02b4089f)




https://github.com/llvm/llvm-project/pull/82240


More information about the llvm-commits mailing list