diff --git a/_gdb.spec.Patch.include b/_gdb.spec.Patch.include index d975b3c..e97d205 100644 --- a/_gdb.spec.Patch.include +++ b/_gdb.spec.Patch.include @@ -376,3 +376,6 @@ Patch090: gdb-rhbz1970741-early-exit-for-empty-debuginfod-url.patch # type field location kind (RHBZ 1976887). Patch091: gdb-rhbz1976887-field-location-kind.patch + +Patch092: gdb-test-for-rhbz1976887.patch + diff --git a/_gdb.spec.patch.include b/_gdb.spec.patch.include index ad51f50..481c43f 100644 --- a/_gdb.spec.patch.include +++ b/_gdb.spec.patch.include @@ -89,3 +89,4 @@ %patch089 -p1 %patch090 -p1 %patch091 -p1 +%patch092 -p1 diff --git a/_patch_order b/_patch_order index f0e152e..2233461 100644 --- a/_patch_order +++ b/_patch_order @@ -89,3 +89,4 @@ gdb-dont-overwrite-fsgsbase-m32.patch gdb-rhbz1916516-pathstuff.cc132-internal-error.patch gdb-rhbz1970741-early-exit-for-empty-debuginfod-url.patch gdb-rhbz1976887-field-location-kind.patch +gdb-test-for-rhbz1976887.patch diff --git a/gdb-test-for-rhbz1976887.patch b/gdb-test-for-rhbz1976887.patch new file mode 100644 index 0000000..6e9b355 --- /dev/null +++ b/gdb-test-for-rhbz1976887.patch @@ -0,0 +1,591 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= +Date: Sun, 26 Sep 2021 23:52:21 +0200 +Subject: gdb-test-for-rhbz1976887.patch + +; Backport test for RHBZ 1976887 (Kevin Buettner). +Test case reproducing PR28030 bug + +The original reproducer for PR28030 required use of a specific +compiler version - gcc-c++-11.1.1-3.fc34 is mentioned in the PR, +though it seems probable that other gcc versions might also be able to +reproduce the bug as well. This commit introduces a test case which, +using the DWARF assembler, provides a reproducer which is independent +of the compiler version. (Well, it'll work with whatever compilers +the DWARF assembler works with.) + +To the best of my knowledge, it's also the first test case which uses +the DWARF assembler to provide debug info for a shared object. That +being the case, I provided more than the usual commentary which should +allow this case to be used as a template when a combo shared +library / DWARF assembler test case is required in the future. + +I provide some details regarding the bug in a comment near the +beginning of locexpr-dml.exp. + +This problem was difficult to reproduce; I found myself constantly +referring to the backtrace while trying to figure out what (else) I +might be missing while trying to create a reproducer. Below is a +partial backtrace which I include for posterity. + + #0 internal_error ( + file=0xc50110 "/ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/gdbtypes.c", line=5575, + fmt=0xc520c0 "Unexpected type field location kind: %d") + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdbsupport/errors.cc:51 + #1 0x00000000006ef0c5 in copy_type_recursive (objfile=0x1635930, + type=0x274c260, copied_types=0x30bb290) + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/gdbtypes.c:5575 + #2 0x00000000006ef382 in copy_type_recursive (objfile=0x1635930, + type=0x274ca10, copied_types=0x30bb290) + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/gdbtypes.c:5602 + #3 0x0000000000a7409a in preserve_one_value (value=0x24269f0, + objfile=0x1635930, copied_types=0x30bb290) + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/value.c:2529 + #4 0x000000000072012a in gdbscm_preserve_values ( + extlang=0xc55720 , objfile=0x1635930, + copied_types=0x30bb290) + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/guile/scm-value.c:94 + #5 0x00000000006a3f82 in preserve_ext_lang_values (objfile=0x1635930, + copied_types=0x30bb290) + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/extension.c:568 + #6 0x0000000000a7428d in preserve_values (objfile=0x1635930) + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/value.c:2579 + #7 0x000000000082d514 in objfile::~objfile (this=0x1635930, + __in_chrg=) + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/objfiles.c:549 + #8 0x0000000000831cc8 in std::_Sp_counted_ptr::_M_dispose (this=0x1654580) + at /usr/include/c++/11/bits/shared_ptr_base.h:348 + #9 0x00000000004e6617 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x1654580) at /usr/include/c++/11/bits/shared_ptr_base.h:168 + #10 0x00000000004e1d2f in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=0x190bb88, __in_chrg=) + at /usr/include/c++/11/bits/shared_ptr_base.h:705 + #11 0x000000000082feee in std::__shared_ptr::~__shared_ptr (this=0x190bb80, __in_chrg=) + at /usr/include/c++/11/bits/shared_ptr_base.h:1154 + #12 0x000000000082ff0a in std::shared_ptr::~shared_ptr ( + this=0x190bb80, __in_chrg=) + at /usr/include/c++/11/bits/shared_ptr.h:122 + #13 0x000000000085ed7e in __gnu_cxx::new_allocator > >::destroy > (this=0x114bc00, + __p=0x190bb80) at /usr/include/c++/11/ext/new_allocator.h:168 + #14 0x000000000085e88d in std::allocator_traits > > >::destroy > (__a=..., + __p=0x190bb80) at /usr/include/c++/11/bits/alloc_traits.h:531 + #15 0x000000000085e50c in std::__cxx11::list, std::allocator > >::_M_erase (this=0x114bc00, __position= + std::shared_ptr (expired, weak count 1) = {get() = 0x1635930}) + at /usr/include/c++/11/bits/stl_list.h:1925 + #16 0x000000000085df0e in std::__cxx11::list, std::allocator > >::erase (this=0x114bc00, __position= + std::shared_ptr (expired, weak count 1) = {get() = 0x1635930}) + at /usr/include/c++/11/bits/list.tcc:158 + #17 0x000000000085c748 in program_space::remove_objfile (this=0x114bbc0, + objfile=0x1635930) + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/progspace.c:210 + #18 0x000000000082d3ae in objfile::unlink (this=0x1635930) + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/objfiles.c:487 + #19 0x000000000082e68c in objfile_purge_solibs () + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/objfiles.c:875 + #20 0x000000000092dd37 in no_shared_libraries (ignored=0x0, from_tty=1) + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/solib.c:1236 + #21 0x00000000009a37fe in target_pre_inferior (from_tty=1) + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/target.c:2496 + #22 0x00000000007454d6 in run_command_1 (args=0x0, from_tty=1, + run_how=RUN_NORMAL) + at /ironwood1/sourceware-git/f34-pr28030/bld/../../worktree-pr28030/gdb/infcmd.c:437 + +I'll note a few points regarding this backtrace: + +Frame #1 is where the internal error occurs. It's caused by an +unhandled case for FIELD_LOC_KIND_DWARF_BLOCK. The fix for this bug +adds support for this case. + +Frame #22 - it's a partial backtrace - shows that GDB is attempting to +(re)run the program. You can see the exact command sequence that was +used for reproducing this problem in the PR (at +https://sourceware.org/bugzilla/show_bug.cgi?id=28030), but in a +nutshell, after starting the program and advancing to the appropriate +source line, GDB was asked to step into libstdc++; a "finish" command +was issued, returning a value. The fact that a value was returned is +very important. GDB was then used to step back into libstdc++. A +breakpoint was set on a source line in the library after which a "run" +command was issued. + +Frame #19 shows a call to objfile_purge_solibs. It's aptly named. + +Frame #7 is a call to the destructor for one of the objfile solibs; it +turned out to be the one for libstdc++. + +Frames #6 thru #3 show various value preservation frames. If you look +at preserve_values() in gdb/value.c, the value history is preserved +first, followed by internal variables, followed by values for the +extension languages (python and guile). + +diff --git a/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location-lib.c b/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location-lib.c +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location-lib.c +@@ -0,0 +1,48 @@ ++/* Copyright (C) 2021 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 . */ ++ ++#include "locexpr-data-member-location.h" ++ ++struct A g_A = {3, 4}; ++struct B g_B = { {8, 9}, 10, 11 }; ++ ++B * ++foo () ++{ /* foo prologue */ ++ asm ("foo_label: .globl foo_label"); ++ return &g_B; /* foo return */ ++} /* foo end */ ++ ++B * ++bar (B *v) ++{ /* bar prologue */ ++ asm ("bar_label: .globl bar_label"); ++ return v; /* bar return */ ++} /* bar end */ ++ ++/* Some of the DWARF assembler procs (e.g. function_range) compile ++ this file, expecting it to be a complete program with a main() ++ function. When IS_SHAREDLIB is NOT defined, we have main() as ++ defined below. */ ++ ++#ifndef IS_SHAREDLIB ++int ++main () ++{ ++ B *b = foo (); ++} ++#endif +diff --git a/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location-main.c b/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location-main.c +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location-main.c +@@ -0,0 +1,27 @@ ++/* Copyright (C) 2021 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 . */ ++ ++#include "locexpr-data-member-location.h" ++ ++int ++main (void) ++{ ++ B *v1; ++ v1 = bar (foo ()); ++ ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location.exp b/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location.exp +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location.exp +@@ -0,0 +1,349 @@ ++# Copyright 2021 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++# This test case uses the DWARF assembler to reproduce the problem ++# described by PR28030. The bug turned out to be that ++# FIELD_LOC_KIND_DWARF_BLOCK was not handled when recursively copying ++# a value's type when preserving the value history during the freeing ++# up of objfiles associated with a shared object. (Yes, figuring out ++# how to make this happen in a concise test case turned out to be ++# challenging.) ++# ++# The following elements proved to be necessary for reproducing the ++# problem: ++# ++# 1) A location expression needed to be used with ++# DW_AT_data_member_location rather than a simple offset. ++# Moreover, this location expression needed to use opcodes ++# which GDB's DWARF reader could not convert to a simple ++# offset. (Note, however, that GDB could probably be improved ++# to handle the opcodes chosen for this test; if decode_locdesc() ++# in dwarf2/read.c is ever updated to handle both DW_OP_pick and ++# DW_OP_drop, then this test could end up passing even if ++# the bug it's intended to test has not been fixed.) ++# ++# 2) The debug info containing the above DWARF info needed ++# to be associated with a shared object since the problem ++# occurred while GDB was preserving values during the ++# purging of shared objects. ++# ++# 3) After performing some simple gdb commands, the program is ++# run again. In the course of running the objfile destructor ++# associated with the shared object, values are preserved ++# along with their types. As noted earlier, it was during ++# the recursive type copy that the bug was observed. ++# ++# Therefore, due to #2 above, this test case creates debug info ++# which is then used by a shared object. ++ ++# This test can't be run on targets lacking shared library support. ++if [skip_shlib_tests] { ++ return 0 ++} ++ ++load_lib dwarf.exp ++ ++# This test can only be run on targets which support DWARF-2 and use gas. ++if ![dwarf2_support] { ++ return 0 ++} ++ ++# gdb_test_file_name is the name of this file without the .exp ++# extension. Use it to form basenames for the main program ++# and shared object. ++set main_basename ${::gdb_test_file_name}-main ++set lib_basename ${::gdb_test_file_name}-lib ++ ++# We're generating DWARF assembly for the shared object; therefore, ++# the source file for the library / shared object must be listed first ++# (in the standard_testfile invocation) since ${srcfile} is used by ++# get_func_info (for determining the start, end, and length of a ++# function). ++# ++# The output of Dwarf::assemble will be placed in $lib_basename.S ++# which will be ${srcfile3} after the execution of standard_testfile. ++ ++standard_testfile $lib_basename.c $main_basename.c $lib_basename.S ++ ++set libsrc "${::srcdir}/${::subdir}/${::srcfile}" ++set lib_so [standard_output_file ${lib_basename}.so] ++set asm_file [standard_output_file ${::srcfile3}] ++ ++# We need to know the size of some types in order to write some of the ++# debugging info that we're about to generate. For that, we ask GDB ++# by debugging the shared object associated with this test case. ++ ++# Compile the shared library: -DIS_SHAREDLIB prevents main() from ++# being defined. Note that debugging symbols will be present for ++# this compilation. ++if {[gdb_compile_shlib $libsrc $lib_so \ ++ {additional_flags=-DIS_SHAREDLIB debug}] != ""} { ++ untested "failed to compile shared library" ++ return ++} ++ ++# Start a fresh GDB and load the shared library. ++clean_restart $lib_so ++ ++# Using our running GDB session, determine sizes of several types. ++set long_size [get_sizeof "long" -1] ++set addr_size [get_sizeof "void *" -1] ++set struct_A_size [get_sizeof "g_A" -1] ++set struct_B_size [get_sizeof "g_B" -1] ++ ++if { $long_size == -1 || $addr_size == -1 \ ++ || $struct_A_size == -1 || $struct_B_size == -1} { ++ perror "Can't determine type sizes" ++ return ++} ++ ++# Retrieve struct offset of MBR in struct TP ++proc get_offsetof { tp mbr } { ++ return [get_integer_valueof "&((${tp} *) 0)->${mbr}" -1] ++} ++ ++# Use running GDB session to get struct offsets ++set A_a [get_offsetof A a] ++set A_x [get_offsetof A x] ++set B_a [get_offsetof B a] ++set B_b [get_offsetof B b] ++set B_x2 [get_offsetof B x2] ++ ++# Create the DWARF. ++Dwarf::assemble ${asm_file} { ++ declare_labels L ++ ++ # Find start, end, and length of functions foo and bar. ++ # These calls to get_func_info will create and set variables ++ # foo_start, bar_start, foo_end, bar_end, foo_len, and ++ # bar_len. ++ # ++ # In order to get the right answers, get_func_info (and, ++ # underneath, function_range) should use the same compiler flags ++ # as those used to make a shared object. For any targets that get ++ # this far, -fpic is probably correct. ++ # ++ # Also, it should be noted that IS_SHAREDLIB is NOT defined as one ++ # of the additional flags. Not defining IS_SHAREDLIB will cause a ++ # main() to be defined for the compilation of the shared library ++ # source file which happens as a result of using get_func_info; ++ # this is currently required in order to this facility. ++ set flags {additional_flags=-fpic debug} ++ get_func_info foo $flags ++ get_func_info bar $flags ++ ++ cu {} { ++ DW_TAG_compile_unit { ++ {DW_AT_language @DW_LANG_C_plus_plus} ++ {name ${::srcfile}} ++ {stmt_list $L DW_FORM_sec_offset} ++ } { ++ declare_labels int_label class_A_label class_B_label \ ++ B_ptr_label ++ ++ int_label: DW_TAG_base_type { ++ {DW_AT_byte_size ${::long_size} DW_FORM_udata} ++ {DW_AT_encoding @DW_ATE_signed} ++ {DW_AT_name "int"} ++ } ++ ++ class_A_label: DW_TAG_class_type { ++ {DW_AT_name "A"} ++ {DW_AT_byte_size ${::struct_A_size} DW_FORM_sdata} ++ } { ++ DW_TAG_member { ++ {DW_AT_name "a"} ++ {DW_AT_type :$int_label} ++ {DW_AT_data_member_location ${::A_a} DW_FORM_udata} ++ } ++ DW_TAG_member { ++ {DW_AT_name "x"} ++ {DW_AT_type :$int_label} ++ {DW_AT_data_member_location ${::A_x} DW_FORM_udata} ++ } ++ } ++ ++ class_B_label: DW_TAG_class_type { ++ {DW_AT_name "B"} ++ {DW_AT_byte_size ${::struct_B_size} DW_FORM_sdata} ++ } { ++ # While there are easier / better ways to specify an ++ # offset used by DW_AT_data_member_location than that ++ # used below, we need a location expression here in ++ # order to reproduce the bug. Moreover, this location ++ # expression needs to use opcodes that aren't handled ++ # by decode_locdesc() in dwarf2/read.c; if we use ++ # opcodes that _are_ handled by that function, the ++ # location expression will be converted into a simple ++ # offset - which will then (again) not reproduce the ++ # bug. At the time that this test was written, ++ # neither DW_OP_pick nor DW_OP_drop were being handled ++ # by decode_locdesc(); this is why those opcodes were ++ # chosen. ++ DW_TAG_inheritance { ++ {DW_AT_type :$class_A_label} ++ {DW_AT_data_member_location { ++ DW_OP_constu ${::B_a} ++ DW_OP_plus ++ DW_OP_pick 0 ++ DW_OP_drop} SPECIAL_expr} ++ {DW_AT_accessibility 1 DW_FORM_data1} ++ } ++ DW_TAG_member { ++ {DW_AT_name "b"} ++ {DW_AT_type :$int_label} ++ {DW_AT_data_member_location ${::B_b} DW_FORM_udata} ++ } ++ DW_TAG_member { ++ {DW_AT_name "x2"} ++ {DW_AT_type :$int_label} ++ {DW_AT_data_member_location ${::B_x2} DW_FORM_udata} ++ } ++ } ++ ++ B_ptr_label: DW_TAG_pointer_type { ++ {DW_AT_type :$class_B_label} ++ {DW_AT_byte_size ${::addr_size} DW_FORM_sdata} ++ } ++ ++ DW_TAG_variable { ++ {DW_AT_name "g_A"} ++ {DW_AT_type :$class_A_label} ++ {DW_AT_external 1 flag} ++ {DW_AT_location {DW_OP_addr [gdb_target_symbol "g_A"]} \ ++ SPECIAL_expr} ++ } ++ ++ DW_TAG_variable { ++ {DW_AT_name "g_B"} ++ {DW_AT_type :$class_B_label} ++ {DW_AT_external 1 flag} ++ {DW_AT_location {DW_OP_addr [gdb_target_symbol "g_B"]} \ ++ SPECIAL_expr} ++ } ++ ++ # We can't use MACRO_AT for the definitions of foo and bar ++ # because it doesn't provide a way to pass the appropriate ++ # flags. Therefore, we list the name, low_pc, and high_pc ++ # explicitly. ++ DW_TAG_subprogram { ++ {DW_AT_name foo} ++ {DW_AT_low_pc $foo_start DW_FORM_addr} ++ {DW_AT_high_pc $foo_end DW_FORM_addr} ++ {DW_AT_type :${B_ptr_label}} ++ {DW_AT_external 1 flag} ++ } ++ ++ DW_TAG_subprogram { ++ {DW_AT_name bar} ++ {DW_AT_low_pc $bar_start DW_FORM_addr} ++ {DW_AT_high_pc $bar_end DW_FORM_addr} ++ {DW_AT_type :${B_ptr_label}} ++ {DW_AT_external 1 flag} ++ } { ++ DW_TAG_formal_parameter { ++ {DW_AT_name v} ++ {DW_AT_type :${B_ptr_label}} ++ } ++ } ++ } ++ } ++ ++ lines {version 2} L { ++ include_dir "${::srcdir}/${::subdir}" ++ file_name "${::srcfile}" 1 ++ ++ # Generate a line table program. ++ program { ++ {DW_LNE_set_address $foo_start} ++ {line [gdb_get_line_number "foo prologue"]} ++ {DW_LNS_copy} ++ {DW_LNE_set_address foo_label} ++ {line [gdb_get_line_number "foo return"]} ++ {DW_LNS_copy} ++ {line [gdb_get_line_number "foo end"]} ++ {DW_LNS_copy} ++ {DW_LNE_set_address $foo_end} ++ {DW_LNS_advance_line 1} ++ {DW_LNS_copy} ++ {DW_LNE_end_sequence} ++ ++ {DW_LNE_set_address $bar_start} ++ {line [gdb_get_line_number "bar prologue"]} ++ {DW_LNS_copy} ++ {DW_LNE_set_address bar_label} ++ {line [gdb_get_line_number "bar return"]} ++ {DW_LNS_copy} ++ {line [gdb_get_line_number "bar end"]} ++ {DW_LNS_copy} ++ {DW_LNE_set_address $bar_end} ++ {DW_LNS_advance_line 1} ++ {DW_LNS_copy} ++ {DW_LNE_end_sequence} ++ } ++ } ++} ++ ++# Compile the shared object again, but this time include / use the ++# DWARF info that we've created above. Note that (again) ++# -DIS_SHAREDLIB is used to prevent inclusion of main() in the shared ++# object. Also note the use of the "nodebug" option. Any debugging ++# information that we need will be provided by the DWARF info created ++# above. ++if {[gdb_compile_shlib [list $libsrc $asm_file] $lib_so \ ++ {additional_flags=-DIS_SHAREDLIB nodebug}] != ""} { ++ untested "failed to compile shared library" ++ return ++} ++ ++# Compile the main program for use with the shared object. ++if [prepare_for_testing "failed to prepare" ${testfile} \ ++ ${::srcfile2} [list debug shlib=$lib_so]] { ++ return -1 ++} ++ ++# Do whatever is necessary to make sure that the shared library is ++# loaded for remote targets. ++gdb_load_shlib ${lib_so} ++ ++if ![runto_main] then { ++ fail "can't run to main" ++ return ++} ++ ++# Step into foo so that we can finish out of it. ++gdb_test "step" "foo .. at .* foo end.*" "step into foo" ++ ++# Finishing out of foo will create a value that will later need to ++# be preserved when restarting the program. ++gdb_test "finish" "= \\(class B \\*\\) ${::hex} .*" "finish out of foo" ++ ++# Dereferencing and printing the return value isn't necessary ++# for reproducing the bug, but we should make sure that the ++# return value is what we expect it to be. ++gdb_test "p *$" { = { = {a = 8, x = 9}, b = 10, x2 = 11}} \ ++ "dereference return value" ++ ++# The original PR28030 reproducer stepped back into the shared object, ++# so we'll do the same here: ++gdb_test "step" "bar \\(.*" "step into bar" ++ ++# We don't want a clean restart here since that will be too clean. ++# The original reproducer for PR28030 set a breakpoint in the shared ++# library and then restarted via "run". The command below does roughly ++# the same thing. It's at this step that an internal error would ++# occur for PR28030. The "message" argument tells runto to turn on ++# the printing of PASSes while runto is doing its job. ++runto "bar" message +diff --git a/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location.h b/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location.h +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location.h +@@ -0,0 +1,30 @@ ++/* Copyright (C) 2021 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 . */ ++ ++typedef struct A { ++ long a; ++ long x; ++} A; ++ ++typedef struct B { ++ A a; ++ long b; ++ long x2; ++} B; ++ ++extern B *foo (); ++extern B *bar (B *v); diff --git a/gdb.spec b/gdb.spec index b4b7bbb..29b1010 100644 --- a/gdb.spec +++ b/gdb.spec @@ -1148,6 +1148,9 @@ fi %endif %changelog +* Fri Sep 24 2021 Alexandra Hájková - 10.2-3 +- Backport test for RHBZ 1976887 (Kevin Buettner). + * Fri Sep 24 2021 Alexandra Hájková - 10.2-3 - Backport upstream patch which fixes internal-error: Unexpected type field location kind (RHBZ 1976887, Alexandra Hájková).