diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 690c8b3498..ad97b669cc 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,35 @@ +2021-04-07 Andrew Burgess + + * gdb.dwarf2/fission-absolute-dwo.c: New file. + * gdb.dwarf2/fission-absolute-dwo.exp: New file. + * gdb.dwarf2/fission-base.exp: Use build_executable_and_dwo_files + instead of build_executable_from_fission_assembler. + * gdb.dwarf2/fission-loclists-pie.exp: Likewise. + * gdb.dwarf2/fission-loclists.exp: Likewise. + + * gdb.dwarf2/fission-multi-cu.S: Delete file. + * gdb.dwarf2/fission-multi-cu.c: New file based on old + fission-multi-cu1.c and fission-multi-cu2.c files. + * gdb.dwarf2/fission-multi-cu1.c: Delete file. + * gdb.dwarf2/fission-multi-cu2.c: Delete file. + * gdb.dwarf2/fission-multi-cu.exp: Rewrite to use Dwarf assembler. + * gdb.dwarf2/fission-reread.exp: Likewise. + * lib/dwarf.exp (extract_dwo_information): New proc. + (strip_dwo_information): New proc. + (build_executable_and_dwo_files): New proc. + (build_executable_from_fission_assembler): Delete. + (Dwarf::_debug_addr_index): New variable. + (Dwarf::_cu_is_fission): New variable. + (Dwarf::_handle_DW_FORM): Handle DW_OP_GNU_addr_index. + (Dwarf::_default_form): Supply a default for DW_AT_GNU_addr_base. + (Dwarf::_handle_macro_at_range): Use form DW_FORM_GNU_addr_index + if this is a fission CU. + (Dwarf::_location): Handle DW_OP_GNU_addr_index. + (Dwarf::debug_addr_label): New proc. + (Dwarf::cu): Initialise _cu_is_fission. + (Dwarf::tu): Likewise. + (Dwarf::assemble): Initialise _debug_addr_index. + 2021-04-07 Andrew Burgess * gdb.dwarf2/dw2-using-debug-str.exp: Add an additional test. diff --git a/gdb/testsuite/gdb.dwarf2/fission-multi-cu2.c b/gdb/testsuite/gdb.dwarf2/fission-absolute-dwo.c similarity index 71% rename from gdb/testsuite/gdb.dwarf2/fission-multi-cu2.c rename to gdb/testsuite/gdb.dwarf2/fission-absolute-dwo.c index 6f0ed1f5ae..27f7f0dfb4 100644 --- a/gdb/testsuite/gdb.dwarf2/fission-multi-cu2.c +++ b/gdb/testsuite/gdb.dwarf2/fission-absolute-dwo.c @@ -1,6 +1,6 @@ /* This testcase is part of GDB, the GNU debugger. - Copyright 2012-2021 Free Software Foundation, Inc. + Copyright 2021 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,12 +13,16 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program. If not, see + . */ -void func (); +/* Our fake object. */ +int global_var[100]; int -main () +main (int argc, char **argv) { - func (-1); + asm ("main_label: .globl main_label"); + + return 0; } diff --git a/gdb/testsuite/gdb.dwarf2/fission-absolute-dwo.exp b/gdb/testsuite/gdb.dwarf2/fission-absolute-dwo.exp new file mode 100644 index 0000000000..2483349bf7 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/fission-absolute-dwo.exp @@ -0,0 +1,133 @@ +# Copyright 2021 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This is a basic first test for using the testsuite's Dwarf assembler to +# create split debug information. There's not unique feature of GDB being +# tested here, this exists only as a basic test for the testsuite +# infrastructure. + +load_lib dwarf.exp + +# This test can only be run on targets which support DWARF-2 and use gas. +if {![dwarf2_support]} { + return 0 +} + +standard_testfile .c -dw.S + +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { + return -1 +} + +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble $asm_file { + global srcfile binfile objdir + + set debug_addr_lbl ".unknown!!" + + # The information that will be split out into the .dwo file. + cu {fission 1} { + + # Capture a label to the current start of the .debug_addr + # section. This will be passed to DW_AT_GNU_addr_base in the + # non-split CU later. + set debug_addr_lbl [debug_addr_label] + + compile_unit { + {language @DW_LANG_C} + {name ${srcfile}} + {DW_AT_comp_dir ${objdir}} + {DW_AT_GNU_dwo_id 0x1234 DW_FORM_data8} + } { + declare_labels int4_type struct_type + + int4_type: DW_TAG_base_type { + {DW_AT_byte_size 4 DW_FORM_sdata} + {DW_AT_encoding @DW_ATE_signed} + {DW_AT_name integer} + } + + struct_type: DW_TAG_structure_type { + {DW_AT_name "foo_t"} + {DW_AT_byte_size 12 DW_FORM_sdata} + } { + member { + {name "aa"} + {type :$int4_type} + {data_member_location 0 data1} + } + member { + {name "bb"} + {type :$int4_type} + {data_member_location 4 data1} + } + member { + {name "cc"} + {type :$int4_type} + {data_member_location 8 data1} + } + } + + DW_TAG_variable { + {DW_AT_name global_var} + {DW_AT_type :$struct_type} + {DW_AT_location { + DW_OP_GNU_addr_index [gdb_target_symbol global_var] + } SPECIAL_expr} + {external 1 flag} + } + + subprogram { + {external 1 flag} + {DW_AT_name main DW_FORM_string} + {MACRO_AT_func {main}} + } + } + } + + # The information that will remain in the .o file. + cu {} { + compile_unit { + {DW_AT_GNU_dwo_name ${binfile}.dwo DW_FORM_strp} + {DW_AT_comp_dir ${objdir}} + {DW_AT_GNU_dwo_id 0x1234 DW_FORM_data8} + {DW_AT_GNU_addr_base $debug_addr_lbl} + } { + # Nothing. + } + } +} + +# Compile both source files to create the executable. As we compile +# ASM_FILE we split out the debug information into the dwo file. +set object_file [standard_output_file ${testfile}.o] +if { [build_executable_and_dwo_files "${testfile}.exp" ${binfile} {nodebug} \ + [list $asm_file {nodebug split-dwo} ${object_file}] \ + [list $srcfile {nodebug}]] } { + perror "failed to compile ${gdb_test_file_name}" + return -1 +} + +# Now we can start GDB. +clean_restart ${testfile} + +if ![runto_main] { + return -1 +} + +# Print the type of global_var. This type information is entirely +# fictional, it only exists in the DWARF. If we don't have the DWARF +# information then there's no way we can print this. +gdb_test "p global_var" " = \\{aa = 0, bb = 0, cc = 0\\}" diff --git a/gdb/testsuite/gdb.dwarf2/fission-base.exp b/gdb/testsuite/gdb.dwarf2/fission-base.exp index 40a7e2a4e3..00eb7fec1b 100644 --- a/gdb/testsuite/gdb.dwarf2/fission-base.exp +++ b/gdb/testsuite/gdb.dwarf2/fission-base.exp @@ -32,11 +32,12 @@ if {![istarget x86_64-*] || ![is_lp64_target]} { standard_testfile .S -set dwo [standard_output_file "fission-base.dwo"] - -if [build_executable_from_fission_assembler \ - "$testfile.exp" "$binfile" "$srcfile" \ - [list nodebug additional_flags=-DDWO=$dwo]] { +set obj [standard_output_file "${testfile}.o"] +set dwo [standard_output_file "${testfile}.dwo"] +if [build_executable_and_dwo_files "$testfile.exp" "${binfile}" {nodebug} \ + [list $srcfile \ + [list nodebug split-dwo additional_flags=-DDWO=$dwo] \ + $obj]] { return -1 } diff --git a/gdb/testsuite/gdb.dwarf2/fission-loclists-pie.exp b/gdb/testsuite/gdb.dwarf2/fission-loclists-pie.exp index c0a7785985..21098a2462 100644 --- a/gdb/testsuite/gdb.dwarf2/fission-loclists-pie.exp +++ b/gdb/testsuite/gdb.dwarf2/fission-loclists-pie.exp @@ -37,11 +37,12 @@ if {![istarget x86_64-*] || ![is_lp64_target]} { standard_testfile .S -set dwo [standard_output_file "fission-loclists-pie.dwo"] - -if [build_executable_from_fission_assembler \ - "$testfile.exp" "$binfile" "$srcfile" \ - [list "nodebug" "ldflags=-pie" additional_flags=-DDWO=$dwo]] { +set obj [standard_output_file "${testfile}.o"] +set dwo [standard_output_file "${testfile}.dwo"] +if [build_executable_and_dwo_files "$testfile.exp" "${binfile}" \ + {nodebug ldflags=-pie} \ + [list $srcfile [list nodebug split-dwo additional_flags=-DDWO=$dwo] \ + $obj]] { return -1 } diff --git a/gdb/testsuite/gdb.dwarf2/fission-loclists.exp b/gdb/testsuite/gdb.dwarf2/fission-loclists.exp index 54eace0496..c490763982 100644 --- a/gdb/testsuite/gdb.dwarf2/fission-loclists.exp +++ b/gdb/testsuite/gdb.dwarf2/fission-loclists.exp @@ -32,11 +32,12 @@ if {![istarget x86_64-*] || ![is_lp64_target]} { standard_testfile .S -set dwo [standard_output_file "fission-loclists.dwo"] - -if [build_executable_from_fission_assembler \ - "$testfile.exp" "$binfile" "$srcfile" \ - [list nodebug additional_flags=-DDWO=$dwo]] { +set obj [standard_output_file "${testfile}.o"] +set dwo [standard_output_file "${testfile}.dwo"] +if [build_executable_and_dwo_files "$testfile.exp" "${binfile}" {nodebug} \ + [list $srcfile \ + [list nodebug split-dwo additional_flags=-DDWO=$dwo] \ + $obj]] { return -1 } diff --git a/gdb/testsuite/gdb.dwarf2/fission-multi-cu.S b/gdb/testsuite/gdb.dwarf2/fission-multi-cu.S deleted file mode 100644 index df83613831..0000000000 --- a/gdb/testsuite/gdb.dwarf2/fission-multi-cu.S +++ /dev/null @@ -1,364 +0,0 @@ -/* This testcase is part of GDB, the GNU debugger. - - Copyright 2012-2021 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - This file was created by doing: - - clang fission-multi-cu*.c -g -fno-split-dwarf-inlining -emit-llvm -S -c - llvm-link fission-multi-cu*.ll -S -o fission-multi-cu.ll - clang-tot fission-multi-cu.ll -gsplit-dwarf -S - - and then massaging the output. -*/ - -#define XSTR(s) STR(s) -#define STR(s) #s - - .text - .file "llvm-link" - .globl func - .p2align 4, 0x90 - .type func,@function -func: # @func -.Lfunc_begin0: - .file 1 "fission-multi-cu1.c" - .loc 1 20 0 # fission-multi-cu1.c:20:0 - .cfi_startproc -# BB#0: # %entry - pushq %rbp - .cfi_def_cfa_offset 16 - .cfi_offset %rbp, -16 - movq %rsp, %rbp - .cfi_def_cfa_register %rbp - movl %edi, -4(%rbp) - .loc 1 21 10 prologue_end # fission-multi-cu1.c:21:10 - movl -4(%rbp), %edi - .loc 1 21 14 is_stmt 0 # fission-multi-cu1.c:21:14 - addl $1, %edi - .loc 1 21 3 # fission-multi-cu1.c:21:3 - movl %edi, %eax - popq %rbp - retq -.Lfunc_end0: - .size func, .Lfunc_end0-func - .cfi_endproc - - .globl main - .p2align 4, 0x90 - .type main,@function -main: # @main -.Lfunc_begin1: - .file 2 "fission-multi-cu2.c" - .loc 2 23 0 is_stmt 1 # fission-multi-cu2.c:23:0 - .cfi_startproc -# BB#0: # %entry - pushq %rbp - .cfi_def_cfa_offset 16 - .cfi_offset %rbp, -16 - movq %rsp, %rbp - .cfi_def_cfa_register %rbp - movl $4294967295, %edi # imm = 0xFFFFFFFF - .loc 2 24 3 prologue_end # fission-multi-cu2.c:24:3 - movb $0, %al - callq func - xorl %eax, %eax - .loc 2 25 1 # fission-multi-cu2.c:25:1 - popq %rbp - retq -.Lfunc_end1: - .size main, .Lfunc_end1-main - .cfi_endproc - - .section .debug_str,"MS",@progbits,1 -.Lskel_string0: - .asciz XSTR(DWO) # string offset=0 -.Lskel_string1: - .asciz "/tmp/src/gdb/testsuite" # string offset=21 - .section .debug_loc.dwo,"",@progbits - .section .debug_abbrev,"",@progbits - .byte 1 # Abbreviation Code - .byte 17 # DW_TAG_compile_unit - .byte 0 # DW_CHILDREN_no - .byte 16 # DW_AT_stmt_list - .byte 23 # DW_FORM_sec_offset - .ascii "\260B" # DW_AT_GNU_dwo_name - .byte 14 # DW_FORM_strp - .byte 27 # DW_AT_comp_dir - .byte 14 # DW_FORM_strp - .ascii "\261B" # DW_AT_GNU_dwo_id - .byte 7 # DW_FORM_data8 - .ascii "\263B" # DW_AT_GNU_addr_base - .byte 23 # DW_FORM_sec_offset - .byte 17 # DW_AT_low_pc - .byte 1 # DW_FORM_addr - .byte 18 # DW_AT_high_pc - .byte 6 # DW_FORM_data4 - .byte 0 # EOM(1) - .byte 0 # EOM(2) - .byte 0 # EOM(3) - .section .debug_info,"",@progbits -.Lcu_begin0: - .long 44 # Length of Unit - .short 4 # DWARF version number - .long .debug_abbrev # Offset Into Abbrev. Section - .byte 8 # Address Size (in bytes) - .byte 1 # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit - .long .Lline_table_start0 # DW_AT_stmt_list - .long .Lskel_string0 # DW_AT_GNU_dwo_name - .long .Lskel_string1 # DW_AT_comp_dir - .quad 7615852067747431413 # DW_AT_GNU_dwo_id - .long .debug_addr # DW_AT_GNU_addr_base - .quad .Lfunc_begin0 # DW_AT_low_pc - .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc -.Lcu_begin1: - .long 44 # Length of Unit - .short 4 # DWARF version number - .long .debug_abbrev # Offset Into Abbrev. Section - .byte 8 # Address Size (in bytes) - .byte 1 # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit - .long .Lline_table_start0 # DW_AT_stmt_list - .long .Lskel_string0 # DW_AT_GNU_dwo_name - .long .Lskel_string1 # DW_AT_comp_dir - .quad 2037650261599692324 # DW_AT_GNU_dwo_id - .long .debug_addr # DW_AT_GNU_addr_base - .quad .Lfunc_begin1 # DW_AT_low_pc - .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc - .section .debug_ranges,"",@progbits - .section .debug_macinfo,"",@progbits -.Lcu_macro_begin1: -.Lcu_macro_begin3: - .byte 0 # End Of Macro List Mark - .section .debug_str.dwo,"MS",@progbits,1 -.Linfo_string0: - .asciz "fission-multi-cu.dwo" # string offset=0 -.Linfo_string1: - .asciz "clang version 5.0.0 (trunk 302855) (llvm/trunk 302853)" # string offset=21 -.Linfo_string2: - .asciz "fission-multi-cu1.c" # string offset=76 -.Linfo_string3: - .asciz "fission-multi-cu2.c" # string offset=96 -.Linfo_string4: - .asciz "func" # string offset=116 -.Linfo_string5: - .asciz "int" # string offset=121 -.Linfo_string6: - .asciz "main" # string offset=125 -.Linfo_string7: - .asciz "arg" # string offset=130 - .section .debug_str_offsets.dwo,"",@progbits - .long 0 - .long 21 - .long 76 - .long 96 - .long 116 - .long 121 - .long 125 - .long 130 - .section .debug_info.dwo,"",@progbits - .long 53 # Length of Unit - .short 4 # DWARF version number - .long 0 # Offset Into Abbrev. Section - .byte 8 # Address Size (in bytes) - .byte 1 # Abbrev [1] 0xb:0x2e DW_TAG_compile_unit - .byte 0 # DW_AT_GNU_dwo_name - .byte 1 # DW_AT_producer - .short 12 # DW_AT_language - .byte 2 # DW_AT_name - .quad 7615852067747431413 # DW_AT_GNU_dwo_id - .byte 2 # Abbrev [2] 0x19:0x1b 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 86 - .byte 4 # DW_AT_name - .byte 1 # DW_AT_decl_file - .byte 19 # DW_AT_decl_line - # DW_AT_prototyped - .long 52 # DW_AT_type - # DW_AT_external - .byte 3 # Abbrev [3] 0x28:0xb DW_TAG_formal_parameter - .byte 2 # DW_AT_location - .byte 145 - .byte 124 - .byte 7 # DW_AT_name - .byte 1 # DW_AT_decl_file - .byte 19 # DW_AT_decl_line - .long 52 # DW_AT_type - .byte 0 # End Of Children Mark - .byte 4 # Abbrev [4] 0x34:0x4 DW_TAG_base_type - .byte 5 # DW_AT_name - .byte 5 # DW_AT_encoding - .byte 4 # DW_AT_byte_size - .byte 0 # End Of Children Mark - .long 41 # Length of Unit - .short 4 # DWARF version number - .long 0 # Offset Into Abbrev. Section - .byte 8 # Address Size (in bytes) - .byte 1 # Abbrev [1] 0xb:0x22 DW_TAG_compile_unit - .byte 0 # DW_AT_GNU_dwo_name - .byte 1 # DW_AT_producer - .short 12 # DW_AT_language - .byte 3 # DW_AT_name - .quad 2037650261599692324 # DW_AT_GNU_dwo_id - .byte 5 # Abbrev [5] 0x19:0xf 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 86 - .byte 6 # DW_AT_name - .byte 2 # DW_AT_decl_file - .byte 22 # DW_AT_decl_line - .long 40 # DW_AT_type - # DW_AT_external - .byte 4 # Abbrev [4] 0x28:0x4 DW_TAG_base_type - .byte 5 # DW_AT_name - .byte 5 # DW_AT_encoding - .byte 4 # DW_AT_byte_size - .byte 0 # End Of Children Mark - .section .debug_abbrev.dwo,"",@progbits - .byte 1 # Abbreviation Code - .byte 17 # DW_TAG_compile_unit - .byte 1 # DW_CHILDREN_yes - .ascii "\260B" # DW_AT_GNU_dwo_name - .ascii "\202>" # DW_FORM_GNU_str_index - .byte 37 # DW_AT_producer - .ascii "\202>" # DW_FORM_GNU_str_index - .byte 19 # DW_AT_language - .byte 5 # DW_FORM_data2 - .byte 3 # DW_AT_name - .ascii "\202>" # DW_FORM_GNU_str_index - .ascii "\261B" # DW_AT_GNU_dwo_id - .byte 7 # DW_FORM_data8 - .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 - .ascii "\201>" # DW_FORM_GNU_addr_index - .byte 18 # DW_AT_high_pc - .byte 6 # DW_FORM_data4 - .byte 64 # DW_AT_frame_base - .byte 24 # DW_FORM_exprloc - .byte 3 # DW_AT_name - .ascii "\202>" # DW_FORM_GNU_str_index - .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 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 3 # DW_AT_name - .ascii "\202>" # DW_FORM_GNU_str_index - .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 4 # Abbreviation Code - .byte 36 # DW_TAG_base_type - .byte 0 # DW_CHILDREN_no - .byte 3 # DW_AT_name - .ascii "\202>" # DW_FORM_GNU_str_index - .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 5 # Abbreviation Code - .byte 46 # DW_TAG_subprogram - .byte 0 # DW_CHILDREN_no - .byte 17 # DW_AT_low_pc - .ascii "\201>" # DW_FORM_GNU_addr_index - .byte 18 # DW_AT_high_pc - .byte 6 # DW_FORM_data4 - .byte 64 # DW_AT_frame_base - .byte 24 # DW_FORM_exprloc - .byte 3 # DW_AT_name - .ascii "\202>" # DW_FORM_GNU_str_index - .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 63 # DW_AT_external - .byte 25 # DW_FORM_flag_present - .byte 0 # EOM(1) - .byte 0 # EOM(2) - .byte 0 # EOM(3) - .section .debug_addr,"",@progbits - .quad .Lfunc_begin0 - .quad .Lfunc_begin1 - .section .debug_pubnames,"",@progbits - .long .LpubNames_end0-.LpubNames_begin0 # Length of Public Names Info -.LpubNames_begin0: - .short 2 # DWARF Version - .long .Lcu_begin0 # Offset of Compilation Unit Info - .long 48 # Compilation Unit Length - .long 25 # DIE offset - .asciz "func" # External Name - .long 0 # End Mark -.LpubNames_end0: - .long .LpubNames_end1-.LpubNames_begin1 # Length of Public Names Info -.LpubNames_begin1: - .short 2 # DWARF Version - .long .Lcu_begin1 # Offset of Compilation Unit Info - .long 48 # Compilation Unit Length - .long 25 # DIE offset - .asciz "main" # External Name - .long 0 # End Mark -.LpubNames_end1: - .section .debug_pubtypes,"",@progbits - .long .LpubTypes_end0-.LpubTypes_begin0 # Length of Public Types Info -.LpubTypes_begin0: - .short 2 # DWARF Version - .long .Lcu_begin0 # Offset of Compilation Unit Info - .long 48 # Compilation Unit Length - .long 52 # DIE offset - .asciz "int" # External Name - .long 0 # End Mark -.LpubTypes_end0: - .long .LpubTypes_end1-.LpubTypes_begin1 # Length of Public Types Info -.LpubTypes_begin1: - .short 2 # DWARF Version - .long .Lcu_begin1 # Offset of Compilation Unit Info - .long 48 # Compilation Unit Length - .long 40 # DIE offset - .asciz "int" # External Name - .long 0 # End Mark -.LpubTypes_end1: - - .ident "clang version 5.0.0 (trunk 302855) (llvm/trunk 302853)" - .ident "clang version 5.0.0 (trunk 302855) (llvm/trunk 302853)" - .section ".note.GNU-stack","",@progbits - .section .debug_line,"",@progbits -.Lline_table_start0: diff --git a/gdb/testsuite/gdb.dwarf2/fission-multi-cu1.c b/gdb/testsuite/gdb.dwarf2/fission-multi-cu.c similarity index 72% rename from gdb/testsuite/gdb.dwarf2/fission-multi-cu1.c rename to gdb/testsuite/gdb.dwarf2/fission-multi-cu.c index 08674a9b4a..6a177ad4e6 100644 --- a/gdb/testsuite/gdb.dwarf2/fission-multi-cu1.c +++ b/gdb/testsuite/gdb.dwarf2/fission-multi-cu.c @@ -15,8 +15,27 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#define LL(N) asm ("line_label_" #N ": .globl line_label_" #N) + +/* Fake parameter location. */ +int global_param = 0; + int func (int arg) { + asm ("func_label: .globl func_label"); + LL(4); return arg + 1; } + +int +main () +{ + asm ("main_label: .globl main_label"); + LL(1); + global_param = -1; + LL(2); + func (-1); + LL(3); + return 0; +} diff --git a/gdb/testsuite/gdb.dwarf2/fission-multi-cu.exp b/gdb/testsuite/gdb.dwarf2/fission-multi-cu.exp index dec754798b..0f7f796a54 100644 --- a/gdb/testsuite/gdb.dwarf2/fission-multi-cu.exp +++ b/gdb/testsuite/gdb.dwarf2/fission-multi-cu.exp @@ -13,6 +13,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +# This test checks that GDB can load DWARF information from two +# separate split .DWO files. + load_lib dwarf.exp # We run objcopy locally to split out the .dwo file. @@ -25,18 +28,186 @@ if ![dwarf2_support] { return 0 } -# This test can only be run on x86-64 targets. -if {![istarget x86_64-*] || ![is_lp64_target]} { - return 0 +# We place the entire source code for the test into a single .c file, +# but we generate the DWARF in two separate .S files. Each .S is +# compiled to a .o, then the DWARF is split into a .dwo file. Finally +# the all three .o files are merged into a single executable that will +# reference the two .dwo files. +standard_testfile .c -1-dw.S -2-cw.S + +# Generate the first .S file. +set asm_file_1 [standard_output_file $srcfile2] +Dwarf::assemble $asm_file_1 { + global srcfile binfile objdir srcdir subdir + + get_func_info func + + declare_labels int4_type lines_table + + set debug_addr_lbl ".unknown!!" + + # The information that will be split out into the .dwo file. + cu {fission 1} { + + # Capture a label to the current start of the .debug_addr + # section. This will be passed to DW_AT_GNU_addr_base in the + # non-split CU later. + set debug_addr_lbl [debug_addr_label] + + compile_unit { + {language @DW_LANG_C} + {name ${srcfile}} + {DW_AT_comp_dir ${objdir}} + {DW_AT_GNU_dwo_id 0x1234 DW_FORM_data8} + } { + int4_type: DW_TAG_base_type { + {DW_AT_byte_size 4 DW_FORM_sdata} + {DW_AT_encoding @DW_ATE_signed} + {DW_AT_name int} + } + + subprogram { + {external 1 flag} + {DW_AT_name func DW_FORM_string} + {MACRO_AT_func {func}} + {DW_AT_type :$int4_type} + } { + DW_TAG_formal_parameter { + {DW_AT_name arg} + {DW_AT_type :$int4_type} + {DW_AT_location { + DW_OP_GNU_addr_index [gdb_target_symbol global_param] + } SPECIAL_expr} + } + } + } + } + + lines {version 2} lines_table { + include_dir "${srcdir}/${subdir}" + file_name "$srcfile" 1 + + program { + {DW_LNE_set_address $func_start} + {DW_LNS_advance_line 24} + {DW_LNS_copy} + + {DW_LNE_set_address line_label_4} + {DW_LNS_advance_line 3} + {DW_LNS_copy} + + {DW_LNE_set_address $func_end} + {DW_LNS_advance_line 1} + {DW_LNS_copy} + {DW_LNE_end_sequence} + } + } + + # The information that will remain in the .o file. + cu {} { + compile_unit { + {DW_AT_GNU_dwo_name ${binfile}-1-dw.dwo DW_FORM_strp} + {DW_AT_comp_dir ${objdir}} + {DW_AT_GNU_dwo_id 0x1234 DW_FORM_data8} + {DW_AT_GNU_addr_base $debug_addr_lbl} + {stmt_list $lines_table DW_FORM_sec_offset} + } { + # Nothing. + } + } } -standard_testfile .S +# Generate the second .S file. +set asm_file_2 [standard_output_file $srcfile3] +Dwarf::assemble $asm_file_2 { + global srcfile binfile objdir srcdir subdir -set dwo [standard_output_file "fission-multi-cu.dwo"] + set debug_addr_lbl ".unknown!!" -if [build_executable_from_fission_assembler \ - "$testfile.exp" "$binfile" "$srcfile" \ - [list nodebug additional_flags=-DDWO=$dwo]] { + declare_labels int4_type lines_table + + get_func_info main + + # The information that will be split out into the .dwo file. + cu {fission 1} { + + # Capture a label to the current start of the .debug_addr + # section. This will be passed to DW_AT_GNU_addr_base in the + # non-split CU later. + set debug_addr_lbl [debug_addr_label] + + compile_unit { + {language @DW_LANG_C} + {name ${srcfile}} + {DW_AT_comp_dir ${objdir}} + {DW_AT_GNU_dwo_id 0x4567 DW_FORM_data8} + } { + int4_type: DW_TAG_base_type { + {DW_AT_byte_size 4 DW_FORM_sdata} + {DW_AT_encoding @DW_ATE_signed} + {DW_AT_name int} + } + + subprogram { + {external 1 flag} + {DW_AT_name main DW_FORM_string} + {MACRO_AT_func {main}} + {DW_AT_type :$int4_type} + {DW_AT_decl_file 1 data1} + {DW_AT_decl_line 29 data1} + } + } + } + + lines {version 2} lines_table { + include_dir "${srcdir}/${subdir}" + file_name "$srcfile" 1 + + program { + {DW_LNE_set_address $main_start} + {DW_LNS_advance_line 32} + {DW_LNS_copy} + + {DW_LNE_set_address line_label_1} + {DW_LNS_advance_line 3} + {DW_LNS_copy} + + {DW_LNE_set_address line_label_2} + {DW_LNS_advance_line 2} + {DW_LNS_copy} + + {DW_LNE_set_address line_label_3} + {DW_LNS_advance_line 2} + {DW_LNS_copy} + + {DW_LNE_set_address $main_end} + {DW_LNS_advance_line 2} + {DW_LNS_copy} + {DW_LNE_end_sequence} + } + } + + # The information that will remain in the .o file. + cu {} { + compile_unit { + {DW_AT_GNU_dwo_name ${binfile}-2-dw.dwo DW_FORM_strp} + {DW_AT_comp_dir ${objdir}} + {DW_AT_GNU_dwo_id 0x4567 DW_FORM_data8} + {DW_AT_GNU_addr_base $debug_addr_lbl} + {stmt_list $lines_table DW_FORM_sec_offset} + } { + # Nothing. + } + } +} + +# Compile all of the input files, split the DWARF into the .dwo files. +set obj1 [standard_output_file "${testfile}-1-dw.o"] +set obj2 [standard_output_file "${testfile}-2-dw.o"] +if [build_executable_and_dwo_files "$testfile.exp" "${binfile}" {nodebug} \ + [list $asm_file_1 [list nodebug split-dwo] $obj1] \ + [list $asm_file_2 [list nodebug split-dwo] $obj2] \ + [list $srcfile [list nodebug]]] { return -1 } @@ -51,13 +222,13 @@ if ![runto_main] { gdb_test "ptype main" "type = int \\(\\)" gdb_test "ptype func" "type = int \\(int\\)" -gdb_test "frame" "#0 *main \\(\\) at ${testfile}2\\.c:$decimal.*" \ +gdb_test "frame" "#0 *main \\(\\) at \[^\r\n\]+${srcfile}:$decimal.*" \ "frame in main" -gdb_test "break func" "Breakpoint.*at.* file .*${testfile}1\\.c, line .*" +gdb_test "break func" "Breakpoint.*at.* file .*${srcfile}, line .*" gdb_test "continue" "Breakpoint.* func \\(arg=-1\\).*" \ "continue to func" -gdb_test "frame" "#0 *func \\(arg=-1\\) at ${testfile}1\\.c:$decimal.*" \ +gdb_test "frame" "#0 *func \\(arg=-1\\) at \[^\r\n\]+${srcfile}:$decimal.*" \ "frame in func" diff --git a/gdb/testsuite/gdb.dwarf2/fission-reread.exp b/gdb/testsuite/gdb.dwarf2/fission-reread.exp index 58132794ee..16a139eb0c 100644 --- a/gdb/testsuite/gdb.dwarf2/fission-reread.exp +++ b/gdb/testsuite/gdb.dwarf2/fission-reread.exp @@ -30,17 +30,20 @@ set additional_flags [gdb_target_symbol_prefix_flags_asm] standard_testfile .S -set dwo [standard_output_file "fission-reread.dwo"] +set obj [standard_output_file "${testfile}.o"] +set dwo [standard_output_file "${testfile}.dwo"] -set options [list] -lappend options nodebug +set options [list nodebug] if { $additional_flags != "" } { lappend options $additional_flags } -lappend options additional_flags=-DDWO=$dwo -if [build_executable_from_fission_assembler \ - "$testfile.exp" "$binfile" "$srcfile" $options] { +set dwo_options $options +lappend dwo_options split-dwo +lappend dwo_options additional_flags=-DDWO=$dwo + +if [build_executable_and_dwo_files "$testfile.exp" "${binfile}" $options \ + [list $srcfile $dwo_options $obj]] { return -1 } diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp index b9a493863a..f6a35749ca 100644 --- a/gdb/testsuite/lib/dwarf.exp +++ b/gdb/testsuite/lib/dwarf.exp @@ -28,39 +28,12 @@ proc dwarf2_support {} { return 0 } -# Build an executable from a fission-based .S file. -# This handles the extra work of splitting the .o into non-dwo and dwo -# pieces, making sure the .dwo is available if we're using cc-with-tweaks.sh -# to build a .dwp file. -# The arguments and results are the same as for build_executable. +# Use 'objcopy --extract-dwo to extract DWO information from +# OBJECT_FILE and place it into DWO_FILE. # -# Current restrictions: -# - only supports one source file -# - cannot be run on remote hosts - -proc build_executable_from_fission_assembler { testname executable sources options } { - verbose -log "build_executable_from_fission_assembler $testname $executable $sources $options" - if { [llength $sources] != 1 } { - error "Only one source file supported." - } - if [is_remote host] { - error "Remote hosts are not supported." - } - - global srcdir subdir - set source_file ${srcdir}/${subdir}/${sources} - set root_name [file rootname [file tail $source_file]] - set output_base [standard_output_file $root_name] - set object_file ${output_base}.o - set dwo_file ${output_base}.dwo - set object_options "object $options" +# Return 0 on success, otherwise, return -1. +proc extract_dwo_information { object_file dwo_file } { set objcopy [gdb_find_objcopy] - - set result [gdb_compile $source_file $object_file object $options] - if { "$result" != "" } { - return -1 - } - set command "$objcopy --extract-dwo $object_file $dwo_file" verbose -log "Executing $command" set result [catch "exec $command" output] @@ -68,19 +41,157 @@ proc build_executable_from_fission_assembler { testname executable sources optio if { $result == 1 } { return -1 } + return 0 +} - set command "$objcopy --strip-dwo $object_file" +# Use 'objcopy --strip-dwo to remove DWO information from +# FILENAME. +# +# Return 0 on success, otherwise, return -1. +proc strip_dwo_information { filename } { + set objcopy [gdb_find_objcopy] + set command "$objcopy --strip-dwo $filename" verbose -log "Executing $command" set result [catch "exec $command" output] verbose -log "objcopy --strip-dwo output: $output" if { $result == 1 } { return -1 } + return 0 +} - set result [gdb_compile $object_file $executable executable $options] - if { "$result" != "" } { +# Build an executable, with the debug information split out into a +# separate .dwo file. +# +# This function is based on build_executable_from_specs in +# lib/gdb.exp, but with threading support, and rust support removed. +# +# TESTNAME is the name of the test; this is passed to 'untested' if +# something fails. +# +# EXECUTABLE is the executable to create, this can be an absolute +# path, or a relative path, in which case the EXECUTABLE will be +# created in the standard output directory. +# +# OPTIONS is passed to the final link, using gdb_compile. If OPTIONS +# contains any option that indicates threads is required, of if the +# option rust is included, then this function will return failure. +# +# ARGS is a series of lists. Each list is a spec for one source file +# that will be compiled to make EXECUTABLE. Each spec in ARGS has the +# form: +# [ SOURCE OPTIONS ] +# or: +# [ SOURCE OPTIONS OBJFILE ] +# +# Where SOURCE is the path to the source file to compile. This can be +# absolute, or relative to the standard global ${subdir}/${srcdir}/ +# path. +# +# OPTIONS are the options to use when compiling SOURCE into an object +# file. +# +# OBJFILE is optional, if present this is the name of the object file +# to create for SOURCE. If this is not provided then a suitable name +# will be auto-generated. +# +# If OPTIONS contains the option 'split-dwo' then the debug +# information is extracted from the object file created by compiling +# SOURCE and placed into a file with a dwo extension. The name of +# this file is generated based on the name of the object file that was +# created (with the .o replaced with .dwo). +proc build_executable_and_dwo_files { testname executable options args } { + global subdir + global srcdir + + if { ! [regexp "^/" "$executable"] } then { + set binfile [standard_output_file $executable] + } else { + set binfile $executable + } + + set info_options "" + if { [lsearch -exact $options "c++"] >= 0 } { + set info_options "c++" + } + if [get_compiler_info ${info_options}] { + return -1 + } + + set func gdb_compile + if {[lsearch -regexp $options \ + {^(pthreads|shlib|shlib_pthreads|openmp)$}] != -1} { + # Currently don't support compiling thread based tests here. + # If this is required then look to build_executable_from_specs + # for inspiration. return -1 } + if {[lsearch -exact $options rust] != -1} { + # Currently don't support compiling rust tests here. If this + # is required then look to build_executable_from_specs for + # inspiration. + return -1 + } + + # Must be run on local host due to use of objcopy. + if [is_remote host] { + return -1 + } + + set objects {} + set i 0 + foreach spec $args { + if {[llength $spec] < 2} { + error "invalid spec length" + return -1 + } + + verbose -log "APB: SPEC: $spec" + + set s [lindex $spec 0] + set local_options [lindex $spec 1] + + if { ! [regexp "^/" "$s"] } then { + set s "$srcdir/$subdir/$s" + } + + if {[llength $spec] > 2} { + set objfile [lindex $spec 2] + } else { + set objfile "${binfile}${i}.o" + incr i + } + + if { [$func "${s}" "${objfile}" object $local_options] != "" } { + untested $testname + return -1 + } + + lappend objects "$objfile" + + if {[lsearch -exact $local_options "split-dwo"] >= 0} { + # Split out the DWO file. + set dwo_file "[file rootname ${objfile}].dwo" + + if { [extract_dwo_information $objfile $dwo_file] == -1 } { + untested $testname + return -1 + } + + if { [strip_dwo_information $objfile] == -1 } { + untested $testname + return -1 + } + } + } + + verbose -log "APB: OBJECTS = $objects" + + set ret [$func $objects "${binfile}" executable $options] + if { $ret != "" } { + untested $testname + return -1 + } return 0 } @@ -329,6 +440,14 @@ namespace eval Dwarf { # The address size for debug ranges section. variable _debug_ranges_64_bit + # The index into the .debug_addr section (used for fission + # generation). + variable _debug_addr_index + + # Flag, true if the current CU is contains fission information, + # otherwise false. + variable _cu_is_fission + proc _process_one_constant {name value} { variable _constants variable _AT @@ -486,6 +605,18 @@ namespace eval Dwarf { _op .${_cu_addr_size}byte $value } + DW_FORM_GNU_addr_index { + variable _debug_addr_index + variable _cu_addr_size + + _op .uleb128 ${_debug_addr_index} + incr _debug_addr_index + + _defer_output .debug_addr { + _op .${_cu_addr_size}byte $value + } + } + DW_FORM_data2 - DW_FORM_ref2 { _op .2byte $value @@ -553,7 +684,6 @@ namespace eval Dwarf { DW_FORM_strx3 - DW_FORM_strx4 - - DW_FORM_GNU_addr_index - DW_FORM_GNU_str_index - default { @@ -609,6 +739,9 @@ namespace eval Dwarf { DW_AT_name { return DW_FORM_string } + DW_AT_GNU_addr_base { + return DW_FORM_sec_offset + } } return "" } @@ -649,6 +782,8 @@ namespace eval Dwarf { # Handle macro attribute MACRO_AT_range. proc _handle_macro_at_range { attr_value } { + variable _cu_is_fission + if {[llength $attr_value] != 1} { error "usage: MACRO_AT_range { func }" } @@ -658,10 +793,14 @@ namespace eval Dwarf { set src ${srcdir}/${subdir}/${srcfile} set result [function_range $func $src] - _handle_attribute DW_AT_low_pc [lindex $result 0] \ - DW_FORM_addr + set form DW_FORM_addr + if { $_cu_is_fission } { + set form DW_FORM_GNU_addr_index + } + + _handle_attribute DW_AT_low_pc [lindex $result 0] $form _handle_attribute DW_AT_high_pc \ - "[lindex $result 0] + [lindex $result 1]" DW_FORM_addr + "[lindex $result 0] + [lindex $result 1]" $form } # Handle macro attribute MACRO_AT_func. @@ -945,6 +1084,18 @@ namespace eval Dwarf { _op .${addr_size}byte $argvec(size) } + DW_OP_GNU_addr_index { + variable _debug_addr_index + variable _cu_addr_size + + _op .uleb128 ${_debug_addr_index} + incr _debug_addr_index + + _defer_output .debug_addr { + _op .${_cu_addr_size}byte [lindex $line 1] + } + } + DW_OP_regx { _get_args $line $opcode register _op .uleb128 $argvec(register) @@ -1069,6 +1220,23 @@ namespace eval Dwarf { } } + # Return a label that references the current position in the + # .debug_addr table. When a user is creating split DWARF they + # will define two CUs, the first will be the split DWARF content, + # and the second will be the non-split stub CU. The split DWARF + # CU fills in the .debug_addr section, but the non-split CU + # includes a reference to the start of the section. The label + # returned by this proc provides that reference. + proc debug_addr_label {} { + variable _debug_addr_index + + set lbl [new_label "debug_addr_idx_${_debug_addr_index}_"] + _defer_output .debug_addr { + define_label $lbl + } + return $lbl + } + # Emit a DWARF CU. # OPTIONS is a list with an even number of elements containing # option-name and option-value pairs. @@ -1092,12 +1260,13 @@ namespace eval Dwarf { variable _cu_version variable _cu_addr_size variable _cu_offset_size + variable _cu_is_fission # Establish the defaults. set is_64 0 set _cu_version 4 set _cu_addr_size default - set fission 0 + set _cu_is_fission 0 set section ".debug_info" set _abbrev_section ".debug_abbrev" @@ -1107,7 +1276,7 @@ namespace eval Dwarf { is_64 { set is_64 $value } version { set _cu_version $value } addr_size { set _cu_addr_size $value } - fission { set fission $value } + fission { set _cu_is_fission $value } default { error "unknown option $name" } } } @@ -1119,7 +1288,7 @@ namespace eval Dwarf { } } set _cu_offset_size [expr { $is_64 ? 8 : 4 }] - if { $fission } { + if { $_cu_is_fission } { set section ".debug_info.dwo" set _abbrev_section ".debug_abbrev.dwo" } @@ -1199,12 +1368,13 @@ namespace eval Dwarf { variable _cu_version variable _cu_addr_size variable _cu_offset_size + variable _cu_is_fission # Establish the defaults. set is_64 0 set _cu_version 4 set _cu_addr_size default - set fission 0 + set _cu_is_fission 0 set section ".debug_types" set _abbrev_section ".debug_abbrev" @@ -1213,7 +1383,7 @@ namespace eval Dwarf { is_64 { set is_64 $value } version { set _cu_version $value } addr_size { set _cu_addr_size $value } - fission { set fission $value } + fission { set _cu_is_fission $value } default { error "unknown option $name" } } } @@ -1225,7 +1395,7 @@ namespace eval Dwarf { } } set _cu_offset_size [expr { $is_64 ? 8 : 4 }] - if { $fission } { + if { $_cu_is_fission } { set section ".debug_types.dwo" set _abbrev_section ".debug_abbrev.dwo" } @@ -2075,6 +2245,7 @@ namespace eval Dwarf { variable _line_saw_program variable _line_header_end_label variable _debug_ranges_64_bit + variable _debug_addr_index if {!$_initialized} { _read_constants @@ -2093,6 +2264,8 @@ namespace eval Dwarf { set _line_saw_program 0 set _debug_ranges_64_bit [is_64_target] + set _debug_addr_index 0 + # Not "uplevel" here, because we want to evaluate in this # namespace. This is somewhat bad because it means we can't # readily refer to outer variables.