diff options
Diffstat (limited to 'testsuite')
102 files changed, 5393 insertions, 0 deletions
diff --git a/testsuite/config/default.exp b/testsuite/config/default.exp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testsuite/config/default.exp diff --git a/testsuite/dwz.tests/cycle.c b/testsuite/dwz.tests/cycle.c new file mode 100644 index 0000000..4795a79 --- /dev/null +++ b/testsuite/dwz.tests/cycle.c @@ -0,0 +1,13 @@ +struct s; + +struct s { + struct s *p; +}; + +struct s var; + +int +main (void) +{ + return 0; +} diff --git a/testsuite/dwz.tests/cycle.sh b/testsuite/dwz.tests/cycle.sh new file mode 100644 index 0000000..ce42521 --- /dev/null +++ b/testsuite/dwz.tests/cycle.sh @@ -0,0 +1,36 @@ +readelf_flags="" +if readelf -h 2>&1 | grep -q "\-wN"; then + readelf_flags=-wN +fi + +cp $execs/cycle 1 + +# Using mode 3 in checksum_die_ref. +$execs/dwz-for-test 1 -o 1.z --devel-dump-dies 2> DUMP.1 +rm -f 1.z + +# Skipping mode 3 in checksum_die_ref. +$execs/dwz-for-test 1 -o 1.z --devel-dump-dies --devel-no-checksum-cycle-opt 2> DUMP.2 +rm -f 1.z + +# Verify that mode 3 and mode 4 have different checksums. +grep " s structure_type" DUMP.1 > LINE.1 +grep " s structure_type" DUMP.2 > LINE.2 +! diff -q LINE.1 LINE.2 +rm -f DUMP.1 DUMP.2 LINE.1 LINE.2 + +# Verify that dwz actually works with --devel-no-checksum-cycle-opt. +cp 1 2 +$execs/dwz-for-test -m 3 1 2 --devel-no-checksum-cycle-opt --devel-ignore-size + +cnt=$(readelf -wi 3 | grep -c "DW_AT_name.*: s$") +[ $cnt -eq 1 ] + +# Even with -wN readelf 2.38-15.fc37 follows and prints the contents +# of the alt file. So make sure it cannot do that by removing it. +rm 3 + +cnt=$(readelf -wi $readelf_flags 1 | grep -c "DW_AT_name.*: s$" || true) +[ $cnt -eq 0 ] + +rm -f 1 2 3 diff --git a/testsuite/dwz.tests/decl.cc b/testsuite/dwz.tests/decl.cc new file mode 100644 index 0000000..4953853 --- /dev/null +++ b/testsuite/dwz.tests/decl.cc @@ -0,0 +1,3 @@ +class ao_ref; + +ao_ref *p3; diff --git a/testsuite/dwz.tests/def.cc b/testsuite/dwz.tests/def.cc new file mode 100644 index 0000000..8645b9c --- /dev/null +++ b/testsuite/dwz.tests/def.cc @@ -0,0 +1,11 @@ +#include "def.h" + +ao_ref *p1; + +int +main (void) +{ + ao_ref *p1 = new ao_ref; + return 0; +} + diff --git a/testsuite/dwz.tests/def.h b/testsuite/dwz.tests/def.h new file mode 100644 index 0000000..dc3a602 --- /dev/null +++ b/testsuite/dwz.tests/def.h @@ -0,0 +1,10 @@ +class bla { + int a; + public: + bla() { a = 1; } +}; + +class ao_ref +{ + bla a; +}; diff --git a/testsuite/dwz.tests/def2.cc b/testsuite/dwz.tests/def2.cc new file mode 100644 index 0000000..794933f --- /dev/null +++ b/testsuite/dwz.tests/def2.cc @@ -0,0 +1,9 @@ +#include "def.h" + +ao_ref *p2; + +void +foo (void) +{ + p2 = new ao_ref; +} diff --git a/testsuite/dwz.tests/devel-ignore-locus.sh b/testsuite/dwz.tests/devel-ignore-locus.sh new file mode 100644 index 0000000..a8b2dcd --- /dev/null +++ b/testsuite/dwz.tests/devel-ignore-locus.sh @@ -0,0 +1,27 @@ +cp $execs/two-typedef 1 + +cnt=$(readelf -wi 1 \ + | grep 'DW_AT_name.*: aaa' \ + | wc -l) + +[ $cnt -eq 2 ] + +$execs/dwz-for-test 1 2>/dev/null + +cnt=$(readelf -wi 1 \ + | grep 'DW_AT_name.*: aaa' \ + | wc -l) + +[ $cnt -eq 2 ] + +cp $execs/two-typedef 1 + +$execs/dwz-for-test --devel-ignore-locus --devel-ignore-size 1 + +cnt=$(readelf -wi 1 \ + | grep 'DW_AT_name.*: aaa' \ + | wc -l) + +[ $cnt -eq 1 ] + +rm -f 1 diff --git a/testsuite/dwz.tests/devel-ignore-size.sh b/testsuite/dwz.tests/devel-ignore-size.sh new file mode 100644 index 0000000..a30684f --- /dev/null +++ b/testsuite/dwz.tests/devel-ignore-size.sh @@ -0,0 +1,29 @@ +cp $execs/min 1 + +cnt=$(readelf -wi 1 \ + | grep '(DW_TAG_partial_unit' \ + | wc -l) + +[ $cnt -eq 0 ] + +$execs/dwz-for-test 1 2>/dev/null + +cnt=$(readelf -wi 1 \ + | grep '(DW_TAG_partial_unit' \ + | wc -l) + +if [ $cnt -ne 0 ]; then + exit 77 +fi + +cp $execs/min 1 + +$execs/dwz-for-test --devel-ignore-size 1 + +cnt=$(readelf -wi 1 \ + | grep '(DW_TAG_partial_unit' \ + | wc -l) + +[ $cnt -gt 0 ] + +rm -f 1 diff --git a/testsuite/dwz.tests/devel-trace.sh b/testsuite/dwz.tests/devel-trace.sh new file mode 100644 index 0000000..50c4a3d --- /dev/null +++ b/testsuite/dwz.tests/devel-trace.sh @@ -0,0 +1,5 @@ +cp $execs/hello 1 + +$execs/dwz-for-test --devel-trace 1 2>/dev/null + +rm -f 1 diff --git a/testsuite/dwz.tests/dw2-skip-prologue.S b/testsuite/dwz.tests/dw2-skip-prologue.S new file mode 100644 index 0000000..4d2e198 --- /dev/null +++ b/testsuite/dwz.tests/dw2-skip-prologue.S @@ -0,0 +1,403 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011-2019 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 <http://www.gnu.org/licenses/>. + + This was copied from the git://sourceware.org/git/binutils-gdb.git + repository, file gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.S. */ + +#if PTRBITS == 64 +# define PTRBYTE .8byte +#elif PTRBITS == 32 +# define PTRBYTE .4byte +#else +# error "Unsupported pointer size" +#endif + + .section .debug_info +.Lcu1_begin: + /* CU header */ + .4byte .Lcu1_end - .Lcu1_start /* Length of Compilation Unit */ +.Lcu1_start: + .2byte 2 /* DWARF Version */ + .4byte .Labbrev1_begin /* Offset into abbrev section */ + .byte PTRBITS / 8 /* Pointer size */ + + /* CU die */ + .uleb128 1 /* Abbrev: DW_TAG_compile_unit */ + .4byte .Lline1_begin /* DW_AT_stmt_list */ + PTRBYTE func_start /* DW_AT_low_pc */ + PTRBYTE func_end /* DW_AT_high_pc */ + .ascii "main.c\0" /* DW_AT_name */ + .ascii "GNU C 4.5.0\0" /* DW_AT_producer must be >= 4.5 */ + .byte 2 /* DW_AT_language (DW_LANG_C) */ + + .uleb128 2 /* Abbrev: DW_TAG_subprogram */ + .byte 1 /* DW_AT_external */ + .ascii "func\0" /* DW_AT_name */ + .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */ + PTRBYTE func_start /* DW_AT_low_pc */ + PTRBYTE func_end /* DW_AT_high_pc */ + +/* GDB `has_loclist' detection of -O2 -g code needs to see a DW_AT_location + location list. There may exist -O2 -g CUs still not needing/using any such + location list - exactly like this CU. Make one up. */ + + .uleb128 0x7 /* (DIE (0x42) DW_TAG_formal_parameter) */ + .ascii "param\0" /* DW_AT_name */ + .4byte .Ltype_int - .Lcu1_begin /* DW_AT_type */ + .4byte loclist /* DW_AT_location */ + + .uleb128 4 /* Abbrev: DW_TAG_inlined_subroutine */ + .ascii "inlined\0" /* DW_AT_name */ + PTRBYTE func0 /* DW_AT_low_pc */ + PTRBYTE func1 /* DW_AT_high_pc */ + .byte 3 /* DW_AT_inline (DW_INL_declared_inlined) */ + .byte 1 /* DW_AT_call_file */ + .byte 8 /* DW_AT_call_line */ + + .uleb128 4 /* Abbrev: DW_TAG_inlined_subroutine */ + .ascii "inlined2\0" /* DW_AT_name */ + PTRBYTE func2 /* DW_AT_low_pc */ + PTRBYTE func3 /* DW_AT_high_pc */ + .byte 3 /* DW_AT_inline (DW_INL_declared_inlined) */ + .byte 1 /* DW_AT_call_file */ + .byte 11 /* DW_AT_call_line */ + +#ifdef INLINED + .uleb128 4 /* Abbrev: DW_TAG_inlined_subroutine */ + .ascii "otherinline\0" /* DW_AT_name */ + PTRBYTE func3 /* DW_AT_low_pc */ + PTRBYTE func_end /* DW_AT_high_pc */ + .byte 3 /* DW_AT_inline (DW_INL_declared_inlined) */ + .byte 1 /* DW_AT_call_file */ + .byte 9 /* DW_AT_call_line */ +#endif + +#ifdef LEXICAL + .uleb128 5 /* Abbrev: DW_TAG_lexical_block */ + PTRBYTE func3 /* DW_AT_low_pc */ + PTRBYTE func_end /* DW_AT_high_pc */ + + /* GDB would otherwise ignore the DW_TAG_lexical_block. */ + .uleb128 6 /* Abbrev: DW_TAG_variable */ + .ascii "lexicalvar\0" /* DW_AT_name */ + .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */ + + .byte 0 /* End of children of DW_TAG_lexical_block */ +#endif + + .byte 0 /* End of children of DW_TAG_subprogram */ + +/* Simulate `fund' is also named `func' so that the function name matches and + fund's SAL is not discarded in expand_line_sal_maybe. */ + + .uleb128 2 /* Abbrev: DW_TAG_subprogram */ + .byte 1 /* DW_AT_external */ + .ascii "func\0" /* DW_AT_name */ + .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */ + PTRBYTE fund_start /* DW_AT_low_pc */ + PTRBYTE fund_end /* DW_AT_high_pc */ + + .byte 0 /* End of children of DW_TAG_subprogram */ + +.Ltype_int: + .uleb128 3 /* Abbrev: DW_TAG_base_type */ + .ascii "int\0" /* DW_AT_name */ + .byte 4 /* DW_AT_byte_size */ + .byte 5 /* DW_AT_encoding */ + + .byte 0 /* End of children of CU */ + +.Lcu1_end: + + .section .debug_loc +loclist: + /* Reset the location list base address first. */ + .4byte -1, 0 + + PTRBYTE func_start, func_end + .2byte 2f-1f +1: .byte 0x50 /* DW_OP_reg0 */ +2: + /* Location list end. */ + .4byte 0, 0 + +/* Abbrev table */ + .section .debug_abbrev +.Labbrev1_begin: + .uleb128 1 /* Abbrev code */ + .uleb128 0x11 /* DW_TAG_compile_unit */ + .byte 1 /* has_children */ + .uleb128 0x10 /* DW_AT_stmt_list */ + .uleb128 0x6 /* DW_FORM_data4 */ + .uleb128 0x11 /* DW_AT_low_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x12 /* DW_AT_high_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x25 /* DW_AT_producer */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x13 /* DW_AT_language */ + .uleb128 0xb /* DW_FORM_data1 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 2 /* Abbrev code */ + .uleb128 0x2e /* DW_TAG_subprogram */ + .byte 1 /* has_children */ + .uleb128 0x3f /* DW_AT_external */ + .uleb128 0xc /* DW_FORM_flag */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x11 /* DW_AT_low_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x12 /* DW_AT_high_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 3 /* Abbrev code */ + .uleb128 0x24 /* DW_TAG_base_type */ + .byte 0 /* has_children */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0xb /* DW_AT_byte_size */ + .uleb128 0xb /* DW_FORM_data1 */ + .uleb128 0x3e /* DW_AT_encoding */ + .uleb128 0xb /* DW_FORM_data1 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 4 /* Abbrev code */ + .uleb128 0x1d /* DW_TAG_inlined_subroutine */ + .byte 0 /* has_children */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x11 /* DW_AT_low_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x12 /* DW_AT_high_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x20 /* DW_AT_inline */ + .uleb128 0xb /* DW_FORM_data1 */ + .uleb128 0x58 /* DW_AT_call_file */ + .uleb128 0xb /* DW_FORM_data1 */ + .uleb128 0x59 /* DW_AT_call_line */ + .uleb128 0xb /* DW_FORM_data1 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 5 /* Abbrev code */ + .uleb128 0x0b /* DW_TAG_lexical_block */ + .byte 1 /* has_children */ + .uleb128 0x11 /* DW_AT_low_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x12 /* DW_AT_high_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 6 /* Abbrev code */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 0x7 /* (abbrev code) */ + .uleb128 0x5 /* (TAG: DW_TAG_formal_parameter) */ + .byte 0x0 /* DW_children_no */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x49 /* (DW_AT_type) */ + .uleb128 0x13 /* (DW_FORM_ref4) */ + .uleb128 0x02 /* (DW_AT_location) */ + .uleb128 0x06 /* (DW_FORM_data4) */ + .byte 0x0 + .byte 0x0 + + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + +/* Line table */ + .section .debug_line +.Lline1_begin: + .4byte .Lline1_end - .Lline1_start /* Initial length */ +.Lline1_start: + .2byte 2 /* Version */ + .4byte .Lline1_lines - .Lline1_hdr /* header_length */ +.Lline1_hdr: + .byte 1 /* Minimum insn length */ + .byte 1 /* default_is_stmt */ + .byte 1 /* line_base */ + .byte 1 /* line_range */ + .byte 0x10 /* opcode_base */ + + /* Standard lengths */ + .byte 0 + .byte 1 + .byte 1 + .byte 1 + .byte 1 + .byte 0 + .byte 0 + .byte 0 + .byte 1 + .byte 0 + .byte 0 + .byte 1 + .byte 0 + .byte 0 + .byte 0 + + /* Include directories */ + .byte 0 + + /* File names */ + .ascii "main.c\0" + .uleb128 0 + .uleb128 0 + .uleb128 0 + + .ascii "other.c\0" + .uleb128 0 + .uleb128 0 + .uleb128 0 + + .byte 0 + +.Lline1_lines: + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + PTRBYTE func_start + .byte 3 /* DW_LNS_advance_line */ + .sleb128 4 /* ... to 5 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + PTRBYTE func0 + .byte 4 /* DW_LNS_set_file */ + .uleb128 2 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 -4 /* ... to 1 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + PTRBYTE func1 + .byte 4 /* DW_LNS_set_file */ + .uleb128 1 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 8 /* ... to 9 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + PTRBYTE func2 + .byte 4 /* DW_LNS_set_file */ + .uleb128 2 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 -8 /* ... to 1 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + PTRBYTE func3 + .byte 4 /* DW_LNS_set_file */ + .uleb128 1 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 8 /* ... to 9 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + PTRBYTE func_end + +/* Equivalent copy but renamed s/func/fund/. */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + PTRBYTE fund_start + .byte 3 /* DW_LNS_advance_line */ + .sleb128 -4 /* ... to 5 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + PTRBYTE fund0 + .byte 4 /* DW_LNS_set_file */ + .uleb128 2 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 -4 /* ... to 1 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + PTRBYTE fund1 + .byte 4 /* DW_LNS_set_file */ + .uleb128 1 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 8 /* ... to 9 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + PTRBYTE fund2 + .byte 4 /* DW_LNS_set_file */ + .uleb128 2 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 -8 /* ... to 1 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + PTRBYTE fund3 + .byte 4 /* DW_LNS_set_file */ + .uleb128 1 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 8 /* ... to 9 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + PTRBYTE fund_end + +/* Line numbering end. */ + + .byte 0 /* DW_LNE_end_of_sequence */ + .uleb128 1 + .byte 1 + +.Lline1_end: + .section .note.GNU-stack,"",@progbits diff --git a/testsuite/dwz.tests/dw2-skip-prologue.c b/testsuite/dwz.tests/dw2-skip-prologue.c new file mode 100644 index 0000000..34b0a7c --- /dev/null +++ b/testsuite/dwz.tests/dw2-skip-prologue.c @@ -0,0 +1,61 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011-2019 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 <http://www.gnu.org/licenses/>. + + This was copied from the git://sourceware.org/git/binutils-gdb.git + repository, file gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.c. */ + +static volatile int v; + +asm ("func_start: .globl func_start\n"); +static int +func (void) +{ + v++; +asm ("func0: .globl func0\n"); + v++; +asm ("func1: .globl func1\n"); + v++; +asm ("func2: .globl func2\n"); + v++; +asm ("func3: .globl func3\n"); + return v; +} +asm ("func_end: .globl func_end\n"); + +/* Equivalent copy but renamed s/func/fund/. */ + +asm ("fund_start: .globl fund_start\n"); +static int +fund (void) +{ + v++; +asm ("fund0: .globl fund0\n"); + v++; +asm ("fund1: .globl fund1\n"); + v++; +asm ("fund2: .globl fund2\n"); + v++; +asm ("fund3: .globl fund3\n"); + return v; +} +asm ("fund_end: .globl fund_end\n"); + +int +main (void) +{ + return func () + fund (); +} diff --git a/testsuite/dwz.tests/dwz-tests.exp b/testsuite/dwz.tests/dwz-tests.exp new file mode 100644 index 0000000..811767f --- /dev/null +++ b/testsuite/dwz.tests/dwz-tests.exp @@ -0,0 +1,145 @@ +set tests [find $srcdir/$subdir *.sh] + +set pwd [pwd] + +set env(PATH) $srcdir/scripts:$::env(PATH) +set env(execs) $pwd + +exec mkdir -p $pwd/testsuite/dwz.tests/execs +exec $srcdir/scripts/xunzip-dir.sh \ + $srcdir/dwz.tests/execs.xz \ + $pwd/testsuite/dwz.tests/execs + +foreach test $tests { + global runtests + + set basename [exec basename $test] + + if ![runtest_file_p $runtests $basename] { + continue + } + + set required_execs [] + if { $basename == "pr24173.sh" } { + lappend required_execs "py-section-script" + } + if { $basename == "pr24341.sh" } { + if { [catch {exec readelf -wi min | grep DW_AT_name | grep -c / } matches] } { + # Some error occurred in the supported test, f.i. DWARF in min + # unsupported by readelf. + unsupported "$test" + continue + } + if { $matches != 2 } { + # The exec min is used for the regression test for pr24341, but it + # only functions as such if the DWARF only contains the CUs of the + # test-case itself. + unsupported "$test" + continue + } + } + if { $basename == "pr24172.sh" } { + if { ![istarget x86_64-*-*] } { + unsupported "$test" + continue + } + lappend required_execs "dw2-skip-prologue" + } + if { $basename == "pr24170.sh" } { + lappend required_execs "implptr-64bit-d2o4a8r8t0" + } + if { $basename == "gold-gdb-index.sh" } { + lappend required_execs "hello-gold-gdb-index" + } + if { $basename == "pr24747.sh" } { + lappend required_execs "start-gold" + } + if { $basename == "pr24771.sh" } { + lappend required_execs "hello-gnu-pubnames" + } + if { $basename == "pr24823.sh" } { + lappend required_execs "varval" + } + if { ![istarget x86_64-*-*] } { + if { $basename == "pr24468.sh" } { + unsupported "$test" + continue + } + if { $basename == "ld-2.26.1-multifile.sh" } { + unsupported "$test" + continue + } + } + if { $basename == "gdb-add-index.sh" } { + if { [catch { exec which gdb-add-index } ] } { + unsupported "$test" + continue + } + } + if { [istarget mips*-*-*] } { + # elfutils don't have a MIPS backend (PR elfutils/24795), so eu-strip + # doesn't work as expected. + if { $basename == "eu-strip-unstrip.sh" || \ + $basename == "eu-strip-unstrip-multifile.sh" || \ + $basename == "pr24173.sh" } { + unsupported "$test" + continue + } + } + if { $basename == "pr25109.sh" } { + lappend required_execs no-multifile-prop + } + if { $basename == "pr27463.sh" } { + lappend required_execs unavailable-dwarf-piece + } + + set unsupported 0 + foreach required_exec $required_execs { + set exists [file exists $required_exec] + if { $exists == 0 } { + set unsupported 1 + break + } + set size [file size $required_exec] + if { $size == 0 } { + set unsupported 1 + break + } + } + if { $unsupported == 1 } { + unsupported "$test" + continue + } + + set dir $pwd/tmp.$basename + exec rm -Rf $dir + exec mkdir $dir + + cd $dir + if { [catch { exec sh -e $test } msg] } { + if { [lindex $::errorCode 0] == "CHILDSTATUS" && \ + [lindex $::errorCode 2] == 77 } { + unsupported "$test" + exec rm -Rf $dir + } else { + puts "$msg" + fail "$test" + } + } else { + if { [file exists dwz.info ] } { + set info [exec cat dwz.info] + verbose -log "$test:" 1 + verbose -log "$info" 1 + exec rm -f dwz.info + } + set file_list [glob -nocomplain "$dir/*"] + if {[llength $file_list] != 0} { + puts "$dir is not empty" + fail "$test" + } else { + pass "$test" + exec rm -Rf $dir + } + } + cd $pwd +} diff --git a/testsuite/dwz.tests/dwz.sh b/testsuite/dwz.tests/dwz.sh new file mode 100644 index 0000000..1cb16d2 --- /dev/null +++ b/testsuite/dwz.tests/dwz.sh @@ -0,0 +1,7 @@ +cp $execs/dwz-for-test 1 + +dwz 1 + +smaller-than.sh 1 $execs/dwz-for-test + +rm -f 1 diff --git a/testsuite/dwz.tests/eu-strip-unstrip-multifile.sh b/testsuite/dwz.tests/eu-strip-unstrip-multifile.sh new file mode 100644 index 0000000..afe0994 --- /dev/null +++ b/testsuite/dwz.tests/eu-strip-unstrip-multifile.sh @@ -0,0 +1,18 @@ +cp $execs/hello 1 +cp $execs/hello 2 + +eu-strip 1 -o 1.stripped -f 1.debug +eu-strip 2 -o 2.stripped -f 2.debug + +dwz -m 3 1.debug 2.debug + +eu-unstrip 1.stripped 1.debug -o 1.unstripped +eu-unstrip 2.stripped 2.debug -o 2.unstripped + +smaller-than.sh 1.unstripped 1 +smaller-than.sh 2.unstripped 2 + +[ "$(gnu-debugaltlink-name.sh 1.unstripped)" = "3" ] +[ "$(gnu-debugaltlink-name.sh 2.unstripped)" = "3" ] + +rm -f 1 1.debug 1.stripped 1.unstripped 2 2.debug 2.stripped 2.unstripped 3 diff --git a/testsuite/dwz.tests/eu-strip-unstrip.sh b/testsuite/dwz.tests/eu-strip-unstrip.sh new file mode 100644 index 0000000..ce3adad --- /dev/null +++ b/testsuite/dwz.tests/eu-strip-unstrip.sh @@ -0,0 +1,11 @@ +cp $execs/hello 1 + +eu-strip 1 -o 1.stripped -f 1.debug + +dwz 1.debug + +eu-unstrip 1.stripped 1.debug -o 1.unstripped + +smaller-than.sh 1.unstripped 1 + +rm -f 1 1.debug 1.stripped 1.unstripped diff --git a/testsuite/dwz.tests/execs.xz/hello-ld-2.26.1.xz b/testsuite/dwz.tests/execs.xz/hello-ld-2.26.1.xz Binary files differnew file mode 100755 index 0000000..3514195 --- /dev/null +++ b/testsuite/dwz.tests/execs.xz/hello-ld-2.26.1.xz diff --git a/testsuite/dwz.tests/execs.xz/hello-leap-15.0.xz b/testsuite/dwz.tests/execs.xz/hello-leap-15.0.xz Binary files differnew file mode 100755 index 0000000..598c88e --- /dev/null +++ b/testsuite/dwz.tests/execs.xz/hello-leap-15.0.xz diff --git a/testsuite/dwz.tests/gdb-add-index.sh b/testsuite/dwz.tests/gdb-add-index.sh new file mode 100644 index 0000000..3095efb --- /dev/null +++ b/testsuite/dwz.tests/gdb-add-index.sh @@ -0,0 +1,15 @@ +cp $execs/hello 1 + +# Redirect gdb-add-index stderr to stdout. +# https://sourceware.org/bugzilla/show_bug.cgi?id=29316 +gdb-add-index 1 2>&1 + +readelf -S 1 | grep -q '\.gdb_index' + +dwz 1 -o 2 + +readelf -S 2 | grep -q '\.gdb_index' + +smaller-than.sh 2 1 + +rm -f 1 2 diff --git a/testsuite/dwz.tests/gold-gdb-index.sh b/testsuite/dwz.tests/gold-gdb-index.sh new file mode 100644 index 0000000..eb2a164 --- /dev/null +++ b/testsuite/dwz.tests/gold-gdb-index.sh @@ -0,0 +1,7 @@ +cp ../hello-gold-gdb-index 1 + +dwz 1 + +smaller-than.sh 1 ../hello-gold-gdb-index + +rm -f 1 diff --git a/testsuite/dwz.tests/hardlink-multifile.sh b/testsuite/dwz.tests/hardlink-multifile.sh new file mode 100644 index 0000000..160a7ed --- /dev/null +++ b/testsuite/dwz.tests/hardlink-multifile.sh @@ -0,0 +1,15 @@ +cp $execs/hello 1 +ln 1 2 +cp $execs/hello 3 + +dwz -h -m 4 1 2 3 + +hardlinks-p.sh 1 2 + +smaller-than.sh 1 $execs/hello +smaller-than.sh 3 $execs/hello + +[ "$(gnu-debugaltlink-name.sh 1)" = "4" ] +[ "$(gnu-debugaltlink-name.sh 3)" = "4" ] + +rm -f 1 2 3 4 diff --git a/testsuite/dwz.tests/hardlink.sh b/testsuite/dwz.tests/hardlink.sh new file mode 100644 index 0000000..3a956b2 --- /dev/null +++ b/testsuite/dwz.tests/hardlink.sh @@ -0,0 +1,11 @@ +cp $execs/hello 1 +ln 1 2 + +dwz -h 1 2 + +smaller-than.sh 1 $execs/hello +smaller-than.sh 2 $execs/hello + +hardlinks-p.sh 1 2 + +rm -f 1 2 diff --git a/testsuite/dwz.tests/hello.c b/testsuite/dwz.tests/hello.c new file mode 100644 index 0000000..82d070e --- /dev/null +++ b/testsuite/dwz.tests/hello.c @@ -0,0 +1,8 @@ +#include <stdio.h> + +int +main (void) +{ + printf ("hello\n"); + return 0; +} diff --git a/testsuite/dwz.tests/help.sh b/testsuite/dwz.tests/help.sh new file mode 100644 index 0000000..b4d5e28 --- /dev/null +++ b/testsuite/dwz.tests/help.sh @@ -0,0 +1,13 @@ +cp $execs/hello 1 + +if dwz -? 1 2> dwz.err; status=$?; then + true +fi + +[ $status -eq 1 ] + +grep -q "Usage:" dwz.err + +cmp 1 $execs/hello + +rm -f 1 dwz.err diff --git a/testsuite/dwz.tests/illegal-option.sh b/testsuite/dwz.tests/illegal-option.sh new file mode 100644 index 0000000..f767f4c --- /dev/null +++ b/testsuite/dwz.tests/illegal-option.sh @@ -0,0 +1,25 @@ +cp $execs/hello 1 + +if dwz -x 1 2> dwz.err; status=$?; then + true +fi + +[ $status -eq 1 ] + +grep -q ": invalid option -- 'x'" dwz.err +grep -q "Usage:" dwz.err + +cmp 1 $execs/hello + +if dwz --x 1 2> dwz.err; status=$?; then + true +fi + +[ $status -eq 1 ] + +grep -q ": unrecognized option '--x'" dwz.err +grep -q "Usage:" dwz.err + +cmp 1 $execs/hello + +rm -f 1 dwz.err diff --git a/testsuite/dwz.tests/implptr-64bit-d2o4a8r8t0.S b/testsuite/dwz.tests/implptr-64bit-d2o4a8r8t0.S new file mode 100644 index 0000000..08e1563 --- /dev/null +++ b/testsuite/dwz.tests/implptr-64bit-d2o4a8r8t0.S @@ -0,0 +1,157 @@ +/* This was generated using git://sourceware.org/git/binutils-gdb.git + repository, file gdb/testsuite/gdb.dwarf2/implptr-64bit.exp. */ + .section .debug_info +.Lcu1_begin: + .4byte .Lcu1_end - .Lcu1_start +.Lcu1_start: + .2byte 2 /* Version */ + .4byte .Labbrev1_begin /* Abbrevs */ + .byte 8 /* Pointer size */ + .uleb128 2 /* Abbrev (DW_TAG_compile_unit) */ + .ascii "GNU C 4.4.3\0" + .sleb128 0x0001 + .ascii "1.c\0" +.Llabel3: + .uleb128 3 /* Abbrev (DW_TAG_base_type) */ + .sleb128 4 + .sleb128 0x5 + .ascii "int\0" +.Llabel1: + .uleb128 4 /* Abbrev (DW_TAG_structure_type) */ + .ascii "s\0" + .sleb128 4 + .uleb128 5 /* Abbrev (DW_TAG_member) */ + .ascii "f\0" + .4byte .Llabel3 - .Lcu1_begin + .byte 0 + .byte 0x0 /* Terminate children */ +.Llabel4: + .uleb128 6 /* Abbrev (DW_TAG_pointer_type) */ + .sleb128 8 + .4byte .Llabel1 - .Lcu1_begin +.Llabel2: + .uleb128 7 /* Abbrev (DW_TAG_variable) */ + .ascii "v\0" + .uleb128 .Lexpr_end6 - .Lexpr_start5/* expression */ +.Lexpr_start5: + .byte 0x9e /* DW_OP_implicit_value */ + .uleb128 .Lvalue_end8 - .Lvalue_start7 +.Lvalue_start7: + .byte 0x1 + .byte 0x1 + .byte 0x1 + .byte 0x1 +.Lvalue_end8: +.Lexpr_end6: + .8byte .Llabel1 - .Lcu1_begin + .uleb128 8 /* Abbrev (DW_TAG_subprogram) */ + .ascii "main\0" + .8byte main + .8byte main+0x100 + .8byte .Llabel3 + .byte 1 + .uleb128 9 /* Abbrev (DW_TAG_variable) */ + .ascii "p\0" + .uleb128 .Lexpr_end10 - .Lexpr_start9/* expression */ +.Lexpr_start9: + .byte 0xf2 /* DW_OP_GNU_implicit_pointer */ + .8byte .Llabel2 + .sleb128 0 +.Lexpr_end10: + .8byte .Llabel4 - .Lcu1_begin + .byte 0x0 /* Terminate children */ + .byte 0x0 /* Terminate children */ +.Lcu1_end: + .section .debug_abbrev +.Labbrev1_begin: + .uleb128 2 /* Abbrev start */ + .uleb128 0x11 /* DW_TAG_compile_unit */ + .byte 1 /* has_children */ + .uleb128 0x25 /* DW_AT_producer */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x13 /* DW_AT_language */ + .uleb128 0x0d /* DW_FORM_sdata */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 3 /* Abbrev start */ + .uleb128 0x24 /* DW_TAG_base_type */ + .byte 0 /* has_children */ + .uleb128 0x0b /* DW_AT_byte_size */ + .uleb128 0x0d /* DW_FORM_sdata */ + .uleb128 0x3e /* DW_AT_encoding */ + .uleb128 0x0d /* DW_FORM_sdata */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 4 /* Abbrev start */ + .uleb128 0x13 /* DW_TAG_structure_type */ + .byte 1 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x0b /* DW_AT_byte_size */ + .uleb128 0x0d /* DW_FORM_sdata */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 5 /* Abbrev start */ + .uleb128 0x0d /* DW_TAG_member */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x38 /* DW_AT_data_member_location */ + .uleb128 0x0b /* DW_FORM_data1 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 6 /* Abbrev start */ + .uleb128 0x0f /* DW_TAG_pointer_type */ + .byte 0 /* has_children */ + .uleb128 0x0b /* DW_AT_byte_size */ + .uleb128 0x0d /* DW_FORM_sdata */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 7 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x09 /* SPECIAL_expr */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x14 /* DW_FORM_ref8 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 8 /* Abbrev start */ + .uleb128 0x2e /* DW_TAG_subprogram */ + .byte 1 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x11 /* DW_AT_low_pc */ + .uleb128 0x01 /* DW_FORM_addr */ + .uleb128 0x12 /* DW_AT_high_pc */ + .uleb128 0x01 /* DW_FORM_addr */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x10 /* DW_FORM_ref_addr */ + .uleb128 0x3f /* DW_AT_external */ + .uleb128 0x0c /* DW_FORM_flag */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 9 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x09 /* SPECIAL_expr */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x14 /* DW_FORM_ref8 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .section .note.GNU-stack,"",@progbits diff --git a/testsuite/dwz.tests/ld-2.26.1-multifile.sh b/testsuite/dwz.tests/ld-2.26.1-multifile.sh new file mode 100644 index 0000000..a63253c --- /dev/null +++ b/testsuite/dwz.tests/ld-2.26.1-multifile.sh @@ -0,0 +1,14 @@ +exec=../testsuite/dwz.tests/execs/hello-ld-2.26.1 + +cp $exec 1 +cp 1 2 + +dwz -m 3 1 2 + +smaller-than.sh 1 $exec +smaller-than.sh 2 $exec + +[ "$(gnu-debugaltlink-name.sh 1)" = "3" ] +[ "$(gnu-debugaltlink-name.sh 2)" = "3" ] + +rm -f 1 2 3 diff --git a/testsuite/dwz.tests/low-mem-die-limit-0.sh b/testsuite/dwz.tests/low-mem-die-limit-0.sh new file mode 100644 index 0000000..7105431 --- /dev/null +++ b/testsuite/dwz.tests/low-mem-die-limit-0.sh @@ -0,0 +1,13 @@ +cp $execs/hello 1 + +$execs/dwz-for-test \ + -l0 \ + --devel-trace \ + 1 \ + 2> dwz.err + +if grep -q "Compressing 1$" dwz.err; then + exit 1 +fi + +rm -f 1 dwz.err diff --git a/testsuite/dwz.tests/low-mem-die-limit-at-limit-multifile.sh b/testsuite/dwz.tests/low-mem-die-limit-at-limit-multifile.sh new file mode 100644 index 0000000..ece4fd5 --- /dev/null +++ b/testsuite/dwz.tests/low-mem-die-limit-at-limit-multifile.sh @@ -0,0 +1,23 @@ +cp $execs/hello 1 +cp 1 2 + +count=$(readelf -wi 1 \ + | grep '(DW_TAG' \ + | wc -l) +limit=$count + +if $execs/dwz-for-test \ + -l$limit \ + --devel-trace \ + -m 3 1 2 \ + 2> dwz.err; status=$?; then + true +fi + +if grep -q "Hit low-mem die-limit" dwz.err; then + exit 1 +fi + +[ $status -eq 0 ] + +rm -f 1 2 3 dwz.err diff --git a/testsuite/dwz.tests/low-mem-die-limit-at-limit.sh b/testsuite/dwz.tests/low-mem-die-limit-at-limit.sh new file mode 100644 index 0000000..03ff273 --- /dev/null +++ b/testsuite/dwz.tests/low-mem-die-limit-at-limit.sh @@ -0,0 +1,18 @@ +cp $execs/hello 1 + +count=$(readelf -wi 1 \ + | grep '(DW_TAG' \ + | wc -l) +limit=$count + +$execs/dwz-for-test \ + -l$limit \ + --devel-trace \ + 1 \ + 2> dwz.err + +if grep -q "Compressing 1 in low-mem mode" dwz.err; then + exit 1 +fi + +rm -f 1 dwz.err diff --git a/testsuite/dwz.tests/low-mem-die-limit-none.sh b/testsuite/dwz.tests/low-mem-die-limit-none.sh new file mode 100644 index 0000000..20b8cad --- /dev/null +++ b/testsuite/dwz.tests/low-mem-die-limit-none.sh @@ -0,0 +1,13 @@ +cp $execs/hello 1 + +$execs/dwz-for-test \ + -lnone \ + --devel-trace \ + 1 \ + 2> dwz.err + +if grep -q "Compressing 1 in low-mem mode" dwz.err; then + exit 1 +fi + +rm -f 1 dwz.err diff --git a/testsuite/dwz.tests/low-mem-die-limit-one-above.sh b/testsuite/dwz.tests/low-mem-die-limit-one-above.sh new file mode 100644 index 0000000..9b9a6ff --- /dev/null +++ b/testsuite/dwz.tests/low-mem-die-limit-one-above.sh @@ -0,0 +1,18 @@ +cp $execs/hello 1 + +count=$(readelf -wi 1 \ + | grep '(DW_TAG' \ + | wc -l) +limit=$((count + 1)) + +$execs/dwz-for-test \ + -l$limit \ + --devel-trace \ + 1 \ + 2> dwz.err + +if grep -q "Compressing 1 in low-mem mode" dwz.err; then + exit 1 +fi + +rm -f 1 dwz.err diff --git a/testsuite/dwz.tests/low-mem-die-limit-one-below.sh b/testsuite/dwz.tests/low-mem-die-limit-one-below.sh new file mode 100644 index 0000000..4136336 --- /dev/null +++ b/testsuite/dwz.tests/low-mem-die-limit-one-below.sh @@ -0,0 +1,18 @@ +cp $execs/hello 1 + +count=$(readelf -wi 1 \ + | grep '(DW_TAG' \ + | wc -l) +limit=$((count - 1)) + +$execs/dwz-for-test \ + -l$limit \ + --devel-trace \ + 1 \ + 2> dwz.err + +if ! grep -q "Compressing 1 in low-mem mode" dwz.err; then + exit 1 +fi + +rm -f 1 dwz.err diff --git a/testsuite/dwz.tests/low-mem.sh b/testsuite/dwz.tests/low-mem.sh new file mode 100644 index 0000000..e75a198 --- /dev/null +++ b/testsuite/dwz.tests/low-mem.sh @@ -0,0 +1,7 @@ +cp $execs/hello 1 + +dwz -l0 1 + +smaller-than.sh 1 $execs/hello + +rm -f 1 diff --git a/testsuite/dwz.tests/main.c b/testsuite/dwz.tests/main.c new file mode 100644 index 0000000..486b018 --- /dev/null +++ b/testsuite/dwz.tests/main.c @@ -0,0 +1,25 @@ +int +main (void) +{ + return 0; +} + +int +foo (int i) +{ + int j; + asm (".global foo_start_lbl\nfoo_start_lbl:"); + j = i *2; + asm (".global foo_end_lbl\nfoo_end_lbl:"); + return j; +} + +int +bar (int i) +{ + int j; + asm (".global bar_start_lbl\nbar_start_lbl:"); + j = i *2; + asm (".global bar_end_lbl\nbar_end_lbl:"); + return j; +} diff --git a/testsuite/dwz.tests/max-die-limit-none.sh b/testsuite/dwz.tests/max-die-limit-none.sh new file mode 100644 index 0000000..f45d566 --- /dev/null +++ b/testsuite/dwz.tests/max-die-limit-none.sh @@ -0,0 +1,7 @@ +cp $execs/hello 1 + +$execs/dwz-for-test \ + -Lnone \ + 1 + +rm -f 1 diff --git a/testsuite/dwz.tests/min-2.c b/testsuite/dwz.tests/min-2.c new file mode 100644 index 0000000..a1b61ce --- /dev/null +++ b/testsuite/dwz.tests/min-2.c @@ -0,0 +1,5 @@ +int +foo (void) +{ + return 0; +} diff --git a/testsuite/dwz.tests/min.c b/testsuite/dwz.tests/min.c new file mode 100644 index 0000000..cd4ef42 --- /dev/null +++ b/testsuite/dwz.tests/min.c @@ -0,0 +1,7 @@ +extern int foo (void); + +int +main (void) +{ + return 0; +} diff --git a/testsuite/dwz.tests/multifile-name.sh b/testsuite/dwz.tests/multifile-name.sh new file mode 100644 index 0000000..31e73f2 --- /dev/null +++ b/testsuite/dwz.tests/multifile-name.sh @@ -0,0 +1,12 @@ +cp $execs/hello 1 +cp $execs/hello 2 + +dwz -m 3 -M /xxx/yyy/3 1 2 + +smaller-than.sh 1 $execs/hello +smaller-than.sh 2 $execs/hello + +[ "$(gnu-debugaltlink-name.sh 1)" = "/xxx/yyy/3" ] +[ "$(gnu-debugaltlink-name.sh 2)" = "/xxx/yyy/3" ] + +rm -f 1 2 3 diff --git a/testsuite/dwz.tests/multifile-relative.sh b/testsuite/dwz.tests/multifile-relative.sh new file mode 100644 index 0000000..7254206 --- /dev/null +++ b/testsuite/dwz.tests/multifile-relative.sh @@ -0,0 +1,12 @@ +cp $execs/hello 1 +cp $execs/hello 2 + +dwz -m $(pwd -P)/3 -r 1 2 + +smaller-than.sh 1 $execs/hello +smaller-than.sh 2 $execs/hello + +[ "$(gnu-debugaltlink-name.sh 1)" = "3" ] +[ "$(gnu-debugaltlink-name.sh 2)" = "3" ] + +rm -f 1 2 3 diff --git a/testsuite/dwz.tests/multifile.sh b/testsuite/dwz.tests/multifile.sh new file mode 100644 index 0000000..b5f6112 --- /dev/null +++ b/testsuite/dwz.tests/multifile.sh @@ -0,0 +1,12 @@ +cp $execs/hello 1 +cp $execs/hello 2 + +dwz -m 3 1 2 + +smaller-than.sh 1 $execs/hello +smaller-than.sh 2 $execs/hello + +[ "$(gnu-debugaltlink-name.sh 1)" = "3" ] +[ "$(gnu-debugaltlink-name.sh 2)" = "3" ] + +rm -f 1 2 3 diff --git a/testsuite/dwz.tests/objcopy-eu-unstrip-multifile.sh b/testsuite/dwz.tests/objcopy-eu-unstrip-multifile.sh new file mode 100644 index 0000000..15ed418 --- /dev/null +++ b/testsuite/dwz.tests/objcopy-eu-unstrip-multifile.sh @@ -0,0 +1,39 @@ +cp ../hello 1 + +objcopy --only-keep-debug 1 1.debug +objcopy --strip-debug 1 1.stripped + +if ! eu-unstrip 1.stripped 1.debug -o 1.unstripped; then + exit 77 +fi +rm 1.unstripped + +cp 1.debug 2.debug + +if dwz -m 3 1.debug 2.debug 2> dwz.err; status=$?; then + true +fi + +rm 2.debug + +if grep -q "dwz: Section overlap detected" dwz.err; then + exit 77 +fi + +[ $status -eq 0 ] + +version=$(eu-unstrip --version | head -n 1 | cut -d ' ' -f3) +major=$(echo $version | sed 's%\..*%%') +minor=$(echo $version | sed 's%.*\.%%') +if [ $major -gt 0 ] || [ $minor -ge 168 ]; then + true +else + exit 77 +fi + +eu-unstrip 1.stripped 1.debug -o 1.unstripped + +# An unstripped exec can end up larger than the original (PR elfutils/24809). +#smaller-than.sh 1.unstripped 1 + +rm -f 1 1.debug 1.stripped 1.unstripped 3 dwz.err diff --git a/testsuite/dwz.tests/objcopy-eu-unstrip.sh b/testsuite/dwz.tests/objcopy-eu-unstrip.sh new file mode 100644 index 0000000..18593d0 --- /dev/null +++ b/testsuite/dwz.tests/objcopy-eu-unstrip.sh @@ -0,0 +1,35 @@ +cp ../hello 1 + +objcopy --only-keep-debug 1 1.debug +objcopy --strip-debug 1 1.stripped + +if ! eu-unstrip 1.stripped 1.debug -o 1.unstripped; then + exit 77 +fi +rm 1.unstripped + +if dwz 1.debug 2> dwz.err; status=$?; then + true +fi + +if grep -q "dwz: Section overlap detected" dwz.err; then + exit 77 +fi + +[ $status -eq 0 ] + +version=$(eu-unstrip --version | head -n 1 | cut -d ' ' -f3) +major=$(echo $version | sed 's%\..*%%') +minor=$(echo $version | sed 's%.*\.%%') +if [ $major -gt 0 ] || [ $minor -ge 168 ]; then + true +else + exit 77 +fi + +eu-unstrip 1.stripped 1.debug -o 1.unstripped + +# An unstripped exec can end up larger than the original (PR elfutils/24809). +#smaller-than.sh 1.unstripped 1 + +rm -f 1 1.debug 1.stripped 1.unstripped dwz.err diff --git a/testsuite/dwz.tests/objcopy-remove-debug-abbrev.sh b/testsuite/dwz.tests/objcopy-remove-debug-abbrev.sh new file mode 100644 index 0000000..98ab12c --- /dev/null +++ b/testsuite/dwz.tests/objcopy-remove-debug-abbrev.sh @@ -0,0 +1,18 @@ +objcopy --remove-section=.debug_abbrev $execs/hello 1 + +cp 1 1.saved + +if dwz 1 2>dwz.err; status=$?; then + true +fi + +if ! grep -q "\.debug_abbrev not present" dwz.err; then + cat dwz.err + exit 1 +fi + +[ $status -eq 1 ] + +cmp 1 1.saved + +rm -f 1 1.saved dwz.err diff --git a/testsuite/dwz.tests/objcopy-strip-debug.sh b/testsuite/dwz.tests/objcopy-strip-debug.sh new file mode 100644 index 0000000..a22ba3a --- /dev/null +++ b/testsuite/dwz.tests/objcopy-strip-debug.sh @@ -0,0 +1,30 @@ +objcopy --strip-debug $execs/hello 1 + +cp 1 1.saved + +if dwz 1 2>dwz.err; status=$?; then + true +fi + +if ! grep -q "\.debug_info section not present" dwz.err; then + cat dwz.err + exit 1 +fi + +[ $status -eq 0 ] + +cmp 1 1.saved + +if dwz 1 -o 2 2>dwz.err; status=$?; then + true +fi + +if ! grep -q "\.debug_info section not present" dwz.err; then + cat dwz.err + exit 1 +fi + +[ $status -eq 1 ] +[ ! -f 2 ] + +rm -f 1 1.saved dwz.err diff --git a/testsuite/dwz.tests/odr-2.cc b/testsuite/dwz.tests/odr-2.cc new file mode 100644 index 0000000..8b3dcd2 --- /dev/null +++ b/testsuite/dwz.tests/odr-2.cc @@ -0,0 +1,20 @@ +#if NAMESPACE +namespace ns { +#endif + KIND bbb + { + int member_four; + }; + KIND ccc; +#if NAMESPACE +} +#endif +#include "odr.h" + +#if NAMESPACE +KIND ns::aaa var2; +KIND ns::bbb var4; +#else +KIND aaa var2; +KIND bbb var4; +#endif diff --git a/testsuite/dwz.tests/odr-class-ns.sh b/testsuite/dwz.tests/odr-class-ns.sh new file mode 100644 index 0000000..4b890a3 --- /dev/null +++ b/testsuite/dwz.tests/odr-class-ns.sh @@ -0,0 +1,29 @@ +if ! $execs/dwz-for-test --odr -v 2>/dev/null; then + exit 77 +fi + +cp $execs/odr-class-ns 1 + +verify-dwarf.sh 1 + +aaa=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*aaa') +[ $aaa -eq 2 ] + +bbb=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*bbb') +[ $bbb -eq 2 ] + +ccc=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*ccc') +[ $ccc -eq 2 ] + +$execs/dwz-for-test --odr 1 + +aaa=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*aaa') +[ $aaa -eq 1 ] + +bbb=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*bbb') +[ $bbb -eq 1 ] + +ccc=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*ccc') +[ $ccc -eq 1 ] + +rm -f 1 diff --git a/testsuite/dwz.tests/odr-class.sh b/testsuite/dwz.tests/odr-class.sh new file mode 100644 index 0000000..872c3ca --- /dev/null +++ b/testsuite/dwz.tests/odr-class.sh @@ -0,0 +1,29 @@ +if ! $execs/dwz-for-test --odr -v 2>/dev/null; then + exit 77 +fi + +cp $execs/odr-class 1 + +verify-dwarf.sh 1 + +aaa=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*aaa') +[ $aaa -eq 2 ] + +bbb=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*bbb') +[ $bbb -eq 2 ] + +ccc=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*ccc') +[ $ccc -eq 2 ] + +$execs/dwz-for-test --odr 1 + +aaa=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*aaa') +[ $aaa -eq 1 ] + +bbb=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*bbb') +[ $bbb -eq 1 ] + +ccc=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*ccc') +[ $ccc -eq 1 ] + +rm -f 1 diff --git a/testsuite/dwz.tests/odr-def-decl.sh b/testsuite/dwz.tests/odr-def-decl.sh new file mode 100644 index 0000000..8905e52 --- /dev/null +++ b/testsuite/dwz.tests/odr-def-decl.sh @@ -0,0 +1,19 @@ +if ! $execs/dwz-for-test --odr -v 2>/dev/null; then + exit 77 +fi + +cp $execs/def-decl 1 + +verify-dwarf.sh 1 + +cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*ao_ref" || true) +[ $cnt -eq 5 ] + +$execs/dwz-for-test --odr 1 --devel-ignore-size + +verify-dwarf.sh 1 + +cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*ao_ref" || true) +[ $cnt -eq 2 ] + +rm -f 1 diff --git a/testsuite/dwz.tests/odr-loc-2.cc b/testsuite/dwz.tests/odr-loc-2.cc new file mode 100644 index 0000000..7cf832b --- /dev/null +++ b/testsuite/dwz.tests/odr-loc-2.cc @@ -0,0 +1,14 @@ +struct bbb +{ + int member_four; +}; +struct ccc; + +struct aaa +{ + struct bbb *member_one; + struct ccc *member_two; +}; + +struct aaa var2; +struct bbb var4; diff --git a/testsuite/dwz.tests/odr-loc.cc b/testsuite/dwz.tests/odr-loc.cc new file mode 100644 index 0000000..953fd66 --- /dev/null +++ b/testsuite/dwz.tests/odr-loc.cc @@ -0,0 +1,19 @@ +struct bbb; +struct ccc { + int member_three; +}; + +struct aaa +{ + struct bbb *member_one; + struct ccc *member_two; +}; + +struct aaa var1; +struct ccc var3; + +int +main (void) +{ + return 0; +} diff --git a/testsuite/dwz.tests/odr-loc.sh b/testsuite/dwz.tests/odr-loc.sh new file mode 100644 index 0000000..a8b3318 --- /dev/null +++ b/testsuite/dwz.tests/odr-loc.sh @@ -0,0 +1,39 @@ +if ! $execs/dwz-for-test --odr -v 2>/dev/null; then + exit 77 +fi + +cp $execs/odr-loc 1 + +for name in aaa bbb ccc; do + cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true) + [ $cnt -eq 2 ] +done + +$execs/dwz-for-test --odr 1 --devel-ignore-size + +verify-dwarf.sh 1 + +for name in aaa bbb ccc; do + cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true) + case $name in + aaa) + [ $cnt -eq 2 ] + ;; + *) + [ $cnt -eq 1 ] + ;; + esac +done + +cp $execs/odr-loc 1 + +$execs/dwz-for-test --odr --devel-ignore-locus 1 + +verify-dwarf.sh 1 + +for name in aaa bbb ccc; do + cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true) + [ $cnt -eq 1 ] +done + +rm -f 1 diff --git a/testsuite/dwz.tests/odr-struct-multifile.sh b/testsuite/dwz.tests/odr-struct-multifile.sh new file mode 100755 index 0000000..5961abf --- /dev/null +++ b/testsuite/dwz.tests/odr-struct-multifile.sh @@ -0,0 +1,61 @@ +if ! $execs/dwz-for-test --odr -v 2>/dev/null; then + exit 77 +fi + +readelf_flags="" +if readelf -h 2>&1 | grep -q "\-wN"; then + readelf_flags=-wN +fi + +cp $execs/odr-struct 1 +cp 1 2 + +for name in aaa bbb ccc; do + cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true) + [ $cnt -eq 2 ] +done + +for name in member_one member_two member_three member_four; do + cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true) + case $name in + member_one|member_two) + [ $cnt -eq 2 ] + ;; + member_three|member_four) + [ $cnt -eq 1 ] + ;; + esac +done + +decl_cnt=$(readelf -wi 1 | grep -c "DW_AT_declaration" || true) + +$execs/dwz-for-test --odr 1 2 -m 3 + +verify-dwarf.sh 1 +verify-dwarf.sh 3 + +for name in aaa bbb ccc; do + cnt=$(readelf -wi 3 | grep -c "DW_AT_name.*:.*$name" || true) + [ $cnt -eq 1 ] +done + +for name in member_one member_two member_three member_four; do + cnt=$(readelf -wi 3 | grep -c "DW_AT_name.*:.*$name" || true) + [ $cnt -eq 1 ] +done + +# Even with -wN readelf 2.38-15.fc37 follows and prints the contents +# of the alt file. So make sure it cannot do that by removing it. +rm 3 + +for name in aaa bbb ccc; do + cnt=$(readelf -wi $readelf_flags 1 | grep -c "DW_AT_name.*:.*$name" || true) + [ $cnt -eq 0 ] +done + +for name in member_one member_two member_three member_four; do + cnt=$(readelf -wi $readelf_flags 1 | grep -c "DW_AT_name.*:.*$name" || true) + [ $cnt -eq 0 ] +done + +rm -f 1 2 3 diff --git a/testsuite/dwz.tests/odr-struct-ns.sh b/testsuite/dwz.tests/odr-struct-ns.sh new file mode 100644 index 0000000..c6e0f1d --- /dev/null +++ b/testsuite/dwz.tests/odr-struct-ns.sh @@ -0,0 +1,49 @@ +if ! $execs/dwz-for-test --odr -v 2>/dev/null; then + exit 77 +fi + +cp $execs/odr-struct-ns 1 + +for name in aaa bbb ccc; do + cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true) + [ $cnt -eq 2 ] +done + +for name in member_one member_two member_three member_four; do + cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true) + case $name in + member_one|member_two) + [ $cnt -eq 2 ] + ;; + member_three|member_four) + [ $cnt -eq 1 ] + ;; + esac +done + +# Check that bbb and ccc are present as DW_AT_declaration +readelf -wi 1 | grep -3 DW_AT_declaration > decls +grep bbb decls >/dev/null +grep ccc decls >/dev/null + +$execs/dwz-for-test --odr 1 + +verify-dwarf.sh 1 + +for name in aaa bbb ccc; do + cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true) + [ $cnt -eq 1 ] +done + +for name in member_one member_two member_three member_four; do + cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true) + [ $cnt -eq 1 ] +done + +# We expect two decls to be removed, for bbb and ccc. +readelf -wi 1 | grep -3 DW_AT_declaration > decls || true + +if grep bbb decls >/dev/null ; then exit 1; fi +if grep ccc decls >/dev/null ; then exit 2; fi + +rm -f 1 decls diff --git a/testsuite/dwz.tests/odr-struct.sh b/testsuite/dwz.tests/odr-struct.sh new file mode 100644 index 0000000..c6793f9 --- /dev/null +++ b/testsuite/dwz.tests/odr-struct.sh @@ -0,0 +1,49 @@ +if ! $execs/dwz-for-test --odr -v 2>/dev/null; then + exit 77 +fi + +cp $execs/odr-struct 1 + +for name in aaa bbb ccc; do + cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true) + [ $cnt -eq 2 ] +done + +for name in member_one member_two member_three member_four; do + cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true) + case $name in + member_one|member_two) + [ $cnt -eq 2 ] + ;; + member_three|member_four) + [ $cnt -eq 1 ] + ;; + esac +done + +# Check that bbb and ccc are present as DW_AT_declaration +readelf -wi 1 | grep -3 DW_AT_declaration > decls +grep bbb decls >/dev/null +grep ccc decls >/dev/null + +$execs/dwz-for-test --odr 1 + +verify-dwarf.sh 1 + +for name in aaa bbb ccc; do + cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true) + [ $cnt -eq 1 ] +done + +for name in member_one member_two member_three member_four; do + cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true) + [ $cnt -eq 1 ] +done + +# We expect two decls to be removed, for bbb and ccc. +readelf -wi 1 | grep -3 DW_AT_declaration > decls || true + +if grep bbb decls >/dev/null ; then exit 1; fi +if grep ccc decls >/dev/null ; then exit 2; fi + +rm -f 1 decls diff --git a/testsuite/dwz.tests/odr-union-ns.sh b/testsuite/dwz.tests/odr-union-ns.sh new file mode 100644 index 0000000..7d86dba --- /dev/null +++ b/testsuite/dwz.tests/odr-union-ns.sh @@ -0,0 +1,29 @@ +if ! $execs/dwz-for-test --odr -v 2>/dev/null; then + exit 77 +fi + +cp $execs/odr-union-ns 1 + +aaa=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*aaa') +[ $aaa -eq 2 ] + +bbb=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*bbb') +[ $bbb -eq 2 ] + +ccc=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*ccc') +[ $ccc -eq 2 ] + +$execs/dwz-for-test --odr 1 + +verify-dwarf.sh 1 + +aaa=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*aaa') +[ $aaa -eq 1 ] + +bbb=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*bbb') +[ $bbb -eq 1 ] + +ccc=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*ccc') +[ $ccc -eq 1 ] + +rm -f 1 diff --git a/testsuite/dwz.tests/odr-union.sh b/testsuite/dwz.tests/odr-union.sh new file mode 100644 index 0000000..a32a46c --- /dev/null +++ b/testsuite/dwz.tests/odr-union.sh @@ -0,0 +1,29 @@ +if ! $execs/dwz-for-test --odr -v 2>/dev/null; then + exit 77 +fi + +cp $execs/odr-union 1 + +aaa=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*aaa') +[ $aaa -eq 2 ] + +bbb=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*bbb') +[ $bbb -eq 2 ] + +ccc=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*ccc') +[ $ccc -eq 2 ] + +$execs/dwz-for-test --odr 1 + +verify-dwarf.sh 1 + +aaa=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*aaa') +[ $aaa -eq 1 ] + +bbb=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*bbb') +[ $bbb -eq 1 ] + +ccc=$(readelf -wi 1 | grep -c 'DW_AT_name.*:.*ccc') +[ $ccc -eq 1 ] + +rm -f 1 diff --git a/testsuite/dwz.tests/odr.cc b/testsuite/dwz.tests/odr.cc new file mode 100644 index 0000000..9505cb3 --- /dev/null +++ b/testsuite/dwz.tests/odr.cc @@ -0,0 +1,26 @@ +#if NAMESPACE +namespace ns { +#endif + KIND bbb; + KIND ccc { + int member_three; + }; +#if NAMESPACE +} +#endif + +#include "odr.h" + +#if NAMESPACE +KIND ns::aaa var1; +KIND ns::ccc var3; +#else +KIND aaa var1; +KIND ccc var3; +#endif + +int +main (void) +{ + return 0; +} diff --git a/testsuite/dwz.tests/odr.h b/testsuite/dwz.tests/odr.h new file mode 100644 index 0000000..ae0e07d --- /dev/null +++ b/testsuite/dwz.tests/odr.h @@ -0,0 +1,11 @@ +#if NAMESPACE +namespace ns { +#endif + KIND aaa + { + KIND bbb *member_one; + KIND ccc *member_two; + }; +#if NAMESPACE +} +#endif diff --git a/testsuite/dwz.tests/pointer-size.c b/testsuite/dwz.tests/pointer-size.c new file mode 100644 index 0000000..320633d --- /dev/null +++ b/testsuite/dwz.tests/pointer-size.c @@ -0,0 +1,8 @@ +#include <stdio.h> + +int +main (void) +{ + printf ("%llu\n", (unsigned long long)sizeof (void *)); + return 0; +} diff --git a/testsuite/dwz.tests/pr24170.sh b/testsuite/dwz.tests/pr24170.sh new file mode 100644 index 0000000..ec57a71 --- /dev/null +++ b/testsuite/dwz.tests/pr24170.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +exec=$execs/implptr-64bit-d2o4a8r8t0 + +pointer_sizes=$(readelf -wi $exec \ + | grep "Pointer Size:" \ + | sort -u \ + | wc -l) + +if [ $pointer_sizes -ne 1 ]; then + exit 77 +fi + +cp $exec 1 +cp 1 2 + +dwz -m 3 1 2 + +smaller-than.sh 1 $exec +smaller-than.sh 2 $exec + +[ "$(gnu-debugaltlink-name.sh 1)" = "3" ] +[ "$(gnu-debugaltlink-name.sh 2)" = "3" ] + +rm -f 1 2 3 diff --git a/testsuite/dwz.tests/pr24171.sh b/testsuite/dwz.tests/pr24171.sh new file mode 100644 index 0000000..dd99c05 --- /dev/null +++ b/testsuite/dwz.tests/pr24171.sh @@ -0,0 +1,15 @@ +cp $execs/invalid-dw-at-stmt-list-encoding 1 +cp 1 2 + +if dwz -m 3 1 2 2>dwz.err; status=$?; then + true +fi + +if ! grep -q "DW_AT_stmt_list not DW_FORM_sec_offset or DW_FORM_data4" dwz.err; then + cat dwz.err + exit 1 +fi + +[ $status -eq 1 ] + +rm -f 1 2 dwz.err diff --git a/testsuite/dwz.tests/pr24172.sh b/testsuite/dwz.tests/pr24172.sh new file mode 100644 index 0000000..f455b27 --- /dev/null +++ b/testsuite/dwz.tests/pr24172.sh @@ -0,0 +1,14 @@ +cp $execs/dw2-skip-prologue 1 + +if dwz 1 2>dwz.err; status=$?; then + true +fi + +if ! grep -q "locexpr length .* exceeds .debug_loc section" dwz.err; then + cat dwz.err + exit 1 +fi + +[ $status -eq 1 ] + +rm -f 1 dwz.err diff --git a/testsuite/dwz.tests/pr24173.sh b/testsuite/dwz.tests/pr24173.sh new file mode 100644 index 0000000..908c219 --- /dev/null +++ b/testsuite/dwz.tests/pr24173.sh @@ -0,0 +1,16 @@ +cp $execs/py-section-script 1 + +eu-strip -g -f 1.debug 1 + +if dwz 1.debug 2>dwz.err; status=$?; then + true +fi + +if ! grep -q "Found empty .debug_gdb_scripts section, not attempting dwz compression" dwz.err; then + cat dwz.err + exit 1 +fi + +[ $status -eq 1 ] + +rm -f 1 1.debug dwz.err diff --git a/testsuite/dwz.tests/pr24174.sh b/testsuite/dwz.tests/pr24174.sh new file mode 100644 index 0000000..8d1192c --- /dev/null +++ b/testsuite/dwz.tests/pr24174.sh @@ -0,0 +1,24 @@ +exec=$execs/hello +cp $exec 1 +objcopy --compress-debug-sections 1 +if readelf -S 1 \ + | grep -A1 '\.debug_' \ + | grep -v '\.debug_' \ + | grep -q 'C'; then + true +else + exit 77 +fi + +if dwz 1 2>dwz.err; status=$?; then + true +fi + +if grep -q "DWARF version 0 unhandled" dwz.err; then + cat dwz.err + exit 1 +fi + +[ $status -eq 1 ] + +rm -f 1 dwz.err diff --git a/testsuite/dwz.tests/pr24341.sh b/testsuite/dwz.tests/pr24341.sh new file mode 100644 index 0000000..4f044f6 --- /dev/null +++ b/testsuite/dwz.tests/pr24341.sh @@ -0,0 +1,17 @@ +cp $execs/min 1 +cp 1 2 + +dwz -m 3 1 2 + +cnt=$(readelf -S 3 | grep "\.debug_info" | wc -l) +if [ $cnt -ne 0 ]; then + exit 77 +fi + +smaller-than.sh 1 $execs/min +smaller-than.sh 2 $execs/min + +[ "$(gnu-debugaltlink-name.sh 1)" = "3" ] +[ "$(gnu-debugaltlink-name.sh 2)" = "3" ] + +rm -f 1 2 3 diff --git a/testsuite/dwz.tests/pr24468.sh b/testsuite/dwz.tests/pr24468.sh new file mode 100644 index 0000000..7990e83 --- /dev/null +++ b/testsuite/dwz.tests/pr24468.sh @@ -0,0 +1,19 @@ +exec=$execs/testsuite/dwz.tests/execs/hello-leap-15.0 + +cp $exec 1 +cp 1 2 + +dwz -m 3 1 2 + +readelf -wi 1 > READELF 2>/dev/null + +offsets=$(grep '(DW_TAG_partial_unit' READELF \ + | grep -v "DW_AT_import" \ + | awk '{print $1}' \ + | sed 's/.*<//;s/>.*//') +for off in $offsets; do + imports=$(grep -c "DW_AT_import.*0x$off" READELF || true) + [ $imports -gt 0 ] +done + +rm -f 1 2 3 READELF diff --git a/testsuite/dwz.tests/pr24542.sh b/testsuite/dwz.tests/pr24542.sh new file mode 100644 index 0000000..f797034 --- /dev/null +++ b/testsuite/dwz.tests/pr24542.sh @@ -0,0 +1,15 @@ +cp $execs/start 1 +cp 1 2 + +if dwz -m 3 1 2 2> dwz.err; status=$?; then + true +fi + +if ! grep -q "No suitable DWARF found for multifile optimization" dwz.err; then + cat dwz.err + exit 1 +fi + +[ $status -eq 0 ] + +rm -f 1 2 3 dwz.err diff --git a/testsuite/dwz.tests/pr24747.sh b/testsuite/dwz.tests/pr24747.sh new file mode 100644 index 0000000..7182f72 --- /dev/null +++ b/testsuite/dwz.tests/pr24747.sh @@ -0,0 +1,7 @@ +exec=$execs/start-gold + +cp $exec 1 + +dwz 1 + +rm -f 1 diff --git a/testsuite/dwz.tests/pr24771.sh b/testsuite/dwz.tests/pr24771.sh new file mode 100644 index 0000000..4eb6c02 --- /dev/null +++ b/testsuite/dwz.tests/pr24771.sh @@ -0,0 +1,9 @@ +exec=$execs/hello-gnu-pubnames + +cp $exec 1 + +dwz 1 + +smaller-than.sh 1 $exec + +rm -f 1 diff --git a/testsuite/dwz.tests/pr24823.sh b/testsuite/dwz.tests/pr24823.sh new file mode 100644 index 0000000..8720aec --- /dev/null +++ b/testsuite/dwz.tests/pr24823.sh @@ -0,0 +1,25 @@ +exec=$execs/varval + +pointer_sizes=$(readelf -wi $exec \ + | grep "Pointer Size:" \ + | sort -u \ + | wc -l) + +if [ $pointer_sizes -ne 1 ]; then + exit 77 +fi + +cp $exec 1 +cp 1 2 + +dwz -m 3 1 2 + +if [ -f 3 ]; then + readelf -wi 3 > READELF.3 + if grep -q var_c READELF.3; status=$?; then + true + fi + [ $status -ne 0 ] +fi + +rm -f 1 2 3 READELF.3 diff --git a/testsuite/dwz.tests/pr25109.sh b/testsuite/dwz.tests/pr25109.sh new file mode 100644 index 0000000..6da1f22 --- /dev/null +++ b/testsuite/dwz.tests/pr25109.sh @@ -0,0 +1,6 @@ +cp $execs/no-multifile-prop 1 +cp 1 2 + +$execs/dwz-for-test -m 3 1 2 --devel-ignore-size + +rm -f 1 2 3 diff --git a/testsuite/dwz.tests/pr27463.sh b/testsuite/dwz.tests/pr27463.sh new file mode 100644 index 0000000..cd0238c --- /dev/null +++ b/testsuite/dwz.tests/pr27463.sh @@ -0,0 +1,6 @@ +cp $execs/unavailable-dwarf-piece 1 +cp 1 2 + +dwz -m 3 1 2 + +rm -f 1 2 3 diff --git a/testsuite/dwz.tests/py-section-script.s b/testsuite/dwz.tests/py-section-script.s new file mode 100644 index 0000000..1f5efc7 --- /dev/null +++ b/testsuite/dwz.tests/py-section-script.s @@ -0,0 +1,393 @@ +# Generated using gdb/testsuite/gdb.python/py-section-script.c from repo +# git://sourceware.org/git/binutils-gdb.git. + + .file "py-section-script.c" + .text +.Ltext0: +#APP + .pushsection ".debug_gdb_scripts", "S",%progbits +.byte 1 +.asciz "py-section-script.py" +.popsection + + .pushsection ".debug_gdb_scripts", "S",%progbits +.byte 1 +.asciz "py-section-script.py" +.popsection + + .pushsection ".debug_gdb_scripts", "S",%progbits +.byte 4 +.ascii "gdb.inlined-script\n" +.ascii "class test_cmd (gdb.Command):\n" +.ascii " def __init__ (self):\n" +.ascii " super (test_cmd, self).__init__ (\"test-cmd\", gdb.COMMAND_OBSCURE)\n" +.ascii " def invoke (self, arg, from_tty):\n" +.ascii " print (\"test-cmd output, arg = %s\" % arg)\n" +.ascii "test_cmd ()\n" +.byte 0 +.popsection + + .pushsection ".debug_gdb_scripts", "S",%progbits +.byte 4 +.ascii "gdb.inlined-script\n" +.ascii "class test_cmd (gdb.Command):\n" +.ascii " def __init__ (self):\n" +.ascii " super (test_cmd, self).__init__ (\"test-cmd\", gdb.COMMAND_OBSCURE)\n" +.ascii " def invoke (self, arg, from_tty):\n" +.ascii " print (\"test-cmd output, arg = %s\" % arg)\n" +.ascii "test_cmd ()\n" +.byte 0 +.popsection + +#NO_APP + .globl init_ss + .type init_ss, @function +init_ss: +.LFB0: + .file 1 "py-section-script.c" + # py-section-script.c:76 + .loc 1 76 0 + .cfi_startproc +# BLOCK 2 seq:0 +# PRED: ENTRY (FALLTHRU) + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movq %rdi, -8(%rbp) + movl %esi, -12(%rbp) + movl %edx, -16(%rbp) + # py-section-script.c:77 + .loc 1 77 0 + movq -8(%rbp), %rax + movl -12(%rbp), %edx + movl %edx, (%rax) + # py-section-script.c:78 + .loc 1 78 0 + movq -8(%rbp), %rax + movl -16(%rbp), %edx + movl %edx, 4(%rax) + # py-section-script.c:79 + .loc 1 79 0 + nop + popq %rbp + .cfi_def_cfa 7, 8 +# SUCC: EXIT [100.0%] + ret + .cfi_endproc +.LFE0: + .size init_ss, .-init_ss + .globl main + .type main, @function +main: +.LFB1: + # py-section-script.c:83 + .loc 1 83 0 + .cfi_startproc +# BLOCK 2 seq:0 +# PRED: ENTRY (FALLTHRU) + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + subq $16, %rsp + # py-section-script.c:86 + .loc 1 86 0 + leaq -8(%rbp), %rax + movl $2, %edx + movl $1, %esi + movq %rax, %rdi + call init_ss + # py-section-script.c:88 + .loc 1 88 0 + movl $0, %eax + # py-section-script.c:89 + .loc 1 89 0 + leave + .cfi_def_cfa 7, 8 +# SUCC: EXIT [100.0%] + ret + .cfi_endproc +.LFE1: + .size main, .-main +.Letext0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .long 0xc8 # Length of Compilation Unit Info + .value 0x4 # DWARF version number + .long .Ldebug_abbrev0 # Offset Into Abbrev. Section + .byte 0x8 # Pointer Size (in bytes) + .uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit) + .long .LASF2 # DW_AT_producer: "GNU C11 7.3.1 20180323 [gcc-7-branch revision 258812] -mtune=generic -march=x86-64 -g" + .byte 0xc # DW_AT_language + .long .LASF3 # DW_AT_name: "py-section-script.c" + .long .LASF4 # DW_AT_comp_dir: "/home/vries/gdb_versions/devel" + .quad .Ltext0 # DW_AT_low_pc + .quad .Letext0-.Ltext0 # DW_AT_high_pc + .long .Ldebug_line0 # DW_AT_stmt_list + .uleb128 0x2 # (DIE (0x2d) DW_TAG_structure_type) + .ascii "ss\0" # DW_AT_name + .byte 0x8 # DW_AT_byte_size + .byte 0x1 # DW_AT_decl_file (py-section-script.c) + .byte 0x44 # DW_AT_decl_line + .long 0x4d # DW_AT_sibling + .uleb128 0x3 # (DIE (0x38) DW_TAG_member) + .ascii "a\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (py-section-script.c) + .byte 0x46 # DW_AT_decl_line + .long 0x4d # DW_AT_type + .byte 0 # DW_AT_data_member_location + .uleb128 0x3 # (DIE (0x42) DW_TAG_member) + .ascii "b\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (py-section-script.c) + .byte 0x47 # DW_AT_decl_line + .long 0x4d # DW_AT_type + .byte 0x4 # DW_AT_data_member_location + .byte 0 # end of children of DIE 0x2d + .uleb128 0x4 # (DIE (0x4d) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .ascii "int\0" # DW_AT_name + .uleb128 0x5 # (DIE (0x54) DW_TAG_subprogram) + # DW_AT_external + .long .LASF0 # DW_AT_name: "main" + .byte 0x1 # DW_AT_decl_file (py-section-script.c) + .byte 0x52 # DW_AT_decl_line + .long 0x4d # DW_AT_type + .quad .LFB1 # DW_AT_low_pc + .quad .LFE1-.LFB1 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_tail_call_sites + .long 0x83 # DW_AT_sibling + .uleb128 0x6 # (DIE (0x75) DW_TAG_variable) + .ascii "ss\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (py-section-script.c) + .byte 0x54 # DW_AT_decl_line + .long 0x2d # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -24 + .byte 0 # end of children of DIE 0x54 + .uleb128 0x7 # (DIE (0x83) DW_TAG_subprogram) + # DW_AT_external + .long .LASF1 # DW_AT_name: "init_ss" + .byte 0x1 # DW_AT_decl_file (py-section-script.c) + .byte 0x4b # DW_AT_decl_line + # DW_AT_prototyped + .quad .LFB0 # DW_AT_low_pc + .quad .LFE0-.LFB0 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_call_sites + .long 0xc5 # DW_AT_sibling + .uleb128 0x8 # (DIE (0xa0) DW_TAG_formal_parameter) + .ascii "s\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (py-section-script.c) + .byte 0x4b # DW_AT_decl_line + .long 0xc5 # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -24 + .uleb128 0x8 # (DIE (0xac) DW_TAG_formal_parameter) + .ascii "a\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (py-section-script.c) + .byte 0x4b # DW_AT_decl_line + .long 0x4d # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -28 + .uleb128 0x8 # (DIE (0xb8) DW_TAG_formal_parameter) + .ascii "b\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (py-section-script.c) + .byte 0x4b # DW_AT_decl_line + .long 0x4d # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -32 + .byte 0 # end of children of DIE 0x83 + .uleb128 0x9 # (DIE (0xc5) DW_TAG_pointer_type) + .byte 0x8 # DW_AT_byte_size + .long 0x2d # DW_AT_type + .byte 0 # end of children of DIE 0xb + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .uleb128 0x1 # (abbrev code) + .uleb128 0x11 # (TAG: DW_TAG_compile_unit) + .byte 0x1 # DW_children_yes + .uleb128 0x25 # (DW_AT_producer) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x13 # (DW_AT_language) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x1b # (DW_AT_comp_dir) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x7 # (DW_FORM_data8) + .uleb128 0x10 # (DW_AT_stmt_list) + .uleb128 0x17 # (DW_FORM_sec_offset) + .byte 0 + .byte 0 + .uleb128 0x2 # (abbrev code) + .uleb128 0x13 # (TAG: DW_TAG_structure_type) + .byte 0x1 # DW_children_yes + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x1 # (DW_AT_sibling) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x3 # (abbrev code) + .uleb128 0xd # (TAG: DW_TAG_member) + .byte 0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x38 # (DW_AT_data_member_location) + .uleb128 0xb # (DW_FORM_data1) + .byte 0 + .byte 0 + .uleb128 0x4 # (abbrev code) + .uleb128 0x24 # (TAG: DW_TAG_base_type) + .byte 0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3e # (DW_AT_encoding) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .byte 0 + .byte 0 + .uleb128 0x5 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0x1 # DW_children_yes + .uleb128 0x3f # (DW_AT_external) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x7 # (DW_FORM_data8) + .uleb128 0x40 # (DW_AT_frame_base) + .uleb128 0x18 # (DW_FORM_exprloc) + .uleb128 0x2116 # (DW_AT_GNU_all_tail_call_sites) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x1 # (DW_AT_sibling) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x6 # (abbrev code) + .uleb128 0x34 # (TAG: DW_TAG_variable) + .byte 0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x2 # (DW_AT_location) + .uleb128 0x18 # (DW_FORM_exprloc) + .byte 0 + .byte 0 + .uleb128 0x7 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0x1 # DW_children_yes + .uleb128 0x3f # (DW_AT_external) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x27 # (DW_AT_prototyped) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x7 # (DW_FORM_data8) + .uleb128 0x40 # (DW_AT_frame_base) + .uleb128 0x18 # (DW_FORM_exprloc) + .uleb128 0x2117 # (DW_AT_GNU_all_call_sites) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x1 # (DW_AT_sibling) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x8 # (abbrev code) + .uleb128 0x5 # (TAG: DW_TAG_formal_parameter) + .byte 0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x2 # (DW_AT_location) + .uleb128 0x18 # (DW_FORM_exprloc) + .byte 0 + .byte 0 + .uleb128 0x9 # (abbrev code) + .uleb128 0xf # (TAG: DW_TAG_pointer_type) + .byte 0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .byte 0 + .section .debug_aranges,"",@progbits + .long 0x2c # Length of Address Ranges Info + .value 0x2 # DWARF Version + .long .Ldebug_info0 # Offset of Compilation Unit Info + .byte 0x8 # Size of Address + .byte 0 # Size of Segment Descriptor + .value 0 # Pad to 16 byte boundary + .value 0 + .quad .Ltext0 # Address + .quad .Letext0-.Ltext0 # Length + .quad 0 + .quad 0 + .section .debug_line,"",@progbits +.Ldebug_line0: + .section .debug_str,"MS",@progbits,1 +.LASF2: + .string "GNU C11 7.3.1 20180323 [gcc-7-branch revision 258812] -mtune=generic -march=x86-64 -g" +.LASF3: + .string "py-section-script.c" +.LASF0: + .string "main" +.LASF4: + .string "/home/vries/gdb_versions/devel" +.LASF1: + .string "init_ss" + .ident "GCC: (SUSE Linux) 7.3.1 20180323 [gcc-7-branch revision 258812]" + .section .note.GNU-stack,"",@progbits diff --git a/testsuite/dwz.tests/regular-o.sh b/testsuite/dwz.tests/regular-o.sh new file mode 100644 index 0000000..1416e90 --- /dev/null +++ b/testsuite/dwz.tests/regular-o.sh @@ -0,0 +1,9 @@ +cp $execs/hello 1 + +dwz 1 -o 2 + +cmp 1 $execs/hello + +smaller-than.sh 2 1 + +rm -f 1 2 diff --git a/testsuite/dwz.tests/regular.sh b/testsuite/dwz.tests/regular.sh new file mode 100644 index 0000000..9d33153 --- /dev/null +++ b/testsuite/dwz.tests/regular.sh @@ -0,0 +1,7 @@ +cp $execs/hello 1 + +dwz 1 + +smaller-than.sh 1 $execs/hello + +rm -f 1 diff --git a/testsuite/dwz.tests/save-temps.sh b/testsuite/dwz.tests/save-temps.sh new file mode 100644 index 0000000..bcc1f1b --- /dev/null +++ b/testsuite/dwz.tests/save-temps.sh @@ -0,0 +1,20 @@ +cp $execs/hello 1 +cp $execs/hello 2 + +$execs/dwz-for-test --devel-save-temps -m 3 1 2 + +files=" + dwz.debug_abbrev + dwz.debug_info + dwz.debug_line + dwz.debug_macro + dwz.debug_str + dwz.1 + dwz.2 +" + +for f in $files; do + [ -f $f ] +done + +rm -f 1 2 3 $files diff --git a/testsuite/dwz.tests/start.c b/testsuite/dwz.tests/start.c new file mode 100644 index 0000000..a925613 --- /dev/null +++ b/testsuite/dwz.tests/start.c @@ -0,0 +1,3 @@ +void _start (void) +{ +} diff --git a/testsuite/dwz.tests/too-many-dies.sh b/testsuite/dwz.tests/too-many-dies.sh new file mode 100644 index 0000000..53a0f4b --- /dev/null +++ b/testsuite/dwz.tests/too-many-dies.sh @@ -0,0 +1,16 @@ +cp $execs/hello 1 + +if dwz -L0 1 2>dwz.err; status=?; then + true +fi + +if ! grep -q "Too many DIEs, not optimizing" dwz.err; then + cat dwz.err + exit 1 +fi + +[ $status -eq 1 ] + +cmp 1 $execs/hello + +rm -f 1 dwz.err diff --git a/testsuite/dwz.tests/twice-hardlink.sh b/testsuite/dwz.tests/twice-hardlink.sh new file mode 100644 index 0000000..6bc0794 --- /dev/null +++ b/testsuite/dwz.tests/twice-hardlink.sh @@ -0,0 +1,31 @@ +cp $execs/hello 1 +ln 1 2 + +dwz -h 1 2 + +smaller-than.sh 1 $execs/hello + +hardlinks-p.sh 1 2 + +cp 1 1.saved + +if dwz -h 1 2 2>dwz.err; status=$?; then + true +fi + +if ! grep -q "DWARF compression not beneficial" dwz.err; then + cat dwz.err + exit 1 +fi + +if [ $(grep -qv "DWARF compression not beneficial" dwz.err \ + | wc -l) -gt 0 ]; then + cat dwz.err + exit 1 +fi + +[ $status -eq 0 ] + +cmp 1 1.saved + +rm -f 1 1.saved 2 2.saved dwz.err diff --git a/testsuite/dwz.tests/twice-multifile.sh b/testsuite/dwz.tests/twice-multifile.sh new file mode 100644 index 0000000..1ff0166 --- /dev/null +++ b/testsuite/dwz.tests/twice-multifile.sh @@ -0,0 +1,34 @@ +cp $execs/hello 1 +cp 1 2 + +dwz 1 2 + +smaller-than.sh 1 $execs/hello +smaller-than.sh 2 $execs/hello + +cp 1 1.saved +cp 2 2.saved + +if dwz -m 3 1 2 2>dwz.err; status=$?; then + true +fi + +if ! grep -q "DWARF compression not beneficial" dwz.err; then + cat dwz.err + exit 1 +fi + +if [ $(grep -qv "DWARF compression not beneficial" dwz.err \ + | wc -l) -gt 0 ]; then + cat dwz.err + exit 1 +fi + +if [ $status -ne 0 ]; then + cat dwz.err + exit 1 +fi + +smaller-than.sh 1 1.saved + +rm -f 1 1.saved 2 2.saved dwz.err 3 diff --git a/testsuite/dwz.tests/twice.sh b/testsuite/dwz.tests/twice.sh new file mode 100644 index 0000000..210a966 --- /dev/null +++ b/testsuite/dwz.tests/twice.sh @@ -0,0 +1,28 @@ +cp $execs/hello 1 + +dwz 1 + +smaller-than.sh 1 $execs/hello + +cp 1 1.saved + +if dwz 1 2>dwz.err; status=$?; then + true +fi + +if ! grep -q "DWARF compression not beneficial" dwz.err; then + cat dwz.err + exit 1 +fi + +if [ $(grep -qv "DWARF compression not beneficial" dwz.err \ + | wc -l) -gt 0 ]; then + cat dwz.err + exit 1 +fi + +[ $status -eq 0 ] + +cmp 1 1.saved + +rm -f 1 1.saved dwz.err diff --git a/testsuite/dwz.tests/two-files-low-mem-die-limit-0.sh b/testsuite/dwz.tests/two-files-low-mem-die-limit-0.sh new file mode 100644 index 0000000..ee31359 --- /dev/null +++ b/testsuite/dwz.tests/two-files-low-mem-die-limit-0.sh @@ -0,0 +1,15 @@ +cp $execs/hello 1 +cp 1 2 + +$execs/dwz-for-test \ + -l0 \ + --devel-trace \ + 1 2 \ + -j 1 \ + 2> dwz.err + +if grep -Eq "Compressing (1|2)$" dwz.err; then + exit 1 +fi + +rm -f 1 2 dwz.err diff --git a/testsuite/dwz.tests/two-files-too-many-dies-2.sh b/testsuite/dwz.tests/two-files-too-many-dies-2.sh new file mode 100644 index 0000000..91b5ccc --- /dev/null +++ b/testsuite/dwz.tests/two-files-too-many-dies-2.sh @@ -0,0 +1,22 @@ +cp $execs/hello 1 +cp $execs/dwz-for-test 2 + +limit=$(readelf -wi 2 \ + | grep '(DW_TAG' \ + | wc -l) +limit=$((limit - 1)) + +if dwz -L$limit 2 1 2>dwz.err; status=$?; then + true +fi + +if [ $status -eq 0 ]; then + echo "PR24301 workaround used" > dwz.info +else + [ $status -eq 1 ] +fi + +smaller-than.sh 1 $execs/hello +cmp 2 $execs/dwz-for-test + +rm -f 1 2 dwz.err diff --git a/testsuite/dwz.tests/two-files-too-many-dies.sh b/testsuite/dwz.tests/two-files-too-many-dies.sh new file mode 100644 index 0000000..13950ba --- /dev/null +++ b/testsuite/dwz.tests/two-files-too-many-dies.sh @@ -0,0 +1,17 @@ +cp $execs/hello 1 +cp 1 2 +if dwz -L0 1 2 2>dwz.err; status=$?; then + true +fi + +if ! grep -q "Too many DIEs, not optimizing" dwz.err; then + cat dwz.err + exit 1 +fi + +[ $status -eq 1 ] + +cmp 1 $execs/hello +cmp 2 $execs/hello + +rm -f 1 2 dwz.err diff --git a/testsuite/dwz.tests/two-typedef-2.c b/testsuite/dwz.tests/two-typedef-2.c new file mode 100644 index 0000000..8af8df6 --- /dev/null +++ b/testsuite/dwz.tests/two-typedef-2.c @@ -0,0 +1,6 @@ + +typedef long unsigned int size_t; + +#include "two-typedef.h" + +struct aaa var2; diff --git a/testsuite/dwz.tests/two-typedef.c b/testsuite/dwz.tests/two-typedef.c new file mode 100644 index 0000000..fb1e044 --- /dev/null +++ b/testsuite/dwz.tests/two-typedef.c @@ -0,0 +1,11 @@ +typedef long unsigned int size_t; + +#include "two-typedef.h" + +struct aaa var; + +int +main (void) +{ + return 0; +} diff --git a/testsuite/dwz.tests/two-typedef.h b/testsuite/dwz.tests/two-typedef.h new file mode 100644 index 0000000..1675f39 --- /dev/null +++ b/testsuite/dwz.tests/two-typedef.h @@ -0,0 +1,3 @@ +struct aaa { + size_t size; +}; diff --git a/testsuite/dwz.tests/varval.S b/testsuite/dwz.tests/varval.S new file mode 100644 index 0000000..09f65d9 --- /dev/null +++ b/testsuite/dwz.tests/varval.S @@ -0,0 +1,515 @@ +# Generated using gdb/testsuite/gdb.dwarf2/varval.exp from repo +# git://sourceware.org/git/binutils-gdb.git. + .section .debug_info +.Lcu1_begin: + .4byte .Lcu1_end - .Lcu1_start +.Lcu1_start: + .2byte 4 /* Version */ + .4byte .Labbrev1_begin /* Abbrevs */ + .byte 8 /* Pointer size */ + .uleb128 2 /* Abbrev (DW_TAG_compile_unit) */ + .sleb128 0x0004 +.Llabel1: + .uleb128 3 /* Abbrev (DW_TAG_base_type) */ + .uleb128 4 + .sleb128 0x5 + .ascii "int\0" +.Llabel2: + .uleb128 4 /* Abbrev (DW_TAG_pointer_type) */ + .4byte .Llabel1 - .Lcu1_begin +.Llabel4: + .uleb128 5 /* Abbrev (DW_TAG_variable) */ + .ascii "var_a\0" + .4byte .Llabel1 - .Lcu1_begin + .byte 1 + .uleb128 .Lexpr_end16 - .Lexpr_start15/* expression */ +.Lexpr_start15: + .byte 0x03 /* DW_OP_addr */ + .8byte var_a +.Lexpr_end16: +.Llabel12: + .uleb128 6 /* Abbrev (DW_TAG_variable) */ + .4byte .Llabel1 - .Lcu1_begin + .byte 1 +.Llabel5: + .uleb128 7 /* Abbrev (DW_TAG_variable) */ + .ascii "var_b\0" + .4byte .Llabel1 - .Lcu1_begin + .byte 1 + .uleb128 .Lexpr_end18 - .Lexpr_start17/* expression */ +.Lexpr_start17: + .byte 0x03 /* DW_OP_addr */ + .8byte var_b +.Lexpr_end18: +.Llabel6: + .uleb128 8 /* Abbrev (DW_TAG_variable) */ + .ascii "var_c\0" + .4byte .Llabel1 - .Lcu1_begin + .byte 1 + .sleb128 53 +.Llabel7: + .uleb128 9 /* Abbrev (DW_TAG_variable) */ + .ascii "var_p\0" + .4byte .Llabel2 - .Lcu1_begin + .byte 1 + .uleb128 .Lexpr_end20 - .Lexpr_start19/* expression */ +.Lexpr_start19: + .byte 0x03 /* DW_OP_addr */ + .8byte var_p +.Lexpr_end20: +.Llabel3: + .uleb128 10 /* Abbrev (DW_TAG_structure_type) */ + .sleb128 8*4 + .uleb128 11 /* Abbrev (DW_TAG_member) */ + .ascii "a\0" + .4byte .Llabel1 - .Lcu1_begin + .uleb128 0*4 + .uleb128 12 /* Abbrev (DW_TAG_member) */ + .ascii "b\0" + .4byte .Llabel1 - .Lcu1_begin + .uleb128 1*4 + .uleb128 13 /* Abbrev (DW_TAG_member) */ + .ascii "c\0" + .4byte .Llabel1 - .Lcu1_begin + .uleb128 2*4 + .uleb128 14 /* Abbrev (DW_TAG_member) */ + .ascii "d\0" + .4byte .Llabel1 - .Lcu1_begin + .uleb128 3*4 + .uleb128 15 /* Abbrev (DW_TAG_member) */ + .ascii "e\0" + .4byte .Llabel1 - .Lcu1_begin + .uleb128 4*4 + .uleb128 16 /* Abbrev (DW_TAG_member) */ + .ascii "f\0" + .4byte .Llabel1 - .Lcu1_begin + .uleb128 5*4 + .uleb128 17 /* Abbrev (DW_TAG_member) */ + .ascii "g\0" + .4byte .Llabel1 - .Lcu1_begin + .uleb128 6*4 + .uleb128 18 /* Abbrev (DW_TAG_member) */ + .ascii "h\0" + .4byte .Llabel1 - .Lcu1_begin + .uleb128 7*4 + .byte 0x0 /* Terminate children */ +.Llabel10: + .uleb128 19 /* Abbrev (DW_TAG_variable) */ + .ascii "var_s\0" + .4byte .Llabel3 - .Lcu1_begin + .byte 1 + .uleb128 .Lexpr_end22 - .Lexpr_start21/* expression */ +.Lexpr_start21: + .byte 0x03 /* DW_OP_addr */ + .8byte var_s +.Lexpr_end22: +.Llabel11: + .uleb128 20 /* Abbrev (DW_TAG_variable) */ + .ascii "var_untyped\0" + .byte 1 + .uleb128 .Lexpr_end24 - .Lexpr_start23/* expression */ +.Lexpr_start23: + .byte 0x03 /* DW_OP_addr */ + .8byte var_b +.Lexpr_end24: + .uleb128 21 /* Abbrev (DW_TAG_subprogram) */ + .ascii "main\0" + .8byte main_label - 4 + .8byte main_label - 4 + 11 + .4byte .Llabel1 - .Lcu1_begin + .byte 1 +.Llabel9: + .uleb128 22 /* Abbrev (DW_TAG_variable) */ + .ascii "varval\0" + .4byte .Llabel1 - .Lcu1_begin + .uleb128 .Lexpr_end26 - .Lexpr_start25/* expression */ +.Lexpr_start25: + .byte 0xfd /* DW_OP_GNU_variable_value */ + .4byte .Llabel4 + .byte 0x9f /* DW_OP_stack_value */ +.Lexpr_end26: +.Llabel14: + .uleb128 23 /* Abbrev (DW_TAG_variable) */ + .ascii "varval2\0" + .4byte .Llabel1 - .Lcu1_begin + .uleb128 .Lexpr_end28 - .Lexpr_start27/* expression */ +.Lexpr_start27: + .byte 0xfd /* DW_OP_GNU_variable_value */ + .4byte .Llabel12 + .byte 0x9f /* DW_OP_stack_value */ +.Lexpr_end28: +.Llabel13: + .uleb128 24 /* Abbrev (DW_TAG_variable) */ + .4byte .Llabel12 - .Lcu1_begin + .uleb128 .Lexpr_end30 - .Lexpr_start29/* expression */ +.Lexpr_start29: + .byte 0x03 /* DW_OP_addr */ + .8byte var_a +.Lexpr_end30: + .uleb128 25 /* Abbrev (DW_TAG_variable) */ + .ascii "constval\0" + .4byte .Llabel1 - .Lcu1_begin + .uleb128 .Lexpr_end32 - .Lexpr_start31/* expression */ +.Lexpr_start31: + .byte 0xfd /* DW_OP_GNU_variable_value */ + .4byte .Llabel6 + .byte 0x9f /* DW_OP_stack_value */ +.Lexpr_end32: + .uleb128 26 /* Abbrev (DW_TAG_variable) */ + .ascii "mixedval\0" + .4byte .Llabel1 - .Lcu1_begin + .uleb128 .Lexpr_end34 - .Lexpr_start33/* expression */ +.Lexpr_start33: + .byte 0xfd /* DW_OP_GNU_variable_value */ + .4byte .Llabel6 + .byte 0xfd /* DW_OP_GNU_variable_value */ + .4byte .Llabel5 + .byte 0x1b /* DW_OP_div */ + .byte 0xfd /* DW_OP_GNU_variable_value */ + .4byte .Llabel9 + .byte 0x22 /* DW_OP_plus */ + .byte 0x12 /* DW_OP_dup */ + .byte 0x22 /* DW_OP_plus */ + .byte 0xfd /* DW_OP_GNU_variable_value */ + .4byte .Llabel9 + .byte 0x1c /* DW_OP_minus */ + .byte 0x9f /* DW_OP_stack_value */ +.Lexpr_end34: + .uleb128 27 /* Abbrev (DW_TAG_variable) */ + .ascii "pointerval\0" + .4byte .Llabel2 - .Lcu1_begin + .uleb128 .Lexpr_end36 - .Lexpr_start35/* expression */ +.Lexpr_start35: + .byte 0xfd /* DW_OP_GNU_variable_value */ + .4byte .Llabel7 + .byte 0x9f /* DW_OP_stack_value */ +.Lexpr_end36: + .uleb128 28 /* Abbrev (DW_TAG_variable) */ + .ascii "structval\0" + .4byte .Llabel3 - .Lcu1_begin + .uleb128 .Lexpr_end38 - .Lexpr_start37/* expression */ +.Lexpr_start37: + .byte 0xfd /* DW_OP_GNU_variable_value */ + .4byte .Llabel10 + .byte 0x9f /* DW_OP_stack_value */ +.Lexpr_end38: + .uleb128 29 /* Abbrev (DW_TAG_variable) */ + .ascii "untypedval\0" + .uleb128 .Lexpr_end40 - .Lexpr_start39/* expression */ +.Lexpr_start39: + .byte 0xfd /* DW_OP_GNU_variable_value */ + .4byte .Llabel11 + .byte 0x9f /* DW_OP_stack_value */ +.Lexpr_end40: + .byte 0x0 /* Terminate children */ + .byte 0x0 /* Terminate children */ +.Lcu1_end: + .section .debug_abbrev +.Labbrev1_begin: + .uleb128 2 /* Abbrev start */ + .uleb128 0x11 /* DW_TAG_compile_unit */ + .byte 1 /* has_children */ + .uleb128 0x13 /* DW_AT_language */ + .uleb128 0x0d /* DW_FORM_sdata */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 3 /* Abbrev start */ + .uleb128 0x24 /* DW_TAG_base_type */ + .byte 0 /* has_children */ + .uleb128 0x0b /* DW_AT_byte_size */ + .uleb128 0x0f /* DW_FORM_udata */ + .uleb128 0x3e /* DW_AT_encoding */ + .uleb128 0x0d /* DW_FORM_sdata */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 4 /* Abbrev start */ + .uleb128 0x0f /* DW_TAG_pointer_type */ + .byte 0 /* has_children */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 5 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x3f /* DW_AT_external */ + .uleb128 0x0c /* DW_FORM_flag */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x18 /* DW_FORM_exprloc */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 6 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x3f /* DW_AT_external */ + .uleb128 0x0c /* DW_FORM_flag */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 7 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x3f /* DW_AT_external */ + .uleb128 0x0c /* DW_FORM_flag */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x18 /* DW_FORM_exprloc */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 8 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x3f /* DW_AT_external */ + .uleb128 0x0c /* DW_FORM_flag */ + .uleb128 0x1c /* DW_AT_const_value */ + .uleb128 0x0d /* DW_FORM_sdata */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 9 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x3f /* DW_AT_external */ + .uleb128 0x0c /* DW_FORM_flag */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x18 /* DW_FORM_exprloc */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 10 /* Abbrev start */ + .uleb128 0x13 /* DW_TAG_structure_type */ + .byte 1 /* has_children */ + .uleb128 0x0b /* DW_AT_byte_size */ + .uleb128 0x0d /* DW_FORM_sdata */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 11 /* Abbrev start */ + .uleb128 0x0d /* DW_TAG_member */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x38 /* DW_AT_data_member_location */ + .uleb128 0x0f /* DW_FORM_udata */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 12 /* Abbrev start */ + .uleb128 0x0d /* DW_TAG_member */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x38 /* DW_AT_data_member_location */ + .uleb128 0x0f /* DW_FORM_udata */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 13 /* Abbrev start */ + .uleb128 0x0d /* DW_TAG_member */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x38 /* DW_AT_data_member_location */ + .uleb128 0x0f /* DW_FORM_udata */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 14 /* Abbrev start */ + .uleb128 0x0d /* DW_TAG_member */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x38 /* DW_AT_data_member_location */ + .uleb128 0x0f /* DW_FORM_udata */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 15 /* Abbrev start */ + .uleb128 0x0d /* DW_TAG_member */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x38 /* DW_AT_data_member_location */ + .uleb128 0x0f /* DW_FORM_udata */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 16 /* Abbrev start */ + .uleb128 0x0d /* DW_TAG_member */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x38 /* DW_AT_data_member_location */ + .uleb128 0x0f /* DW_FORM_udata */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 17 /* Abbrev start */ + .uleb128 0x0d /* DW_TAG_member */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x38 /* DW_AT_data_member_location */ + .uleb128 0x0f /* DW_FORM_udata */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 18 /* Abbrev start */ + .uleb128 0x0d /* DW_TAG_member */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x38 /* DW_AT_data_member_location */ + .uleb128 0x0f /* DW_FORM_udata */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 19 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x3f /* DW_AT_external */ + .uleb128 0x0c /* DW_FORM_flag */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x18 /* DW_FORM_exprloc */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 20 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x3f /* DW_AT_external */ + .uleb128 0x0c /* DW_FORM_flag */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x18 /* DW_FORM_exprloc */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 21 /* Abbrev start */ + .uleb128 0x2e /* DW_TAG_subprogram */ + .byte 1 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x11 /* DW_AT_low_pc */ + .uleb128 0x01 /* DW_FORM_addr */ + .uleb128 0x12 /* DW_AT_high_pc */ + .uleb128 0x01 /* DW_FORM_addr */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x3f /* DW_AT_external */ + .uleb128 0x0c /* DW_FORM_flag */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 22 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x18 /* DW_FORM_exprloc */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 23 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x18 /* DW_FORM_exprloc */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 24 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x31 /* DW_AT_abstract_origin */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x18 /* DW_FORM_exprloc */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 25 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x18 /* DW_FORM_exprloc */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 26 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x18 /* DW_FORM_exprloc */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 27 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x18 /* DW_FORM_exprloc */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 28 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x18 /* DW_FORM_exprloc */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .uleb128 29 /* Abbrev start */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x03 /* DW_AT_name */ + .uleb128 0x08 /* DW_FORM_string */ + .uleb128 0x02 /* DW_AT_location */ + .uleb128 0x18 /* DW_FORM_exprloc */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .section .note.GNU-stack,"",@progbits diff --git a/testsuite/dwz.tests/varval.c b/testsuite/dwz.tests/varval.c new file mode 100644 index 0000000..f76bfa8 --- /dev/null +++ b/testsuite/dwz.tests/varval.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2018-2019 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 <http://www.gnu.org/licenses/>. + + This was copied from the git://sourceware.org/git/binutils-gdb.git + repository, file gdb/testsuite/gdb.dwarf2/varval.c. */ + +/* Test program for DW_OP_GNU_variable_value. */ + +int var_a = 8; +int var_b = 3; +int *var_p = &var_b; +struct { int a, b, c, d, e, f, g, h; } var_s = { 101, 102, 103, 104, 105, 106, 107, 108 }; + +int +main (void) +{ + asm ("main_label: .globl main_label"); + return 0; +} diff --git a/testsuite/dwz.tests/version.sh b/testsuite/dwz.tests/version.sh new file mode 100644 index 0000000..fb000c7 --- /dev/null +++ b/testsuite/dwz.tests/version.sh @@ -0,0 +1,9 @@ +cp $execs/hello 1 + +dwz -v 1 > dwz.out 2> /dev/null + +grep -q "dwz version" dwz.out + +cmp 1 $execs/hello + +rm -f 1 dwz.out diff --git a/testsuite/lib/dwarf-lib.exp b/testsuite/lib/dwarf-lib.exp new file mode 100644 index 0000000..aca710e --- /dev/null +++ b/testsuite/lib/dwarf-lib.exp @@ -0,0 +1,28 @@ +# Copyright 2019 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 <http://www.gnu.org/licenses/>. + +# Auxiliary stuff to make the dwarf assembler in dwarf.exp work outside of the +# gdb testsuite context. We don't add this to dwarf.exp to keep differences +# between dwz's dwarf.exp and gdb's dwarf.exp minimal. + +proc is_64_target {} { + if { $::env(POINTER_SIZE) == 8 } { + return 1 + } elseif { $::env(POINTER_SIZE) == 4 } { + return 0 + } else { + error "POINTER_SIZE not defined in env" + } +} diff --git a/testsuite/lib/dwarf.exp b/testsuite/lib/dwarf.exp new file mode 100644 index 0000000..4dbbc6c --- /dev/null +++ b/testsuite/lib/dwarf.exp @@ -0,0 +1,1674 @@ +# Copyright 2010-2020 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 <http://www.gnu.org/licenses/>. + +# This was copied from the git://sourceware.org/git/binutils-gdb.git +# repository, file gdb/testsuite/lib/dwarf.exp + +# Return true if the target supports DWARF-2 and uses gas. +# For now pick a sampling of likely targets. +proc dwarf2_support {} { + if {[istarget *-*-linux*] + || [istarget *-*-gnu*] + || [istarget *-*-elf*] + || [istarget *-*-openbsd*] + || [istarget arm*-*-eabi*] + || [istarget arm*-*-symbianelf*] + || [istarget powerpc-*-eabi*]} { + return 1 + } + + 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. +# +# 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" + 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] + verbose -log "objcopy --extract-dwo output: $output" + if { $result == 1 } { + return -1 + } + + set command "$objcopy --strip-dwo $object_file" + verbose -log "Executing $command" + set result [catch "exec $command" output] + verbose -log "objcopy --strip-dwo output: $output" + if { $result == 1 } { + return -1 + } + + set result [gdb_compile $object_file $executable executable $options] + if { "$result" != "" } { + return -1 + } + + return 0 +} + +# Return a list of expressions about function FUNC's address and length. +# The first expression is the address of function FUNC, and the second +# one is FUNC's length. SRC is the source file having function FUNC. +# An internal label ${func}_label must be defined inside FUNC: +# +# int main (void) +# { +# asm ("main_label: .globl main_label"); +# return 0; +# } +# +# This label is needed to compute the start address of function FUNC. +# If the compiler is gcc, we can do the following to get function start +# and end address too: +# +# asm ("func_start: .globl func_start"); +# static void func (void) {} +# asm ("func_end: .globl func_end"); +# +# however, this isn't portable, because other compilers, such as clang, +# may not guarantee the order of global asms and function. The code +# becomes: +# +# asm ("func_start: .globl func_start"); +# asm ("func_end: .globl func_end"); +# static void func (void) {} +# + +proc function_range { func src {options {debug}} } { + global decimal gdb_prompt + + set exe [standard_temp_file func_addr[pid].x] + + gdb_compile $src $exe executable $options + + gdb_exit + gdb_start + gdb_load "$exe" + + # Compute the label offset, and we can get the function start address + # by "${func}_label - $func_label_offset". + set func_label_offset "" + set test "p ${func}_label - ${func}" + gdb_test_multiple $test $test { + -re ".* = ($decimal)\r\n$gdb_prompt $" { + set func_label_offset $expect_out(1,string) + } + } + + # Compute the function length. + global hex + set func_length "" + set test "disassemble $func" + gdb_test_multiple $test $test { + -re ".*$hex <\\+($decimal)>:\[^\r\n\]+\r\nEnd of assembler dump\.\r\n$gdb_prompt $" { + set func_length $expect_out(1,string) + } + } + + # Compute the size of the last instruction. + if { $func_length == 0 } then { + set func_pattern "$func" + } else { + set func_pattern "$func\\+$func_length" + } + set test "x/2i $func+$func_length" + gdb_test_multiple $test $test { + -re ".*($hex) <$func_pattern>:\[^\r\n\]+\r\n\[ \]+($hex).*\.\r\n$gdb_prompt $" { + set start $expect_out(1,string) + set end $expect_out(2,string) + + set func_length [expr $func_length + $end - $start] + } + } + + return [list "${func}_label - $func_label_offset" $func_length] +} + +# Extract the start, length, and end for function called NAME and +# create suitable variables in the callers scope. +proc get_func_info { name {options {debug}} } { + global srcdir subdir srcfile + + upvar 1 "${name}_start" func_start + upvar 1 "${name}_len" func_len + upvar 1 "${name}_end" func_end + + lassign [function_range ${name} \ + [list ${srcdir}/${subdir}/$srcfile] \ + ${options}] \ + func_start func_len + set func_end "$func_start + $func_len" +} + +# A DWARF assembler. +# +# All the variables in this namespace are private to the +# implementation. Also, any procedure whose name starts with "_" is +# private as well. Do not use these. +# +# Exported functions are documented at their definition. +# +# In addition to the hand-written functions documented below, this +# module automatically generates a function for each DWARF tag. For +# most tags, two forms are made: a full name, and one with the +# "DW_TAG_" prefix stripped. For example, you can use either +# 'DW_TAG_compile_unit' or 'compile_unit' interchangeably. +# +# There are two exceptions to this rule: DW_TAG_variable and +# DW_TAG_namespace. For these, the full name must always be used, +# as the short name conflicts with Tcl builtins. (Should future +# versions of Tcl or DWARF add more conflicts, this list will grow. +# If you want to be safe you should always use the full names.) +# +# Each tag procedure is defined like: +# +# proc DW_TAG_mumble {{attrs {}} {children {}}} { ... } +# +# ATTRS is an optional list of attributes. +# It is run through 'subst' in the caller's context before processing. +# +# Each attribute in the list has one of two forms: +# 1. { NAME VALUE } +# 2. { NAME VALUE FORM } +# +# In each case, NAME is the attribute's name. +# This can either be the full name, like 'DW_AT_name', or a shortened +# name, like 'name'. These are fully equivalent. +# +# Besides DWARF standard attributes, assembler supports 'macro' attribute +# which will be substituted by one or more standard or macro attributes. +# supported macro attributes are: +# +# - MACRO_AT_range { FUNC } +# It is substituted by DW_AT_low_pc and DW_AT_high_pc with the start and +# end address of function FUNC in file $srcdir/$subdir/$srcfile. +# +# - MACRO_AT_func { FUNC } +# It is substituted by DW_AT_name with FUNC and MACRO_AT_range. +# +# If FORM is given, it should name a DW_FORM_ constant. +# This can either be the short form, like 'DW_FORM_addr', or a +# shortened version, like 'addr'. If the form is given, VALUE +# is its value; see below. In some cases, additional processing +# is done; for example, DW_FORM_strp manages the .debug_str +# section automatically. +# +# If FORM is 'SPECIAL_expr', then VALUE is treated as a location +# expression. The effective form is then DW_FORM_block or DW_FORM_exprloc +# for DWARF version >= 4, and VALUE is passed to the (internal) +# '_location' proc to be translated. +# This proc implements a miniature DW_OP_ assembler. +# +# If FORM is not given, it is guessed: +# * If VALUE starts with the "@" character, the rest of VALUE is +# looked up as a DWARF constant, and DW_FORM_sdata is used. For +# example, '@DW_LANG_c89' could be used. +# * If VALUE starts with the ":" character, then it is a label +# reference. The rest of VALUE is taken to be the name of a label, +# and DW_FORM_ref4 is used. See 'new_label' and 'define_label'. +# * If VALUE starts with the "%" character, then it is a label +# reference too, but DW_FORM_ref_addr is used. +# * Otherwise, if the attribute name has a default form (f.i. DW_FORM_addr for +# DW_AT_low_pc), then that one is used. +# * Otherwise, an error is reported. Either specify a form explicitly, or +# add a default for the the attribute name in _default_form. +# +# CHILDREN is just Tcl code that can be used to define child DIEs. It +# is evaluated in the caller's context. +# +# Currently this code is missing nice support for CFA handling, and +# probably other things as well. + +namespace eval Dwarf { + # True if the module has been initialized. + variable _initialized 0 + + # Constants from dwarf2.h. + variable _constants + # DW_AT short names. + variable _AT + # DW_FORM short names. + variable _FORM + # DW_OP short names. + variable _OP + + # The current output file. + variable _output_file + + # Note: The _cu_ values here also apply to type units (TUs). + # Think of a TU as a special kind of CU. + + # Current CU count. + variable _cu_count + + # The current CU's base label. + variable _cu_label + + # The current CU's version. + variable _cu_version + + # The current CU's address size. + variable _cu_addr_size + # The current CU's offset size. + variable _cu_offset_size + + # Label generation number. + variable _label_num + + # The deferred output array. The index is the section name; the + # contents hold the data for that section. + variable _deferred_output + + # If empty, we should write directly to the output file. + # Otherwise, this is the name of a section to write to. + variable _defer + + # The abbrev section. Typically .debug_abbrev but can be .debug_abbrev.dwo + # for Fission. + variable _abbrev_section + + # The next available abbrev number in the current CU's abbrev + # table. + variable _abbrev_num + + # The string table for this assembly. The key is the string; the + # value is the label for that string. + variable _strings + + # Current .debug_line unit count. + variable _line_count + + # Whether a file_name entry was seen. + variable _line_saw_file + + # Whether a line table program has been seen. + variable _line_saw_program + + # A Label for line table header generation. + variable _line_header_end_label + + # The address size for debug ranges section. + variable _debug_ranges_64_bit + + proc _process_one_constant {name value} { + variable _constants + variable _AT + variable _FORM + variable _OP + + set _constants($name) $value + + if {![regexp "^DW_(\[A-Z\]+)_(\[A-Za-z0-9_\]+)$" $name \ + ignore prefix name2]} { + error "non-matching name: $name" + } + + if {$name2 == "lo_user" || $name2 == "hi_user"} { + return + } + + # We only try to shorten some very common things. + # FIXME: CFA? + switch -exact -- $prefix { + TAG { + # Create two procedures for the tag. These call + # _handle_DW_TAG with the full tag name baked in; this + # does all the actual work. + proc $name {{attrs {}} {children {}}} \ + "_handle_DW_TAG $name \$attrs \$children" + + # Filter out ones that are known to clash. + if {$name2 == "variable" || $name2 == "namespace"} { + set name2 "tag_$name2" + } + + if {[info commands $name2] != {}} { + error "duplicate proc name: from $name" + } + + proc $name2 {{attrs {}} {children {}}} \ + "_handle_DW_TAG $name \$attrs \$children" + } + + AT { + set _AT($name2) $name + } + + FORM { + set _FORM($name2) $name + } + + OP { + set _OP($name2) $name + } + + default { + return + } + } + } + + proc _read_constants {} { + global srcdir hex decimal + + # DWARF name-matching regexp. + set dwrx "DW_\[a-zA-Z0-9_\]+" + # Whitespace regexp. + set ws "\[ \t\]+" + + set fd [open [file join $srcdir .. dwarf2.h]] + while {![eof $fd]} { + set line [gets $fd] + if {[regexp -- "^${ws}($dwrx)${ws}=${ws}($hex|$decimal),?$" \ + $line ignore name value ignore2]} { + _process_one_constant $name $value + } + } + close $fd + + set fd [open [file join $srcdir .. dwarf2.def]] + while {![eof $fd]} { + set line [gets $fd] + if {[regexp -- \ + "^DW_\[A-Z_\]+${ws}\\(($dwrx),${ws}($hex|$decimal)\\)$" \ + $line ignore name value ignore2]} { + _process_one_constant $name $value + } + } + close $fd + } + + proc _quote {string} { + # FIXME + return "\"${string}\\0\"" + } + + proc _nz_quote {string} { + # For now, no quoting is done. + return "\"${string}\"" + } + + proc _handle_DW_FORM {form value} { + switch -exact -- $form { + DW_FORM_string { + _op .ascii [_quote $value] + } + + DW_FORM_flag_present { + # We don't need to emit anything. + } + + DW_FORM_data4 - + DW_FORM_ref4 { + _op .4byte $value + } + + DW_FORM_ref_addr { + variable _cu_offset_size + variable _cu_version + variable _cu_addr_size + + if {$_cu_version == 2} { + set size $_cu_addr_size + } else { + set size $_cu_offset_size + } + + _op .${size}byte $value + } + + DW_FORM_sec_offset { + variable _cu_offset_size + _op .${_cu_offset_size}byte $value + } + + DW_FORM_ref1 - + DW_FORM_flag - + DW_FORM_data1 { + _op .byte $value + } + + DW_FORM_sdata { + _op .sleb128 $value + } + + DW_FORM_ref_udata - + DW_FORM_udata { + _op .uleb128 $value + } + + DW_FORM_addr { + variable _cu_addr_size + + _op .${_cu_addr_size}byte $value + } + + DW_FORM_data2 - + DW_FORM_ref2 { + _op .2byte $value + } + + DW_FORM_data8 - + DW_FORM_ref8 - + DW_FORM_ref_sig8 { + _op .8byte $value + } + + DW_FORM_data16 { + _op .8byte $value + } + + DW_FORM_strp { + variable _strings + variable _cu_offset_size + + if {![info exists _strings($value)]} { + set _strings($value) [new_label strp] + _defer_output .debug_string { + define_label $_strings($value) + _op .ascii [_quote $value] + } + } + + _op .${_cu_offset_size}byte $_strings($value) "strp: $value" + } + + SPECIAL_expr { + set l1 [new_label "expr_start"] + set l2 [new_label "expr_end"] + _op .uleb128 "$l2 - $l1" "expression" + define_label $l1 + _location $value + define_label $l2 + } + + DW_FORM_block1 { + set len [string length $value] + if {$len > 255} { + error "DW_FORM_block1 length too long" + } + _op .byte $len + _op .ascii [_nz_quote $value] + } + + DW_FORM_block2 - + DW_FORM_block4 - + + DW_FORM_block - + + DW_FORM_ref2 - + DW_FORM_indirect - + DW_FORM_exprloc - + + DW_FORM_strx - + DW_FORM_strx1 - + DW_FORM_strx2 - + DW_FORM_strx3 - + DW_FORM_strx4 - + + DW_FORM_GNU_addr_index - + DW_FORM_GNU_str_index - + DW_FORM_GNU_ref_alt - + DW_FORM_GNU_strp_alt - + + default { + error "unhandled form $form" + } + } + } + + proc _guess_form {value varname} { + upvar $varname new_value + + switch -exact -- [string range $value 0 0] { + @ { + # Constant reference. + variable _constants + + set new_value $_constants([string range $value 1 end]) + # Just the simplest. + return DW_FORM_sdata + } + + : { + # Label reference. + variable _cu_label + + set new_value "[string range $value 1 end] - $_cu_label" + + return DW_FORM_ref4 + } + + % { + # Label reference, an offset from .debug_info. + set new_value "[string range $value 1 end]" + + return DW_FORM_ref_addr + } + + default { + return "" + } + } + } + + proc _default_form { attr } { + switch -exact -- $attr { + DW_AT_low_pc { + return DW_FORM_addr + } + DW_AT_producer - + DW_AT_comp_dir - + DW_AT_linkage_name - + DW_AT_MIPS_linkage_name - + DW_AT_name { + return DW_FORM_string + } + } + return "" + } + + # Map NAME to its canonical form. + proc _map_name {name ary} { + variable $ary + + if {[info exists ${ary}($name)]} { + set name [set ${ary}($name)] + } + + return $name + } + + proc _handle_attribute { attr_name attr_value attr_form } { + variable _abbrev_section + variable _constants + variable _cu_version + + _handle_DW_FORM $attr_form $attr_value + + _defer_output $_abbrev_section { + if { $attr_form eq "SPECIAL_expr" } { + if { $_cu_version < 4 } { + set attr_form_comment "DW_FORM_block" + } else { + set attr_form_comment "DW_FORM_exprloc" + } + } else { + set attr_form_comment $attr_form + } + _op .uleb128 $_constants($attr_name) $attr_name + _op .uleb128 $_constants($attr_form) $attr_form_comment + } + } + + # Handle macro attribute MACRO_AT_range. + + proc _handle_macro_at_range { attr_value } { + if {[llength $attr_value] != 1} { + error "usage: MACRO_AT_range { func }" + } + + set func [lindex $attr_value 0] + global srcdir subdir srcfile + set src ${srcdir}/${subdir}/${srcfile} + set result [function_range $func $src] + + _handle_attribute DW_AT_low_pc [lindex $result 0] \ + DW_FORM_addr + _handle_attribute DW_AT_high_pc \ + "[lindex $result 0] + [lindex $result 1]" DW_FORM_addr + } + + # Handle macro attribute MACRO_AT_func. + + proc _handle_macro_at_func { attr_value } { + if {[llength $attr_value] != 1} { + error "usage: MACRO_AT_func { func file }" + } + _handle_attribute DW_AT_name [lindex $attr_value 0] DW_FORM_string + _handle_macro_at_range $attr_value + } + + proc _handle_DW_TAG {tag_name {attrs {}} {children {}}} { + variable _abbrev_section + variable _abbrev_num + variable _constants + + set has_children [expr {[string length $children] > 0}] + set my_abbrev [incr _abbrev_num] + + # We somewhat wastefully emit a new abbrev entry for each tag. + # There's no reason for this other than laziness. + _defer_output $_abbrev_section { + _op .uleb128 $my_abbrev "Abbrev start" + _op .uleb128 $_constants($tag_name) $tag_name + _op .byte $has_children "has_children" + } + + _op .uleb128 $my_abbrev "Abbrev ($tag_name)" + + foreach attr $attrs { + set attr_name [_map_name [lindex $attr 0] _AT] + + # When the length of ATTR is greater than 2, the last + # element of the list must be a form. The second through + # the penultimate elements are joined together and + # evaluated using subst. This allows constructs such as + # [gdb_target_symbol foo] to be used. + + if {[llength $attr] > 2} { + set attr_value [uplevel 2 [list subst [join [lrange $attr 1 end-1]]]] + } else { + set attr_value [uplevel 2 [list subst [lindex $attr 1]]] + } + + if { [string equal "MACRO_AT_func" $attr_name] } { + _handle_macro_at_func $attr_value + } elseif { [string equal "MACRO_AT_range" $attr_name] } { + _handle_macro_at_range $attr_value + } else { + if {[llength $attr] > 2} { + set attr_form [uplevel 2 [list subst [lindex $attr end]]] + + if { [string index $attr_value 0] == ":" } { + # It is a label, get its value. + _guess_form $attr_value attr_value + } + } else { + set attr_form [_guess_form $attr_value attr_value] + if { $attr_form eq "" } { + set attr_form [_default_form $attr_name] + } + if { $attr_form eq "" } { + error "No form for $attr_name $attr_value" + } + } + set attr_form [_map_name $attr_form _FORM] + + _handle_attribute $attr_name $attr_value $attr_form + } + } + + _defer_output $_abbrev_section { + # Terminator. + _op .byte 0x0 "DW_AT - Terminator" + _op .byte 0x0 "DW_FORM - Terminator" + } + + if {$has_children} { + uplevel 2 $children + + # Terminate children. + _op .byte 0x0 "Terminate children" + } + } + + proc _emit {string} { + variable _output_file + variable _defer + variable _deferred_output + + if {$_defer == ""} { + puts $_output_file $string + } else { + append _deferred_output($_defer) ${string}\n + } + } + + proc _section {name {flags ""} {type ""}} { + if {$flags == "" && $type == ""} { + _emit " .section $name" + } elseif {$type == ""} { + _emit " .section $name, \"$flags\"" + } else { + _emit " .section $name, \"$flags\", %$type" + } + } + + # SECTION_SPEC is a list of arguments to _section. + proc _defer_output {section_spec body} { + variable _defer + variable _deferred_output + + set old_defer $_defer + set _defer [lindex $section_spec 0] + + if {![info exists _deferred_output($_defer)]} { + set _deferred_output($_defer) "" + eval _section $section_spec + } + + uplevel $body + + set _defer $old_defer + } + + proc _defer_to_string {body} { + variable _defer + variable _deferred_output + + set old_defer $_defer + set _defer temp + + set _deferred_output($_defer) "" + + uplevel $body + + set result $_deferred_output($_defer) + unset _deferred_output($_defer) + + set _defer $old_defer + return $result + } + + proc _write_deferred_output {} { + variable _output_file + variable _deferred_output + + foreach section [array names _deferred_output] { + # The data already has a newline. + puts -nonewline $_output_file $_deferred_output($section) + } + + # Save some memory. + unset _deferred_output + } + + proc _op {name value {comment ""}} { + set text " ${name} ${value}" + if {$comment != ""} { + # Try to make stuff line up nicely. + while {[string length $text] < 40} { + append text " " + } + append text "/* ${comment} */" + } + _emit $text + } + + proc _compute_label {name} { + return ".L${name}" + } + + # Return a name suitable for use as a label. If BASE_NAME is + # specified, it is incorporated into the label name; this is to + # make debugging the generated assembler easier. If BASE_NAME is + # not specified a generic default is used. This proc does not + # define the label; see 'define_label'. 'new_label' attempts to + # ensure that label names are unique. + proc new_label {{base_name label}} { + variable _label_num + + return [_compute_label ${base_name}[incr _label_num]] + } + + # Define a label named NAME. Ordinarily, NAME comes from a call + # to 'new_label', but this is not required. + proc define_label {name} { + _emit "${name}:" + } + + # A higher-level interface to label handling. + # + # ARGS is a list of label descriptors. Each one is either a + # single element, or a list of two elements -- a name and some + # text. For each descriptor, 'new_label' is invoked. If the list + # form is used, the second element in the list is passed as an + # argument. The label name is used to define a variable in the + # enclosing scope; this can be used to refer to the label later. + # The label name is also used to define a new proc whose name is + # the label name plus a trailing ":". This proc takes a body as + # an argument and can be used to define the label at that point; + # then the body, if any, is evaluated in the caller's context. + # + # For example: + # + # declare_labels int_label + # something { ... $int_label } ;# refer to the label + # int_label: constant { ... } ;# define the label + proc declare_labels {args} { + foreach arg $args { + set name [lindex $arg 0] + set text [lindex $arg 1] + + if { $text == "" } { + set text $name + } + + upvar $name label_var + set label_var [new_label $text] + + proc ${name}: {args} [format { + define_label %s + uplevel $args + } $label_var] + } + } + + # This is a miniature assembler for location expressions. It is + # suitable for use in the attributes to a DIE. Its output is + # prefixed with "=" to make it automatically use DW_FORM_block. + # BODY is split by lines, and each line is taken to be a list. + # (FIXME should use 'info complete' here.) + # Each list's first element is the opcode, either short or long + # forms are accepted. + # FIXME argument handling + # FIXME move docs + proc _location {body} { + variable _constants + variable _cu_label + variable _cu_version + variable _cu_addr_size + variable _cu_offset_size + + foreach line [split $body \n] { + # Ignore blank lines, and allow embedded comments. + if {[lindex $line 0] == "" || [regexp -- {^[ \t]*#} $line]} { + continue + } + set opcode [_map_name [lindex $line 0] _OP] + _op .byte $_constants($opcode) $opcode + + switch -exact -- $opcode { + DW_OP_addr { + _op .${_cu_addr_size}byte [lindex $line 1] + } + + DW_OP_regx { + _op .uleb128 [lindex $line 1] + } + + DW_OP_pick - + DW_OP_const1u - + DW_OP_const1s { + _op .byte [lindex $line 1] + } + + DW_OP_const2u - + DW_OP_const2s { + _op .2byte [lindex $line 1] + } + + DW_OP_const4u - + DW_OP_const4s { + _op .4byte [lindex $line 1] + } + + DW_OP_const8u - + DW_OP_const8s { + _op .8byte [lindex $line 1] + } + + DW_OP_constu { + _op .uleb128 [lindex $line 1] + } + DW_OP_consts { + _op .sleb128 [lindex $line 1] + } + + DW_OP_plus_uconst { + _op .uleb128 [lindex $line 1] + } + + DW_OP_piece { + _op .uleb128 [lindex $line 1] + } + + DW_OP_bit_piece { + _op .uleb128 [lindex $line 1] + _op .uleb128 [lindex $line 2] + } + + DW_OP_skip - + DW_OP_bra { + _op .2byte [lindex $line 1] + } + + DW_OP_implicit_value { + set l1 [new_label "value_start"] + set l2 [new_label "value_end"] + _op .uleb128 "$l2 - $l1" + define_label $l1 + foreach value [lrange $line 1 end] { + switch -regexp -- $value { + {^0x[[:xdigit:]]{1,2}$} {_op .byte $value} + {^0x[[:xdigit:]]{4}$} {_op .2byte $value} + {^0x[[:xdigit:]]{8}$} {_op .4byte $value} + {^0x[[:xdigit:]]{16}$} {_op .8byte $value} + default { + error "bad value '$value' in DW_OP_implicit_value" + } + } + } + define_label $l2 + } + + DW_OP_implicit_pointer - + DW_OP_GNU_implicit_pointer { + if {[llength $line] != 3} { + error "usage: $opcode LABEL OFFSET" + } + + # Here label is a section offset. + set label [lindex $line 1] + if { $_cu_version == 2 } { + _op .${_cu_addr_size}byte $label + } else { + _op .${_cu_offset_size}byte $label + } + _op .sleb128 [lindex $line 2] + } + + DW_OP_GNU_variable_value { + if {[llength $line] != 2} { + error "usage: $opcode LABEL" + } + + # Here label is a section offset. + set label [lindex $line 1] + if { $_cu_version == 2 } { + _op .${_cu_addr_size}byte $label + } else { + _op .${_cu_offset_size}byte $label + } + } + + DW_OP_deref_size { + if {[llength $line] != 2} { + error "usage: DW_OP_deref_size SIZE" + } + + _op .byte [lindex $line 1] + } + + DW_OP_bregx { + _op .uleb128 [lindex $line 1] + _op .sleb128 [lindex $line 2] + } + + default { + if {[llength $line] > 1} { + error "Unimplemented: operands in location for $opcode" + } + } + } + } + } + + # Emit a DWARF CU. + # OPTIONS is a list with an even number of elements containing + # option-name and option-value pairs. + # Current options are: + # is_64 0|1 - boolean indicating if you want to emit 64-bit DWARF + # default = 0 (32-bit) + # version n - DWARF version number to emit + # default = 4 + # addr_size n - the size of addresses in bytes: 4, 8, or default + # default = default + # fission 0|1 - boolean indicating if generating Fission debug info + # default = 0 + # BODY is Tcl code that emits the DIEs which make up the body of + # the CU. It is evaluated in the caller's context. + proc cu {options body} { + variable _constants + variable _cu_count + variable _abbrev_section + variable _abbrev_num + variable _cu_label + variable _cu_version + variable _cu_addr_size + variable _cu_offset_size + + # Establish the defaults. + set is_64 0 + set _cu_version 4 + set _cu_addr_size default + set fission 0 + set section ".debug_info" + set _abbrev_section ".debug_abbrev" + + foreach { name value } $options { + set value [uplevel 1 "subst \"$value\""] + switch -exact -- $name { + is_64 { set is_64 $value } + version { set _cu_version $value } + addr_size { set _cu_addr_size $value } + fission { set fission $value } + default { error "unknown option $name" } + } + } + if {$_cu_addr_size == "default"} { + if {[is_64_target]} { + set _cu_addr_size 8 + } else { + set _cu_addr_size 4 + } + } + set _cu_offset_size [expr { $is_64 ? 8 : 4 }] + if { $fission } { + set section ".debug_info.dwo" + set _abbrev_section ".debug_abbrev.dwo" + } + + if {$_cu_version < 4} { + set _constants(SPECIAL_expr) $_constants(DW_FORM_block) + } else { + set _constants(SPECIAL_expr) $_constants(DW_FORM_exprloc) + } + + _section $section + + set cu_num [incr _cu_count] + set my_abbrevs [_compute_label "abbrev${cu_num}_begin"] + set _abbrev_num 1 + + set _cu_label [_compute_label "cu${cu_num}_begin"] + set start_label [_compute_label "cu${cu_num}_start"] + set end_label [_compute_label "cu${cu_num}_end"] + + define_label $_cu_label + if {$is_64} { + _op .4byte 0xffffffff + _op .8byte "$end_label - $start_label" + } else { + _op .4byte "$end_label - $start_label" + } + define_label $start_label + _op .2byte $_cu_version Version + _op .${_cu_offset_size}byte $my_abbrevs Abbrevs + _op .byte $_cu_addr_size "Pointer size" + + _defer_output $_abbrev_section { + define_label $my_abbrevs + } + + uplevel $body + + _defer_output $_abbrev_section { + # Emit the terminator. + _op .byte 0x0 "Abbrev end - Terminator" + } + + define_label $end_label + } + + # Emit a DWARF TU. + # OPTIONS is a list with an even number of elements containing + # option-name and option-value pairs. + # Current options are: + # is_64 0|1 - boolean indicating if you want to emit 64-bit DWARF + # default = 0 (32-bit) + # version n - DWARF version number to emit + # default = 4 + # addr_size n - the size of addresses in bytes: 4, 8, or default + # default = default + # fission 0|1 - boolean indicating if generating Fission debug info + # default = 0 + # SIGNATURE is the 64-bit signature of the type. + # TYPE_LABEL is the label of the type defined by this TU, + # or "" if there is no type (i.e., type stubs in Fission). + # BODY is Tcl code that emits the DIEs which make up the body of + # the TU. It is evaluated in the caller's context. + proc tu {options signature type_label body} { + variable _cu_count + variable _abbrev_section + variable _abbrev_num + variable _cu_label + variable _cu_version + variable _cu_addr_size + variable _cu_offset_size + + # Establish the defaults. + set is_64 0 + set _cu_version 4 + set _cu_addr_size default + set fission 0 + set section ".debug_types" + set _abbrev_section ".debug_abbrev" + + foreach { name value } $options { + switch -exact -- $name { + is_64 { set is_64 $value } + version { set _cu_version $value } + addr_size { set _cu_addr_size $value } + fission { set fission $value } + default { error "unknown option $name" } + } + } + if {$_cu_addr_size == "default"} { + if {[is_64_target]} { + set _cu_addr_size 8 + } else { + set _cu_addr_size 4 + } + } + set _cu_offset_size [expr { $is_64 ? 8 : 4 }] + if { $fission } { + set section ".debug_types.dwo" + set _abbrev_section ".debug_abbrev.dwo" + } + + _section $section + + set cu_num [incr _cu_count] + set my_abbrevs [_compute_label "abbrev${cu_num}_begin"] + set _abbrev_num 1 + + set _cu_label [_compute_label "cu${cu_num}_begin"] + set start_label [_compute_label "cu${cu_num}_start"] + set end_label [_compute_label "cu${cu_num}_end"] + + define_label $_cu_label + if {$is_64} { + _op .4byte 0xffffffff + _op .8byte "$end_label - $start_label" + } else { + _op .4byte "$end_label - $start_label" + } + define_label $start_label + _op .2byte $_cu_version Version + _op .${_cu_offset_size}byte $my_abbrevs Abbrevs + _op .byte $_cu_addr_size "Pointer size" + _op .8byte $signature Signature + if { $type_label != "" } { + uplevel declare_labels $type_label + upvar $type_label my_type_label + if {$is_64} { + _op .8byte "$my_type_label - $_cu_label" + } else { + _op .4byte "$my_type_label - $_cu_label" + } + } else { + if {$is_64} { + _op .8byte 0 + } else { + _op .4byte 0 + } + } + + _defer_output $_abbrev_section { + define_label $my_abbrevs + } + + uplevel $body + + _defer_output $_abbrev_section { + # Emit the terminator. + _op .byte 0x0 "Abbrev end - Terminator" + } + + define_label $end_label + } + + # Emit a DWARF .debug_ranges unit. + # OPTIONS is a list with an even number of elements containing + # option-name and option-value pairs. + # Current options are: + # is_64 0|1 - boolean indicating if you want to emit 64-bit DWARF + # default = 0 (32-bit) + # + # BODY is Tcl code that emits the content of the .debug_ranges + # unit, it is evaluated in the caller's context. + proc ranges {options body} { + variable _debug_ranges_64_bit + + foreach { name value } $options { + switch -exact -- $name { + is_64 { set _debug_ranges_64_bit [subst $value] } + default { error "unknown option $name" } + } + } + + set section ".debug_ranges" + _section $section + + proc sequence { body } { + variable _debug_ranges_64_bit + + # Emit the sequence of addresses. + + proc base { addr } { + variable _debug_ranges_64_bit + + if { $_debug_ranges_64_bit } then { + _op .8byte 0xffffffffffffffff "Base Marker" + _op .8byte $addr "Base Address" + } else { + _op .4byte 0xffffffff "Base Marker" + _op .4byte $addr "Base Address" + } + } + + proc range { start end } { + variable _debug_ranges_64_bit + + if { $_debug_ranges_64_bit } then { + _op .8byte $start "Start Address" + _op .8byte $end "End Address" + } else { + _op .4byte $start "Start Address" + _op .4byte $end "End Address" + } + } + + uplevel $body + + # End of the sequence. + if { $_debug_ranges_64_bit } then { + _op .8byte 0x0 "End of Sequence Marker (Part 1)" + _op .8byte 0x0 "End of Sequence Marker (Part 2)" + } else { + _op .4byte 0x0 "End of Sequence Marker (Part 1)" + _op .4byte 0x0 "End of Sequence Marker (Part 2)" + } + } + + uplevel $body + } + + + # Emit a DWARF .debug_line unit. + # OPTIONS is a list with an even number of elements containing + # option-name and option-value pairs. + # Current options are: + # is_64 0|1 - boolean indicating if you want to emit 64-bit DWARF + # default = 0 (32-bit) + # version n - DWARF version number to emit + # default = 4 + # addr_size n - the size of addresses in bytes: 4, 8, or default + # default = default + # + # LABEL is the label of the current unit (which is probably + # referenced by a DW_AT_stmt_list), or "" if there is no such + # label. + # + # BODY is Tcl code that emits the parts which make up the body of + # the line unit. It is evaluated in the caller's context. The + # following commands are available for the BODY section: + # + # include_dir "dirname" -- adds a new include directory + # + # file_name "file.c" idx -- adds a new file name. IDX is a + # 1-based index referencing an include directory or 0 for + # current directory. + + proc lines {options label body} { + variable _line_count + variable _line_saw_file + variable _line_saw_program + variable _line_header_end_label + + # Establish the defaults. + set is_64 0 + set _unit_version 4 + set _unit_addr_size default + set _line_saw_program 0 + set _line_saw_file 0 + set _default_is_stmt 1 + + foreach { name value } $options { + switch -exact -- $name { + is_64 { set is_64 $value } + version { set _unit_version $value } + addr_size { set _unit_addr_size $value } + default_is_stmt { set _default_is_stmt $value } + default { error "unknown option $name" } + } + } + if {$_unit_addr_size == "default"} { + if {[is_64_target]} { + set _unit_addr_size 8 + } else { + set _unit_addr_size 4 + } + } + + set unit_num [incr _line_count] + + set section ".debug_line" + _section $section + + if { "$label" != "" } { + # Define the user-provided label at this point. + $label: + } + + set unit_len_label [_compute_label "line${_line_count}_start"] + set unit_end_label [_compute_label "line${_line_count}_end"] + set header_len_label [_compute_label "line${_line_count}_header_start"] + set _line_header_end_label [_compute_label "line${_line_count}_header_end"] + + if {$is_64} { + _op .4byte 0xffffffff + _op .8byte "$unit_end_label - $unit_len_label" "unit_length" + } else { + _op .4byte "$unit_end_label - $unit_len_label" "unit_length" + } + + define_label $unit_len_label + + _op .2byte $_unit_version version + + if {$is_64} { + _op .8byte "$_line_header_end_label - $header_len_label" "header_length" + } else { + _op .4byte "$_line_header_end_label - $header_len_label" "header_length" + } + + define_label $header_len_label + + _op .byte 1 "minimum_instruction_length" + _op .byte $_default_is_stmt "default_is_stmt" + _op .byte 1 "line_base" + _op .byte 1 "line_range" + _op .byte 10 "opcode_base" + + # The standard_opcode_lengths table. The number of arguments + # for each of the standard opcodes. Generating 9 entries here + # matches the use of 10 in the opcode_base above. These 9 + # entries match the 9 standard opcodes for DWARF2, making use + # of only 9 should be fine, even if we are generating DWARF3 + # or DWARF4. + _op .byte 0 "standard opcode 1" + _op .byte 1 "standard opcode 2" + _op .byte 1 "standard opcode 3" + _op .byte 1 "standard opcode 4" + _op .byte 1 "standard opcode 5" + _op .byte 0 "standard opcode 6" + _op .byte 0 "standard opcode 7" + _op .byte 0 "standard opcode 8" + _op .byte 1 "standard opcode 9" + + proc include_dir {dirname} { + _op .ascii [_quote $dirname] + } + + proc file_name {filename diridx} { + variable _line_saw_file + if "! $_line_saw_file" { + # Terminate the dir list. + _op .byte 0 "Terminator." + set _line_saw_file 1 + } + + _op .ascii [_quote $filename] + _op .sleb128 $diridx + _op .sleb128 0 "mtime" + _op .sleb128 0 "length" + } + + proc program {statements} { + variable _line_saw_program + variable _line_header_end_label + variable _line + + set _line 1 + + if "! $_line_saw_program" { + # Terminate the file list. + _op .byte 0 "Terminator." + define_label $_line_header_end_label + set _line_saw_program 1 + } + + proc DW_LNE_set_address {addr} { + _op .byte 0 + set start [new_label "set_address_start"] + set end [new_label "set_address_end"] + _op .uleb128 "${end} - ${start}" + define_label ${start} + _op .byte 2 + if {[is_64_target]} { + _op .8byte ${addr} + } else { + _op .4byte ${addr} + } + define_label ${end} + } + + proc DW_LNE_end_sequence {} { + variable _line + _op .byte 0 + _op .uleb128 1 + _op .byte 1 + set _line 1 + } + + proc DW_LNE_user { len opcode } { + set DW_LNE_lo_usr 0x80 + set DW_LNE_hi_usr 0xff + if { $DW_LNE_lo_usr <= $opcode + && $opcode <= $DW_LNE_hi_usr } { + _op .byte 0 + _op .uleb128 $len + _op .byte $opcode + for {set i 1} {$i < $len} {incr i} { + _op .byte 0 + } + } else { + error "unknown vendor specific extended opcode: $opcode" + } + } + + proc DW_LNS_copy {} { + _op .byte 1 + } + + proc DW_LNS_negate_stmt {} { + _op .byte 6 + } + + proc DW_LNS_advance_pc {offset} { + _op .byte 2 + _op .uleb128 ${offset} + } + + proc DW_LNS_advance_line {offset} { + variable _line + _op .byte 3 + _op .sleb128 ${offset} + set _line [expr $_line + $offset] + } + + # A pseudo line number program instruction, that can be used instead + # of DW_LNS_advance_line. Rather than writing: + # {DW_LNS_advance_line [expr $line1 - 1]} + # {DW_LNS_advance_line [expr $line2 - $line1]} + # {DW_LNS_advance_line [expr $line3 - $line2]} + # we can just write: + # {line $line1} + # {line $line2} + # {line $line3} + proc line {line} { + variable _line + set offset [expr $line - $_line] + DW_LNS_advance_line $offset + } + + proc DW_LNS_set_file {num} { + _op .byte 4 + _op .sleb128 ${num} + } + + foreach statement $statements { + uplevel 1 $statement + } + } + + uplevel $body + + rename include_dir "" + rename file_name "" + + # Terminate dir list if we saw no files. + if "! $_line_saw_file" { + _op .byte 0 "Terminator." + } + + # Terminate the file list. + if "! $_line_saw_program" { + _op .byte 0 "Terminator." + define_label $_line_header_end_label + } + + define_label $unit_end_label + } + + proc _empty_array {name} { + upvar $name the_array + + catch {unset the_array} + set the_array(_) {} + unset the_array(_) + } + + # Emit a .gnu_debugaltlink section with the given file name and + # build-id. The buildid should be represented as a hexadecimal + # string, like "ffeeddcc". + proc gnu_debugaltlink {filename buildid} { + _defer_output .gnu_debugaltlink { + _op .ascii [_quote $filename] + foreach {a b} [split $buildid {}] { + _op .byte 0x$a$b + } + } + } + + proc _note {type name hexdata} { + set namelen [expr [string length $name] + 1] + + # Name size. + _op .4byte $namelen + # Data size. + _op .4byte [expr [string length $hexdata] / 2] + # Type. + _op .4byte $type + # The name. + _op .ascii [_quote $name] + # Alignment. + set align 2 + set total [expr {($namelen + (1 << $align) - 1) & -(1 << $align)}] + for {set i $namelen} {$i < $total} {incr i} { + _op .byte 0 + } + # The data. + foreach {a b} [split $hexdata {}] { + _op .byte 0x$a$b + } + } + + # Emit a note section holding the given build-id. + proc build_id {buildid} { + _defer_output {.note.gnu.build-id a note} { + # From elf/common.h. + set NT_GNU_BUILD_ID 3 + + _note $NT_GNU_BUILD_ID GNU $buildid + } + } + + # The top-level interface to the DWARF assembler. + # FILENAME is the name of the file where the generated assembly + # code is written. + # BODY is Tcl code to emit the assembly. It is evaluated via + # "eval" -- not uplevel as you might expect, because it is + # important to run the body in the Dwarf namespace. + # + # A typical invocation is something like: + # Dwarf::assemble $file { + # cu 0 2 8 { + # compile_unit { + # ... + # } + # } + # cu 0 2 8 { + # ... + # } + # } + proc assemble {filename body} { + variable _initialized + variable _output_file + variable _deferred_output + variable _defer + variable _label_num + variable _strings + variable _cu_count + variable _line_count + variable _line_saw_file + variable _line_saw_program + variable _line_header_end_label + variable _debug_ranges_64_bit + + if {!$_initialized} { + _read_constants + set _initialized 1 + } + + set _output_file [open $filename w] + set _cu_count 0 + _empty_array _deferred_output + set _defer "" + set _label_num 0 + _empty_array _strings + + set _line_count 0 + set _line_saw_file 0 + set _line_saw_program 0 + set _debug_ranges_64_bit [is_64_target] + + # 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. + eval $body + + _write_deferred_output + + _section .note.GNU-stack "" progbits + + catch {close $_output_file} + set _output_file {} + } +} diff --git a/testsuite/lib/dwz.exp b/testsuite/lib/dwz.exp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testsuite/lib/dwz.exp diff --git a/testsuite/lib/invalid-dw-at-stmt-list-encoding.exp b/testsuite/lib/invalid-dw-at-stmt-list-encoding.exp new file mode 100644 index 0000000..490fca4 --- /dev/null +++ b/testsuite/lib/invalid-dw-at-stmt-list-encoding.exp @@ -0,0 +1,21 @@ +load_lib dwarf-lib.exp +load_lib dwarf.exp + +set asm_file invalid-dw-at-stmt-list-encoding-dw.S + +Dwarf::assemble $asm_file { + cu {} { + DW_TAG_compile_unit { + {DW_AT_language @DW_LANG_C} + {DW_AT_name foo.c} + {DW_AT_comp_dir /bar} + {stmt_list 0 DW_FORM_addr} + } { + DW_TAG_base_type { + {DW_AT_byte_size 4 DW_FORM_data1} + {DW_AT_name integer} + } + } + } + +} diff --git a/testsuite/lib/no-multifile-prop.exp b/testsuite/lib/no-multifile-prop.exp new file mode 100644 index 0000000..bcd9669 --- /dev/null +++ b/testsuite/lib/no-multifile-prop.exp @@ -0,0 +1,132 @@ +# Copyright 2019 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 <http://www.gnu.org/licenses/>. + +load_lib dwarf-lib.exp +load_lib dwarf.exp + +set asm_file no-multifile-prop-dw.S + +Dwarf::assemble $asm_file { + + # CU 1 + cu {} { + DW_TAG_compile_unit { + {DW_AT_language @DW_LANG_C_plus_plus} + {DW_AT_name 1.c} + {DW_AT_comp_dir /tmp} + } { + declare_labels integer_label var_label + + integer_label: DW_TAG_base_type { + {DW_AT_byte_size 4 DW_FORM_data1} + {DW_AT_encoding @DW_ATE_signed} + {DW_AT_name integer} + } + + var_label: DW_TAG_variable { + {DW_AT_name foo1} + {DW_AT_type :$integer_label} + {external 1 flag} + } + + DW_TAG_variable { + {DW_AT_name foo2} + {DW_AT_type :$integer_label} + {DW_AT_location { + DW_OP_GNU_implicit_pointer $var_label 0 + } SPECIAL_expr} + {external 1 flag} + } + } + } + + # CU 2 + cu {} { + DW_TAG_compile_unit { + {DW_AT_language @DW_LANG_C_plus_plus} + {DW_AT_name 2.c} + {DW_AT_comp_dir /tmp} + } { + declare_labels integer_label var_label + + integer_label: DW_TAG_base_type { + {DW_AT_byte_size 4 DW_FORM_data1} + {DW_AT_encoding @DW_ATE_signed} + {DW_AT_name integer} + } + + var_label: DW_TAG_variable { + {DW_AT_name foo1} + {DW_AT_type :$integer_label} + {external 1 flag} + } + + DW_TAG_imported_declaration { + {DW_AT_import :$var_label} + } + } + } + + # CU 3 + cu {} { + DW_TAG_compile_unit { + {DW_AT_language @DW_LANG_C_plus_plus} + {DW_AT_name 3.c} + {DW_AT_comp_dir /tmp} + } { + declare_labels integer_label + + integer_label: DW_TAG_base_type { + {DW_AT_byte_size 4 DW_FORM_data1} + {DW_AT_encoding @DW_ATE_signed} + {DW_AT_name integer} + } + + DW_TAG_variable { + {DW_AT_name foo1} + {DW_AT_type :$integer_label} + {external 1 flag} + } + + } + } + + # CU 4 + cu {} { + DW_TAG_compile_unit { + {DW_AT_language @DW_LANG_C_plus_plus} + {DW_AT_name 4.c} + {DW_AT_comp_dir /tmp} + } { + declare_labels integer_label var_label + + integer_label: DW_TAG_base_type { + {DW_AT_byte_size 4 DW_FORM_data1} + {DW_AT_encoding @DW_ATE_signed} + {DW_AT_name integer} + } + + var_label: DW_TAG_variable { + {DW_AT_name foo1} + {DW_AT_type :$integer_label} + {external 1 flag} + } + + DW_TAG_imported_declaration { + {DW_AT_import :$var_label} + } + } + } +} diff --git a/testsuite/lib/unavailable-dwarf-piece.exp b/testsuite/lib/unavailable-dwarf-piece.exp new file mode 100644 index 0000000..0fa1df9 --- /dev/null +++ b/testsuite/lib/unavailable-dwarf-piece.exp @@ -0,0 +1,272 @@ +# Copyright (C) 2013-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 <http://www.gnu.org/licenses/>. + +load_lib dwarf-lib.exp +load_lib dwarf.exp + +set asm_file unavailable-dwarf-piece-dw.S + +Dwarf::assemble $asm_file { + declare_labels uchar_label struct_s_label foo_label struct_t_label bar_label + + cu {} { + compile_unit {{language @DW_LANG_C}} { + uchar_label: DW_TAG_base_type { + {name "unsigned char"} + {byte_size 1 DW_FORM_sdata} + {encoding @DW_ATE_unsigned_char} + } + + struct_s_label: DW_TAG_structure_type { + {name s} + {byte_size 3 DW_FORM_sdata} + {decl_file 0 DW_FORM_udata} + {decl_line 1 DW_FORM_sdata} + } { + DW_TAG_member { + {name a} + {type :$uchar_label} + {data_member_location { + DW_OP_plus_uconst 0 + } SPECIAL_expr} + } + DW_TAG_member { + {name b} + {type :$uchar_label} + {data_member_location { + DW_OP_plus_uconst 1 + } SPECIAL_expr} + } + DW_TAG_member { + {name c} + {type :$uchar_label} + {data_member_location { + DW_OP_plus_uconst 2 + } SPECIAL_expr} + } + } + + struct_t_label: DW_TAG_structure_type { + {name t} + {byte_size 3 DW_FORM_sdata} + {decl_file 0 DW_FORM_udata} + {decl_line 1 DW_FORM_sdata} + } { + DW_TAG_member { + {name a} + {type :$uchar_label} + {data_member_location { + DW_OP_plus_uconst 0 + } SPECIAL_expr} + } + DW_TAG_member { + {name b} + {type :$uchar_label} + {byte_size 1 DW_FORM_sdata} + {bit_size 1 DW_FORM_sdata} + {bit_offset 7 DW_FORM_sdata} + {data_member_location { + DW_OP_plus_uconst 1 + } SPECIAL_expr} + } + DW_TAG_member { + {name c} + {type :$uchar_label} + {byte_size 1 DW_FORM_sdata} + {bit_size 1 DW_FORM_sdata} + {bit_offset 6 DW_FORM_sdata} + {data_member_location { + DW_OP_plus_uconst 1 + } SPECIAL_expr} + } + DW_TAG_member { + {name d} + {type :$uchar_label} + {byte_size 1 DW_FORM_sdata} + {bit_size 1 DW_FORM_sdata} + {bit_offset 5 DW_FORM_sdata} + {data_member_location { + DW_OP_plus_uconst 1 + } SPECIAL_expr} + } + DW_TAG_member { + {name e} + {type :$uchar_label} + {byte_size 1 DW_FORM_sdata} + {bit_size 1 DW_FORM_sdata} + {bit_offset 4 DW_FORM_sdata} + {data_member_location { + DW_OP_plus_uconst 1 + } SPECIAL_expr} + } + DW_TAG_member { + {name f} + {type :$uchar_label} + {byte_size 1 DW_FORM_sdata} + {bit_size 1 DW_FORM_sdata} + {bit_offset 3 DW_FORM_sdata} + {data_member_location { + DW_OP_plus_uconst 1 + } SPECIAL_expr} + } + DW_TAG_member { + {name g} + {type :$uchar_label} + {byte_size 1 DW_FORM_sdata} + {bit_size 1 DW_FORM_sdata} + {bit_offset 2 DW_FORM_sdata} + {data_member_location { + DW_OP_plus_uconst 1 + } SPECIAL_expr} + } + DW_TAG_member { + {name h} + {type :$uchar_label} + {byte_size 1 DW_FORM_sdata} + {bit_size 1 DW_FORM_sdata} + {bit_offset 1 DW_FORM_sdata} + {data_member_location { + DW_OP_plus_uconst 1 + } SPECIAL_expr} + } + DW_TAG_member { + {name i} + {type :$uchar_label} + {byte_size 1 DW_FORM_sdata} + {bit_size 1 DW_FORM_sdata} + {bit_offset 0 DW_FORM_sdata} + {data_member_location { + DW_OP_plus_uconst 1 + } SPECIAL_expr} + } + DW_TAG_member { + {name j} + {type :$uchar_label} + {data_member_location { + DW_OP_plus_uconst 2 + } SPECIAL_expr} + } + } + + DW_TAG_subprogram { + {name foo} + {decl_file 0 udata} + {low_pc foo_start_lbl addr} + {high_pc foo_end_lbl addr} + } { + DW_TAG_formal_parameter { + {type :$struct_s_label} + {name x} + {location { + DW_OP_lit0 + DW_OP_stack_value + DW_OP_piece 2 + DW_OP_reg0 + DW_OP_piece 1 + } SPECIAL_expr} + } + DW_TAG_formal_parameter { + {type :$struct_s_label} + {name y} + {location { + DW_OP_lit0 + DW_OP_stack_value + DW_OP_piece 1 + DW_OP_reg0 + DW_OP_piece 1 + DW_OP_lit0 + DW_OP_stack_value + DW_OP_piece 1 + } SPECIAL_expr} + } + DW_TAG_formal_parameter { + {type :$struct_s_label} + {name z} + {location { + DW_OP_reg0 + DW_OP_piece 1 + DW_OP_lit0 + DW_OP_stack_value + DW_OP_piece 2 + } SPECIAL_expr} + } + } + + + DW_TAG_subprogram { + {name bar} + {decl_file 0 udata} + {low_pc bar_start_lbl addr} + {high_pc bar_end_lbl addr} + } { + DW_TAG_formal_parameter { + {type :$struct_t_label} + {name x} + {location { + DW_OP_lit0 + DW_OP_stack_value + DW_OP_piece 1 + DW_OP_reg0 + DW_OP_bit_piece 1 0 + DW_OP_lit0 + DW_OP_stack_value + DW_OP_bit_piece 7 0 + DW_OP_lit0 + DW_OP_stack_value + DW_OP_piece 1 + } SPECIAL_expr} + } + DW_TAG_formal_parameter { + {type :$struct_t_label} + {name y} + {location { + DW_OP_lit0 + DW_OP_stack_value + DW_OP_piece 1 + DW_OP_lit0 + DW_OP_stack_value + DW_OP_bit_piece 3 0 + DW_OP_reg0 + DW_OP_bit_piece 1 0 + DW_OP_lit0 + DW_OP_stack_value + DW_OP_bit_piece 4 0 + DW_OP_lit0 + DW_OP_stack_value + DW_OP_piece 1 + } SPECIAL_expr} + } + DW_TAG_formal_parameter { + {type :$struct_t_label} + {name z} + {location { + DW_OP_lit0 + DW_OP_stack_value + DW_OP_piece 1 + DW_OP_lit0 + DW_OP_stack_value + DW_OP_bit_piece 7 0 + DW_OP_reg0 + DW_OP_bit_piece 1 0 + DW_OP_lit0 + DW_OP_stack_value + DW_OP_piece 1 + } SPECIAL_expr} + } + } + + } + } +} diff --git a/testsuite/scripts/gnu-debugaltlink-name.sh b/testsuite/scripts/gnu-debugaltlink-name.sh new file mode 100755 index 0000000..667c5fd --- /dev/null +++ b/testsuite/scripts/gnu-debugaltlink-name.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +if ! readelf -S $1 | grep -q '\.gnu_debugaltlink'; then + exit +fi + +readelf \ + --string-dump=.gnu_debugaltlink \ + $1 \ + | grep -a '\[[ ]*0\]' \ + | sed 's/.*0\] //' diff --git a/testsuite/scripts/hardlinks-p.sh b/testsuite/scripts/hardlinks-p.sh new file mode 100755 index 0000000..a9a3020 --- /dev/null +++ b/testsuite/scripts/hardlinks-p.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +hardlinks=$(find -samefile "$1") + +for f in "$@"; do + found=false + for hl in $hardlinks; do + if [ "$hl" = "./$f" ]; then + found=true + break + fi + done + if ! $found; then + exit 1 + fi +done diff --git a/testsuite/scripts/smaller-than.sh b/testsuite/scripts/smaller-than.sh new file mode 100755 index 0000000..3b452dc --- /dev/null +++ b/testsuite/scripts/smaller-than.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +f1=$1 +f2=$2 + +section_size () +{ + local f="$1" + local section="$2" + + local s + s=$(readelf -S -W $f \ + | grep "\.debug_$section" \ + | sed 's/.*\.debug_//' \ + | awk '{print $5}') + + if [ "$s" = "" ]; then + echo 0 + return + fi + + # Convert hex to decimal. + s=$(printf "%d" $((16#$s))) + + echo $s +} + +size () +{ + local f="$1" + + local total=0 + local section + for section in info abbrev str macro types; do + total=$(($total + $(section_size $f $section))) + done + + echo $total +} + +s1=$(size $f1) +s2=$(size $f2) + +if [ $s1 -ge $s2 ]; then + exit 1 +fi + +exit 0 diff --git a/testsuite/scripts/verify-dwarf.sh b/testsuite/scripts/verify-dwarf.sh new file mode 100755 index 0000000..8e97c3c --- /dev/null +++ b/testsuite/scripts/verify-dwarf.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +exec="$1" + +gdb -batch "$exec" diff --git a/testsuite/scripts/xunzip-dir.sh b/testsuite/scripts/xunzip-dir.sh new file mode 100755 index 0000000..624d525 --- /dev/null +++ b/testsuite/scripts/xunzip-dir.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +src="$1" +dst="$2" + +if [ ! -d $src ]; then + exit 0 +fi + +files=$(cd $src; find -name "*.xz") + +for f in $files; do + df=$(echo $f \ + | sed 's/\.xz$//') + if [ -f $dst/$df ]; then + continue + fi + cp $src/$f $dst/$f + xz -d $dst/$f +done |