From 7eb1526a8096133aae3164aea6388d186608ae74 Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Mon, 6 Dec 2021 11:25:04 +0000 Subject: gdb: update gdb-gdb.py.in for latest changes to struct field This commit updates uses of 'loc' and 'loc_kind' to 'm_loc' and 'm_loc_kind' respectively, in gdb-gdb.py.in, which is required after this commit: commit cd3f655cc7a55437a05aa8e7b1fcc9051b5fe404 Date: Thu Sep 30 22:38:29 2021 -0400 gdb: add accessors for field (and call site) location I have also incorporated this change: https://sourceware.org/pipermail/gdb-patches/2021-September/182171.html Which means we print 'm_name' instead of 'name' when displaying the 'm_name' member variable. Finally, I have also added support for the new TYPE_SPECIFIC_INT fields, which were added with this commit: commit 20a5fcbd5b28cca88511ac5a9ad5e54251e8fa6d Date: Wed Sep 23 09:39:24 2020 -0600 Handle bit offset and bit size in base types I updated the gdb.gdb/python-helper.exp test to cover all of these changes. --- gdb/gdb-gdb.py.in | 18 ++-- gdb/testsuite/gdb.gdb/python-helper.cc | 40 +++++++++ gdb/testsuite/gdb.gdb/python-helper.exp | 153 +++++++++++++++++++++++++++++--- 3 files changed, 191 insertions(+), 20 deletions(-) create mode 100644 gdb/testsuite/gdb.gdb/python-helper.cc diff --git a/gdb/gdb-gdb.py.in b/gdb/gdb-gdb.py.in index 15dbf38..a60ad01 100644 --- a/gdb/gdb-gdb.py.in +++ b/gdb/gdb-gdb.py.in @@ -153,8 +153,8 @@ class StructMainTypePrettyPrinter: """Return an image of the loc component inside the given field gdb.Value. """ - loc_val = field_val["loc"] - loc_kind = str(field_val["loc_kind"]) + loc_val = field_val["m_loc"] + loc_kind = str(field_val["m_loc_kind"]) if loc_kind == "FIELD_LOC_KIND_BITPOS": return "bitpos = %d" % loc_val["bitpos"] elif loc_kind == "FIELD_LOC_KIND_ENUMVAL": @@ -166,7 +166,7 @@ class StructMainTypePrettyPrinter: elif loc_kind == "FIELD_LOC_KIND_DWARF_BLOCK": return "dwarf_block = %s" % loc_val["dwarf_block"] else: - return "loc = ??? (unsupported loc_kind value)" + return "m_loc = ??? (unsupported m_loc_kind value)" def struct_field_img(self, fieldno): """Return an image of the main_type field number FIELDNO.""" @@ -175,9 +175,9 @@ class StructMainTypePrettyPrinter: if f["artificial"]: label += " (artificial)" fields = [] - fields.append("name = %s" % f["name"]) - fields.append("type = %s" % f["m_type"]) - fields.append("loc_kind = %s" % f["loc_kind"]) + fields.append("m_name = %s" % f["m_name"]) + fields.append("m_type = %s" % f["m_type"]) + fields.append("m_loc_kind = %s" % f["m_loc_kind"]) fields.append("bitsize = %d" % f["bitsize"]) fields.append(self.struct_field_location_img(f)) return label + "\n" + " {" + ",\n ".join(fields) + "}" @@ -241,9 +241,13 @@ class StructMainTypePrettyPrinter: "scaling_factor: (call __gmpz_dump with " " _mp_num and _mp_den fields if needed)" ) + elif type_specific_kind == "TYPE_SPECIFIC_INT": + img = ("int_stuff = { bit_size = %d, bit_offset = %d }" + % (type_specific["int_stuff"]["bit_size"], + type_specific["int_stuff"]["bit_offset"])) else: img = ( - "type_specific = ??? (unknown type_secific_kind: %s)" + "type_specific = ??? (unknown type_specific_kind: %s)" % type_specific_kind ) return img diff --git a/gdb/testsuite/gdb.gdb/python-helper.cc b/gdb/testsuite/gdb.gdb/python-helper.cc new file mode 100644 index 0000000..2bacf80 --- /dev/null +++ b/gdb/testsuite/gdb.gdb/python-helper.cc @@ -0,0 +1,40 @@ +/* This testcase is part of GDB, the GNU debugger. + + 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 . */ + +struct CC +{ + CC (int val) + : m_val (val) + { + /* Nothing. */ + } + + int a_method () + { + return m_val; + } + + int m_val; +}; + +CC global_c (0); + +int +main () +{ + return 0; +} diff --git a/gdb/testsuite/gdb.gdb/python-helper.exp b/gdb/testsuite/gdb.gdb/python-helper.exp index 7013a3a..58f4338 100644 --- a/gdb/testsuite/gdb.gdb/python-helper.exp +++ b/gdb/testsuite/gdb.gdb/python-helper.exp @@ -24,6 +24,12 @@ if [target_info exists gdb,noinferiorio] { return } +standard_testfile .cc + +if { [build_executable "failed to build" $testfile $srcfile {debug c++}] } { + return -1 +} + # Find the helper script in the GDB build directory. set py_helper_script [file dirname $GDB]/gdb-gdb.py if { ![file readable $py_helper_script] \ @@ -63,16 +69,23 @@ proc test_python_helper {} { "end"] ".*" \ "register the type pretty printer" - # Now place a breakpoint somewhere useful. This can be any function that: + # Now place breakpoints somewhere useful. These locations can be + # any function that: + # # (a) is easy to reach by issuing a simple gdb command, and # (b) is unlikely to be modified very often within gdb, and # (c) has a parameter that is either a 'struct type *' or a 'struct value *'. - gdb_breakpoint value_print + gdb_breakpoint value_print qualified + gdb_breakpoint c_print_type qualified + + # Disable all breakpoints until after we have loaded the test + # binary into the inner GDB. + gdb_test_no_output "disable breakpoints" # Adjust the prompt on the outer gdb, this just makes things a # little clearer when trying to unpick which GDB is active. - gdb_test_multiple "set prompt (xgdb) " "set xgdb prompt" { - -re "\[(\]xgdb\[)\].*\[(\]xgdb\[)\] $" { + gdb_test_multiple "set prompt (outer-gdb) " "set outer gdb prompt" { + -re "\[(\]outer-gdb\[)\].*\[(\]outer-gdb\[)\] $" { pass $gdb_test_name } } @@ -87,12 +100,45 @@ proc test_python_helper {} { } } - # Send a command to the inner GDB (hence send_inferior), this - # should result in the outer GDB stopping at the breakpoint we - # just created. + # Load the test executable into the inner GDB. The output here is + # being read from the inner GDB, hence the use of -i here. + send_inferior "file -readnow $::binfile\n" + gdb_test_multiple "" "loading test binary into inner GDB" { + -i "$inferior_spawn_id" + -re "Reading symbols from.*\r\n$gdb_prompt $" { + pass $gdb_test_name + } + } + + # Send Ctrl-C to the inner GDB, this should kick us back to the + # prompt of the outer GDB. + send_inferior "\003" + gdb_test_multiple "" "interrupted the inner" { + -re ".*\\(outer-gdb\\) $" { + pass $gdb_test_name + } + } + + # Now enable all breakpoints within the outer GDB. + gdb_test_multiple "enable breakpoints" "" { + -re "\\(outer-gdb\\) $" { + pass $gdb_test_name + } + } + + # We need to resume the inner GDB after interrupting it, this is + # done by sending 'continue'. However, GDB will not redisplay the + # prompt in this case, so we have nothing that we can detect in + # order to know this continue was successful. Still, if this + # didn't work, then later tests should fail. + send_gdb "continue\n" + + # Control is back with the inner GDB. Send a command to the inner + # GDB, this should result in the outer GDB stopping at one of the + # breakpoints we created.. send_inferior "print 1\n" - gdb_test_multiple "" "hit breakpoint in inner gdb" { - -re "Breakpoint $decimal, value_print.*\\(xgdb\\) $" { + gdb_test_multiple "" "hit breakpoint in outer gdb" { + -re "Breakpoint $decimal, value_print.*\\(outer-gdb\\) $" { pass $gdb_test_name } } @@ -107,12 +153,12 @@ proc test_python_helper {} { " instance_flags = 0," \ " length = $decimal," \ " main_type = $hex}" \ - "\\(xgdb\\) $"] + "\\(outer-gdb\\) $"] gdb_test_multiple "print *val->type" "pretty print type" { -re "$answer" { pass $gdb_test_name } - -re "There is no member named.*\r\n\\(xgdb\\) $" { + -re "There is no member named.*\r\n\\(outer-gdb\\) $" { fail $gdb_test_name } } @@ -125,12 +171,93 @@ proc test_python_helper {} { " owner = $hex \\(gdbarch\\)," \ " target_type = 0x0," \ " type_specific_field = TYPE_SPECIFIC_NONE}" \ - "\\(xgdb\\) $"] + "\\(outer-gdb\\) $"] gdb_test_multiple "print *val->type->main_type" "pretty print type->main_type" { -re "$answer" { pass $gdb_test_name } - -re "There is no member named.*\r\n\\(xgdb\\) $" { + -re "There is no member named.*\r\n\\(outer-gdb\\) $" { + fail $gdb_test_name + } + } + + # Send the continue to the outer GDB, which resumes the inner GDB, + # we then detect the prompt from the inner GDB, hence the use of + # -i here. + gdb_test_multiple "continue" "resume inner gdb" { + -i $inferior_spawn_id + -re "\r\n$gdb_prompt $" { + pass $gdb_test_name + } + } + + # Now print an integer that was created from the DWARF + # information, this will include the TYPE_SPECIFIC_INT + # information. + send_inferior "print global_c.m_val\n" + gdb_test_multiple "" "print integer from DWARF info" { + -re "Breakpoint $decimal, value_print.*\\(outer-gdb\\) $" { + pass $gdb_test_name + } + } + + set answer [multi_line \ + "$decimal = " \ + "{name = $hex \"int\"," \ + " code = TYPE_CODE_INT," \ + " flags = \[^\r\n\]+," \ + " owner = $hex \\(objfile\\)," \ + " target_type = 0x0," \ + " int_stuff = { bit_size = $decimal, bit_offset = $decimal }}" \ + "\\(outer-gdb\\) $"] + gdb_test_multiple "print *val->type->main_type" "pretty print type->main_type for DWARF type" { + -re "$answer" { + pass $gdb_test_name + } + -re "There is no member named.*\r\n\\(outer-gdb\\) $" { + fail $gdb_test_name + } + } + + # Send the continue to the outer GDB, which resumes the inner GDB, + # we then detect the prompt from the inner GDB, hence the use of + # -i here. + gdb_test_multiple "continue" "resume inner gdb again" { + -i $inferior_spawn_id + -re "\r\n$gdb_prompt $" { + pass $gdb_test_name + } + } + + # Send a command to the inner GDB, this should result in the outer + # GDB stopping at the value_print breakpoint again. + send_inferior "ptype global_c\n" + gdb_test_multiple "" "hit breakpoint in outer gdb again" { + -re "Breakpoint $decimal, c_print_type .*\\(outer-gdb\\) $" { + pass $gdb_test_name + } + } + + set answer [multi_line \ + "$decimal = " \ + "{name = $hex \"CC\"," \ + " code = TYPE_CODE_STRUCT," \ + " flags = \[^\r\n\]+," \ + " owner = $hex \\(objfile\\)," \ + " target_type = 0x0," \ + " flds_bnds\\.fields\\\[0\\\]:" \ + " {m_name = $hex \"m_val\"," \ + " m_type = $hex," \ + " m_loc_kind = FIELD_LOC_KIND_BITPOS," \ + " bitsize = 0," \ + " bitpos = 0}," \ + " cplus_stuff = $hex}" \ + "\\(outer-gdb\\) $"] + gdb_test_multiple "print *type->main_type" "" { + -re "$answer" { + pass $gdb_test_name + } + -re "\r\n\\(outer-gdb\\) $" { fail $gdb_test_name } } -- cgit v1.1