aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.python
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/testsuite/gdb.python')
-rw-r--r--gdb/testsuite/gdb.python/amd64-py-framefilter-invalidarg.S2
-rw-r--r--gdb/testsuite/gdb.python/gdb_leak_detector.py121
-rw-r--r--gdb/testsuite/gdb.python/lookup-type-block.exp68
-rw-r--r--gdb/testsuite/gdb.python/lookup1.c44
-rw-r--r--gdb/testsuite/gdb.python/lookup2.c46
-rw-r--r--gdb/testsuite/gdb.python/make-visualizer.exp176
-rw-r--r--gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp2
-rw-r--r--gdb/testsuite/gdb.python/pretty-print-call-by-hand.py5
-rw-r--r--gdb/testsuite/gdb.python/py-arch-reg-groups.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-arch-reg-names.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-arch.exp4
-rw-r--r--gdb/testsuite/gdb.python/py-as-string.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-auto-load-chaining-f1.o-gdb.py2
-rw-r--r--gdb/testsuite/gdb.python/py-auto-load-chaining-f2.o-gdb.py2
-rw-r--r--gdb/testsuite/gdb.python/py-auto-load-chaining.c2
-rw-r--r--gdb/testsuite/gdb.python/py-auto-load-chaining.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-bad-printers.py3
-rw-r--r--gdb/testsuite/gdb.python/py-block.exp16
-rw-r--r--gdb/testsuite/gdb.python/py-bp-locations.exp4
-rw-r--r--gdb/testsuite/gdb.python/py-breakpoint-create-fail.exp6
-rw-r--r--gdb/testsuite/gdb.python/py-breakpoint.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-caller-is.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-cmd.exp93
-rw-r--r--gdb/testsuite/gdb.python/py-color-leak.exp28
-rw-r--r--gdb/testsuite/gdb.python/py-color-leak.py39
-rw-r--r--gdb/testsuite/gdb.python/py-color-pagination.exp194
-rw-r--r--gdb/testsuite/gdb.python/py-color-pagination.py82
-rw-r--r--gdb/testsuite/gdb.python/py-color.exp76
-rw-r--r--gdb/testsuite/gdb.python/py-commands-breakpoint.py6
-rw-r--r--gdb/testsuite/gdb.python/py-connection-removed.exp13
-rw-r--r--gdb/testsuite/gdb.python/py-corefile.c25
-rw-r--r--gdb/testsuite/gdb.python/py-corefile.exp281
-rw-r--r--gdb/testsuite/gdb.python/py-corefile.py187
-rw-r--r--gdb/testsuite/gdb.python/py-disasm.exp.tcl17
-rw-r--r--gdb/testsuite/gdb.python/py-disasm.py71
-rw-r--r--gdb/testsuite/gdb.python/py-event-load.exp6
-rw-r--r--gdb/testsuite/gdb.python/py-events-shlib.c1
-rw-r--r--gdb/testsuite/gdb.python/py-evsignal.exp4
-rw-r--r--gdb/testsuite/gdb.python/py-evthreads.exp10
-rw-r--r--gdb/testsuite/gdb.python/py-exec-file.exp8
-rw-r--r--gdb/testsuite/gdb.python/py-explore-cc.exp158
-rw-r--r--gdb/testsuite/gdb.python/py-explore.c2
-rw-r--r--gdb/testsuite/gdb.python/py-explore.exp528
-rw-r--r--gdb/testsuite/gdb.python/py-finish-breakpoint-deletion.py3
-rw-r--r--gdb/testsuite/gdb.python/py-finish-breakpoint.exp8
-rw-r--r--gdb/testsuite/gdb.python/py-finish-breakpoint.py3
-rw-r--r--gdb/testsuite/gdb.python/py-finish-breakpoint2.cc4
-rw-r--r--gdb/testsuite/gdb.python/py-finish-breakpoint2.exp4
-rw-r--r--gdb/testsuite/gdb.python/py-finish-breakpoint2.py2
-rw-r--r--gdb/testsuite/gdb.python/py-format-address.exp12
-rw-r--r--gdb/testsuite/gdb.python/py-format-string.exp21
-rw-r--r--gdb/testsuite/gdb.python/py-frame-args.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-frame-args.py1
-rw-r--r--gdb/testsuite/gdb.python/py-frame.exp15
-rw-r--r--gdb/testsuite/gdb.python/py-framefilter-addr.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-framefilter-addr.py1
-rw-r--r--gdb/testsuite/gdb.python/py-framefilter-gdb.py3
-rw-r--r--gdb/testsuite/gdb.python/py-framefilter-invalidarg-gdb.py2
-rw-r--r--gdb/testsuite/gdb.python/py-framefilter-invalidarg.py1
-rw-r--r--gdb/testsuite/gdb.python/py-framefilter-mi.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-framefilter.exp4
-rw-r--r--gdb/testsuite/gdb.python/py-framefilter.py1
-rw-r--r--gdb/testsuite/gdb.python/py-inferior-leak.exp14
-rw-r--r--gdb/testsuite/gdb.python/py-inferior-leak.py107
-rw-r--r--gdb/testsuite/gdb.python/py-inferior.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-label-symbol-value.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-lazy-string.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-linetable-empty.exp8
-rw-r--r--gdb/testsuite/gdb.python/py-linetable.exp4
-rw-r--r--gdb/testsuite/gdb.python/py-lookup-type.exp4
-rw-r--r--gdb/testsuite/gdb.python/py-mi-events.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-mi-objfile.exp4
-rw-r--r--gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-mi-var-info-path-expression.py1
-rw-r--r--gdb/testsuite/gdb.python/py-mi.exp4
-rw-r--r--gdb/testsuite/gdb.python/py-missing-debug.py3
-rw-r--r--gdb/testsuite/gdb.python/py-missing-objfile.exp24
-rw-r--r--gdb/testsuite/gdb.python/py-missing-objfile.py10
-rw-r--r--gdb/testsuite/gdb.python/py-objfile-script-gdb.py2
-rw-r--r--gdb/testsuite/gdb.python/py-objfile-script.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-objfile.c2
-rw-r--r--gdb/testsuite/gdb.python/py-objfile.exp14
-rw-r--r--gdb/testsuite/gdb.python/py-parameter-prefix.exp382
-rw-r--r--gdb/testsuite/gdb.python/py-parameter.exp230
-rw-r--r--gdb/testsuite/gdb.python/py-pp-cast.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-pp-integral.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-pp-maint.c2
-rw-r--r--gdb/testsuite/gdb.python/py-pp-maint.exp8
-rw-r--r--gdb/testsuite/gdb.python/py-pp-maint.py2
-rw-r--r--gdb/testsuite/gdb.python/py-pp-re-notag.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-pp-registration.c2
-rw-r--r--gdb/testsuite/gdb.python/py-pp-registration.exp10
-rw-r--r--gdb/testsuite/gdb.python/py-pp-registration.py6
-rw-r--r--gdb/testsuite/gdb.python/py-prettyprint.c40
-rw-r--r--gdb/testsuite/gdb.python/py-prettyprint.exp11
-rw-r--r--gdb/testsuite/gdb.python/py-progspace.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-read-memory-leak.exp16
-rw-r--r--gdb/testsuite/gdb.python/py-read-memory-leak.py84
-rw-r--r--gdb/testsuite/gdb.python/py-record-btrace.exp6
-rw-r--r--gdb/testsuite/gdb.python/py-record-full.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-recurse-unwind.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-recurse-unwind.py13
-rw-r--r--gdb/testsuite/gdb.python/py-section-script.exp8
-rw-r--r--gdb/testsuite/gdb.python/py-section-script.py2
-rw-r--r--gdb/testsuite/gdb.python/py-send-packet.py4
-rw-r--r--gdb/testsuite/gdb.python/py-source-styling-2.exp24
-rw-r--r--gdb/testsuite/gdb.python/py-source-styling.exp8
-rw-r--r--gdb/testsuite/gdb.python/py-startup-opt.exp1
-rw-r--r--gdb/testsuite/gdb.python/py-strfns.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-style-parameter-set.exp366
-rw-r--r--gdb/testsuite/gdb.python/py-style.exp371
-rw-r--r--gdb/testsuite/gdb.python/py-styled-execute.exp1
-rw-r--r--gdb/testsuite/gdb.python/py-sym-artificial.exp16
-rw-r--r--gdb/testsuite/gdb.python/py-symbol.exp43
-rw-r--r--gdb/testsuite/gdb.python/py-template.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-thread-exited.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-thread-exited.py2
-rw-r--r--gdb/testsuite/gdb.python/py-thrhandle.exp18
-rw-r--r--gdb/testsuite/gdb.python/py-type.exp23
-rw-r--r--gdb/testsuite/gdb.python/py-typeprint.py3
-rw-r--r--gdb/testsuite/gdb.python/py-unwind-inline.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-unwind-inline.py4
-rw-r--r--gdb/testsuite/gdb.python/py-unwind-maint.py4
-rw-r--r--gdb/testsuite/gdb.python/py-unwind.c4
-rw-r--r--gdb/testsuite/gdb.python/py-unwind.exp7
-rw-r--r--gdb/testsuite/gdb.python/py-unwind.py26
-rw-r--r--gdb/testsuite/gdb.python/py-value-cc.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-value.c9
-rw-r--r--gdb/testsuite/gdb.python/py-value.exp91
-rw-r--r--gdb/testsuite/gdb.python/py-varobj.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-warning.exp63
-rw-r--r--gdb/testsuite/gdb.python/py-watchpoint.py3
-rw-r--r--gdb/testsuite/gdb.python/py-xmethods.exp2
-rw-r--r--gdb/testsuite/gdb.python/python.exp20
-rw-r--r--gdb/testsuite/gdb.python/source2.py2
-rw-r--r--gdb/testsuite/gdb.python/tui-window-disabled.py7
-rw-r--r--gdb/testsuite/gdb.python/tui-window-factory.py3
137 files changed, 3714 insertions, 905 deletions
diff --git a/gdb/testsuite/gdb.python/amd64-py-framefilter-invalidarg.S b/gdb/testsuite/gdb.python/amd64-py-framefilter-invalidarg.S
index 0280591..1e5d8ac7 100644
--- a/gdb/testsuite/gdb.python/amd64-py-framefilter-invalidarg.S
+++ b/gdb/testsuite/gdb.python/amd64-py-framefilter-invalidarg.S
@@ -46,7 +46,7 @@ main:
.loc 1 3 0
popq %rbp
.cfi_def_cfa 7, 8
-# SUCC: EXIT [100.0%]
+# SUCC: EXIT [100.0%]
ret
.cfi_endproc
.LFE0:
diff --git a/gdb/testsuite/gdb.python/gdb_leak_detector.py b/gdb/testsuite/gdb.python/gdb_leak_detector.py
new file mode 100644
index 0000000..8f74b67
--- /dev/null
+++ b/gdb/testsuite/gdb.python/gdb_leak_detector.py
@@ -0,0 +1,121 @@
+# Copyright (C) 2021-2025 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/>.
+
+# Defines a base class, which can be sub-classed, in order to run
+# memory leak tests on some aspects of GDB's Python API. See the
+# comments on the gdb_leak_detector class for more details.
+
+import os
+import tracemalloc
+
+import gdb
+
+
+# This class must be sub-classed to create a memory leak test. The
+# sub-classes __init__ method should call the parent classes __init__
+# method, and the sub-class should override allocate() and
+# deallocate(). See the comments on the various methods below for
+# more details of required arguments and expected usage.
+class gdb_leak_detector:
+
+ # Class initialisation. FILENAME is the file in which the
+ # sub-class is defined, usually passed as just '__file__'. This
+ # is used when looking for memory allocations; only allocations in
+ # FILENAME are considered.
+ def __init__(self, filename):
+ self.filters = [tracemalloc.Filter(True, "*" + os.path.basename(filename))]
+
+ # Internal helper function to actually run the test. Calls the
+ # allocate() method to allocate an object from GDB's Python API.
+ # When CLEAR is True the object will then be deallocated by
+ # calling deallocate(), otherwise, deallocate() is not called.
+ #
+ # Finally, this function checks for any memory allocatios
+ # originating from 'self.filename' that have not been freed, and
+ # returns the total (in bytes) of the memory that has been
+ # allocated, but not freed.
+ def _do_test(self, clear):
+ # Start tracing, and take a snapshot of the current allocations.
+ tracemalloc.start()
+ snapshot1 = tracemalloc.take_snapshot()
+
+ # Generate the GDB Python API object by calling the allocate
+ # method.
+ self.allocate()
+
+ # Possibly clear the reference to the allocated object.
+ if clear:
+ self.deallocate()
+
+ # Now grab a second snapshot of memory allocations, and stop
+ # tracing memory allocations.
+ snapshot2 = tracemalloc.take_snapshot()
+ tracemalloc.stop()
+
+ # Filter the snapshots; we only care about allocations originating
+ # from this file.
+ snapshot1 = snapshot1.filter_traces(self.filters)
+ snapshot2 = snapshot2.filter_traces(self.filters)
+
+ # Compare the snapshots, this leaves only things that were
+ # allocated, but not deallocated since the first snapshot.
+ stats = snapshot2.compare_to(snapshot1, "traceback")
+
+ # Total up all the allocated things.
+ total = 0
+ for stat in stats:
+ total += stat.size_diff
+ return total
+
+ # Run the memory leak test. Prints 'PASS' if successful,
+ # otherwise, raises an exception (of type GdbError).
+ def run(self):
+ # The first time we run this some global state will be allocated which
+ # shows up as memory that is allocated, but not released. So, run the
+ # test once and discard the result.
+ self._do_test(True)
+
+ # Now run the test twice, the first time we clear our global reference
+ # to the allocated object, which should allow Python to deallocate the
+ # object. The second time we hold onto the global reference, preventing
+ # Python from performing the deallocation.
+ bytes_with_clear = self._do_test(True)
+ bytes_without_clear = self._do_test(False)
+
+ # If there are any allocations left over when we cleared the reference
+ # (and expected deallocation) then this indicates a leak.
+ if bytes_with_clear > 0:
+ raise gdb.GdbError("memory leak when object reference was released")
+
+ # If there are no allocations showing when we hold onto a reference,
+ # then this likely indicates that the testing infrastructure is broken,
+ # and we're no longer spotting the allocations at all.
+ if bytes_without_clear == 0:
+ raise gdb.GdbError("object is unexpectedly not showing as allocated")
+
+ # Print a PASS message that the TCL script can see.
+ print("PASS")
+
+ # Sub-classes must override this method. Allocate an object (or
+ # multiple objects) from GDB's Python API. Store references to
+ # these objects within SELF.
+ def allocate(self):
+ raise NotImplementedError("allocate() not implemented")
+
+ # Sub-classes must override this method. Deallocate the object(s)
+ # allocated by the allocate() method. All that is required is for
+ # the references created in allocate() to be set to None.
+ def deallocate(self):
+ raise NotImplementedError("allocate() not implemented")
diff --git a/gdb/testsuite/gdb.python/lookup-type-block.exp b/gdb/testsuite/gdb.python/lookup-type-block.exp
new file mode 100644
index 0000000..7d04eb6
--- /dev/null
+++ b/gdb/testsuite/gdb.python/lookup-type-block.exp
@@ -0,0 +1,68 @@
+# Copyright (C) 2025 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/>.
+
+# Test the 'block' argument to gdb.lookup_type.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+
+standard_testfile lookup1.c lookup2.c
+
+if {[prepare_for_testing "failed to prepare" ${testfile} \
+ [list $srcfile $srcfile2]]} {
+ return
+}
+
+proc check_type {which type_name} {
+ if {$which == "one"} {
+ set fn_name function
+ } else {
+ set fn_name main
+ }
+
+ gdb_test_no_output \
+ "python block = gdb.decode_line(\"$fn_name\")\[1\]\[0\].symtab.static_block()" \
+ "compute block"
+ gdb_test_no_output \
+ "python ty = gdb.lookup_type(\"$type_name\", block).strip_typedefs()" \
+ "find the type"
+ gdb_test "python print(ty.fields()\[0\].name)" \
+ "$which" \
+ "examine first field"
+}
+
+proc check_all_types {} {
+ foreach_with_prefix which {one two} {
+ foreach_with_prefix type_name {
+ "struct the_struct"
+ "enum the_enum"
+ "union the_union"
+ "the_typedef"
+ } {
+ check_type $which $type_name
+ }
+ }
+}
+
+check_all_types
+
+if {![runto_main]} {
+ return
+}
+
+with_test_prefix "while running" {
+ check_all_types
+}
diff --git a/gdb/testsuite/gdb.python/lookup1.c b/gdb/testsuite/gdb.python/lookup1.c
new file mode 100644
index 0000000..488ffcb
--- /dev/null
+++ b/gdb/testsuite/gdb.python/lookup1.c
@@ -0,0 +1,44 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2025 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/>. */
+
+struct the_struct {
+ int one;
+};
+
+struct the_struct struct1;
+
+enum the_enum {
+ one
+};
+
+enum the_enum enum1;
+
+union the_union {
+ int one;
+ void *ptr;
+};
+
+union the_union union1;
+
+typedef struct the_struct the_typedef;
+
+the_typedef typedef1;
+
+int function (void)
+{
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.python/lookup2.c b/gdb/testsuite/gdb.python/lookup2.c
new file mode 100644
index 0000000..63d1030
--- /dev/null
+++ b/gdb/testsuite/gdb.python/lookup2.c
@@ -0,0 +1,46 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2025 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/>. */
+
+struct the_struct {
+ int two;
+};
+
+struct the_struct struct2;
+
+enum the_enum {
+ two
+};
+
+enum the_enum enum2;
+
+union the_union {
+ int two;
+ void *ptr;
+};
+
+union the_union union2;
+
+typedef struct the_struct the_typedef;
+
+the_typedef typedef2;
+
+extern int function (void);
+
+int main (void)
+{
+ return function ();
+}
diff --git a/gdb/testsuite/gdb.python/make-visualizer.exp b/gdb/testsuite/gdb.python/make-visualizer.exp
new file mode 100644
index 0000000..2c6b40d
--- /dev/null
+++ b/gdb/testsuite/gdb.python/make-visualizer.exp
@@ -0,0 +1,176 @@
+# Copyright (C) 2025 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/>.
+
+# Tests for gdb.printing.make_visualizer; specifically that the
+# optimized-out and synthetic pointer cases work properly.
+
+load_lib dwarf.exp
+load_lib gdb-python.exp
+
+require dwarf2_support
+require allow_python_tests
+
+# Use a simple plain-"main" source file.
+standard_testfile py-progspace.c -dw.S
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug}]} {
+ return
+}
+
+if {![runto_main]} {
+ return
+}
+
+# Get size to create fake DWARF for the test.
+set ptr_size [get_sizeof "void *" 96]
+
+set asm_file [standard_output_file ${srcfile2}]
+Dwarf::assemble $asm_file {
+ cu {} {
+ compile_unit {} {
+ declare_labels i32_type i32_array \
+ struct_label variable_label pointer_label
+
+ i32_type: DW_TAG_base_type {
+ DW_AT_name "int32_t"
+ DW_AT_encoding @DW_ATE_signed
+ DW_AT_byte_size 4 DW_FORM_sdata
+ }
+
+ i32_array: DW_TAG_array_type {
+ DW_AT_name array_type
+ DW_AT_type :$i32_type
+ } {
+ DW_TAG_subrange_type {
+ DW_AT_type :$i32_type
+ DW_AT_lower_bound 0 DW_FORM_data1
+ DW_AT_upper_bound 3 DW_FORM_data1
+ }
+ }
+
+ # Used for testing optimized-out elements of an array.
+ DW_TAG_variable {
+ DW_AT_name i32_noptr
+ DW_AT_type :$i32_array
+ DW_AT_location {
+ DW_OP_constu 1779823878
+ DW_OP_stack_value
+ DW_OP_piece 4
+ } SPECIAL_expr
+ }
+
+ struct_label: DW_TAG_structure_type {
+ DW_AT_name i32_noptr
+ DW_AT_byte_size 4 DW_FORM_sdata
+ } {
+ DW_TAG_member {
+ DW_AT_name f
+ DW_AT_type :$i32_type
+ DW_AT_data_member_location 0 DW_FORM_data1
+ }
+ }
+
+ pointer_label: DW_TAG_pointer_type {
+ DW_AT_byte_size $::ptr_size DW_FORM_sdata
+ DW_AT_type :$struct_label
+ }
+
+ variable_label: DW_TAG_variable {
+ DW_AT_name v
+ DW_AT_location {
+ DW_OP_implicit_value 0x1 0x1 0x1 0x1
+ } SPECIAL_expr
+ DW_AT_type :$struct_label
+ }
+
+ # Used for testing synthetic pointers.
+ DW_TAG_variable {
+ DW_AT_name synthptr
+ DW_AT_location {
+ DW_OP_GNU_implicit_pointer $variable_label 0
+ } SPECIAL_expr
+ DW_AT_type :$pointer_label
+ }
+
+ # Optimized-out pointer.
+ DW_TAG_variable {
+ DW_AT_name optoutptr
+ DW_AT_location { } SPECIAL_expr
+ DW_AT_type :$pointer_label
+ }
+ }
+ }
+}
+
+if {[prepare_for_testing "failed to prepare" ${testfile} \
+ [list $srcfile $asm_file] {nodebug}]} {
+ return
+}
+
+# Need a frame to evaluate a synthetic pointer.
+if {![runto_main]} {
+ return
+}
+
+gdb_test_no_output "python import gdb"
+gdb_test_no_output "python import gdb.printing"
+
+gdb_test_no_output "python val = gdb.parse_and_eval('i32_noptr')" \
+ "fetch i32_noptr"
+gdb_test_no_output "python vz = gdb.printing.make_visualizer(val)" \
+ "create i32_noptr visualizer"
+gdb_test "python print(isinstance(vz, gdb.printing.NoOpArrayPrinter))" \
+ True \
+ "i32_noptr uses array printer"
+
+gdb_test_no_output "python vz1 = gdb.printing.make_visualizer(val\[0\])" \
+ "create visualizer for valid element"
+gdb_test "python print(isinstance(vz1, gdb.printing.NoOpScalarPrinter))" \
+ True \
+ "valid element uses scalar printer"
+gdb_test "python print(vz1.to_string())" \
+ 1779823878 \
+ "string form of valid element"
+
+gdb_test_no_output "python vz2 = gdb.printing.make_visualizer(val\[1\])" \
+ "create visualizer for optimized-out element"
+gdb_test "python print(isinstance(vz2, gdb.printing.NoOpScalarPrinter))" \
+ True \
+ "optimized-out element uses scalar printer"
+gdb_test "python print(vz2.to_string())" \
+ "<optimized out>" \
+ "string form of optimized-out element"
+
+gdb_test_no_output "python val2 = gdb.parse_and_eval('synthptr')" \
+ "fetch synthetic pointer"
+gdb_test_no_output "python vzv2 = gdb.printing.make_visualizer(val2)" \
+ "create synthetic pointer visualizer"
+gdb_test "python print(isinstance(vzv2, gdb.printing.NoOpPointerReferencePrinter))" \
+ True \
+ "synthetic pointer uses pointer printer"
+gdb_test "python print(vzv2.child(0)\[1\])" \
+ "{f = 16843009}" \
+ "child of synthetic pointer"
+
+gdb_test_no_output "python val3 = gdb.parse_and_eval('optoutptr')" \
+ "fetch optimized-out pointer"
+gdb_test_no_output "python vzv3 = gdb.printing.make_visualizer(val3)" \
+ "create optimized-out pointer visualizer"
+gdb_test "python print(isinstance(vzv3, gdb.printing.NoOpScalarPrinter))" \
+ True \
+ "optimized-out pointer uses scalar printer"
+gdb_test "python print(vzv3.to_string())" \
+ "<optimized out>" \
+ "string representation of optimized-out pointer"
diff --git a/gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp b/gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp
index dd6cb59..17b8afe 100644
--- a/gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp
+++ b/gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp
@@ -39,7 +39,7 @@ proc start_test { breakpoint_comment } {
# Start with a fresh gdb.
# This is important because the test can crash GDB.
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if {![runto_main]} {
untested "couldn't run to breakpoint"
diff --git a/gdb/testsuite/gdb.python/pretty-print-call-by-hand.py b/gdb/testsuite/gdb.python/pretty-print-call-by-hand.py
index 3620354..57af869 100644
--- a/gdb/testsuite/gdb.python/pretty-print-call-by-hand.py
+++ b/gdb/testsuite/gdb.python/pretty-print-call-by-hand.py
@@ -14,6 +14,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import gdb
+
+
class MytypePrinter:
"""pretty print my type"""
@@ -21,7 +24,7 @@ class MytypePrinter:
self.val = val
def to_string(self):
- calls = gdb.parse_and_eval("f()")
+ gdb.parse_and_eval("f()")
return "mytype is %s" % self.val["x"]
diff --git a/gdb/testsuite/gdb.python/py-arch-reg-groups.exp b/gdb/testsuite/gdb.python/py-arch-reg-groups.exp
index 855af27..2b0ac3e 100644
--- a/gdb/testsuite/gdb.python/py-arch-reg-groups.exp
+++ b/gdb/testsuite/gdb.python/py-arch-reg-groups.exp
@@ -23,7 +23,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-arch-reg-names.exp b/gdb/testsuite/gdb.python/py-arch-reg-names.exp
index 7093674..99fb8ce 100644
--- a/gdb/testsuite/gdb.python/py-arch-reg-names.exp
+++ b/gdb/testsuite/gdb.python/py-arch-reg-names.exp
@@ -23,7 +23,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-arch.exp b/gdb/testsuite/gdb.python/py-arch.exp
index 79e5939..531ae50 100644
--- a/gdb/testsuite/gdb.python/py-arch.exp
+++ b/gdb/testsuite/gdb.python/py-arch.exp
@@ -20,7 +20,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
@@ -78,7 +78,7 @@ foreach size {0 1 2 3 4 8 16} {
} else {
set sign_result [lindex $sign_data 1]
}
- set fullsize [expr 8 * $size]
+ set fullsize [expr {8 * $size}]
gdb_test_no_output "python t = arch.integer_type($fullsize$sign)" \
"get integer type for $size$sign"
gdb_test "python print(t.sizeof)" "$size" \
diff --git a/gdb/testsuite/gdb.python/py-as-string.exp b/gdb/testsuite/gdb.python/py-as-string.exp
index 05d55df..2ad179d 100644
--- a/gdb/testsuite/gdb.python/py-as-string.exp
+++ b/gdb/testsuite/gdb.python/py-as-string.exp
@@ -26,7 +26,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return 0
}
diff --git a/gdb/testsuite/gdb.python/py-auto-load-chaining-f1.o-gdb.py b/gdb/testsuite/gdb.python/py-auto-load-chaining-f1.o-gdb.py
index 9641a86..7c107ec 100644
--- a/gdb/testsuite/gdb.python/py-auto-load-chaining-f1.o-gdb.py
+++ b/gdb/testsuite/gdb.python/py-auto-load-chaining-f1.o-gdb.py
@@ -18,6 +18,8 @@
import re
+import gdb
+
print("Entering f1.o auto-load script")
print("Current objfile is: %s" % gdb.current_objfile().filename)
diff --git a/gdb/testsuite/gdb.python/py-auto-load-chaining-f2.o-gdb.py b/gdb/testsuite/gdb.python/py-auto-load-chaining-f2.o-gdb.py
index f1abc2c..6c33118 100644
--- a/gdb/testsuite/gdb.python/py-auto-load-chaining-f2.o-gdb.py
+++ b/gdb/testsuite/gdb.python/py-auto-load-chaining-f2.o-gdb.py
@@ -16,6 +16,8 @@
# This script is auto-loaded when the py-auto-load-chaining-f2.o
# object is loaded.
+import gdb
+
print("Entering f2.o auto-load script")
print("Current objfile is: %s" % gdb.current_objfile().filename)
diff --git a/gdb/testsuite/gdb.python/py-auto-load-chaining.c b/gdb/testsuite/gdb.python/py-auto-load-chaining.c
index 74ec04f..1b6508c 100644
--- a/gdb/testsuite/gdb.python/py-auto-load-chaining.c
+++ b/gdb/testsuite/gdb.python/py-auto-load-chaining.c
@@ -33,7 +33,7 @@ allocate_page (void)
void *addr;
int pgsize = sysconf(_SC_PAGE_SIZE);
addr = mmap (NULL, pgsize, PROT_EXEC | PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (addr == MAP_FAILED)
perror ("mmap");
}
diff --git a/gdb/testsuite/gdb.python/py-auto-load-chaining.exp b/gdb/testsuite/gdb.python/py-auto-load-chaining.exp
index 451dca6..fbb95d9 100644
--- a/gdb/testsuite/gdb.python/py-auto-load-chaining.exp
+++ b/gdb/testsuite/gdb.python/py-auto-load-chaining.exp
@@ -49,7 +49,7 @@ if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-bad-printers.py b/gdb/testsuite/gdb.python/py-bad-printers.py
index c93923c..b4f84bc 100644
--- a/gdb/testsuite/gdb.python/py-bad-printers.py
+++ b/gdb/testsuite/gdb.python/py-bad-printers.py
@@ -18,7 +18,6 @@
# Test a printer with a bad children iterator.
-import re
import gdb.printing
@@ -34,7 +33,6 @@ class BadChildrenContainerPrinter1(object):
@staticmethod
def _bad_iterator(pointer, len):
- start = pointer
end = pointer + len
while pointer != end:
yield "intentional violation of children iterator protocol"
@@ -55,7 +53,6 @@ class BadChildrenContainerPrinter2(object):
@staticmethod
def _bad_iterator(pointer, len):
- start = pointer
end = pointer + len
while pointer != end:
# The first argument is supposed to be a string.
diff --git a/gdb/testsuite/gdb.python/py-block.exp b/gdb/testsuite/gdb.python/py-block.exp
index ce3f7ce..5d0d408 100644
--- a/gdb/testsuite/gdb.python/py-block.exp
+++ b/gdb/testsuite/gdb.python/py-block.exp
@@ -45,9 +45,9 @@ gdb_test "python print (block.start)" "${decimal}" "check start not None"
gdb_test "python print (block.end)" "${decimal}" "check end not None"
gdb_test "python print (block\['f'\].name == 'f')" "True" "check variable access"
gdb_test "python print (block\['nonexistent'\])" ".*KeyError.*: 'nonexistent'.*" \
- "check nonexistent variable"
+ "check nonexistent variable"
gdb_test "python print (block\[42\])" ".*TypeError.*: Expected a string.*" \
- "check non-string key"
+ "check non-string key"
# Test global/static blocks
gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0
@@ -71,7 +71,7 @@ gdb_test_no_output "python block = block.superblock" "get superblock"
gdb_test "python print (block.function)" "None" "second anonymous block"
gdb_test_no_output "python block = block.superblock" "get superblock 2"
gdb_test "python print (block.function)" "block_func" \
- "Print superblock 2 function"
+ "Print superblock 2 function"
# Switch frames, then test block for no_locals_func.
gdb_test "continue" ".*" "continue to no_locals_func breakpoint"
@@ -110,7 +110,7 @@ gdb_test "up" ".*"
gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame 2" 0
gdb_py_test_silent_cmd "python block = frame.block()" "Get Frame 2's block" 0
gdb_test "python print (repr (block))" "<gdb.Block main \{.*\}>" \
- "Check Frame 2's block not None"
+ "Check Frame 2's block not None"
gdb_test "python print (block.function)" "main" "main block"
# Test Block is_valid. This must always be the last test in this
@@ -120,15 +120,15 @@ gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0
gdb_py_test_silent_cmd "python block = frame.block()" "Get Frame block" 0
gdb_py_test_silent_cmd "python block_iter = iter (block)" "Get Frame block" 0
gdb_test "python print (block.is_valid())" "True" \
- "Check block validity"
+ "Check block validity"
gdb_test "python print (block_iter.is_valid())" "True" \
- "Check block_iter validity"
+ "Check block_iter validity"
gdb_test_no_output "python x = hash(block)" "block is hashable"
gdb_test "python print (type (x))" "<class 'int'>" "block hash is integer"
gdb_unload
gdb_test "python print (block.is_valid())" "False" \
- "Check block validity after unload"
+ "Check block validity after unload"
gdb_test "python print (block_iter.is_valid())" "False" \
- "Check block_iter validity after unload"
+ "Check block_iter validity after unload"
gdb_test "python print (hash (block) == x)" "True" \
"block hash did not change"
diff --git a/gdb/testsuite/gdb.python/py-bp-locations.exp b/gdb/testsuite/gdb.python/py-bp-locations.exp
index 61e4e38..b09a401 100644
--- a/gdb/testsuite/gdb.python/py-bp-locations.exp
+++ b/gdb/testsuite/gdb.python/py-bp-locations.exp
@@ -27,7 +27,7 @@ save_vars { GDBFLAGS } {
clean_restart $testfile
}
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
@@ -79,7 +79,7 @@ gdb_test "python print(gdb.breakpoints()\[1\].locations\[0\])" \
"check repr of disabled breakpoint location"
gdb_continue_to_breakpoint "" ".*25.*"
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-breakpoint-create-fail.exp b/gdb/testsuite/gdb.python/py-breakpoint-create-fail.exp
index 391744e..0305604 100644
--- a/gdb/testsuite/gdb.python/py-breakpoint-create-fail.exp
+++ b/gdb/testsuite/gdb.python/py-breakpoint-create-fail.exp
@@ -27,7 +27,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
}
clean_restart "${testfile}"
-if ![runto_main] {
+if {![runto_main]} {
return
}
@@ -46,9 +46,9 @@ gdb_test "break foo"
set test "continuing to foo"
gdb_test_multiple "continue" "$test" {
-re "MyBP\.stop was invoked\!.*$gdb_prompt $" {
- fail "$test"
+ fail "$test"
}
-re "Continuing.*Breakpoint 2, foo.*$gdb_prompt $" {
- pass "$test"
+ pass "$test"
}
}
diff --git a/gdb/testsuite/gdb.python/py-breakpoint.exp b/gdb/testsuite/gdb.python/py-breakpoint.exp
index 1b9c05f..9a901a3 100644
--- a/gdb/testsuite/gdb.python/py-breakpoint.exp
+++ b/gdb/testsuite/gdb.python/py-breakpoint.exp
@@ -707,7 +707,7 @@ proc_with_prefix test_bkpt_explicit_loc {} {
delete_breakpoints
gdb_test "python bp1 = gdb.Breakpoint (line=bp1)" \
- "RuntimeError.*: Line keyword should be an integer or a string.*" \
+ "RuntimeError.*: Line keyword should be an integer or a string\\.\r\n.*" \
"set explicit breakpoint by invalid line type"
delete_breakpoints
diff --git a/gdb/testsuite/gdb.python/py-caller-is.exp b/gdb/testsuite/gdb.python/py-caller-is.exp
index 8e54c3b..0fdb80e 100644
--- a/gdb/testsuite/gdb.python/py-caller-is.exp
+++ b/gdb/testsuite/gdb.python/py-caller-is.exp
@@ -26,7 +26,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return 0
}
diff --git a/gdb/testsuite/gdb.python/py-cmd.exp b/gdb/testsuite/gdb.python/py-cmd.exp
index f76c176..1fa3c73 100644
--- a/gdb/testsuite/gdb.python/py-cmd.exp
+++ b/gdb/testsuite/gdb.python/py-cmd.exp
@@ -278,13 +278,7 @@ gdb_test_multiline "input multi-line-output command" \
set test "verify pagination from test_multiline"
gdb_test_multiple "test_multiline" $test {
- -re "--Type <RET>" {
- exp_continue
- }
- -re " for more, q to quit" {
- exp_continue
- }
- -re ", c to continue without paging--$" {
+ -re "$pagination_prompt$" {
pass $test
}
}
@@ -328,4 +322,89 @@ proc_with_prefix test_command_redefining_itself {} {
"call command redefining itself 2"
}
+# Try to create commands using unknown prefixes and check GDB gives an
+# error. There's also a test in here for an ambiguous prefix, which
+# gives the same error.
+proc_with_prefix test_unknown_prefix {} {
+ clean_restart
+
+ gdb_test_no_output "python gdb.Command('foo1', gdb.COMMAND_NONE, prefix=True)"
+ gdb_test_no_output "python gdb.Command('foo cmd', gdb.COMMAND_NONE)"
+
+ foreach prefix { "xxx" "foo xxx" "foo1 xxx" } {
+ gdb_test "python gdb.Command('$prefix cmd', gdb.COMMAND_NONE)" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: Could not find command prefix $prefix\\." \
+ "Error occurred in Python: Could not find command prefix $prefix\\."]
+ }
+
+ gdb_test_no_output "python gdb.Command('foo2', gdb.COMMAND_NONE, prefix=True)"
+
+ foreach prefix { "foo" "foo xxx" "foo1 xxx" "foo2 xxx" } {
+ gdb_test "python gdb.Command('$prefix cmd2', gdb.COMMAND_NONE)" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: Could not find command prefix $prefix\\." \
+ "Error occurred in Python: Could not find command prefix $prefix\\."]
+ }
+}
+
+# Check what happens if a command object is called without an 'invoke'
+# method.
+proc_with_prefix test_deleting_invoke_methods {} {
+ clean_restart
+
+ gdb_test_multiline "create 'foo' prefix command" \
+ "python" "" \
+ "class test_prefix(gdb.Command):" "" \
+ " def __init__ (self):" "" \
+ " super().__init__ (\"foo\", gdb.COMMAND_USER, prefix=True)" "" \
+ " def invoke (self, arg, from_tty):" "" \
+ " print(\"In 'foo' invoke: %s\" % arg)" "" \
+ "foo = test_prefix()" "" \
+ "end" ""
+
+ gdb_test_multiline "create 'foo bar' command" \
+ "python" "" \
+ "class test_cmd(gdb.Command):" "" \
+ " def __init__ (self):" "" \
+ " super().__init__ (\"foo bar\", gdb.COMMAND_USER)" "" \
+ " def invoke (self, arg, from_tty):" "" \
+ " print(\"In 'foo bar' invoke: %s\" % arg)" "" \
+ "foo_bar = test_cmd()" "" \
+ "end" ""
+
+ gdb_test "foo def" "In 'foo' invoke: def" \
+ "call 'foo' with an unknown sub-command"
+
+ gdb_test "foo bar def" "In 'foo bar' invoke: def" \
+ "call 'foo bar' with arguments"
+
+ gdb_test_no_output "python del(foo_bar.__class__.invoke)" \
+ "delete invoke from test_cmd class"
+
+ with_test_prefix "after deleting test_cmd.invoke" {
+ gdb_test "foo def" "In 'foo' invoke: def" \
+ "call 'foo' with an unknown sub-command"
+
+ gdb_test "foo bar def" \
+ "^Python command object missing 'invoke' method\\." \
+ "call 'foo bar' with arguments"
+ }
+
+ gdb_test_no_output "python del(foo.__class__.invoke)" \
+ "delete invoke from test_prefix class"
+
+ with_test_prefix "after deleting test_prefix.invoke" {
+ gdb_test "foo def" \
+ "^Python command object missing 'invoke' method\\." \
+ "call 'foo' with an unknown sub-command"
+
+ gdb_test "foo bar def" \
+ "^Python command object missing 'invoke' method\\." \
+ "call 'foo bar' with arguments"
+ }
+}
+
test_command_redefining_itself
+test_unknown_prefix
+test_deleting_invoke_methods
diff --git a/gdb/testsuite/gdb.python/py-color-leak.exp b/gdb/testsuite/gdb.python/py-color-leak.exp
new file mode 100644
index 0000000..6d7fa7c
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-color-leak.exp
@@ -0,0 +1,28 @@
+# Copyright (C) 2025 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 file is part of the GDB testsuite. It checks for memory leaks
+# associated with allocating gdb.Color objects.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+
+standard_testfile
+
+clean_restart
+
+gdb_py_run_memory_leak_test ${srcdir}/${subdir}/${testfile}.py \
+ "gdb.Color object deallocates correctly"
diff --git a/gdb/testsuite/gdb.python/py-color-leak.py b/gdb/testsuite/gdb.python/py-color-leak.py
new file mode 100644
index 0000000..852458f
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-color-leak.py
@@ -0,0 +1,39 @@
+# Copyright (C) 2025 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/>.
+
+import sys
+
+import gdb
+
+# Avoid generating
+# src/gdb/testsuite/gdb.python/__pycache__/gdb_leak_detector.cpython-<n>.pyc.
+sys.dont_write_bytecode = True
+
+import gdb_leak_detector # noqa: E402
+
+
+class color_leak_detector(gdb_leak_detector.gdb_leak_detector):
+ def __init__(self):
+ super().__init__(__file__)
+ self.color = None
+
+ def allocate(self):
+ self.color = gdb.Color("red")
+
+ def deallocate(self):
+ self.color = None
+
+
+color_leak_detector().run()
diff --git a/gdb/testsuite/gdb.python/py-color-pagination.exp b/gdb/testsuite/gdb.python/py-color-pagination.exp
new file mode 100644
index 0000000..6b10f9c
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-color-pagination.exp
@@ -0,0 +1,194 @@
+# Copyright (C) 2025 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 file is part of the GDB testsuite. It tests gdb.Color and how this
+# interacts with GDB's pagination system. The test also tests gdb.Style
+# because the tests are very similar.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+require {!is_remote host}
+
+standard_testfile
+
+set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
+
+set str "<[string repeat - 78]>"
+
+# These define all the default attributes for a style: background
+# color, intensity, italics, and underlined.
+set other_attr ";49;22;23;24;27"
+
+# These colors set the foreground color only. Everything else is the
+# default.
+set black "(?:\033\\\[30${other_attr}m)"
+set red "(?:\033\\\[31${other_attr}m)"
+set green "(?:\033\\\[32${other_attr}m)"
+set yellow "(?:\033\\\[33${other_attr}m)"
+set blue "(?:\033\\\[34${other_attr}m)"
+set magenta "(?:\033\\\[35${other_attr}m)"
+set cyan "(?:\033\\\[36${other_attr}m)"
+set white "(?:\033\\\[37${other_attr}m)"
+
+set any_color "(?:${black}|${red}|${green}|${yellow}|${blue}|${magenta}|${cyan}|${white})"
+
+# Run the command 'TYPE-fill MODE' which fills the screen with output and
+# triggers the pagination prompt. Check that styling is applied correctly
+# to the output.
+proc test_pagination { type mode } {
+
+ # Start with a fresh GDB, but enable color support.
+ with_ansi_styling_terminal {
+ clean_restart
+ }
+
+ gdb_test_no_output "source $::pyfile" "source the script"
+
+ gdb_test_no_output "set width 80"
+ gdb_test_no_output "set height 15"
+
+ set saw_bad_color_handling false
+ set expected_restore_color ""
+ set last_color ""
+ gdb_test_multiple "$type-fill $mode" "" {
+ -re "^$type-fill $mode\r\n" {
+ exp_continue
+ }
+
+ -re "^(${::any_color})(${::any_color})$::str" {
+ # After a continuation prompt GDB will restore the previous
+ # color, and then we immediately switch to a new color.
+ set restored_color $expect_out(1,string)
+ if { $restored_color ne $expected_restore_color } {
+ set saw_bad_color_handling true
+ }
+ set last_color $expect_out(2,string)
+ exp_continue
+ }
+
+ -re "^(${::any_color})$::str" {
+ # This pattern matches printing STR in all cases that are not
+ # immediately after a pagination prompt. In this case there is
+ # a single escape sequence to set the color.
+ set last_color $expect_out(1,string)
+ exp_continue
+ }
+
+ -re "^\033\\\[${::decimal}m$::str" {
+ # This catches the case where the color's escape sequence has
+ # not been converted back into a full style. This indicates
+ # something went wrong in the pager_file::puts function.
+ set saw_bad_color_handling true
+ exp_continue
+ }
+
+ -re "^\033\\\[m$::pagination_prompt$" {
+ # After a pagination prompt we expect GDB to restore the last
+ # color.
+ set expected_restore_color $last_color
+
+ # Send '\n' to view more output.
+ send_gdb "\n"
+ exp_continue
+ }
+
+ -re "^$::pagination_prompt$" {
+ # After a pagination prompt we expect GDB to restore the last
+ # color.
+ set expected_restore_color $last_color
+
+ # If we didn't see a color reset sequence before the pagination
+ # prompt, then the prompt will have been printed in the wrong
+ # color, this is a GDB bug.
+ set saw_bad_color_handling true
+
+ # Send '\n' to view more output.
+ send_gdb "\n"
+ exp_continue
+ }
+
+ -re "^\r\n" {
+ # The matches the newline sent to the continuation prompt.
+ exp_continue
+ }
+
+ -re "^\033\\\[m\r\n$::gdb_prompt $" {
+ gdb_assert { !$saw_bad_color_handling } $gdb_test_name
+ }
+ }
+}
+
+# Run the command 'style-fill-v2' which fills the screen with output and
+# triggers the pagination prompt. Check that styling is applied correctly
+# to the output. This v2 command is exercising passing a style to
+# gdb.write() rather than passing the escape sequence for the style.
+proc test_pagination_v2 { } {
+ set saw_bad_color_handling false
+ set expected_restore_color ""
+ set last_color ""
+ gdb_test_multiple "style-fill-v2" "" {
+ -re "^style-fill-v2\r\n" {
+ exp_continue
+ }
+
+ -re "^(${::any_color}\033\\\[m)(${::any_color})$::str\033\\\[m" {
+ # After a continuation prompt GDB will restore the previous
+ # color, and then we immediately switch to a new color.
+ set restored_color $expect_out(1,string)
+ if { $restored_color ne $expected_restore_color } {
+ set saw_bad_color_handling true
+ }
+ set last_color $expect_out(2,string)
+ exp_continue
+ }
+
+ -re "^(${::any_color})$::str\033\\\[m" {
+ # This pattern matches printing STR in all cases that are not
+ # immediately after a pagination prompt. In this case there is
+ # a single escape sequence to set the color.
+ set last_color $expect_out(1,string)
+ exp_continue
+ }
+
+ -re "^$::pagination_prompt$" {
+ # After a pagination prompt we expect GDB to restore the last
+ # color, but this will then be disabled due to a styled
+ # gdb.write emitting a return to default style escape sequence.
+ set expected_restore_color "$last_color\033\[m"
+
+ # Send '\n' to view more output.
+ send_gdb "\n"
+ exp_continue
+ }
+
+ -re "^\r\n" {
+ # The matches the newline sent to the continuation prompt.
+ exp_continue
+ }
+
+ -re "^$::gdb_prompt $" {
+ gdb_assert { !$saw_bad_color_handling } $gdb_test_name
+ }
+ }
+}
+
+foreach_with_prefix type { color style } {
+ foreach_with_prefix mode { write print } {
+ test_pagination $type $mode
+ }
+}
+
+test_pagination_v2
diff --git a/gdb/testsuite/gdb.python/py-color-pagination.py b/gdb/testsuite/gdb.python/py-color-pagination.py
new file mode 100644
index 0000000..9cdc76c
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-color-pagination.py
@@ -0,0 +1,82 @@
+# Copyright (C) 2025 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/>.
+
+import gdb
+
+basic_colors = ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"]
+
+
+def write(mode, text):
+ if mode == "write":
+ gdb.write(text)
+ else:
+ print(text, end="")
+
+
+class ColorTester(gdb.Command):
+ def __init__(self):
+ super().__init__("color-fill", gdb.COMMAND_USER)
+
+ def invoke(self, args, from_tty):
+ mode = args
+ str = "<" + "-" * 78 + ">"
+ for i in range(0, 20):
+ for color_name in basic_colors:
+ c = gdb.Color(color_name)
+ write(mode, c.escape_sequence(True))
+ write(mode, str)
+
+ default = gdb.Color("none")
+ write(mode, default.escape_sequence(True))
+ write(mode, "\n")
+
+
+class StyleTester(gdb.Command):
+ def __init__(self):
+ super().__init__("style-fill", gdb.COMMAND_USER)
+
+ def invoke(self, args, from_tty):
+ mode = args
+ str = "<" + "-" * 78 + ">"
+ for i in range(0, 20):
+ for color_name in basic_colors:
+ c = gdb.Color(color_name)
+ s = gdb.Style(foreground=c)
+ write(mode, s.escape_sequence())
+ write(mode, str)
+
+ default = gdb.Style()
+ write(mode, default.escape_sequence())
+ write(mode, "\n")
+
+
+class StyleTester2(gdb.Command):
+ def __init__(self):
+ super().__init__("style-fill-v2", gdb.COMMAND_USER)
+
+ def invoke(self, args, from_tty):
+ str = "<" + "-" * 78 + ">"
+ for i in range(0, 20):
+ for color_name in basic_colors:
+ c = gdb.Color(color_name)
+ s = gdb.Style(foreground=c)
+ gdb.write(str, style=s)
+
+ gdb.write("\n")
+
+
+ColorTester()
+StyleTester()
+StyleTester2()
diff --git a/gdb/testsuite/gdb.python/py-color.exp b/gdb/testsuite/gdb.python/py-color.exp
index c6f1041..08089e5 100644
--- a/gdb/testsuite/gdb.python/py-color.exp
+++ b/gdb/testsuite/gdb.python/py-color.exp
@@ -13,17 +13,22 @@
# 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 file is part of the GDB testsuite.
-# It tests gdb.parameter and gdb.Parameter.
+# This file is part of the GDB testsuite. It tests gdb.Color.
load_lib gdb-python.exp
require allow_python_tests
+require {!is_remote host}
-# Start with a fresh gdb.
-clean_restart
+# Start with a fresh GDB, but enable color support.
+with_ansi_styling_terminal {
+ clean_restart
+}
-gdb_test_no_output "python print_color_attrs = lambda c: print (c, c.colorspace, c.is_none, c.is_indexed, c.is_direct)" \
+gdb_test_no_output "python get_color_attrs = lambda c: \"%s %s %s %s %s\" % (str(c), c.colorspace, c.is_none, c.is_indexed, c.is_direct)" \
+ "get_color_attrs helper"
+
+gdb_test_no_output "python print_color_attrs = lambda c: print (get_color_attrs (c))" \
"print_color_attrs helper"
gdb_test_no_output "python c = gdb.Color ()" \
@@ -59,6 +64,15 @@ gdb_test "python print_color_attrs (c)" "green 1 False True False" \
gdb_test "python print (c.index)" "2" \
"print index of a basic color with ansi colorspace"
+# Create a color using keyword arguments, and check it matches the
+# non-keyword color.
+gdb_test_no_output "python c2 = gdb.Color (color_space = gdb.COLORSPACE_ANSI_8COLOR, value = 2)" \
+ "create color from basic index and ansi colorspace using keywords"
+gdb_test "python print(get_color_attrs (c) == get_color_attrs (c2))" "True" \
+ "check attributes match"
+gdb_test "python print(c.index == c2.index)" "True" \
+ "check index matches"
+
gdb_test_no_output "python c = gdb.Color (2, gdb.COLORSPACE_XTERM_256COLOR)" \
"create color from basic index and xterm256 colorspace"
gdb_test "python print_color_attrs (c)" "2 3 False True False" \
@@ -97,4 +111,54 @@ gdb_test [concat "python print (c_red.escape_sequence (True) + " \
"c_none.escape_sequence (True))"] \
"\033\\\[31m\033\\\[42mred on green\033\\\[49m red on default\033\\\[39m" \
"escape sequences"
-
+gdb_test [concat "python print (c_red.escape_sequence (is_foreground = True) + " \
+ "c_green.escape_sequence (is_foreground = False) + 'red on green' + " \
+ "c_none.escape_sequence (is_foreground = False) + ' red on default' + " \
+ "c_none.escape_sequence (is_foreground = True))"] \
+ "\033\\\[31m\033\\\[42mred on green\033\\\[49m red on default\033\\\[39m" \
+ "escape sequences using keyword arguments"
+
+# Ensure that turning styling off means no escape sequences.
+gdb_test_no_output "set style enabled off"
+gdb_test_no_output "python print (c_red.escape_sequence (True), end='')"
+gdb_test_no_output "python print (c_red.escape_sequence (False), end='')"
+gdb_test_no_output "set style enabled on"
+
+gdb_test_multiline "Try to sub-class gdb.Color" \
+ "python" "" \
+ "class my_color(gdb.Color):" "" \
+ " def __init__(self):" "" \
+ " super().__init__('red')" "" \
+ "end" \
+ [multi_line \
+ "Python Exception <class 'TypeError'>: type 'gdb\\.Color' is not an acceptable base type" \
+ "Error occurred in Python: type 'gdb\\.Color' is not an acceptable base type"]
+
+gdb_test_multiline "Setup a color parameter and non gdb.Color object" \
+ "python" "" \
+ "class my_param(gdb.Parameter):" "" \
+ " def __init__(self):" "" \
+ " super().__init__('color-param', gdb.COMMAND_NONE, gdb.PARAM_COLOR)" "" \
+ " self.value = gdb.Color('red')" "" \
+ "color_param = my_param()" "" \
+ " " "" \
+ "class bad_type:" "" \
+ " @property" "" \
+ " def __class__(self):" "" \
+ " raise RuntimeError('__class__ error for bad_type')" "" \
+ "bad_obj = bad_type()" "" \
+ "end" ""
+
+gdb_test_no_output "python color_param.value = gdb.Color('blue')" \
+ "set color parameter to blue"
+
+gdb_test "python color_param.value = bad_obj" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: color argument must be a gdb\\.Color object\\." \
+ "Error occurred in Python: color argument must be a gdb\\.Color object\\."] \
+ "set color parameter to a non-color type"
+
+gdb_test "python c_none.escape_sequence(c_red)" \
+ [multi_line \
+ "Python Exception <class 'TypeError'>: argument 1 must be bool, not gdb.Color" \
+ "Error occurred in Python: argument 1 must be bool, not gdb.Color"]
diff --git a/gdb/testsuite/gdb.python/py-commands-breakpoint.py b/gdb/testsuite/gdb.python/py-commands-breakpoint.py
index dbe7676..df732e7 100644
--- a/gdb/testsuite/gdb.python/py-commands-breakpoint.py
+++ b/gdb/testsuite/gdb.python/py-commands-breakpoint.py
@@ -34,10 +34,10 @@ class PyCommandsBreakpoint(gdb.Breakpoint):
def __setattr__(self, name, value):
if name == "commands":
- l = ["python PyCommandsBreakpoint.run_py_commands(%d)" % self.number]
+ cmds = ["python PyCommandsBreakpoint.run_py_commands(%d)" % self.number]
if value != "":
- l.append(value)
- value = "\n".join(l)
+ cmds.append(value)
+ value = "\n".join(cmds)
super().__setattr__(name, value)
diff --git a/gdb/testsuite/gdb.python/py-connection-removed.exp b/gdb/testsuite/gdb.python/py-connection-removed.exp
index d60ebb0..5056eb1 100644
--- a/gdb/testsuite/gdb.python/py-connection-removed.exp
+++ b/gdb/testsuite/gdb.python/py-connection-removed.exp
@@ -58,8 +58,17 @@ if { [target_info exists gdb_protocol] } {
set connection_type "native"
}
-# Add an inferior that shares a connection with inferior 1.
-gdb_test "add-inferior" "Added inferior 2 on connection 1 \[^\r\n\]+"
+# Add an inferior that shares a connection with inferior 1. If we are
+# using a 'remote' connection then this cannot be shared with the new
+# inferior, so we get a warning, and a new inferior with no connection.
+if { $connection_type == "remote" } {
+ gdb_test "add-inferior" \
+ [multi_line \
+ "warning: can't share connection 1 \\(remote \[^\r\n\]+\\) between inferiors" \
+ "Added inferior 2"]
+} else {
+ gdb_test "add-inferior" "Added inferior 2 on connection 1 \[^\r\n\]+"
+}
# Add an inferior with no connection.
gdb_test "add-inferior -no-connection" "Added inferior 3"
diff --git a/gdb/testsuite/gdb.python/py-corefile.c b/gdb/testsuite/gdb.python/py-corefile.c
new file mode 100644
index 0000000..1334ff6
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-corefile.c
@@ -0,0 +1,25 @@
+/* Copyright 2025 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/>. */
+
+#include <stdlib.h>
+
+int
+main (void)
+{
+ /* With correct ulimit, etc. this should cause a core dump. */
+ abort ();
+}
diff --git a/gdb/testsuite/gdb.python/py-corefile.exp b/gdb/testsuite/gdb.python/py-corefile.exp
new file mode 100644
index 0000000..866b60a
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-corefile.exp
@@ -0,0 +1,281 @@
+# Copyright (C) 2025 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 file is part of the GDB testsuite. It tests the core file
+# support in Python.
+
+require isnative
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+
+standard_testfile
+
+if {[build_executable "build executable" $testfile $srcfile] == -1} {
+ return
+}
+
+set corefile [core_find $binfile]
+if {$corefile == ""} {
+ unsupported "couldn't create or find corefile"
+ return
+}
+
+# Create a copy of the corefile.
+set other_corefile [standard_output_file ${testfile}-other.core]
+remote_exec build "cp $corefile $other_corefile"
+
+clean_restart
+
+gdb_test_no_output "python inf = gdb.selected_inferior()" \
+ "capture current inferior"
+
+gdb_test "python print(inf.corefile)" "^None" \
+ "Inferior.corefile is None before loading a core file"
+
+gdb_test "core-file $corefile" ".*" \
+ "load core file"
+
+set file_re [string_to_regexp $corefile]
+gdb_test "python print(inf.corefile)" "^<gdb\\.Corefile inferior=1 filename='$file_re'>" \
+ "Inferior.corefile is a valid object after loading a core file"
+
+gdb_test_no_output "python core1=inf.corefile" "capture gdb.Corefile object"
+
+gdb_test "python print(core1.__dict__)" "^\\{\\}" \
+ "print Corefile.__dict__ when empty"
+
+gdb_test_no_output "python core1._my_attribute = \"Hello\"" \
+ "write new attribute into Corefile object"
+
+gdb_test "python print(core1._my_attribute)" "^Hello" \
+ "immediately read new attribute"
+
+gdb_test "python print(core1.__dict__)" "^\\{'_my_attribute': 'Hello'\\}" \
+ "print Corefile.__dict__ after adding an attribute"
+
+gdb_test "python print(core1.filename)" "^$file_re" \
+ "Corefile.filename attribute works as expected"
+
+gdb_test "python print(core1.is_valid())" "^True" \
+ "Corefile.is_valid() is True while corefile is loaded"
+
+gdb_test "core-file" "^No core file now\\." "unload current core file"
+
+gdb_test "python print(core1.is_valid())" "^False" \
+ "Corefile.is_valid() is False after corefile is unloaded"
+
+gdb_test "python print(core1.__dict__)" "^\\{'_my_attribute': 'Hello'\\}" \
+ "print Corefile.__dict__ with attribute when invalid"
+
+gdb_test "python print(core1)" "^<gdb\\.Corefile \\(invalid\\)>" \
+ "print an invalid gdb.Corefile object"
+
+gdb_test "python print(core1.filename)" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: Corefile no longer exists\\." \
+ "Error occurred in Python: Corefile no longer exists\\."] \
+ "error when reading filename from invalid Corefile"
+
+gdb_test "python print(inf.corefile)" "^None" \
+ "Inferior.corefile is None again after corefile unload"
+
+gdb_test "python print(core1._my_attribute)" "^Hello" \
+ "read new attribute from invalid core file"
+
+# Create a second inferior.
+gdb_test "add-inferior"
+gdb_test "inferior 2"
+
+with_test_prefix "in second inferior" {
+ gdb_test "core-file $corefile" ".*" \
+ "load core file"
+
+ gdb_test "python print(inf.corefile)" "^None" \
+ "first inferior still has no core file"
+
+ gdb_test_no_output "python core2=gdb.selected_inferior().corefile" \
+ "capture gdb.Corefile object"
+
+ # The _my_attribute was added to CORE1, not CORE2. Check it
+ # doesn't somehow appear on CORE2.
+ gdb_test "python print(core2._my_attribute)" \
+ "AttributeError.*: 'gdb\\.Corefile' object has no attribute '_my_attribute'" \
+ "try to read attribute that doesn't exist"
+
+ gdb_test "python print(core2.filename)" "^$file_re" \
+ "Corefile.filename attribute works as expected"
+
+ gdb_test "inferior 1"
+}
+
+# Read the name of the core file from the second program space while
+# the current program space is the first one.
+gdb_test "python print(core2.filename)" "^$file_re" \
+ "Corefile.filename attribute works from different progspace"
+
+# Load the other corefile into the first inferior.
+gdb_test "core $other_corefile" ".*" \
+ "load other corefile into inferior 1"
+
+# Delete the second inferior. We need to switch to the second
+# inferior and unload its corefile before we can do that. Then,
+# switch back to the first inferior, delete the second, and try to
+# read the filename of the core file from the (now deleted) second
+# inferior. We should get an error about the gdb.Corefile being
+# invalid.
+with_test_prefix "remove second inferior" {
+ gdb_test "inferior 2"
+
+ gdb_test "python print(inf.corefile.filename)" \
+ "^[string_to_regexp $other_corefile]" \
+ "read inferior 1 corefile when in inferior 2"
+
+ gdb_test_no_output "python core1=inf.corefile" \
+ "capture inferior 1 gdb.Corefile while in inferior 2"
+
+ # This is a new CORE1 object, check that _my_attribute is gone.
+ gdb_test "python print(core1._my_attribute)" \
+ "AttributeError.*: 'gdb\\.Corefile' object has no attribute '_my_attribute'" \
+ "try to read attribute that doesn't exist"
+
+ gdb_test "core-file"
+
+ gdb_test "python print(core2.filename)" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: Corefile no longer exists\\." \
+ "Error occurred in Python: Corefile no longer exists\\."] \
+ "error when reading filename from invalid Corefile"
+
+ gdb_test "inferior 1"
+
+ gdb_test "remove-inferiors 2"
+
+ gdb_test "python print(core2.is_valid())" "^False" \
+ "Corefile.is_valid() is False after corefile is unloaded, and Progspace is deleted"
+
+ gdb_test "python print(core2.filename)" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: Corefile no longer exists\\." \
+ "Error occurred in Python: Corefile no longer exists\\."] \
+ "error when reading filename of an invalid Corefile, from deleted program space"
+
+ gdb_test "python print(core1.is_valid())" "^True" \
+ "check inferior 1 core file is still valid"
+}
+
+# Test the Corefile.mapped_files() API. The Python script that is
+# sourced here implements 'info proc mappings' in Python using the
+# mapped_files API. The output from the built-in command, and the
+# Python command should be identical.
+with_test_prefix "test mapped files data" {
+ clean_restart
+
+ set remote_python_file \
+ [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
+
+ # Load the Python script into GDB.
+ gdb_test "source $remote_python_file" "^Success" \
+ "source python script"
+
+ # Load the core file.
+ gdb_test "core-file $corefile" ".*" \
+ "load core file"
+
+ # Two files to write the output to.
+ set out_1 [standard_output_file ${gdb_test_file_name}-out-1.txt]
+ set out_2 [standard_output_file ${gdb_test_file_name}-out-2.txt]
+
+ # Run the built-in command, then the new Python command, capture
+ # the output.
+ gdb_test "pipe info proc mappings | tee $out_1" ".*" \
+ "capture built-in mappings output"
+ gdb_test "pipe info proc py-mappings | tee $out_2" ".*" \
+ "capture Python based mappings data"
+
+ # Check the output is identical.
+ gdb_test "shell diff -s $out_1 $out_2" \
+ "Files \[^\r\n\]+-out-1.txt and \[^\r\n\]+-out-2.txt are identical" \
+ "diff input and output one"
+
+ # Check build-ids within the core file mapping data. I'm only
+ # aware of GNU/Linux placing the first page of each mapped ELF
+ # into the generated core file so that the build-id can be found.
+ if {[istarget *-*-linux*]} {
+ set results [list]
+ gdb_test_multiple "show-build-ids" "" {
+ -re "^show-build-ids\r\n" {
+ exp_continue
+ }
+ -re "^Objfile Build-Id\\s+Core File Build-Id\\s+File Name\\s*\r\n" {
+ exp_continue
+ }
+ -re "^(\\S+)\\s+(\\S+)\\s+(\[^\r\n\]+)\r\n" {
+ set objfile_build_id $expect_out(1,string)
+ set core_file_build_id $expect_out(2,string)
+ set file_name $expect_out(3,string)
+ lappend results [list $objfile_build_id \
+ $core_file_build_id \
+ $file_name]
+ exp_continue
+ }
+ -re "^$gdb_prompt " {
+ pass $gdb_test_name
+ }
+ }
+
+ set bad_count 0
+ foreach entry $results {
+ set objfile_build_id [lindex $entry 0]
+ set core_file_build_id [lindex $entry 1]
+ set file_name [lindex $entry 2]
+ if { $objfile_build_id ne $core_file_build_id } {
+ if { $core_file_build_id ne "None" } {
+ verbose -log "Mismatched build-ids $objfile_build_id vs $core_file_build_id for $file_name"
+ incr bad_count
+ } elseif { [expect_build_id_in_core_file $file_name] } {
+ verbose -log "Failed to find build-id for $file_name"
+ incr bad_count
+ } else {
+ verbose -log "This build-id was likely not in the core file"
+ }
+ }
+ }
+
+ gdb_assert { $bad_count == 0 } \
+ "found expected build-ids in core file"
+ }
+
+ # Check the is_main_executable flag in the mapping data.
+ gdb_test "check-main-executable" "^PASS"
+
+ # Check that the mapped files "list" is actually an immutable
+ # tuple.
+ gdb_test_no_output "python core = gdb.selected_inferior().corefile"
+ gdb_test_no_output "python mapped_files = core.mapped_files()"
+ gdb_test "python print(type(mapped_files))" \
+ "^<class 'tuple'>"
+ gdb_test "python mapped_files\[0\] = None" \
+ "'tuple' object does not support item assignment"
+ gdb_test "python print(mapped_files\[0\] is None)" "^False"
+
+ # And same for the list of regions for a mapped file.
+ gdb_test_no_output "python regions = mapped_files\[0\].regions"
+ gdb_test "python print(type(regions))" \
+ "^<class 'tuple'>"
+ gdb_test "python regions\[0\] = None" \
+ "'tuple' object does not support item assignment"
+}
diff --git a/gdb/testsuite/gdb.python/py-corefile.py b/gdb/testsuite/gdb.python/py-corefile.py
new file mode 100644
index 0000000..ab3d1b7
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-corefile.py
@@ -0,0 +1,187 @@
+# Copyright (C) 2025 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/>.
+
+import pathlib
+
+import gdb
+
+
+class Mapping:
+ def __init__(self, mapping, region):
+ self._mapping = mapping
+ self._region = region
+
+ @property
+ def start(self):
+ return self._region.start
+
+ @property
+ def end(self):
+ return self._region.end
+
+ @property
+ def offset(self):
+ return self._region.file_offset
+
+ @property
+ def filename(self):
+ return self._mapping.filename
+
+
+def info_proc_mappings():
+ print("Mapped address spaces:")
+ print("")
+ format_str = "%-18s %-18s %-18s %-18s %s "
+ print(format_str % ("Start Addr", "End Addr", "Size", "Offset", "File"))
+
+ core = gdb.selected_inferior().corefile
+ mappings = core.mapped_files()
+
+ result = []
+ for m in mappings:
+ for r in m.regions:
+ result.append(Mapping(m, r))
+
+ result.sort(key=lambda x: x.start)
+ for r in result:
+ sz = r.end - r.start
+ print(
+ format_str
+ % (
+ "0x%016x" % r.start,
+ "0x%016x" % r.end,
+ "0x%-16x" % sz,
+ "0x%-16x" % r.offset,
+ "%s" % r.filename,
+ )
+ )
+
+
+class InfoProcPyMappings(gdb.Command):
+ def __init__(self):
+ gdb.Command.__init__(self, "info proc py-mappings", gdb.COMMAND_DATA)
+
+ def invoke(self, args, from_tty):
+ info_proc_mappings()
+
+
+InfoProcPyMappings()
+
+
+# Assume that a core file is currently loaded.
+#
+# Look through all the objfiles for the current inferior, and record
+# any that have a build-id.
+#
+# Then look through the core file mapped files. Look for entries that
+# correspond with the loaded objfiles. For these matching entries,
+# capture the build-id extracted from the core file.
+#
+# Finally, print a table with the build-id from the objfile, the
+# build-id from the core file, and the file name.
+#
+# This is then processed from the test script to check the build-ids
+# match.
+class ShowBuildIds(gdb.Command):
+ def __init__(self):
+ gdb.Command.__init__(self, "show-build-ids", gdb.COMMAND_DATA)
+
+ def invoke(self, args, from_tty):
+ inf = gdb.selected_inferior()
+ objfiles = inf.progspace.objfiles()
+
+ path_to_build_id = {}
+
+ # Initial length based on column headings.
+ longest_build_id = 18
+
+ for o in objfiles:
+ if not o.is_file or o.build_id is None or o.owner is not None:
+ continue
+ p = pathlib.Path(o.filename).resolve()
+ b = o.build_id
+ path_to_build_id[p] = {"objfile": b, "corefile": "missing"}
+ if len(b) > longest_build_id:
+ longest_build_id = len(b)
+
+ core_mapped_files = inf.corefile.mapped_files()
+ for m in core_mapped_files:
+ p = pathlib.Path(m.filename).resolve()
+ b = m.build_id
+
+ if b is not None and len(b) > longest_build_id:
+ longest_build_id = len(b)
+
+ if p in path_to_build_id:
+ path_to_build_id[p]["corefile"] = b
+
+ format_str = (
+ "%-" + str(longest_build_id) + "s %-" + str(longest_build_id) + "s %s"
+ )
+
+ def make_title(string, length=0):
+ if length > 0:
+ padding_len = length - len(string)
+ else:
+ padding_len = 0
+
+ padding = " " * padding_len
+ style = gdb.Style("title")
+ return style.apply(string) + padding
+
+ print(
+ "%s %s %s"
+ % (
+ make_title("Objfile Build-Id", longest_build_id),
+ make_title("Core File Build-Id", longest_build_id),
+ make_title("File Name"),
+ )
+ )
+ for p, b in path_to_build_id.items():
+ print(format_str % (b["objfile"], b["corefile"], p))
+
+
+ShowBuildIds()
+
+
+class CheckMainExec(gdb.Command):
+ def __init__(self):
+ gdb.Command.__init__(self, "check-main-executable", gdb.COMMAND_DATA)
+
+ def invoke(self, args, from_tty):
+ inf = gdb.selected_inferior()
+ pspace = inf.progspace
+ exec_filename = pathlib.Path(pspace.executable_filename).resolve()
+
+ count = 0
+ core_mapped_files = inf.corefile.mapped_files()
+ for m in core_mapped_files:
+ if not m.is_main_executable:
+ continue
+
+ p = pathlib.Path(m.filename).resolve()
+
+ count += 1
+ assert exec_filename == p, "main exec filename mismatch"
+
+ assert count == 1, "invalid main executable count"
+
+ print("PASS")
+
+
+CheckMainExec()
+
+
+print("Success")
diff --git a/gdb/testsuite/gdb.python/py-disasm.exp.tcl b/gdb/testsuite/gdb.python/py-disasm.exp.tcl
index 938326d..c936f0d 100644
--- a/gdb/testsuite/gdb.python/py-disasm.exp.tcl
+++ b/gdb/testsuite/gdb.python/py-disasm.exp.tcl
@@ -24,14 +24,16 @@ standard_testfile py-disasm.c
if { $kind == "obj" } {
- set obj [standard_output_file ${gdb_test_file_name}.o]
+ set testfile $testfile.o
+ set binfile [standard_output_file $testfile]
- if { [gdb_compile "$srcdir/$subdir/$srcfile" $obj object "debug"] != "" } {
- untested "failed to compile object file [file tail $obj]"
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile object \
+ "debug"] != "" } {
+ untested "failed to compile object file $testfile"
return -1
}
- clean_restart $obj
+ clean_restart $testfile
} else {
@@ -49,7 +51,7 @@ if { $kind == "obj" } {
set pyfile [gdb_remote_download host ${srcdir}/${subdir}/py-disasm.py]
gdb_test "source ${pyfile}" "Python script imported" \
- "import python scripts"
+ "import python scripts"
set line [gdb_get_line_number "Break here."]
@@ -152,7 +154,10 @@ set test_plans \
"Buffer returned from read_memory is sized $decimal instead of the expected $decimal"]] \
[list "ResultOfWrongType" \
[make_exception_pattern "TypeError" \
- "Result is not a DisassemblerResult."]] \
+ "Result from Disassembler must be gdb.DisassemblerResult, not Blah."]] \
+ [list "ResultOfVeryWrongType" \
+ [make_exception_pattern "TypeError" \
+ "Result from Disassembler must be gdb.DisassemblerResult, not Blah."]] \
[list "ErrorCreatingTextPart_NoArgs" \
[make_exception_pattern "TypeError" \
[missing_arg_pattern "style" 1]]] \
diff --git a/gdb/testsuite/gdb.python/py-disasm.py b/gdb/testsuite/gdb.python/py-disasm.py
index 32d6aa7..d88c7a2 100644
--- a/gdb/testsuite/gdb.python/py-disasm.py
+++ b/gdb/testsuite/gdb.python/py-disasm.py
@@ -39,9 +39,7 @@ def builtin_disassemble_wrapper(info):
def check_building_disassemble_result():
"""Check that we can create DisassembleResult objects correctly."""
-
- result = gdb.disassembler.DisassemblerResult()
-
+ gdb.disassembler.DisassemblerResult()
print("PASS")
@@ -62,16 +60,12 @@ class TestDisassembler(Disassembler):
disassembly wrapping for the global CURRENT_PC."""
def __init__(self):
- global current_pc
-
super().__init__("TestDisassembler")
self.__info = None
- if current_pc == None:
+ if current_pc is None:
raise gdb.GdbError("no current_pc set")
def __call__(self, info):
- global current_pc
-
if info.address != current_pc:
return None
self.__info = info
@@ -234,7 +228,7 @@ class GdbErrorLateDisassembler(TestDisassembler):
"""Raise a GdbError after calling the builtin disassembler."""
def disassemble(self, info):
- result = builtin_disassemble_wrapper(info)
+ builtin_disassemble_wrapper(info)
raise gdb.GdbError("GdbError after builtin disassembler")
@@ -242,7 +236,7 @@ class RuntimeErrorLateDisassembler(TestDisassembler):
"""Raise a RuntimeError after calling the builtin disassembler."""
def disassemble(self, info):
- result = builtin_disassemble_wrapper(info)
+ builtin_disassemble_wrapper(info)
raise RuntimeError("RuntimeError after builtin disassembler")
@@ -265,7 +259,7 @@ class MemoryErrorLateDisassembler(TestDisassembler):
before we return a result."""
def disassemble(self, info):
- result = builtin_disassemble_wrapper(info)
+ builtin_disassemble_wrapper(info)
# The following read will throw an error.
info.read_memory(1, -info.address - 1)
return DisassemblerResult(1, "BAD")
@@ -277,7 +271,7 @@ class RethrowMemoryErrorDisassembler(TestDisassembler):
def disassemble(self, info):
try:
info.read_memory(1, -info.address - 1)
- except gdb.MemoryError as e:
+ except gdb.MemoryError:
raise gdb.MemoryError("cannot read code at address -1")
return DisassemblerResult(1, "BAD")
@@ -294,6 +288,24 @@ class ResultOfWrongType(TestDisassembler):
return self.Blah(1, "ABC")
+class ResultOfVeryWrongType(TestDisassembler):
+ """Return something that is not a DisassemblerResult from disassemble
+ method. The thing returned will raise an exception if used in an
+ isinstance() call, or in PyObject_IsInstance from C++.
+ """
+
+ class Blah:
+ def __init__(self):
+ pass
+
+ @property
+ def __class__(self):
+ raise RuntimeError("error from __class__ in Blah")
+
+ def disassemble(self, info):
+ return self.Blah()
+
+
class TaggingDisassembler(TestDisassembler):
"""A simple disassembler that just tags the output."""
@@ -339,31 +351,31 @@ class GlobalCachingDisassembler(TestDisassembler):
assert isinstance(info, gdb.disassembler.DisassembleInfo)
assert not info.is_valid()
try:
- val = info.address
+ info.address
raise gdb.GdbError("DisassembleInfo.address is still valid")
except RuntimeError as e:
assert str(e) == "DisassembleInfo is no longer valid."
- except:
+ except Exception:
raise gdb.GdbError(
"DisassembleInfo.address raised an unexpected exception"
)
try:
- val = info.architecture
+ info.architecture
raise gdb.GdbError("DisassembleInfo.architecture is still valid")
except RuntimeError as e:
assert str(e) == "DisassembleInfo is no longer valid."
- except:
+ except Exception:
raise gdb.GdbError(
"DisassembleInfo.architecture raised an unexpected exception"
)
try:
- val = info.read_memory(1, 0)
+ info.read_memory(1, 0)
raise gdb.GdbError("DisassembleInfo.read is still valid")
except RuntimeError as e:
assert str(e) == "DisassembleInfo is no longer valid."
- except:
+ except Exception:
raise gdb.GdbError(
"DisassembleInfo.read raised an unexpected exception"
)
@@ -528,32 +540,28 @@ class ErrorCreatingTextPart_NoArgs(TestDisassembler):
"""Try to create a DisassemblerTextPart with no arguments."""
def disassemble(self, info):
- part = info.text_part()
- return None
+ info.text_part()
class ErrorCreatingAddressPart_NoArgs(TestDisassembler):
"""Try to create a DisassemblerAddressPart with no arguments."""
def disassemble(self, info):
- part = info.address_part()
- return None
+ info.address_part()
class ErrorCreatingTextPart_NoString(TestDisassembler):
"""Try to create a DisassemblerTextPart with no string argument."""
def disassemble(self, info):
- part = info.text_part(gdb.disassembler.STYLE_TEXT)
- return None
+ info.text_part(gdb.disassembler.STYLE_TEXT)
class ErrorCreatingTextPart_NoStyle(TestDisassembler):
"""Try to create a DisassemblerTextPart with no string argument."""
def disassemble(self, info):
- part = info.text_part(string="abc")
- return None
+ info.text_part(string="abc")
class ErrorCreatingTextPart_StringAndParts(TestDisassembler):
@@ -600,8 +608,6 @@ class Build_Result_Using_All_Parts(TestDisassembler):
text and address parts."""
def disassemble(self, info):
- global current_pc
-
parts = []
parts.append(info.text_part(gdb.disassembler.STYLE_MNEMONIC, "fake"))
parts.append(info.text_part(gdb.disassembler.STYLE_TEXT, "\t"))
@@ -759,8 +765,8 @@ class AnalyzingDisassembler(Disassembler):
idx > 0
and idx != nop_idx
and not is_nop(self._pass_1_insn[idx])
- and self._pass_1_length[idx] > self._pass_1_length[nop_idx]
- and self._pass_1_length[idx] % self._pass_1_length[nop_idx] == 0
+ and self._pass_1_length[idx] > nop_length
+ and self._pass_1_length[idx] % nop_length == 0
):
replace_idx = idx
break
@@ -774,7 +780,7 @@ class AnalyzingDisassembler(Disassembler):
idx > 0
and idx != nop_idx
and not is_nop(self._pass_1_insn[idx])
- and self._pass_1_length[idx] == self._pass_1_length[nop_idx]
+ and self._pass_1_length[idx] == nop_length
):
replace_idx = idx
break
@@ -795,7 +801,7 @@ class AnalyzingDisassembler(Disassembler):
# is a copy of _pass_1_insn, but replace the instruction we
# identified above with a series of 'nop' instructions.
self._check = list(self._pass_1_insn)
- nop_count = int(self._pass_1_length[replace_idx] / self._pass_1_length[nop_idx])
+ nop_count = int(self._pass_1_length[replace_idx] / nop_length)
nop_insn = self._pass_1_insn[nop_idx]
nops = [nop_insn] * nop_count
self._check[replace_idx : (replace_idx + 1)] = nops
@@ -834,7 +840,6 @@ class InvalidDisassembleInfo(gdb.disassembler.DisassembleInfo):
@property
def address(self):
- global current_pc
return current_pc
@property
diff --git a/gdb/testsuite/gdb.python/py-event-load.exp b/gdb/testsuite/gdb.python/py-event-load.exp
index a09a946..dbb225f 100644
--- a/gdb/testsuite/gdb.python/py-event-load.exp
+++ b/gdb/testsuite/gdb.python/py-event-load.exp
@@ -20,12 +20,6 @@ load_lib gdb-python.exp
require allow_shlib_tests allow_python_tests
-if {[get_compiler_info]} {
- warning "Could not get compiler info"
- untested "no compiler info"
- return -1
-}
-
standard_testfile .c
if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
executable {debug shlib_load}] != ""} {
diff --git a/gdb/testsuite/gdb.python/py-events-shlib.c b/gdb/testsuite/gdb.python/py-events-shlib.c
index d77517a..d480da2 100644
--- a/gdb/testsuite/gdb.python/py-events-shlib.c
+++ b/gdb/testsuite/gdb.python/py-events-shlib.c
@@ -17,4 +17,3 @@
void do_nothing (void) {}
-
diff --git a/gdb/testsuite/gdb.python/py-evsignal.exp b/gdb/testsuite/gdb.python/py-evsignal.exp
index 22b13af..86444d7 100644
--- a/gdb/testsuite/gdb.python/py-evsignal.exp
+++ b/gdb/testsuite/gdb.python/py-evsignal.exp
@@ -39,9 +39,9 @@ gdb_test_no_output "set non-stop on"
gdb_run_cmd
gdb_test_multiple "" "signal Thread 3" {
-re "event type: stop\r\nstop reason: signal\r\nstop signal: SIGUSR1\r\nthread num: 3\r\nevent type: stop\r\n.*$gdb_prompt $" {
- pass "thread 3 was signaled"
+ pass "thread 3 was signaled"
}
-re "The target does not support running in non-stop mode" {
- unsupported "non-stop mode is unsupported"
+ unsupported "non-stop mode is unsupported"
}
}
diff --git a/gdb/testsuite/gdb.python/py-evthreads.exp b/gdb/testsuite/gdb.python/py-evthreads.exp
index 0e9cd97..c0c17b3 100644
--- a/gdb/testsuite/gdb.python/py-evthreads.exp
+++ b/gdb/testsuite/gdb.python/py-evthreads.exp
@@ -41,11 +41,11 @@ gdb_run_cmd
set test "run to breakpoint 1"
gdb_test_multiple "" $test {
-re "event type: stop\r\nstop reason: breakpoint\r\nfirst breakpoint number: 1\r\nbreakpoint number: 1\r\nthread num: 1\r\n.*$gdb_prompt $" {
- pass $test
+ pass $test
}
-re "The target does not support running in non-stop mode" {
- unsupported "non-stop mode is unsupported"
- return
+ unsupported "non-stop mode is unsupported"
+ return
}
}
@@ -61,13 +61,13 @@ set test "continue thread 1"
gdb_test_multiple "continue&" $test {
-re "event type: continue\r\nthread num: 3\r\n$gdb_prompt " {
# This expect string must not expect the end-of-buffer '$'.
- pass $test
+ pass $test
}
}
set test "thread 3 was signaled"
gdb_test_multiple "" $test {
-re "event type: stop\r\nstop reason: signal\r\nstop signal: SIGUSR1\r\nthread num: 3\r\nevent type: stop\r\n" {
- pass $test
+ pass $test
}
}
diff --git a/gdb/testsuite/gdb.python/py-exec-file.exp b/gdb/testsuite/gdb.python/py-exec-file.exp
index b3418a5..139ce83 100644
--- a/gdb/testsuite/gdb.python/py-exec-file.exp
+++ b/gdb/testsuite/gdb.python/py-exec-file.exp
@@ -19,8 +19,10 @@ load_lib gdb-python.exp
standard_testfile
-set binfile1 ${binfile}-a
-set binfile2 ${binfile}-b
+set testfile1 $testfile-a
+set binfile1 [standard_output_file $testfile1]
+set testfile2 $testfile-b
+set binfile2 [standard_output_file $testfile2]
if {[build_executable "failed to prepare first executable" \
$binfile1 $srcfile]} {
@@ -176,7 +178,7 @@ with_test_prefix "using 'symbol-file' command" {
# Check the executable_changed event when the executable changes on disk.
with_test_prefix "exec changes on disk" {
- clean_restart $binfile1
+ clean_restart $::testfile1
setup_exec_change_handler
diff --git a/gdb/testsuite/gdb.python/py-explore-cc.exp b/gdb/testsuite/gdb.python/py-explore-cc.exp
index 0be7019..c3b1309 100644
--- a/gdb/testsuite/gdb.python/py-explore-cc.exp
+++ b/gdb/testsuite/gdb.python/py-explore-cc.exp
@@ -36,7 +36,7 @@ A = <Enter 0 to explore this base class of type 'A'>.*\
i = <Enter 1 to explore this field of type 'int'>.*\
c = <Enter 2 to explore this field of type 'char'>.*"
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
@@ -49,93 +49,93 @@ gdb_test "explore int_ref" "'int_ref' is a scalar value of type 'int'.*int_ref =
gdb_test_multiple "explore int_ptr_ref" "" {
-re "$int_ptr_ref_desc.*Continue exploring it as a pointer to a single value \\\[y/n\\\]:.*" {
- pass "explore int_ptr_ref"
- gdb_test_multiple "y" "explore_int_ptr_ref_as_single_value_pointer" {
- -re "'\[*\]int_ptr_ref' is a scalar value of type 'int'.*\[*\]int_ptr_ref = 10.*$gdb_prompt" {
- pass "explore_int_ptr_ref_as_single_value_pointer"
- }
- }
+ pass "explore int_ptr_ref"
+ gdb_test_multiple "y" "explore_int_ptr_ref_as_single_value_pointer" {
+ -re "'\[*\]int_ptr_ref' is a scalar value of type 'int'.*\[*\]int_ptr_ref = 10.*$gdb_prompt" {
+ pass "explore_int_ptr_ref_as_single_value_pointer"
+ }
+ }
}
}
gdb_test_multiple "explore b" "" {
-re "$b_desc.*Enter the field number of choice:.*" {
- pass "explore b"
- gdb_test_multiple "0" "explore_base_class_A" {
- -re "The value of 'b\.A' is a struct/class of type 'A' with no fields\." {
- pass "explore_base_class_A, exploring b"
- gdb_test_multiple "\0" "return_to_b_from_A" {
- -re ".*$b_desc.*Enter the field number of choice:.*" {
- pass "return_to_b_from_A"
- gdb_test_multiple "1" "explore_field_i_of_b" {
- -re "'b\.i' is a scalar value of type 'int'.*b\.i = 10.*" {
- pass "explore_field_i_of_b"
- gdb_test_multiple "\0" "return_to_b_from_i" {
- -re "$b_desc.*Enter the field number of choice:.*" {
- pass "return_to_b_from_i"
- }
- }
- }
- }
- gdb_test_multiple "2" "explore_field_c_of_b" {
- -re "'b\.c' is a scalar value of type 'char'.*b\.c = .*'a'.*" {
- pass "explore_field_c_of_b"
- gdb_test_multiple "\0" "return_to_b_from_c" {
- -re "$b_desc.*Enter the field number of choice:.*" {
- pass "return_to_b_from_c"
- }
- }
- }
- }
- gdb_test_multiple "\0" "return_to_gdb_prompt" {
- -re "$gdb_prompt" {
- pass "return_to_gdb_prompt_from_b"
- }
- }
- }
- }
- }
- }
+ pass "explore b"
+ gdb_test_multiple "0" "explore_base_class_A" {
+ -re "The value of 'b\.A' is a struct/class of type 'A' with no fields\." {
+ pass "explore_base_class_A, exploring b"
+ gdb_test_multiple "\0" "return_to_b_from_A" {
+ -re ".*$b_desc.*Enter the field number of choice:.*" {
+ pass "return_to_b_from_A"
+ gdb_test_multiple "1" "explore_field_i_of_b" {
+ -re "'b\.i' is a scalar value of type 'int'.*b\.i = 10.*" {
+ pass "explore_field_i_of_b"
+ gdb_test_multiple "\0" "return_to_b_from_i" {
+ -re "$b_desc.*Enter the field number of choice:.*" {
+ pass "return_to_b_from_i"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "2" "explore_field_c_of_b" {
+ -re "'b\.c' is a scalar value of type 'char'.*b\.c = .*'a'.*" {
+ pass "explore_field_c_of_b"
+ gdb_test_multiple "\0" "return_to_b_from_c" {
+ -re "$b_desc.*Enter the field number of choice:.*" {
+ pass "return_to_b_from_c"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "\0" "return_to_gdb_prompt" {
+ -re "$gdb_prompt" {
+ pass "return_to_gdb_prompt_from_b"
+ }
+ }
+ }
+ }
+ }
+ }
}
}
gdb_test_multiple "explore B" "" {
-re "$B_desc.*Enter the field number of choice:.*" {
- pass "explore B"
- gdb_test_multiple "0" "explore_base_class_A" {
- -re "base class 'A' of 'B' is a struct/class of type 'A' with no fields\." {
- pass "explore_base_class_A, exploring B"
- gdb_test_multiple "\0" "return_to_B" {
- -re "$B_desc.*Enter the field number of choice:.*" {
- pass "return_to_B"
- gdb_test_multiple "1" "explore_field_i_of_B" {
- -re "field 'i' of 'B' is of a scalar type 'int'.*" {
- pass "explore_field_i_of_B"
- gdb_test_multiple "\0" "return_to_B_from_i" {
- -re "$B_desc.*Enter the field number of choice:.*" {
- pass "return_to_B_from_i, exploring B"
- }
- }
- }
- }
- gdb_test_multiple "2" "explore_field_c_of_B" {
- -re "field 'c' of 'B' is of a scalar type 'char'.*" {
- pass "explore_field_c_of_B"
- gdb_test_multiple "\0" "return_to_B_from_c" {
- -re "$B_desc.*Enter the field number of choice:.*" {
- pass "return_to_B_from_c"
- }
- }
- }
- }
- gdb_test_multiple "\0" "return_to_gdb_prompt" {
- -re "$gdb_prompt" {
- pass "return_to_gdb_prompt_from_B"
- }
- }
- }
- }
- }
- }
+ pass "explore B"
+ gdb_test_multiple "0" "explore_base_class_A" {
+ -re "base class 'A' of 'B' is a struct/class of type 'A' with no fields\." {
+ pass "explore_base_class_A, exploring B"
+ gdb_test_multiple "\0" "return_to_B" {
+ -re "$B_desc.*Enter the field number of choice:.*" {
+ pass "return_to_B"
+ gdb_test_multiple "1" "explore_field_i_of_B" {
+ -re "field 'i' of 'B' is of a scalar type 'int'.*" {
+ pass "explore_field_i_of_B"
+ gdb_test_multiple "\0" "return_to_B_from_i" {
+ -re "$B_desc.*Enter the field number of choice:.*" {
+ pass "return_to_B_from_i, exploring B"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "2" "explore_field_c_of_B" {
+ -re "field 'c' of 'B' is of a scalar type 'char'.*" {
+ pass "explore_field_c_of_B"
+ gdb_test_multiple "\0" "return_to_B_from_c" {
+ -re "$B_desc.*Enter the field number of choice:.*" {
+ pass "return_to_B_from_c"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "\0" "return_to_gdb_prompt" {
+ -re "$gdb_prompt" {
+ pass "return_to_gdb_prompt_from_B"
+ }
+ }
+ }
+ }
+ }
+ }
}
}
diff --git a/gdb/testsuite/gdb.python/py-explore.c b/gdb/testsuite/gdb.python/py-explore.c
index 5546eaf..cd64a57 100644
--- a/gdb/testsuite/gdb.python/py-explore.c
+++ b/gdb/testsuite/gdb.python/py-explore.c
@@ -64,7 +64,7 @@ main (void)
ss.a = 10;
ss.d = 100.01;
ss_t = ss;
-
+
su.d = 100.1;
cs.s = ss;
diff --git a/gdb/testsuite/gdb.python/py-explore.exp b/gdb/testsuite/gdb.python/py-explore.exp
index a68c110..102355e 100644
--- a/gdb/testsuite/gdb.python/py-explore.exp
+++ b/gdb/testsuite/gdb.python/py-explore.exp
@@ -47,14 +47,14 @@ proc array_description { value_name type } {
proc pointer_description { value_name type_name } {
set type_description "'$value_name' is a pointer to a value of type '$type_name'\.\[\r\n\]+"
- set prompt "Continue exploring it as a pointer to a single value \[\[\]y/n\[\]\]: "
+ set prompt "Continue exploring it as a pointer to a single value \[\[\]y/n\[\]\]: "
return "$type_description$prompt"
}
proc field_values { args } {
set result ""
foreach field $args {
- set result "$result\[ \]*$field \[\.\]\[\.\] \[\(\]Value of type .*\[\)\]\[\r\n\]+"
+ set result "$result\[ \]*$field \[\.\]\[\.\] \[\(\]Value of type .*\[\)\]\[\r\n\]+"
}
return $result
}
@@ -63,8 +63,8 @@ proc field_choices { args } {
set result ""
set field_num 0
foreach field $args {
- set result "$result$field\[ \]+=\[ \]+<Enter $field_num to explore this field of type .*"
- incr field_num
+ set result "$result$field\[ \]+=\[ \]+<Enter $field_num to explore this field of type .*"
+ incr field_num
}
return $result
}
@@ -75,7 +75,7 @@ proc scalar_value { value_name value } {
set SS_fields [field_values {a = 10} {d = 100[.].*}]
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
@@ -93,126 +93,126 @@ gdb_test "explore ss_t" "[typedef_description {ss_t} {SS} $SS].*[compound_descri
gdb_test_multiple "explore ss_ptr" "" {
-re "[pointer_description {ss_ptr} $SS].*" {
- pass "explore ss_ptr"
- gdb_test_multiple "y" "explore_as_single_value_pointer" {
- -re "$SS_fields.*$gdb_prompt" {
- pass "explore ss_ptr as single value pointer"
- }
- }
+ pass "explore ss_ptr"
+ gdb_test_multiple "y" "explore_as_single_value_pointer" {
+ -re "$SS_fields.*$gdb_prompt" {
+ pass "explore ss_ptr as single value pointer"
+ }
+ }
}
}
gdb_test_multiple "explore darray_ref" "" {
-re "[pointer_description {darray_ref} {double}].*" {
- pass "explore darray_ref"
- gdb_test_multiple "n" "no_to_explore_as_pointer" {
- -re "Continue exploring it as a pointer to an array \[\[\]y/n\[\]\]: " {
- pass "no_to_explore_as_pointer"
- gdb_test_multiple "y" "explore_as_array" {
- -re ".*Enter the index of the element you want to explore in 'darray_ref':.*" {
- pass "explore_as_array"
- gdb_test_multiple "2" "explore_as_array_index_2" {
- -re ".*'darray_ref\\\[2\\\]' is a scalar value of type 'double'\..*darray_ref\\\[2\\\] = 0.*" {
- pass "explore_as_array_index_2"
- gdb_test_multiple "\0" "end explore_as_array_index_2" {
- -re ".*Returning to parent value.*Enter the index of the element you want to explore in 'darray_ref':.*" {
- pass "end explore_as_array_index_2"
- gdb_test_multiple "\0" "end explore_as_array" {
- -re "\[\n\r\]+$gdb_prompt" {
- pass "end explore_as_array"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
+ pass "explore darray_ref"
+ gdb_test_multiple "n" "no_to_explore_as_pointer" {
+ -re "Continue exploring it as a pointer to an array \[\[\]y/n\[\]\]: " {
+ pass "no_to_explore_as_pointer"
+ gdb_test_multiple "y" "explore_as_array" {
+ -re ".*Enter the index of the element you want to explore in 'darray_ref':.*" {
+ pass "explore_as_array"
+ gdb_test_multiple "2" "explore_as_array_index_2" {
+ -re ".*'darray_ref\\\[2\\\]' is a scalar value of type 'double'\..*darray_ref\\\[2\\\] = 0.*" {
+ pass "explore_as_array_index_2"
+ gdb_test_multiple "\0" "end explore_as_array_index_2" {
+ -re ".*Returning to parent value.*Enter the index of the element you want to explore in 'darray_ref':.*" {
+ pass "end explore_as_array_index_2"
+ gdb_test_multiple "\0" "end explore_as_array" {
+ -re "\[\n\r\]+$gdb_prompt" {
+ pass "end explore_as_array"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
}
gdb_test_multiple "explore su" "" {
-re "[compound_description {su} {union} {union SimpleUnion}].*[field_choices {i} {c} {f} {d}].*$enter_field_number_prompt" {
- pass "explore su"
- gdb_test_multiple "3" "explore su.d" {
- -re "[scalar_description {su.d} {double}].*[scalar_value {su.d} {100[.].*}].*$return_to_parent_prompt" {
- pass "explore su.d"
- gdb_test_multiple " " "end su.d exploration" {
- -re ".*[compound_description {su} {union} {union SimpleUnion}].*[field_choices {i} {c} {f} {d}].*$enter_field_number_prompt" {
- pass "end su.d exploration"
- gdb_test_multiple "\0" "end su exploration" {
- -re "$gdb_prompt" {
- pass "end su exploration"
- }
- }
- }
- }
- }
- }
+ pass "explore su"
+ gdb_test_multiple "3" "explore su.d" {
+ -re "[scalar_description {su.d} {double}].*[scalar_value {su.d} {100[.].*}].*$return_to_parent_prompt" {
+ pass "explore su.d"
+ gdb_test_multiple " " "end su.d exploration" {
+ -re ".*[compound_description {su} {union} {union SimpleUnion}].*[field_choices {i} {c} {f} {d}].*$enter_field_number_prompt" {
+ pass "end su.d exploration"
+ gdb_test_multiple "\0" "end su exploration" {
+ -re "$gdb_prompt" {
+ pass "end su exploration"
+ }
+ }
+ }
+ }
+ }
+ }
}
}
gdb_test_multiple "explore cs" "" {
-re "[compound_description {cs} {struct/class} {struct ComplexStruct}].*[field_choices {s} {u} {sa}].*$enter_field_number_prompt" {
- pass "explore cs"
- gdb_test_multiple "0" "explore cs.s" {
- -re "[compound_description {cs.s} {struct/class} {struct SimpleStruct}].*[field_values {a = 10} {d = 100[.].*}].*$return_to_parent_prompt" {
- pass "explore cs.s"
- gdb_test_multiple " " "end cs.s exploration" {
- -re ".*$enter_field_number_prompt" {
- pass "end cs.s exploration"
- }
- }
- }
- }
- gdb_test_multiple "1" "explore cs.u" {
- -re "[compound_description {cs.u} {union} {union SimpleUnion}].*.*[field_choices {i} {c} {f} {d}].*$enter_field_number_prompt" {
- pass "explore cs.u"
- gdb_test_multiple " " "end cs.u exploration" {
- -re ".*$enter_field_number_prompt" {
- pass "end cs.u exploration"
- }
- }
- }
- }
- gdb_test_multiple "\0" "explore cs.u" {
- -re "$gdb_prompt" {
- pass "end cs exploration"
- }
- }
+ pass "explore cs"
+ gdb_test_multiple "0" "explore cs.s" {
+ -re "[compound_description {cs.s} {struct/class} {struct SimpleStruct}].*[field_values {a = 10} {d = 100[.].*}].*$return_to_parent_prompt" {
+ pass "explore cs.s"
+ gdb_test_multiple " " "end cs.s exploration" {
+ -re ".*$enter_field_number_prompt" {
+ pass "end cs.s exploration"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "1" "explore cs.u" {
+ -re "[compound_description {cs.u} {union} {union SimpleUnion}].*.*[field_choices {i} {c} {f} {d}].*$enter_field_number_prompt" {
+ pass "explore cs.u"
+ gdb_test_multiple " " "end cs.u exploration" {
+ -re ".*$enter_field_number_prompt" {
+ pass "end cs.u exploration"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "\0" "explore cs.u" {
+ -re "$gdb_prompt" {
+ pass "end cs exploration"
+ }
+ }
}
}
gdb_test_multiple "explore cu" "" {
-re "[compound_description {cu} {union} {union ComplexUnion}].*[field_choices {s} {sa}].*$enter_field_number_prompt" {
- pass "explore cu"
- gdb_test_multiple "1" "explore cu.sa" {
- -re ".*[array_description {cu.sa} $SS].*$array_index_prompt" {
- pass "explore cu.sa"
- gdb_test_multiple "0" "explore cu.sa\[0\]" {
- -re "[compound_description {\(cu.sa\)\[0\]} {struct/class} {struct SimpleStruct}].*[field_values {a = 0} {d = 100[.].*}].*$return_to_parent_prompt" {
- pass "explore cu.sa\[0\]"
- gdb_test_multiple "\0" "end cu.sa\[0\] exploration" {
- -re "[array_description {cu.sa} $SS]$array_index_prompt" {
- pass "end cu.sa\[0\] exploration"
- }
- }
- }
- }
- gdb_test_multiple "\0" "end cu.sa exploration" {
- -re ".*$enter_field_number_prompt" {
- pass "end cu.sa exploration"
- gdb_test_multiple "\0" "end cu exploration" {
- -re "$gdb_prompt" {
- pass "end cu exploration"
- }
- }
- }
- }
- }
- }
+ pass "explore cu"
+ gdb_test_multiple "1" "explore cu.sa" {
+ -re ".*[array_description {cu.sa} $SS].*$array_index_prompt" {
+ pass "explore cu.sa"
+ gdb_test_multiple "0" "explore cu.sa\[0\]" {
+ -re "[compound_description {\(cu.sa\)\[0\]} {struct/class} {struct SimpleStruct}].*[field_values {a = 0} {d = 100[.].*}].*$return_to_parent_prompt" {
+ pass "explore cu.sa\[0\]"
+ gdb_test_multiple "\0" "end cu.sa\[0\] exploration" {
+ -re "[array_description {cu.sa} $SS]$array_index_prompt" {
+ pass "end cu.sa\[0\] exploration"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "\0" "end cu.sa exploration" {
+ -re ".*$enter_field_number_prompt" {
+ pass "end cu.sa exploration"
+ gdb_test_multiple "\0" "end cu exploration" {
+ -re "$gdb_prompt" {
+ pass "end cu exploration"
+ }
+ }
+ }
+ }
+ }
+ }
}
}
@@ -262,186 +262,186 @@ gdb_test "explore int" ".*[scalar_type_decsription {int}].*"
gdb_test_multiple "explore struct SimpleStruct" "" {
-re ".*[compound_type_description $SS {struct/class}].*$SS_fields_types.*" {
- pass "explore struct SimpleStruct"
- gdb_test_multiple "0" "explore type struct SimpleStruct feild 0" {
- -re ".*[child_scalar_type_description {field 'a' of 'struct SimpleStruct'} {int}].*" {
- pass "explore type struct SimpleStruct feild 0"
- gdb_test_multiple "\0" "return to struct SimpleStruct from field 0" {
- -re ".*[compound_type_description $SS {struct/class}].*$SS_fields_types.*" {
- pass "return to struct SimpleStruct from field 0"
- }
- }
- }
- }
- gdb_test_multiple "1" "explore type struct SimpleStruct feild 1" {
- -re ".*[child_scalar_type_description {field 'd' of 'struct SimpleStruct'} {double}].*" {
- pass "explore type struct SimpleStruct feild 1"
- gdb_test_multiple "\0" "return to struct SimpleStruct from field 1" {
- -re ".*[compound_type_description $SS {struct/class}].*$SS_fields_types.*" {
- pass "return to struct SimpleStruct from field 1"
- }
- }
- }
- }
- gdb_test_multiple "\0" "return to GDB prompt from struct SimpleStruct" {
- -re "$gdb_prompt" {
- pass "return to GDB prompt from struct SimpleStruct"
- }
- }
+ pass "explore struct SimpleStruct"
+ gdb_test_multiple "0" "explore type struct SimpleStruct field 0" {
+ -re ".*[child_scalar_type_description {field 'a' of 'struct SimpleStruct'} {int}].*" {
+ pass "explore type struct SimpleStruct field 0"
+ gdb_test_multiple "\0" "return to struct SimpleStruct from field 0" {
+ -re ".*[compound_type_description $SS {struct/class}].*$SS_fields_types.*" {
+ pass "return to struct SimpleStruct from field 0"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "1" "explore type struct SimpleStruct field 1" {
+ -re ".*[child_scalar_type_description {field 'd' of 'struct SimpleStruct'} {double}].*" {
+ pass "explore type struct SimpleStruct field 1"
+ gdb_test_multiple "\0" "return to struct SimpleStruct from field 1" {
+ -re ".*[compound_type_description $SS {struct/class}].*$SS_fields_types.*" {
+ pass "return to struct SimpleStruct from field 1"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "\0" "return to GDB prompt from struct SimpleStruct" {
+ -re "$gdb_prompt" {
+ pass "return to GDB prompt from struct SimpleStruct"
+ }
+ }
}
}
gdb_test_multiple "explore union SimpleUnion" "" {
-re ".*[compound_type_description $SU {union}].*$SU_fields_types.*" {
pass "explore union SimpleUnion"
- gdb_test_multiple "0" "explore type union SimpleUnion feild 0" {
- -re ".*[child_scalar_type_description {field 'i' of 'union SimpleUnion'} {int}].*" {
- pass "explore type union SimpleUnion feild 0"
- gdb_test_multiple "\0" "return to union SimpleUnion from field 0" {
- -re ".*[compound_type_description $SU {union}].*$SU_fields_types.*" {
- pass "return to union SimpleUnion from field 0"
- }
- }
- }
- }
- gdb_test_multiple "1" "explore type union SimpleUnion feild 1" {
- -re ".*[child_scalar_type_description {field 'c' of 'union SimpleUnion'} {char}].*" {
- pass "explore type union SimpleUnion feild 1"
- gdb_test_multiple "\0" "return to union SimpleUnion from field 1" {
- -re ".*[compound_type_description $SU {union}].*$SU_fields_types.*" {
- pass "return to union SimpleUnion from field 1"
- }
- }
- }
- }
- gdb_test_multiple "2" "explore type union SimpleUnion feild 2" {
- -re ".*[child_scalar_type_description {field 'f' of 'union SimpleUnion'} {float}].*" {
- pass "explore type union SimpleUnion feild 2"
- gdb_test_multiple "\0" "return to union SimpleUnion from field 2" {
- -re ".*[compound_type_description $SU {union}].*$SU_fields_types.*" {
- pass "return to union SimpleUnion from field 2"
- }
- }
- }
- }
- gdb_test_multiple "3" "explore type union SimpleUnion feild 3" {
- -re ".*[child_scalar_type_description {field 'd' of 'union SimpleUnion'} {double}].*" {
- pass "explore type union SimpleUnion feild 3"
- gdb_test_multiple "\0" "return to union SimpleUnion from field 3" {
- -re ".*[compound_type_description $SU {union}].*$SU_fields_types.*" {
- pass "return to union SimpleUnion from field 3"
- }
- }
- }
- }
- gdb_test_multiple "\0" "return to GDB prompt from union SimpleUnion" {
- -re "$gdb_prompt" {
- pass "return to GDB prompt from union SimpleUnion"
- }
- }
+ gdb_test_multiple "0" "explore type union SimpleUnion field 0" {
+ -re ".*[child_scalar_type_description {field 'i' of 'union SimpleUnion'} {int}].*" {
+ pass "explore type union SimpleUnion field 0"
+ gdb_test_multiple "\0" "return to union SimpleUnion from field 0" {
+ -re ".*[compound_type_description $SU {union}].*$SU_fields_types.*" {
+ pass "return to union SimpleUnion from field 0"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "1" "explore type union SimpleUnion field 1" {
+ -re ".*[child_scalar_type_description {field 'c' of 'union SimpleUnion'} {char}].*" {
+ pass "explore type union SimpleUnion field 1"
+ gdb_test_multiple "\0" "return to union SimpleUnion from field 1" {
+ -re ".*[compound_type_description $SU {union}].*$SU_fields_types.*" {
+ pass "return to union SimpleUnion from field 1"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "2" "explore type union SimpleUnion field 2" {
+ -re ".*[child_scalar_type_description {field 'f' of 'union SimpleUnion'} {float}].*" {
+ pass "explore type union SimpleUnion field 2"
+ gdb_test_multiple "\0" "return to union SimpleUnion from field 2" {
+ -re ".*[compound_type_description $SU {union}].*$SU_fields_types.*" {
+ pass "return to union SimpleUnion from field 2"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "3" "explore type union SimpleUnion field 3" {
+ -re ".*[child_scalar_type_description {field 'd' of 'union SimpleUnion'} {double}].*" {
+ pass "explore type union SimpleUnion field 3"
+ gdb_test_multiple "\0" "return to union SimpleUnion from field 3" {
+ -re ".*[compound_type_description $SU {union}].*$SU_fields_types.*" {
+ pass "return to union SimpleUnion from field 3"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "\0" "return to GDB prompt from union SimpleUnion" {
+ -re "$gdb_prompt" {
+ pass "return to GDB prompt from union SimpleUnion"
+ }
+ }
}
}
gdb_test_multiple "explore SS" "" {
-re ".*[typedef_type_description {SS} $SS].*[compound_type_description {SS} {struct/class}].*$SS_fields_types.*" {
- pass "explore SS"
- gdb_test_multiple "0" "explore type SS feild 0" {
- -re ".*[child_scalar_type_description {field 'a' of 'SS'} {int}].*" {
- pass "explore type SS feild 0"
- gdb_test_multiple "\0" "return to SS from field 0" {
- -re ".*[compound_type_description {SS} {struct/class}].*$SS_fields_types.*" {
- pass "return to SS from field 0"
- }
- }
- }
- }
- gdb_test_multiple "1" "explore type SS feild 1" {
- -re ".*[child_scalar_type_description {field 'd' of 'SS'} {double}].*" {
- pass "explore type SS feild 1"
- gdb_test_multiple "\0" "return to struct SimpleStruct from field 1" {
- -re ".*[compound_type_description {SS} {struct/class}].*$SS_fields_types.*" {
- pass "return to SS field 1"
- }
- }
- }
- }
- gdb_test_multiple "\0" "return to GDB prompt from SS" {
- -re "$gdb_prompt" {
- pass "return to GDB prompt from SS"
- }
- }
+ pass "explore SS"
+ gdb_test_multiple "0" "explore type SS field 0" {
+ -re ".*[child_scalar_type_description {field 'a' of 'SS'} {int}].*" {
+ pass "explore type SS field 0"
+ gdb_test_multiple "\0" "return to SS from field 0" {
+ -re ".*[compound_type_description {SS} {struct/class}].*$SS_fields_types.*" {
+ pass "return to SS from field 0"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "1" "explore type SS field 1" {
+ -re ".*[child_scalar_type_description {field 'd' of 'SS'} {double}].*" {
+ pass "explore type SS field 1"
+ gdb_test_multiple "\0" "return to struct SimpleStruct from field 1" {
+ -re ".*[compound_type_description {SS} {struct/class}].*$SS_fields_types.*" {
+ pass "return to SS field 1"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "\0" "return to GDB prompt from SS" {
+ -re "$gdb_prompt" {
+ pass "return to GDB prompt from SS"
+ }
+ }
}
}
gdb_test_multiple "explore type struct ComplexStruct" "" {
-re ".*[compound_type_description $CS {struct/class}].*$CS_fields_types.*" {
- pass "explore type struct ComplexStruct"
- gdb_test_multiple "0" "explore type struct ComplexStruct field 0" {
- -re ".*[child_compound_type_description $CS_field_0 $SS {struct/class}].*$SS_fields_types.*" {
- pass "explore type struct ComplexStruct field 0"
- gdb_test_multiple "\0" "return to ComplexStruct from field 0" {
- -re ".*[compound_type_description $CS {struct/class}].*$CS_fields_types.*" {
- pass "return to ComplexStruct from field 0"
- }
- }
- }
- }
- gdb_test_multiple "1" "explore type struct ComplexStruct field 1" {
- -re ".*[child_compound_type_description $CS_field_1 $SU {union}].*$SU_fields_types.*" {
- pass "explore type struct ComplexStruct field 1"
- gdb_test_multiple "\0" "return to ComplexStruct from field 1" {
- -re ".*[compound_type_description $CS {struct/class}].*$CS_fields_types.*" {
- pass "return to ComplexStruct from field 1"
- }
- }
- }
- }
- gdb_test_multiple "2" "explore type struct ComplexStruct field 2" {
- -re ".*[child_array_type_description $CS_field_2 {SS}].*" {
- pass "explore type struct ComplexStruct field 2"
- gdb_test_multiple "\0" "return to ComplexStruct from field 2" {
- -re ".*[compound_type_description $CS {struct/class}].*$CS_fields_types.*" {
- pass "return to ComplexStruct from field 2"
- }
- }
- }
- }
- gdb_test_multiple "\0" "return to GDB prompt from ComplexStruct type exploration" {
- -re "$gdb_prompt" {
- pass "return to GDB prompt from ComplexStruct type exploration"
- }
- }
+ pass "explore type struct ComplexStruct"
+ gdb_test_multiple "0" "explore type struct ComplexStruct field 0" {
+ -re ".*[child_compound_type_description $CS_field_0 $SS {struct/class}].*$SS_fields_types.*" {
+ pass "explore type struct ComplexStruct field 0"
+ gdb_test_multiple "\0" "return to ComplexStruct from field 0" {
+ -re ".*[compound_type_description $CS {struct/class}].*$CS_fields_types.*" {
+ pass "return to ComplexStruct from field 0"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "1" "explore type struct ComplexStruct field 1" {
+ -re ".*[child_compound_type_description $CS_field_1 $SU {union}].*$SU_fields_types.*" {
+ pass "explore type struct ComplexStruct field 1"
+ gdb_test_multiple "\0" "return to ComplexStruct from field 1" {
+ -re ".*[compound_type_description $CS {struct/class}].*$CS_fields_types.*" {
+ pass "return to ComplexStruct from field 1"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "2" "explore type struct ComplexStruct field 2" {
+ -re ".*[child_array_type_description $CS_field_2 {SS}].*" {
+ pass "explore type struct ComplexStruct field 2"
+ gdb_test_multiple "\0" "return to ComplexStruct from field 2" {
+ -re ".*[compound_type_description $CS {struct/class}].*$CS_fields_types.*" {
+ pass "return to ComplexStruct from field 2"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "\0" "return to GDB prompt from ComplexStruct type exploration" {
+ -re "$gdb_prompt" {
+ pass "return to GDB prompt from ComplexStruct type exploration"
+ }
+ }
}
}
gdb_test_multiple "explore type union ComplexUnion" "" {
-re ".*[compound_type_description $CU {union}].*$CU_fields_types.*" {
- pass "explore type union ComplexUnion"
- gdb_test_multiple "0" "explore type union ComplexStruct field 0" {
- -re ".*[child_compound_type_description $CU_field_0 $SS {struct/class}].*$SS_fields_types.*" {
- pass "explore type union ComplexUnion field 0"
- gdb_test_multiple "\0" "return to ComplexUnion from field 0" {
- -re ".*[compound_type_description $CU {union}].*$CU_fields_types.*" {
- pass "return to ComplexUnion from field 0"
- }
- }
- }
- }
- gdb_test_multiple "1" "explore type union ComplexUnion field 1" {
- -re ".*[child_array_type_description $CU_field_1 $SS].*" {
- pass "explore type union ComplexUnion field 1"
- gdb_test_multiple "\0" "return to ComplexUnion array" {
- -re ".*[compound_type_description $CU {union}].*$CU_fields_types.*" {
- pass "return to ComplexUnion from field 1"
- }
- }
- }
- }
- gdb_test_multiple "\0" "return to GDB prompt from ComplexUnion type exploration" {
- -re "$gdb_prompt" {
- pass "return to GDB prompt from ComplexUnion type exploration"
- }
- }
+ pass "explore type union ComplexUnion"
+ gdb_test_multiple "0" "explore type union ComplexStruct field 0" {
+ -re ".*[child_compound_type_description $CU_field_0 $SS {struct/class}].*$SS_fields_types.*" {
+ pass "explore type union ComplexUnion field 0"
+ gdb_test_multiple "\0" "return to ComplexUnion from field 0" {
+ -re ".*[compound_type_description $CU {union}].*$CU_fields_types.*" {
+ pass "return to ComplexUnion from field 0"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "1" "explore type union ComplexUnion field 1" {
+ -re ".*[child_array_type_description $CU_field_1 $SS].*" {
+ pass "explore type union ComplexUnion field 1"
+ gdb_test_multiple "\0" "return to ComplexUnion array" {
+ -re ".*[compound_type_description $CU {union}].*$CU_fields_types.*" {
+ pass "return to ComplexUnion from field 1"
+ }
+ }
+ }
+ }
+ gdb_test_multiple "\0" "return to GDB prompt from ComplexUnion type exploration" {
+ -re "$gdb_prompt" {
+ pass "return to GDB prompt from ComplexUnion type exploration"
+ }
+ }
}
}
diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint-deletion.py b/gdb/testsuite/gdb.python/py-finish-breakpoint-deletion.py
index 8d8ca53..d8235e3 100644
--- a/gdb/testsuite/gdb.python/py-finish-breakpoint-deletion.py
+++ b/gdb/testsuite/gdb.python/py-finish-breakpoint-deletion.py
@@ -14,6 +14,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import gdb
+
+
class MyFinishBreakpoint(gdb.FinishBreakpoint):
def stop(self):
print("stopped at MyFinishBreakpoint")
diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint.exp b/gdb/testsuite/gdb.python/py-finish-breakpoint.exp
index c7d31f0..bec22ee 100644
--- a/gdb/testsuite/gdb.python/py-finish-breakpoint.exp
+++ b/gdb/testsuite/gdb.python/py-finish-breakpoint.exp
@@ -112,7 +112,7 @@ with_test_prefix "return to inlined function" {
}
#
-# Test FinishBreakpoint with no debug symbol
+# Test FinishBreakpoint with no debug symbol
#
with_test_prefix "no debug symbol" {
@@ -140,7 +140,7 @@ with_test_prefix "no debug symbol" {
}
#
-# Test FinishBreakpoint in function returned by longjmp
+# Test FinishBreakpoint in function returned by longjmp
#
with_test_prefix "function returned by longjump" {
@@ -166,7 +166,7 @@ with_test_prefix "function returned by longjump" {
}
#
-# Test FinishBreakpoint in BP condition evaluation
+# Test FinishBreakpoint in BP condition evaluation
# (finish in dummy frame)
#
@@ -194,7 +194,7 @@ with_test_prefix "finish in dummy frame" {
}
#
-# Test FinishBreakpoint in BP condition evaluation
+# Test FinishBreakpoint in BP condition evaluation
# (finish in normal frame)
#
diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint.py b/gdb/testsuite/gdb.python/py-finish-breakpoint.py
index 413489f..dd2e158 100644
--- a/gdb/testsuite/gdb.python/py-finish-breakpoint.py
+++ b/gdb/testsuite/gdb.python/py-finish-breakpoint.py
@@ -17,6 +17,9 @@
# Breakpoints.
+import gdb
+
+
class MyFinishBreakpoint(gdb.FinishBreakpoint):
def __init__(self, val, frame):
gdb.FinishBreakpoint.__init__(self, frame)
diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint2.cc b/gdb/testsuite/gdb.python/py-finish-breakpoint2.cc
index af8801f..d190143 100644
--- a/gdb/testsuite/gdb.python/py-finish-breakpoint2.cc
+++ b/gdb/testsuite/gdb.python/py-finish-breakpoint2.cc
@@ -42,7 +42,7 @@ main (void)
}
catch (const int *e)
{
- std::cerr << "Exception #" << *e << std::endl;
+ std::cerr << "Exception #" << *e << std::endl;
}
i += 1; /* Break after exception 1. */
@@ -52,7 +52,7 @@ main (void)
}
catch (const int *e)
{
- std::cerr << "Exception #" << *e << std::endl;
+ std::cerr << "Exception #" << *e << std::endl;
}
i += 1; /* Break after exception 2. */
diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp b/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp
index 922426f..fe3ef4e 100644
--- a/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp
+++ b/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp
@@ -41,8 +41,8 @@ gdb_breakpoint [gdb_get_line_number "Break before exception"]
gdb_breakpoint [gdb_get_line_number "Break after exception 2"]
gdb_test "source $pyfile" ".*Python script imported.*" \
- "import python scripts"
-
+ "import python scripts"
+
gdb_breakpoint "throw_exception_1"
#
diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint2.py b/gdb/testsuite/gdb.python/py-finish-breakpoint2.py
index ae75e51..01d220c 100644
--- a/gdb/testsuite/gdb.python/py-finish-breakpoint2.py
+++ b/gdb/testsuite/gdb.python/py-finish-breakpoint2.py
@@ -16,6 +16,8 @@
# This file is part of the GDB testsuite. It tests python Finish
# Breakpoints.
+import gdb
+
class ExceptionFinishBreakpoint(gdb.FinishBreakpoint):
def __init__(self, frame):
diff --git a/gdb/testsuite/gdb.python/py-format-address.exp b/gdb/testsuite/gdb.python/py-format-address.exp
index 173297c..2946314 100644
--- a/gdb/testsuite/gdb.python/py-format-address.exp
+++ b/gdb/testsuite/gdb.python/py-format-address.exp
@@ -27,12 +27,14 @@ foreach func_name { foo bar } {
}
}
-set binary_foo [standard_output_file "${testfile}-foo"]
-set binary_bar [standard_output_file "${testfile}-bar"]
+set testfile_foo $testfile-foo
+set testfile_bar $testfile-bar
+set binary_foo [standard_output_file $testfile_foo]
+set binary_bar [standard_output_file $testfile_bar]
-clean_restart $binary_foo
+clean_restart $testfile_foo
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
@@ -51,7 +53,7 @@ gdb_test_multiple "info break 1" "" {
}
}
if { $next_addr == "UNKNOWN" || $next_addr == $main_addr } {
- set next_addr [format 0x%x [expr $main_addr + 1]]
+ set next_addr [format 0x%x [expr {$main_addr + 1}]]
}
verbose -log "main_addr: $main_addr"
diff --git a/gdb/testsuite/gdb.python/py-format-string.exp b/gdb/testsuite/gdb.python/py-format-string.exp
index 114a606..53fa553 100644
--- a/gdb/testsuite/gdb.python/py-format-string.exp
+++ b/gdb/testsuite/gdb.python/py-format-string.exp
@@ -47,7 +47,8 @@ proc build_inferior {exefile lang} {
proc prepare_gdb {exefile} {
global srcdir subdir srcfile testfile hex
- clean_restart $exefile
+ clean_restart
+ gdb_load $exefile
if {![runto_main]} {
return
@@ -109,7 +110,7 @@ proc get_cut_big_string { max } {
return "\"${whole_big_string}\""
}
- set cut_string [string range $whole_big_string 0 [expr $max - 1]]
+ set cut_string [string range $whole_big_string 0 [expr {$max - 1}]]
return "\"${cut_string}\"..."
}
@@ -775,7 +776,7 @@ proc test_max_string_one { setting unlimited } {
check_format_string "a_binary_string" $opts
check_format_string "a_binary_string_array" $opts
check_format_string "a_big_string" $opts \
- [get_cut_big_string 1000]
+ [get_cut_big_string 1000]
if { $setting == "elements"} {
check_format_string "an_array" $opts
check_format_string "an_array_with_repetition" $opts
@@ -783,8 +784,8 @@ proc test_max_string_one { setting unlimited } {
check_format_string "a_symbol_pointer" $opts
if { $current_lang == "c++" } {
- check_format_string "a_point_t_ref" $opts
- check_format_string "a_base_ref" $opts
+ check_format_string "a_point_t_ref" $opts
+ check_format_string "a_base_ref" $opts
}
}
}
@@ -928,12 +929,12 @@ proc_with_prefix test_repeat_threshold {} {
check_format_string "a_big_string" $opts
check_format_string "an_array" $opts
check_format_string "an_array_with_repetition" $opts \
- "\\{1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5\\}"
+ "\\{1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5\\}"
check_format_string "a_symbol_pointer" $opts
if { $current_lang == "c++" } {
- check_format_string "a_point_t_ref" $opts
- check_format_string "a_base_ref" $opts
+ check_format_string "a_point_t_ref" $opts
+ check_format_string "a_base_ref" $opts
}
}
}
@@ -1202,7 +1203,9 @@ with_test_prefix "format_string" {
set current_lang "c"
prepare_gdb "${binfile}"
test_all_common
- test_styling
+ if { ![is_remote host] } {
+ test_styling
+ }
}
}
}
diff --git a/gdb/testsuite/gdb.python/py-frame-args.exp b/gdb/testsuite/gdb.python/py-frame-args.exp
index 1dbd30e..12f1651 100644
--- a/gdb/testsuite/gdb.python/py-frame-args.exp
+++ b/gdb/testsuite/gdb.python/py-frame-args.exp
@@ -21,7 +21,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-frame-args.py b/gdb/testsuite/gdb.python/py-frame-args.py
index 45476b1..b72b453 100644
--- a/gdb/testsuite/gdb.python/py-frame-args.py
+++ b/gdb/testsuite/gdb.python/py-frame-args.py
@@ -23,7 +23,6 @@ class pp_s(object):
self.val = val
def to_string(self):
- m = self.val["m"]
return "m=<" + str(self.val["m"]) + ">"
diff --git a/gdb/testsuite/gdb.python/py-frame.exp b/gdb/testsuite/gdb.python/py-frame.exp
index 5668807..c1e3e33 100644
--- a/gdb/testsuite/gdb.python/py-frame.exp
+++ b/gdb/testsuite/gdb.python/py-frame.exp
@@ -188,6 +188,21 @@ gdb_test "python print(gdb.selected_frame().read_register(list()))" \
".*Invalid type for register.*" \
"test Frame.read_register with list"
+gdb_test_multiline "setup a bad object" \
+ "python" "" \
+ "class bad_type:" "" \
+ " def __init__ (self):" "" \
+ " pass" "" \
+ " @property" "" \
+ " def __class__(self):" "" \
+ " raise RuntimeError('error from __class in bad_type')" "" \
+ "bad_object = bad_type()" "" \
+ "end" ""
+
+gdb_test "python print(gdb.selected_frame().read_register(bad_object))" \
+ ".*Invalid type for register.*" \
+ "test Frame.read_register with bad_type object"
+
# Compile again without debug info.
gdb_exit
if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} {}] } {
diff --git a/gdb/testsuite/gdb.python/py-framefilter-addr.exp b/gdb/testsuite/gdb.python/py-framefilter-addr.exp
index 14eebc2..27c1de3 100644
--- a/gdb/testsuite/gdb.python/py-framefilter-addr.exp
+++ b/gdb/testsuite/gdb.python/py-framefilter-addr.exp
@@ -27,7 +27,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-framefilter-addr.py b/gdb/testsuite/gdb.python/py-framefilter-addr.py
index 513bf6f..336571a 100644
--- a/gdb/testsuite/gdb.python/py-framefilter-addr.py
+++ b/gdb/testsuite/gdb.python/py-framefilter-addr.py
@@ -13,7 +13,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import copy
import itertools
import gdb
diff --git a/gdb/testsuite/gdb.python/py-framefilter-gdb.py b/gdb/testsuite/gdb.python/py-framefilter-gdb.py
index a725dce..969371c 100644
--- a/gdb/testsuite/gdb.python/py-framefilter-gdb.py
+++ b/gdb/testsuite/gdb.python/py-framefilter-gdb.py
@@ -13,12 +13,9 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import itertools
-
# This file is part of the GDB testsuite. It tests Python-based
# frame-filters.
import gdb
-from gdb.FrameDecorator import FrameDecorator
class FrameObjFile:
diff --git a/gdb/testsuite/gdb.python/py-framefilter-invalidarg-gdb.py b/gdb/testsuite/gdb.python/py-framefilter-invalidarg-gdb.py
index 51922fc..96c97aa 100644
--- a/gdb/testsuite/gdb.python/py-framefilter-invalidarg-gdb.py
+++ b/gdb/testsuite/gdb.python/py-framefilter-invalidarg-gdb.py
@@ -13,12 +13,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import itertools
# This file is part of the GDB testsuite. It tests Python-based
# frame-filters.
import gdb
-from gdb.FrameDecorator import FrameDecorator
class FrameObjFile:
diff --git a/gdb/testsuite/gdb.python/py-framefilter-invalidarg.py b/gdb/testsuite/gdb.python/py-framefilter-invalidarg.py
index b262968..a8e52e0 100644
--- a/gdb/testsuite/gdb.python/py-framefilter-invalidarg.py
+++ b/gdb/testsuite/gdb.python/py-framefilter-invalidarg.py
@@ -13,7 +13,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import copy
import itertools
# This file is part of the GDB testsuite. It tests Python-based
diff --git a/gdb/testsuite/gdb.python/py-framefilter-mi.exp b/gdb/testsuite/gdb.python/py-framefilter-mi.exp
index de04236..03e5f90 100644
--- a/gdb/testsuite/gdb.python/py-framefilter-mi.exp
+++ b/gdb/testsuite/gdb.python/py-framefilter-mi.exp
@@ -28,7 +28,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.python/py-framefilter.exp b/gdb/testsuite/gdb.python/py-framefilter.exp
index 7cc8b01..5a7a72b 100644
--- a/gdb/testsuite/gdb.python/py-framefilter.exp
+++ b/gdb/testsuite/gdb.python/py-framefilter.exp
@@ -112,8 +112,8 @@ gdb_test "show frame-filter priority global Elider" \
gdb_test_no_output "set frame-filter priority global Elider 1000" \
"set frame-filter priotiy global Elider 1000"
gdb_test "show frame-filter priority global Elider" \
- "Priority of filter 'Elider' in list 'global' is: 1000" \
- "show frame-filter priority global Elider after setting"
+ "Priority of filter 'Elider' in list 'global' is: 1000" \
+ "show frame-filter priority global Elider after setting"
gdb_test "info frame-filter" \
".*1000.*Yes.*Elider.*100.*Yes.*Reverse.*10.*.*No.*Object.*1.*" \
"info frame filter after setting priority"
diff --git a/gdb/testsuite/gdb.python/py-framefilter.py b/gdb/testsuite/gdb.python/py-framefilter.py
index 5c3790d..1fc8025 100644
--- a/gdb/testsuite/gdb.python/py-framefilter.py
+++ b/gdb/testsuite/gdb.python/py-framefilter.py
@@ -13,7 +13,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import copy
import itertools
# This file is part of the GDB testsuite. It tests Python-based
diff --git a/gdb/testsuite/gdb.python/py-inferior-leak.exp b/gdb/testsuite/gdb.python/py-inferior-leak.exp
index 6710f59..15216ee 100644
--- a/gdb/testsuite/gdb.python/py-inferior-leak.exp
+++ b/gdb/testsuite/gdb.python/py-inferior-leak.exp
@@ -24,15 +24,5 @@ standard_testfile
clean_restart
-# Skip this test if the tracemalloc module is not available.
-if { ![gdb_py_module_available "tracemalloc"] } {
- unsupported "tracemalloc module not available"
- return
-}
-
-set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
-
-# Source the Python script, this runs the test (which is written
-# completely in Python), and either prints PASS, or throws an
-# exception.
-gdb_test "source ${pyfile}" "PASS" "source python script"
+gdb_py_run_memory_leak_test ${srcdir}/${subdir}/${testfile}.py \
+ "gdb.Inferior object deallocates correctly"
diff --git a/gdb/testsuite/gdb.python/py-inferior-leak.py b/gdb/testsuite/gdb.python/py-inferior-leak.py
index 97837dc..375e909e 100644
--- a/gdb/testsuite/gdb.python/py-inferior-leak.py
+++ b/gdb/testsuite/gdb.python/py-inferior-leak.py
@@ -14,99 +14,40 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
-import tracemalloc
+import sys
import gdb
-# A global variable in which we store a reference to the gdb.Inferior
-# object sent to us in the new_inferior event.
-inf = None
+# Avoid generating
+# src/gdb/testsuite/gdb.python/__pycache__/gdb_leak_detector.cpython-<n>.pyc.
+sys.dont_write_bytecode = True
-# Register the new_inferior event handler.
-def new_inferior_handler(event):
- global inf
- inf = event.inferior
+import gdb_leak_detector # noqa: E402
-gdb.events.new_inferior.connect(new_inferior_handler)
+class inferior_leak_detector(gdb_leak_detector.gdb_leak_detector):
+ def __init__(self):
+ super().__init__(__file__)
+ self.inferior = None
+ self.__handler = lambda event: setattr(self, "inferior", event.inferior)
+ gdb.events.new_inferior.connect(self.__handler)
-# A global filters list, we only care about memory allocations
-# originating from this script.
-filters = [tracemalloc.Filter(True, "*py-inferior-leak.py")]
+ def __del__(self):
+ gdb.events.new_inferior.disconnect(self.__handler)
+ def allocate(self):
+ output = gdb.execute("add-inferior", False, True)
+ m = re.search(r"Added inferior (\d+)", output)
+ if m:
+ num = int(m.group(1))
+ else:
+ raise RuntimeError("no match")
-# Add a new inferior, and return the number of the new inferior.
-def add_inferior():
- output = gdb.execute("add-inferior", False, True)
- m = re.search(r"Added inferior (\d+)", output)
- if m:
- num = int(m.group(1))
- else:
- raise RuntimeError("no match")
- return num
+ gdb.execute("remove-inferiors %s" % num)
+ def deallocate(self):
+ self.inferior = None
-# Run the test. When CLEAR is True we clear the global INF variable
-# before comparing the before and after memory allocation traces.
-# When CLEAR is False we leave INF set to reference the gdb.Inferior
-# object, thus preventing the gdb.Inferior from being deallocated.
-def test(clear):
- global filters, inf
- # Start tracing, and take a snapshot of the current allocations.
- tracemalloc.start()
- snapshot1 = tracemalloc.take_snapshot()
-
- # Create an inferior, this triggers the new_inferior event, which
- # in turn holds a reference to the new gdb.Inferior object in the
- # global INF variable.
- num = add_inferior()
- gdb.execute("remove-inferiors %s" % num)
-
- # Possibly clear the global INF variable.
- if clear:
- inf = None
-
- # Now grab a second snapshot of memory allocations, and stop
- # tracing memory allocations.
- snapshot2 = tracemalloc.take_snapshot()
- tracemalloc.stop()
-
- # Filter the snapshots; we only care about allocations originating
- # from this file.
- snapshot1 = snapshot1.filter_traces(filters)
- snapshot2 = snapshot2.filter_traces(filters)
-
- # Compare the snapshots, this leaves only things that were
- # allocated, but not deallocated since the first snapshot.
- stats = snapshot2.compare_to(snapshot1, "traceback")
-
- # Total up all the deallocated things.
- total = 0
- for stat in stats:
- total += stat.size_diff
- return total
-
-
-# The first time we run this some global state will be allocated which
-# shows up as memory that is allocated, but not released. So, run the
-# test once and discard the result.
-test(True)
-
-# Now run the test twice, the first time we clear our global reference
-# to the gdb.Inferior object, which should allow Python to deallocate
-# the object. The second time we hold onto the global reference,
-# preventing Python from performing the deallocation.
-bytes_with_clear = test(True)
-bytes_without_clear = test(False)
-
-# The bug that used to exist in GDB was that even when we released the
-# global reference the gdb.Inferior object would not be deallocated.
-if bytes_with_clear > 0:
- raise gdb.GdbError("memory leak when gdb.Inferior should be released")
-if bytes_without_clear == 0:
- raise gdb.GdbError("gdb.Inferior object is no longer allocated")
-
-# Print a PASS message that the test script can see.
-print("PASS")
+inferior_leak_detector().run()
diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp
index 62af1a4..58632f0 100644
--- a/gdb/testsuite/gdb.python/py-inferior.exp
+++ b/gdb/testsuite/gdb.python/py-inferior.exp
@@ -318,7 +318,7 @@ with_test_prefix "large range" {
# For native targets, test a pattern straddling a chunk boundary.
-if [isnative] {
+if {[isnative]} {
with_test_prefix "straddling" {
gdb_test_no_output "set *(int32_t*) &search_buf\[${CHUNK_SIZE}-1\] = 0xfdb97531"
gdb_test_no_output "py pattern = pack('${python_pack_char}I', 0xfdb97531)"
diff --git a/gdb/testsuite/gdb.python/py-label-symbol-value.exp b/gdb/testsuite/gdb.python/py-label-symbol-value.exp
index ca534d4..07bc870 100644
--- a/gdb/testsuite/gdb.python/py-label-symbol-value.exp
+++ b/gdb/testsuite/gdb.python/py-label-symbol-value.exp
@@ -24,7 +24,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-lazy-string.exp b/gdb/testsuite/gdb.python/py-lazy-string.exp
index 7e7272e..a6fdd77 100644
--- a/gdb/testsuite/gdb.python/py-lazy-string.exp
+++ b/gdb/testsuite/gdb.python/py-lazy-string.exp
@@ -26,7 +26,7 @@ if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} {
return -1
}
-if ![runto_main ] {
+if {![runto_main ]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-linetable-empty.exp b/gdb/testsuite/gdb.python/py-linetable-empty.exp
index 1e737e1..f742d70 100644
--- a/gdb/testsuite/gdb.python/py-linetable-empty.exp
+++ b/gdb/testsuite/gdb.python/py-linetable-empty.exp
@@ -27,11 +27,11 @@ Dwarf::assemble $asm_file {
cu {} {
compile_unit {
- {language @DW_LANG_C}
- {name py-linetable-empty.c}
+ DW_AT_language @DW_LANG_C
+ DW_AT_name py-linetable-empty.c
} {
subprogram {
- {MACRO_AT_func {main}}
+ MACRO_AT_func {main}
}
}
}
@@ -42,7 +42,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} \
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-linetable.exp b/gdb/testsuite/gdb.python/py-linetable.exp
index d27d16e..453ee7a 100644
--- a/gdb/testsuite/gdb.python/py-linetable.exp
+++ b/gdb/testsuite/gdb.python/py-linetable.exp
@@ -18,7 +18,7 @@ require allow_python_tests
set opts {}
standard_testfile .S
-if [info exists COMPILE] {
+if {[info exists COMPILE]} {
# make check RUNTESTFLAGS="gdb.python/py-linetable.exp COMPILE=1"
standard_testfile
lappend opts debug optimize=-O2
@@ -30,7 +30,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} $opts] } {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-lookup-type.exp b/gdb/testsuite/gdb.python/py-lookup-type.exp
index 8673d56..ef04e21 100644
--- a/gdb/testsuite/gdb.python/py-lookup-type.exp
+++ b/gdb/testsuite/gdb.python/py-lookup-type.exp
@@ -30,8 +30,8 @@ clean_restart
proc test_lookup_type { lang type_name } {
gdb_test_no_output "set language ${lang}"
gdb_test "python print(gdb.lookup_type('${type_name}').name)" \
- "${type_name}" \
- "lookup type ${type_name} using language ${lang}"
+ "${type_name}" \
+ "lookup type ${type_name} using language ${lang}"
}
test_lookup_type "ada" "character"
diff --git a/gdb/testsuite/gdb.python/py-mi-events.exp b/gdb/testsuite/gdb.python/py-mi-events.exp
index ecdb74a..a15ba0b 100644
--- a/gdb/testsuite/gdb.python/py-mi-events.exp
+++ b/gdb/testsuite/gdb.python/py-mi-events.exp
@@ -39,7 +39,7 @@ mi_gdb_test "set auto-load safe-path ${remote_python_file}" \
{.*\^done} \
"set safe-path"
-if [is_remote host] {
+if {[is_remote host]} {
set filename ${testfile}
remote_download host ${binfile} ${filename}
} else {
diff --git a/gdb/testsuite/gdb.python/py-mi-objfile.exp b/gdb/testsuite/gdb.python/py-mi-objfile.exp
index 58ecbc5..c1edffe 100644
--- a/gdb/testsuite/gdb.python/py-mi-objfile.exp
+++ b/gdb/testsuite/gdb.python/py-mi-objfile.exp
@@ -33,7 +33,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
# gdb will find it.
set remote_python_file [gdb_remote_download host ${srcdir}/${subdir}/${pyfile}]
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
@@ -41,7 +41,7 @@ mi_gdb_test "set auto-load safe-path ${remote_python_file}" \
{.*\^done} \
"set safe-path"
-if [is_remote host] {
+if {[is_remote host]} {
set filename ${testfile}
remote_download host ${binfile} ${filename}
} else {
diff --git a/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp b/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp
index 07cd40f..7a9124b 100644
--- a/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp
+++ b/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp
@@ -29,7 +29,7 @@ if {[gdb_compile "$srcdir/$subdir/$srcfile" $binfile executable {debug}] != "" }
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
mi_gdb_test "source ${pyfile}" \
diff --git a/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.py b/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.py
index e7638db..46bbb74 100644
--- a/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.py
+++ b/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.py
@@ -13,7 +13,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import sys
import gdb
import gdb.types
diff --git a/gdb/testsuite/gdb.python/py-mi.exp b/gdb/testsuite/gdb.python/py-mi.exp
index 7f1dffc..28d63c1 100644
--- a/gdb/testsuite/gdb.python/py-mi.exp
+++ b/gdb/testsuite/gdb.python/py-mi.exp
@@ -26,7 +26,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
@@ -345,7 +345,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}-cxx" \
return -1
}
-if {[mi_clean_restart ${binfile}-cxx]} {
+if {[mi_clean_restart ${::testfile}-cxx]} {
return
}
diff --git a/gdb/testsuite/gdb.python/py-missing-debug.py b/gdb/testsuite/gdb.python/py-missing-debug.py
index c018d4d..18d37ce 100644
--- a/gdb/testsuite/gdb.python/py-missing-debug.py
+++ b/gdb/testsuite/gdb.python/py-missing-debug.py
@@ -38,7 +38,6 @@ class handler(MissingDebugHandler):
self._mode = Mode.RETURN_NONE
def __call__(self, objfile):
- global handler_call_log
handler_call_log.append(self.name)
self._call_count += 1
if self._mode == Mode.RETURN_NONE:
@@ -95,7 +94,6 @@ class exception_handler(MissingDebugHandler):
self.exception_type = None
def __call__(self, objfile):
- global handler_call_log
handler_call_log.append(self.name)
assert self.exception_type is not None
raise self.exception_type("message")
@@ -103,7 +101,6 @@ class exception_handler(MissingDebugHandler):
class log_handler(MissingDebugHandler):
def __call__(self, objfile):
- global handler_call_log
handler_call_log.append(self.name)
return None
diff --git a/gdb/testsuite/gdb.python/py-missing-objfile.exp b/gdb/testsuite/gdb.python/py-missing-objfile.exp
index e4a1b3f..2f54f61 100644
--- a/gdb/testsuite/gdb.python/py-missing-objfile.exp
+++ b/gdb/testsuite/gdb.python/py-missing-objfile.exp
@@ -34,6 +34,11 @@ if { [build_executable "build exec" $binfile $srcfile $opts] == -1} {
return
}
+set expect_build_id_in_core_file_binfile \
+ [expect_build_id_in_core_file $binfile]
+set expect_build_id_in_core_file_libfile \
+ [expect_build_id_in_core_file $libfile]
+
# The cc-with-gnu-debuglink board will split the debug out into the
# .debug directory. This test script relies on having GDB lookup the
# objfile and debug via the build-id, which this test sets up. Trying
@@ -79,6 +84,16 @@ proc setup_debugdir { dirname files } {
# executable (when EXEC_LOADED is true) and/or the library (when LIB_LOADED
# is true).
proc check_loaded_debug { exec_loaded lib_loaded } {
+ set re_warn \
+ [string_to_regexp \
+ "Warning: the current language does not match this frame."]
+ set cmd "set lang c"
+ gdb_test_multiple $cmd "" {
+ -re -wrap "${cmd}(\r\n$re_warn)?" {
+ pass $gdb_test_name
+ }
+ }
+
if { $exec_loaded } {
gdb_test "whatis global_exec_var" "^type = volatile struct exec_type"
@@ -124,7 +139,7 @@ proc clean_restart_load_python {} {
# For sanity, lets check that we can load the specify the executable
# and then load the core-file the easy way.
with_test_prefix "initial sanity check" {
- clean_restart $binfile
+ clean_restart $::testfile
load_core_file
check_loaded_debug true true
}
@@ -173,6 +188,11 @@ with_test_prefix "no objfiles available" {
check_loaded_debug false false
}
+# The following tests assume that the build-ids of binfile and libfile can be
+# found in the core file.
+require {expr $expect_build_id_in_core_file_binfile}
+require {expr $expect_build_id_in_core_file_libfile}
+
with_test_prefix "all objfiles available" {
# Another sanity check that GDB can find the files via the
# debug-file-directory.
@@ -226,7 +246,7 @@ with_test_prefix "handler installs lib objfile" {
remote_exec host \
"mkdir -p $debugdir_no_lib/[file dirname $build_id_filename]"
gdb_test_no_output "python handler_obj.set_mode(Mode.RETURN_TRUE, \
- \"$hidden_libfile\", \"$debugdir_no_lib/$build_id_filename\")" \
+ \"$hidden_libfile\", \"$debugdir_no_lib/$build_id_filename\")" \
"configure handler"
load_core_file
diff --git a/gdb/testsuite/gdb.python/py-missing-objfile.py b/gdb/testsuite/gdb.python/py-missing-objfile.py
index 5efc36a..dab3416 100644
--- a/gdb/testsuite/gdb.python/py-missing-objfile.py
+++ b/gdb/testsuite/gdb.python/py-missing-objfile.py
@@ -41,10 +41,10 @@ handler_last_filename = None
# A helper function that makes some assertions about the arguments
# passed to a MissingObjfileHandler.__call__() method.
def check_args(pspace, buildid, filename):
- assert type(filename) == str
+ assert type(filename) is str
assert filename != ""
- assert type(pspace) == gdb.Progspace
- assert type(buildid) == str
+ assert type(pspace) is gdb.Progspace
+ assert type(buildid) is str
assert buildid != ""
@@ -65,7 +65,7 @@ class handler(MissingObjfileHandler):
self._mode = Mode.RETURN_NONE
def __call__(self, pspace, buildid, filename):
- global handler_call_log, handler_last_buildid, handler_last_filename
+ global handler_last_buildid, handler_last_filename
check_args(pspace, buildid, filename)
handler_call_log.append(self.name)
handler_last_buildid = buildid
@@ -135,7 +135,6 @@ class exception_handler(MissingObjfileHandler):
self.exception_type = None
def __call__(self, pspace, buildid, filename):
- global handler_call_log
check_args(pspace, buildid, filename)
handler_call_log.append(self.name)
assert self.exception_type is not None
@@ -148,7 +147,6 @@ class exception_handler(MissingObjfileHandler):
# then be checked from the test script.
class log_handler(MissingObjfileHandler):
def __call__(self, pspace, buildid, filename):
- global handler_call_log
check_args(pspace, buildid, filename)
handler_call_log.append(self.name)
return None
diff --git a/gdb/testsuite/gdb.python/py-objfile-script-gdb.py b/gdb/testsuite/gdb.python/py-objfile-script-gdb.py
index 8666074..6661700 100644
--- a/gdb/testsuite/gdb.python/py-objfile-script-gdb.py
+++ b/gdb/testsuite/gdb.python/py-objfile-script-gdb.py
@@ -17,6 +17,8 @@
import re
+import gdb
+
class pp_ss:
def __init__(self, val):
diff --git a/gdb/testsuite/gdb.python/py-objfile-script.exp b/gdb/testsuite/gdb.python/py-objfile-script.exp
index 1a3d394..4e6f5b6 100644
--- a/gdb/testsuite/gdb.python/py-objfile-script.exp
+++ b/gdb/testsuite/gdb.python/py-objfile-script.exp
@@ -41,7 +41,7 @@ gdb_load ${binfile}
# Verify gdb loaded the script.
gdb_test "info auto-load python-scripts" "Yes.*${testfile}-gdb.py.*"
-if ![runto_main] {
+if {![runto_main]} {
return
}
diff --git a/gdb/testsuite/gdb.python/py-objfile.c b/gdb/testsuite/gdb.python/py-objfile.c
index fe68671..d721e0c 100644
--- a/gdb/testsuite/gdb.python/py-objfile.c
+++ b/gdb/testsuite/gdb.python/py-objfile.c
@@ -19,7 +19,7 @@ int global_var = 42;
static int __attribute__ ((used)) static_var = 50;
int
-main ()
+main (void)
{
int some_var = 0;
return 0;
diff --git a/gdb/testsuite/gdb.python/py-objfile.exp b/gdb/testsuite/gdb.python/py-objfile.exp
index d14eec6..ce4e37a 100644
--- a/gdb/testsuite/gdb.python/py-objfile.exp
+++ b/gdb/testsuite/gdb.python/py-objfile.exp
@@ -68,7 +68,7 @@ gdb_test "python print (gdb.lookup_objfile (\"${testfile}\").lookup_static_symbo
"None" "lookup_static_symbol can handle nonexistent symbol"
set binfile_build_id [get_build_id $binfile]
-if [string compare $binfile_build_id ""] {
+if {[string compare $binfile_build_id ""]} {
verbose -log "binfile_build_id = $binfile_build_id"
gdb_test "python print (objfile.build_id)" "$binfile_build_id" \
"Get objfile build id"
@@ -119,7 +119,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile}2 ${srcfile} {nodebug l
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return 0
}
@@ -144,7 +144,8 @@ gdb_test "python print (sep_objfile.owner.filename)" "${testfile}2" \
gdb_test "python print (sep_objfile.owner.username)" "${testfile}2" \
"Test user-name of owner of separate debug file"
-gdb_test "p main" "= {int \\(\\)} $hex <main>" \
+set re_prototype [string_to_regexp "int (void)"]
+gdb_test "p main" "= {$re_prototype} $hex <main>" \
"print main with debug info"
# Separate debug files are not findable.
@@ -157,12 +158,13 @@ if { [get_python_valueof "sep_objfile.build_id" "None"] != "None" } {
# An objfile that was a symlink to a differently named file is still
# findable with its original name.
# On Windows we don't have proper symlinks, so skip this.
-if ![ishost *-*-mingw*] {
+if {![ishost *-*-mingw*]} {
set symlink_binary [standard_output_file "symlink-binary"]
remote_exec host "rm -f ${symlink_binary}"
remote_exec host "ln -sf ${testfile} ${symlink_binary}"
- if [remote_file host exists "${symlink_binary}"] {
- clean_restart "${symlink_binary}"
+ if {[remote_file host exists "${symlink_binary}"]} {
+ clean_restart
+ gdb_load "${symlink_binary}"
gdb_test "python print (gdb.lookup_objfile (\"${symlink_binary}\").filename)" \
"${testfile}" "gdb.lookup_objfile of symlinked binary"
}
diff --git a/gdb/testsuite/gdb.python/py-parameter-prefix.exp b/gdb/testsuite/gdb.python/py-parameter-prefix.exp
new file mode 100644
index 0000000..eb09fe7
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-parameter-prefix.exp
@@ -0,0 +1,382 @@
+# Copyright (C) 2025 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 file is part of the GDB testsuite. It tests
+# gdb.ParameterPrefix. See each of the test procs for a full
+# description of what is being tested.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+
+clean_restart
+
+# Helper proc to generate the output of 'show PREFIX' commands for the
+# case where the prefix command doesn't handle unknown sub-commands.
+# In this case GDB will list the value of every sub-command under
+# PREFIX.
+proc make_show_prefix_re { prefix } {
+ return "$prefix param-1:\\s+The current value of '$prefix param-1' is \"off\"\\."
+}
+
+# Helper proc to generate the help text that describes all of the sub
+# commands under PREFIX. The MODE is either 'set' or 'show'. This
+# output will appear for 'help MODE PREFIX' and also for 'set PREFIX'.
+proc make_sub_cmd_help_re { mode prefix } {
+ if { $mode == "set" } {
+ set word "Set"
+ } else {
+ set word "Show"
+ }
+
+ return \
+ [multi_line \
+ "List of \"$mode $prefix\" subcommands:" \
+ "" \
+ "$mode $prefix param-1 -- $word the current value of '$prefix param-1'\\." \
+ "" \
+ "Type \"help $mode $prefix\" followed by subcommand name for full documentation\\." \
+ "Type \"apropos word\" to search for commands related to \"word\"\\." \
+ "Type \"apropos -v word\" for full documentation of commands related to \"word\"\\." \
+ "Command name abbreviations are allowed if unambiguous\\."]
+}
+
+# Helper proc to generate the output of 'help MODE PREFIX', where MODE
+# will be either 'set' or 'show'. The HELP_TEXT is the expected help
+# text for this prefix command, this should not be a regexp, as this
+# proc converts the text to a regexp.
+#
+# Return a single regexp which should match the output.
+proc make_help_re { mode prefix help_text } {
+ set help_re [string_to_regexp $help_text]
+
+ return \
+ [multi_line \
+ "$help_re" \
+ "" \
+ [make_sub_cmd_help_re $mode $prefix]]
+}
+
+# Create gdb.ParameterPrefix without using a sub-class, both with, and
+# without a doc string. For the doc string case, test single line,
+# and multi-line doc strings.
+proc_with_prefix test_basic_usage {} {
+ gdb_test_multiline "some basic ParameterPrefix usage" \
+ "python" "" \
+ "gdb.ParameterPrefix('prefix-1', gdb.COMMAND_NONE)" "" \
+ "gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.ParameterPrefix('prefix-2', gdb.COMMAND_NONE," "" \
+ " \"\"\"This is prefix-2 help string.\"\"\")" "" \
+ "gdb.Parameter('prefix-2 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.ParameterPrefix('prefix-3', gdb.COMMAND_NONE," "" \
+ " \"\"\"This is prefix-3 help string." "" \
+ " " "" \
+ " This help text spans multiple lines.\"\"\")" "" \
+ "gdb.Parameter('prefix-3 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end"
+
+ foreach mode { "set" "show" } {
+ gdb_test "help $mode prefix-1" \
+ [make_help_re $mode "prefix-1" \
+ "This command is not documented."]
+
+ gdb_test "help $mode prefix-2" \
+ [make_help_re $mode "prefix-2" \
+ "This is prefix-2 help string."]
+
+ gdb_test "help $mode prefix-3" \
+ [make_help_re $mode "prefix-3" \
+ [multi_line \
+ "This is prefix-3 help string." \
+ "" \
+ "This help text spans multiple lines."]]
+
+ foreach prefix { prefix-1 prefix-2 prefix-3 } {
+ gdb_test "$mode $prefix xxx" \
+ "^Undefined $mode $prefix command: \"xxx\"\\. Try \"help $mode $prefix\"\\."
+ }
+ }
+
+ foreach prefix { prefix-1 prefix-2 prefix-3 } {
+ gdb_test "set $prefix" \
+ [make_sub_cmd_help_re "set" $prefix]
+
+ gdb_test "show $prefix" \
+ [make_show_prefix_re $prefix]
+ }
+}
+
+# Create a sub-class of gdb.ParameterPrefix, but don't do anything
+# particularly interesting. Again test the with and without
+# documentation string cases.
+proc_with_prefix test_simple_sub_class {} {
+ gdb_test_multiline "some basic ParameterPrefix usage" \
+ "python" "" \
+ "class BasicParamPrefix(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ "BasicParamPrefix('prefix-4')" "" \
+ "gdb.Parameter('prefix-4 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class BasicParamPrefixWithSingleLineDoc(gdb.ParameterPrefix):" "" \
+ " \"\"\"This is a single line doc string.\"\"\"" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ "BasicParamPrefixWithSingleLineDoc('prefix-5')" "" \
+ "gdb.Parameter('prefix-5 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class BasicParamPrefixWithMultiLineDoc(gdb.ParameterPrefix):" "" \
+ " \"\"\"This is a multi line doc string." "" \
+ " " "" \
+ " The rest of the doc string is here.\"\"\"" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ "BasicParamPrefixWithMultiLineDoc('prefix-6')" "" \
+ "gdb.Parameter('prefix-6 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class BasicParamPrefixWithDocParameter(gdb.ParameterPrefix):" "" \
+ " \"\"\"This is an unsused doc string.\"\"\"" "" \
+ " def __init__(self, name, doc):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE, doc)" "" \
+ "BasicParamPrefixWithDocParameter('prefix-7'," "" \
+ " \"\"\"The doc string text is here.\"\"\")" "" \
+ "gdb.Parameter('prefix-7 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end"
+
+ foreach mode { "set" "show" } {
+ gdb_test "help $mode prefix-4" \
+ [make_help_re $mode "prefix-4" \
+ "This command is not documented."]
+
+ gdb_test "help $mode prefix-5" \
+ [make_help_re $mode "prefix-5" \
+ "This is a single line doc string."]
+
+ gdb_test "help $mode prefix-6" \
+ [make_help_re $mode "prefix-6" \
+ [multi_line \
+ "This is a multi line doc string." \
+ "" \
+ "The rest of the doc string is here."]]
+
+ gdb_test "help $mode prefix-7" \
+ [make_help_re $mode "prefix-7" \
+ "The doc string text is here."]
+
+ foreach prefix { prefix-4 prefix-5 prefix-6 prefix-7 } {
+ gdb_test "$mode $prefix xxx" \
+ "^Undefined $mode $prefix command: \"xxx\"\\. Try \"help $mode $prefix\"\\."
+ }
+ }
+
+ foreach prefix { prefix-4 prefix-5 prefix-6 prefix-7 } {
+ gdb_test "set $prefix" \
+ [make_sub_cmd_help_re "set" $prefix]
+
+ gdb_test "show $prefix" \
+ [make_show_prefix_re $prefix]
+ }
+}
+
+# Create a sub-class of gdb.ParameterPrefix, and make use of
+# 'invoke_set' and 'invoke_show'. Test that the invoke method is
+# executed when expected, and that, by default, these invoke methods
+# repeat when the user issues an empty command.
+proc_with_prefix test_prefix_with_invoke {} {
+ gdb_test_multiline "ParameterPrefix with invoke_set" \
+ "python" "" \
+ "class PrefixWithInvokeSet(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_set(self, args, from_tty):" "" \
+ " print(f\"invoke_set (a): \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithInvokeSet('prefix-8')" "" \
+ "gdb.Parameter('prefix-8 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class PrefixWithInvokeShow(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_show(self, args, from_tty):" "" \
+ " print(f\"invoke_show (b): \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithInvokeShow('prefix-9')" "" \
+ "gdb.Parameter('prefix-9 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class PrefixWithBothInvoke(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_set(self, args, from_tty):" "" \
+ " print(f\"invoke_set (c): \\\"{args}\\\" {from_tty}\")" "" \
+ " def invoke_show(self, args, from_tty):" "" \
+ " print(f\"invoke_show (d): \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithBothInvoke('prefix-10')" "" \
+ "gdb.Parameter('prefix-10 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end"
+
+ gdb_test "set prefix-8 xxx yyy" \
+ "^invoke_set \\(a\\): \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_set \\(a\\): \"xxx yyy\" True" \
+ "repeat set prefix-8 xxx yyy"
+
+ gdb_test "show prefix-8 xxx yyy" \
+ "^Undefined show prefix-8 command: \"xxx yyy\"\\. Try \"help show prefix-8\"\\."
+
+ gdb_test "set prefix-9 xxx yyy" \
+ "^Undefined set prefix-9 command: \"xxx yyy\"\\. Try \"help set prefix-9\"\\."
+
+ gdb_test "show prefix-9 xxx yyy" \
+ "^invoke_show \\(b\\): \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_show \\(b\\): \"xxx yyy\" True" \
+ "repeat show prefix-9 xxx yyy"
+
+ gdb_test "set prefix-10 xxx yyy" \
+ "^invoke_set \\(c\\): \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_set \\(c\\): \"xxx yyy\" True" \
+ "repeat set prefix-10 xxx yyy"
+
+ gdb_test "show prefix-10 xxx yyy" \
+ "^invoke_show \\(d\\): \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_show \\(d\\): \"xxx yyy\" True" \
+ "repeat show prefix-10 xxx yyy"
+
+ gdb_test "set prefix-8" \
+ "^invoke_set \\(a\\): \"\" True"
+
+ gdb_test "show prefix-8" \
+ [make_show_prefix_re "prefix-8"]
+
+ gdb_test "set prefix-9" \
+ [make_sub_cmd_help_re "set" "prefix-9"]
+
+ gdb_test "show prefix-9" \
+ "^invoke_show \\(b\\): \"\" True"
+
+ gdb_test "set prefix-10" \
+ "^invoke_set \\(c\\): \"\" True"
+
+ gdb_test "show prefix-10" \
+ "^invoke_show \\(d\\): \"\" True"
+}
+
+# Create ParameterPrefix sub-classes that make use of the
+# dont_repeat() method. Check that the relevant set/show invoke
+# callback doesn't repeat when an empty command is used.
+proc_with_prefix test_dont_repeat {} {
+ gdb_test_multiline "ParameterPrefix with invoke_set and dont_repeat" \
+ "python" "" \
+ "class PrefixWithInvokeAndDoNotRepeatSet(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_set(self, args, from_tty):" "" \
+ " self.dont_repeat()" "" \
+ " print(f\"invoke_set: \\\"{args}\\\" {from_tty}\")" "" \
+ " def invoke_show(self, args, from_tty):" "" \
+ " print(f\"invoke_show: \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithInvokeAndDoNotRepeatSet('prefix-11')" "" \
+ "gdb.Parameter('prefix-11 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class PrefixWithInvokeAndDoNotRepeatShow(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_set(self, args, from_tty):" "" \
+ " print(f\"invoke_set: \\\"{args}\\\" {from_tty}\")" "" \
+ " def invoke_show(self, args, from_tty):" "" \
+ " self.dont_repeat()" "" \
+ " print(f\"invoke_show: \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithInvokeAndDoNotRepeatShow('prefix-12')" "" \
+ "gdb.Parameter('prefix-12 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end"
+
+ gdb_test "set prefix-11 xxx yyy" \
+ "^invoke_set: \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^" \
+ "repeat set prefix-11 xxx yyy"
+
+ gdb_test "show prefix-11 xxx yyy" \
+ "^invoke_show: \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "invoke_show: \"xxx yyy\" True" \
+ "repeat show prefix-11 xxx yyy"
+
+ gdb_test "set prefix-12 xxx yyy" \
+ "^invoke_set: \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_set: \"xxx yyy\" True" \
+ "repeat set prefix-12 xxx yyy"
+
+ gdb_test "show prefix-12 xxx yyy" \
+ "^invoke_show: \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^" \
+ "repeat show prefix-12 xxx yyy"
+}
+
+# Create a parameter prefixm, and immediately add another prefix under
+# the first. The important thing here is that the second prefix is
+# created into an otherwise empty prefix as this triggered a bug at
+# one point.
+proc_with_prefix test_nested {} {
+ gdb_test_multiline "Create nested parameter prefixes" \
+ "python" "" \
+ "gdb.ParameterPrefix('prefix-13', gdb.COMMAND_NONE)" "" \
+ "gdb.ParameterPrefix('prefix-13 prefix-14', gdb.COMMAND_NONE)" "" \
+ "gdb.Parameter('prefix-13 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('prefix-13 param-2', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('prefix-13 prefix-14 param-3', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('prefix-13 prefix-14 param-4', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end" ""
+
+ gdb_test "show prefix-13 prefix-14" \
+ [multi_line \
+ "^prefix-13 prefix-14 param-3: The current value of 'prefix-13 prefix-14 param-3' is \"off\"\\." \
+ "prefix-13 prefix-14 param-4: The current value of 'prefix-13 prefix-14 param-4' is \"off\"\\."]
+
+ gdb_test "show prefix-13" \
+ [multi_line \
+ "^prefix-13 param-1: The current value of 'prefix-13 param-1' is \"off\"\\." \
+ "prefix-13 param-2: The current value of 'prefix-13 param-2' is \"off\"\\." \
+ "prefix-13 prefix-14 param-3: The current value of 'prefix-13 prefix-14 param-3' is \"off\"\\." \
+ "prefix-13 prefix-14 param-4: The current value of 'prefix-13 prefix-14 param-4' is \"off\"\\."]
+
+ gdb_test "set prefix-13 prefix-14" \
+ [multi_line \
+ "" \
+ "set prefix-13 prefix-14 param-3 -- Set the current value of 'prefix-13 prefix-14 param-3'\\." \
+ "set prefix-13 prefix-14 param-4 -- Set the current value of 'prefix-13 prefix-14 param-4'\\." \
+ "" \
+ ".*"]
+
+ gdb_test "set prefix-13" \
+ [multi_line \
+ "" \
+ "set prefix-13 param-1 -- Set the current value of 'prefix-13 param-1'\\." \
+ "set prefix-13 param-2 -- Set the current value of 'prefix-13 param-2'\\." \
+ "set prefix-13 prefix-14 -- This command is not documented\\." \
+ "" \
+ ".*"]
+}
+
+test_basic_usage
+test_simple_sub_class
+test_prefix_with_invoke
+test_dont_repeat
+test_nested
diff --git a/gdb/testsuite/gdb.python/py-parameter.exp b/gdb/testsuite/gdb.python/py-parameter.exp
index c15bef1..7c2f5c6 100644
--- a/gdb/testsuite/gdb.python/py-parameter.exp
+++ b/gdb/testsuite/gdb.python/py-parameter.exp
@@ -24,7 +24,7 @@ require allow_python_tests
clean_restart
proc py_param_test_maybe_no_output { command pattern args } {
- if [string length $pattern] {
+ if {[string length $pattern]} {
gdb_test $command $pattern $args
} else {
gdb_test_no_output $command $args
@@ -38,13 +38,17 @@ proc_with_prefix test_directories { } {
# doesn't set search directories on remote host.
set directories ".*\\\$cdir.\\\$cwd"
} else {
- set escaped_directory [string_to_regexp "$::srcdir/$::subdir"]
+ set directory [host_file_normalize "$::srcdir/$::subdir"]
+ set escaped_directory [string_to_regexp $directory]
set directories "$escaped_directory.\\\$cdir.\\\$cwd"
}
gdb_test "python print (gdb.parameter ('directories'))" $directories
}
proc_with_prefix test_data_directory { } {
+ # Proc assumes local host.
+ require {!is_remote host}
+
clean_restart
# Check we can correctly read the data-directory parameter. First,
@@ -187,6 +191,8 @@ proc_with_prefix test_enum_parameter { } {
# Test an color parameter.
proc_with_prefix test_color_parameter { } {
+ require {!is_remote host}
+
global env
with_ansi_styling_terminal {
# This enables 256 colors support and disables colors approximation.
@@ -346,6 +352,91 @@ proc_with_prefix test_really_undocumented_parameter { } {
"test general help"
}
+# Test a parameter in which the __doc__ string is empty or None.
+proc_with_prefix test_empty_doc_parameter {} {
+ gdb_test_multiline "empty __doc__ parameter" \
+ "python" "" \
+ "class EmptyDocParam(gdb.Parameter):" "" \
+ " __doc__ = \"\"" "" \
+ " def __init__(self, name):" "" \
+ " super ().__init__(name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "test_empty_doc_param = EmptyDocParam('print test-empty-doc-param')" ""\
+ "end"
+
+ # Setting the __doc__ string to empty means GDB will completely
+ # elide it from the output.
+ gdb_test "help set print test-empty-doc-param" \
+ "^Set the current value of 'print test-empty-doc-param'\\."
+
+ gdb_test_multiline "None __doc__ parameter" \
+ "python" "" \
+ "class NoneDocParam(gdb.Parameter):" "" \
+ " __doc__ = None" "" \
+ " def __init__(self, name):" "" \
+ " super ().__init__(name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "test_none_doc_param = NoneDocParam('print test-none-doc-param')" ""\
+ "end"
+
+ # Setting the __doc__ string to None, or anything else that isn't
+ # a string, causes GDB to use a default string instead.
+ gdb_test "help set print test-none-doc-param" \
+ [multi_line \
+ "^Set the current value of 'print test-none-doc-param'\\." \
+ "This command is not documented\\."]
+}
+
+# Test a parameter in which the set_doc/show_doc strings are either
+# empty, or None.
+proc_with_prefix test_empty_set_show_doc_parameter {} {
+ gdb_test_multiline "empty set/show doc parameter" \
+ "python" "" \
+ "class EmptySetShowParam(gdb.Parameter):" "" \
+ " set_doc = \"\"" "" \
+ " show_doc = \"\"" "" \
+ " def __init__(self, name):" "" \
+ " super ().__init__(name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "test_empty_set_show_param = EmptySetShowParam('print test-empty-set-show-param')" ""\
+ "end"
+
+ # Setting the set_doc/show_doc string to empty means GDB will use
+ # a suitable default string.
+ gdb_test "help set print test-empty-set-show-param" \
+ [multi_line \
+ "^Set the current value of 'print test-empty-set-show-param'\\." \
+ "This command is not documented\\."]
+
+ gdb_test "help show print test-empty-set-show-param" \
+ [multi_line \
+ "^Show the current value of 'print test-empty-set-show-param'\\." \
+ "This command is not documented\\."]
+
+ gdb_test_multiline "None set/show doc parameter" \
+ "python" "" \
+ "class NoneSetShowParam(gdb.Parameter):" "" \
+ " set_doc = None" "" \
+ " show_doc = None" "" \
+ " def __init__(self, name):" "" \
+ " super ().__init__(name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "test_none_set_show_param = NoneSetShowParam('print test-none-set-show-param')" ""\
+ "end"
+
+ # Setting the set_doc/show_doc string to None (or any non-string
+ # value) means GDB will use a suitable default string.
+ gdb_test "help set print test-none-set-show-param" \
+ [multi_line \
+ "^Set the current value of 'print test-none-set-show-param'\\." \
+ "This command is not documented\\."]
+
+ gdb_test "help show print test-none-set-show-param" \
+ [multi_line \
+ "^Show the current value of 'print test-none-set-show-param'\\." \
+ "This command is not documented\\."]
+}
+
# Test deprecated API. Do not use in your own implementations.
proc_with_prefix test_deprecated_api_parameter { } {
clean_restart
@@ -627,6 +718,38 @@ proc_with_prefix test_throwing_parameter { } {
"gdb.GdbError does not show Python stack"
}
+# Some parameters are per inferior. The value returned by gdb.parameter for
+# them should be dependent on which is the current inferior.
+proc_with_prefix test_per_inferior_parameters { } {
+ clean_restart
+
+ # Add a second inferior.
+ gdb_test "add-inferior" "Added inferior 2.*"
+
+ # Set some parameters on each inferior.
+ foreach_with_prefix inf {1 2} {
+ gdb_test "inferior ${inf}" "Switching to inferior ${inf}.*" \
+ "switch to inferior ${inf} before show"
+ gdb_test_no_output "set inferior-tty /inf${inf}-tty"
+ gdb_test_no_output "set cwd /inf${inf}-cwd"
+ gdb_test_no_output "set args /inf${inf}-args"
+ gdb_test_no_output "set remote exec-file /inf${inf}-ref"
+ # Outputs a warning, ignore it.
+ gdb_test "set tdesc filename /inf${inf}-tf"
+ }
+
+ # Check the values on each inferior.
+ foreach_with_prefix inf {1 2} {
+ gdb_test "inferior ${inf}" "Switching to inferior ${inf}.*" \
+ "switch to inferior ${inf} before set"
+ gdb_test "python print(gdb.parameter('inferior-tty'))" "/inf${inf}-tty"
+ gdb_test "python print(gdb.parameter('cwd'))" "/inf${inf}-cwd"
+ gdb_test "python print(gdb.parameter('args'))" "/inf${inf}-args"
+ gdb_test "python print(gdb.parameter('remote exec-file'))" "/inf${inf}-ref"
+ gdb_test "python print(gdb.parameter('tdesc filename'))" "/inf${inf}-tf"
+ }
+}
+
proc_with_prefix test_language {} {
gdb_test "python print(gdb.parameter('language'))" "auto" \
"print language parameter"
@@ -669,6 +792,104 @@ proc_with_prefix test_ambiguous_parameter {} {
"Parameter .* is ambiguous.*Error occurred in Python.*"
gdb_test "python print(gdb.parameter('test-ambiguous-value-1a'))" \
"Could not find parameter.*Error occurred in Python.*"
+
+ # Create command prefixs 'set foo1' and 'show foo1'.
+ gdb_test_no_output "python gdb.Command('set foo1', gdb.COMMAND_NONE, prefix=True)"
+ gdb_test_no_output "python gdb.Command('show foo1', gdb.COMMAND_NONE, prefix=True)"
+
+ # Create a parameter under 'foo1', but use a truncated prefix. At
+ # this point though, the prefix is not ambiguous.
+ gdb_test_no_output "python gdb.Parameter('foo bar', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)"
+ gdb_test "python print(gdb.parameter('foo1 bar'))" "False"
+
+ # Create another prefix command, similar in name to the first.
+ gdb_test_no_output "python gdb.Command('set foo2', gdb.COMMAND_NONE, prefix=True)"
+ gdb_test_no_output "python gdb.Command('show foo2', gdb.COMMAND_NONE, prefix=True)"
+
+ # An attempt to create a parameter using an ambiguous prefix will give an error.
+ gdb_test "python gdb.Parameter('foo baz', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: Could not find command prefix foo\\." \
+ "Error occurred in Python: Could not find command prefix foo\\."]
+}
+
+# Check that creating a gdb.Parameter with an unknown command prefix results in an error.
+proc_with_prefix test_unknown_prefix {} {
+ gdb_test_multiline "create parameter" \
+ "python" "" \
+ "class UnknownPrefixParam(gdb.Parameter):" "" \
+ " def __init__ (self, name):" "" \
+ " super().__init__ (name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "end"
+
+ foreach prefix { "unknown-prefix" "style unknown-prefix" "style disassembler unknown-prefix"} {
+ gdb_test "python UnknownPrefixParam('$prefix new-param')" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: Could not find command prefix $prefix\\." \
+ "Error occurred in Python: Could not find command prefix $prefix\\."]
+ }
+}
+
+# Test the default behaviour of a set/show parameter prefix command.
+proc_with_prefix test_set_show_parameters {} {
+ # This first set/show prefix command doesn't have an invoke
+ # method. As such, GDB installs the default invoke behaviour; set
+ # prints the full list of sub-commands, and show prints all the
+ # sub-command values.
+ gdb_test_multiline "Setup set/show parameter prefix with no invoke" \
+ "python" "" \
+ "class TestParamPrefix(gdb.Command):" "" \
+ " \"\"\"TestParamPrefix documentation string.\"\"\"" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE, prefix = True)" "" \
+ "TestParamPrefix('set test-prefix')" "" \
+ "TestParamPrefix('show test-prefix')" "" \
+ "gdb.Parameter('test-prefix param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('test-prefix param-2', gdb.COMMAND_NONE, gdb.PARAM_INTEGER)" "" \
+ "gdb.Parameter('test-prefix param-3', gdb.COMMAND_NONE, gdb.PARAM_STRING)" "" \
+ "end"
+
+ gdb_test "set test-prefix" \
+ [multi_line \
+ "List of \"set test-prefix\" subcommands:" \
+ "" \
+ "set test-prefix param-1 -- Set the current value of 'test-prefix param-1'." \
+ "set test-prefix param-2 -- Set the current value of 'test-prefix param-2'." \
+ "set test-prefix param-3 -- Set the current value of 'test-prefix param-3'." \
+ "" \
+ "Type \"help set test-prefix\" followed by subcommand name for full documentation\\." \
+ "Type \"apropos word\" to search for commands related to \"word\"\\." \
+ "Type \"apropos -v word\" for full documentation of commands related to \"word\"\\." \
+ "Command name abbreviations are allowed if unambiguous\\."]
+
+ gdb_test "show test-prefix" \
+ [multi_line \
+ "test-prefix param-1: The current value of 'test-prefix param-1' is \"off\"\\." \
+ "test-prefix param-2: The current value of 'test-prefix param-2' is \"0\"\\." \
+ "test-prefix param-3: The current value of 'test-prefix param-3' is \"\"\\."]
+
+ # This next set/show prefix has an invoke method, which will be
+ # called instead of the default behaviour tested above.
+ gdb_test_multiline "Setup set/show parameter prefix with invoke" \
+ "python" "" \
+ "class TestParamPrefix(gdb.Command):" "" \
+ " \"\"\"TestParamPrefix documentation string.\"\"\"" "" \
+ " def __init__(self, name, mode):" "" \
+ " self._mode = mode" "" \
+ " super().__init__(self._mode + ' ' + name, gdb.COMMAND_NONE, prefix = True)" "" \
+ " def invoke(self, args, from_tty):" "" \
+ " print('invoke -- ' + self._mode)" "" \
+ "TestParamPrefix('test-prefix-2', 'set')" "" \
+ "TestParamPrefix('test-prefix-2', 'show')" "" \
+ "gdb.Parameter('test-prefix-2 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('test-prefix-2 param-2', gdb.COMMAND_NONE, gdb.PARAM_INTEGER)" "" \
+ "gdb.Parameter('test-prefix-2 param-3', gdb.COMMAND_NONE, gdb.PARAM_STRING)" "" \
+ "end"
+
+ gdb_test "set test-prefix-2" "^invoke -- set"
+
+ gdb_test "show test-prefix-2" "^invoke -- show"
}
test_directories
@@ -679,11 +900,16 @@ test_color_parameter
test_file_parameter
test_undocumented_parameter
test_really_undocumented_parameter
+test_empty_doc_parameter
+test_empty_set_show_doc_parameter
test_deprecated_api_parameter
test_gdb_parameter
test_integer_parameter
test_throwing_parameter
+test_per_inferior_parameters
test_language
test_ambiguous_parameter
+test_unknown_prefix
+test_set_show_parameters
rename py_param_test_maybe_no_output ""
diff --git a/gdb/testsuite/gdb.python/py-pp-cast.exp b/gdb/testsuite/gdb.python/py-pp-cast.exp
index 7e20756..917547c 100644
--- a/gdb/testsuite/gdb.python/py-pp-cast.exp
+++ b/gdb/testsuite/gdb.python/py-pp-cast.exp
@@ -25,7 +25,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
-if ![runto break_function] {
+if {![runto break_function]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-pp-integral.exp b/gdb/testsuite/gdb.python/py-pp-integral.exp
index 8111d75..45645f9 100644
--- a/gdb/testsuite/gdb.python/py-pp-integral.exp
+++ b/gdb/testsuite/gdb.python/py-pp-integral.exp
@@ -21,7 +21,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
-if ![runto tick_tock] {
+if {![runto tick_tock]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-pp-maint.c b/gdb/testsuite/gdb.python/py-pp-maint.c
index f40bbe5..4221539 100644
--- a/gdb/testsuite/gdb.python/py-pp-maint.c
+++ b/gdb/testsuite/gdb.python/py-pp-maint.c
@@ -81,6 +81,6 @@ main ()
init_flt (&flt, 42, 43);
init_ss (&ss, 1, 2);
-
+
return 0; /* break to inspect */
}
diff --git a/gdb/testsuite/gdb.python/py-pp-maint.exp b/gdb/testsuite/gdb.python/py-pp-maint.exp
index 74d8e76..bd26b91 100644
--- a/gdb/testsuite/gdb.python/py-pp-maint.exp
+++ b/gdb/testsuite/gdb.python/py-pp-maint.exp
@@ -72,10 +72,10 @@ gdb_test "enable pretty-printer" \
"second enable of all pretty printers"
gdb_test "disable pretty-printer global lookup_function_lookup_test" \
- "1 printer disabled.*[expr $num_pp - 1] of $num_pp printers enabled"
+ "1 printer disabled.*[expr {$num_pp - 1}] of $num_pp printers enabled"
gdb_test "disable pretty-printer global pp-test;.*" \
- "[expr 5] printers disabled.*0 of $num_pp printers enabled"
+ "[expr {$num_pp - 1}] printers disabled.*0 of $num_pp printers enabled"
gdb_test "info pretty-printer global .*function" \
{.*function_lookup_test \[disabled\].*} \
@@ -101,10 +101,10 @@ gdb_test "enable pretty-printer global pp-test" \
"0 printers enabled.*1 of $num_pp printers enabled"
gdb_test "enable pretty-printer global pp-test;.*ss.*" \
- "2 printers enabled.*[expr $num_pp - 3] of $num_pp printers enabled"
+ "2 printers enabled.*[expr {$num_pp - 3}] of $num_pp printers enabled"
gdb_test "enable pretty-printer global pp-test;.*s.*" \
- "2 printers enabled.*[expr $num_pp - 1] of $num_pp printers enabled"
+ "2 printers enabled.*[expr {$num_pp - 1}] of $num_pp printers enabled"
gdb_test "enable pretty-printer global pp-test;.*" \
"1 printer enabled.*$num_pp of $num_pp printers enabled"
diff --git a/gdb/testsuite/gdb.python/py-pp-maint.py b/gdb/testsuite/gdb.python/py-pp-maint.py
index 8b96cc0..a7e0815 100644
--- a/gdb/testsuite/gdb.python/py-pp-maint.py
+++ b/gdb/testsuite/gdb.python/py-pp-maint.py
@@ -16,8 +16,6 @@
# This file is part of the GDB testsuite. It tests python pretty
# printers.
-import re
-
import gdb.printing
import gdb.types
diff --git a/gdb/testsuite/gdb.python/py-pp-re-notag.exp b/gdb/testsuite/gdb.python/py-pp-re-notag.exp
index 8111d75..45645f9 100644
--- a/gdb/testsuite/gdb.python/py-pp-re-notag.exp
+++ b/gdb/testsuite/gdb.python/py-pp-re-notag.exp
@@ -21,7 +21,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
-if ![runto tick_tock] {
+if {![runto tick_tock]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-pp-registration.c b/gdb/testsuite/gdb.python/py-pp-registration.c
index 5a95917..e7dfd60 100644
--- a/gdb/testsuite/gdb.python/py-pp-registration.c
+++ b/gdb/testsuite/gdb.python/py-pp-registration.c
@@ -50,6 +50,6 @@ main ()
init_flt (&flt, 42, 43);
init_s (&s, 1);
-
+
return 0; /* break to inspect */
}
diff --git a/gdb/testsuite/gdb.python/py-pp-registration.exp b/gdb/testsuite/gdb.python/py-pp-registration.exp
index c5e7f9a..d0d1fda 100644
--- a/gdb/testsuite/gdb.python/py-pp-registration.exp
+++ b/gdb/testsuite/gdb.python/py-pp-registration.exp
@@ -29,7 +29,7 @@ if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} {
set remote_python_file [gdb_remote_download host \
${srcdir}/${subdir}/${testfile}.py]
-if ![runto_main ] {
+if {![runto_main ]} {
return -1
}
@@ -40,7 +40,7 @@ proc prepare_test { } {
clean_restart ${testfile}
set run_to_here [gdb_get_line_number {break to inspect} ${testfile}.c ]
- if ![runto ${testfile}.c:$run_to_here] {
+ if {![runto ${testfile}.c:$run_to_here]} {
return 0
}
@@ -63,7 +63,7 @@ proc test_printers { s_prefix } {
# Test registration with verbose off.
with_test_prefix "verbose off" {
- if ![prepare_test] {
+ if {![prepare_test]} {
return -1
}
@@ -78,7 +78,7 @@ with_test_prefix "verbose off" {
# Test registration with verbose on.
with_test_prefix "verbose on" {
- if ![prepare_test] {
+ if {![prepare_test]} {
return -1
}
@@ -95,7 +95,7 @@ with_test_prefix "verbose on" {
# Exercise the "replace" argument to register_pretty_printer.
with_test_prefix "replace" {
- if ![prepare_test] {
+ if {![prepare_test]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-pp-registration.py b/gdb/testsuite/gdb.python/py-pp-registration.py
index e9f3dfb..02ef2d2 100644
--- a/gdb/testsuite/gdb.python/py-pp-registration.py
+++ b/gdb/testsuite/gdb.python/py-pp-registration.py
@@ -16,8 +16,6 @@
# This file is part of the GDB testsuite. It tests python pretty
# printer registration.
-import re
-
import gdb.printing
import gdb.types
@@ -42,8 +40,6 @@ class pp_s1(object):
self.val = val
def to_string(self):
- a = self.val["a"]
- b = self.val["b"]
return "s1 a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
@@ -52,8 +48,6 @@ class pp_s2(object):
self.val = val
def to_string(self):
- a = self.val["a"]
- b = self.val["b"]
return "s2 a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.c b/gdb/testsuite/gdb.python/py-prettyprint.c
index 56c19ad..3951b19 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.c
+++ b/gdb/testsuite/gdb.python/py-prettyprint.c
@@ -72,16 +72,16 @@ struct SSS
};
SSS::SSS (int x, const S& r) : a(x), b(r) { }
-class VirtualTest
-{
- private:
- int value;
-
- public:
- VirtualTest ()
- {
+class VirtualTest
+{
+ private:
+ int value;
+
+ public:
+ VirtualTest ()
+ {
value = 1;
- }
+ }
};
class Vbase1 : public virtual VirtualTest { };
@@ -89,21 +89,21 @@ class Vbase2 : public virtual VirtualTest { };
class Vbase3 : public virtual VirtualTest { };
class Derived : public Vbase1, public Vbase2, public Vbase3
-{
- private:
- int value;
-
+{
+ private:
+ int value;
+
public:
- Derived ()
- {
- value = 2;
+ Derived ()
+ {
+ value = 2;
}
};
class Fake
{
int sname;
-
+
public:
Fake (const int name = 0):
sname (name)
@@ -150,7 +150,7 @@ substruct_test (void)
outer.s.a = 3; /* MI outer breakpoint here */
- return outer;
+ return outer;
}
typedef struct string_repr
@@ -362,7 +362,7 @@ main ()
SSS& ref (sss);
Derived derived;
-
+
Fake fake (42);
init_s (&has_static_member::global, 23);
@@ -387,7 +387,7 @@ main ()
nstype.elements[0] = 7;
nstype.elements[1] = 42;
nstype.len = 2;
-
+
nstype2 = nstype;
eval_sub ();
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.exp b/gdb/testsuite/gdb.python/py-prettyprint.exp
index 0b5ca9a..e450edc 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.exp
+++ b/gdb/testsuite/gdb.python/py-prettyprint.exp
@@ -36,7 +36,8 @@ proc run_lang_tests {exefile lang} {
set nl "\[\r\n\]+"
# Start with a fresh gdb.
- clean_restart $exefile
+ clean_restart
+ gdb_load $exefile
if {![runto_main]} {
return
@@ -52,11 +53,11 @@ proc run_lang_tests {exefile lang} {
${srcdir}/${subdir}/${testfile}.py]
gdb_test_no_output "source ${remote_python_file}" "load python file"
-
+
gdb_test "print ss" " = a=< a=<1> b=<$hex>> b=< a=<2> b=<$hex>>"
gdb_test "print ssa\[1\]" " = a=< a=<5> b=<$hex>> b=< a=<6> b=<$hex>>"
gdb_test "print ssa" " = {a=< a=<3> b=<$hex>> b=< a=<4> b=<$hex>>, a=< a=<5> b=<$hex>> b=< a=<6> b=<$hex>>}"
-
+
gdb_test "print arraystruct" " = {$nl *y = 7, *$nl *x = { a=<23> b=<$hex>, a=<24> b=<$hex>} *$nl *}"
# Test that when a pretty-printer returns a gdb.Value in its to_string, we
@@ -192,7 +193,7 @@ with_test_prefix c++ {
# Run various other tests.
-clean_restart $binfile
+clean_restart $::testfile
if {![runto_main]} {
return
@@ -242,5 +243,3 @@ gdb_test "print /r ss" " = {a = {a = 1, b = $hex}, b = {a = 2, b = $hex}}"
gdb_test "with print raw-values off -- print /r ss" " = {a = {a = 1, b = $hex}, b = {a = 2, b = $hex}}"
gdb_test "print -raw-values off -- /r ss" " = {a = {a = 1, b = $hex}, b = {a = 2, b = $hex}}"
-
-
diff --git a/gdb/testsuite/gdb.python/py-progspace.exp b/gdb/testsuite/gdb.python/py-progspace.exp
index 1d271d4..822c079 100644
--- a/gdb/testsuite/gdb.python/py-progspace.exp
+++ b/gdb/testsuite/gdb.python/py-progspace.exp
@@ -76,7 +76,7 @@ gdb_test "python print (blk.end >= ${pc_val})" "True" \
"block end is after \$pc"
# Check what happens when we ask for a block of an invalid address.
-if ![is_address_zero_readable] {
+if {![is_address_zero_readable]} {
gdb_test "python print (gdb.current_progspace ().block_for_pc (0))" "None"
}
diff --git a/gdb/testsuite/gdb.python/py-read-memory-leak.exp b/gdb/testsuite/gdb.python/py-read-memory-leak.exp
index 0015a57..0b663d7 100644
--- a/gdb/testsuite/gdb.python/py-read-memory-leak.exp
+++ b/gdb/testsuite/gdb.python/py-read-memory-leak.exp
@@ -26,19 +26,9 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
-# Skip this test if the tracemalloc module is not available.
-if { ![gdb_py_module_available "tracemalloc"] } {
- unsupported "tracemalloc module not available"
- return
-}
-
-set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
-
-# Source the Python script, this runs the test (which is written
-# completely in Python), and either prints PASS, or throws an
-# exception.
-gdb_test "source ${pyfile}" "PASS" "source python script"
+gdb_py_run_memory_leak_test ${srcdir}/${subdir}/${testfile}.py \
+ "buffers returned by read_memory() deallocates correctly"
diff --git a/gdb/testsuite/gdb.python/py-read-memory-leak.py b/gdb/testsuite/gdb.python/py-read-memory-leak.py
index 348403d..6bab0d7 100644
--- a/gdb/testsuite/gdb.python/py-read-memory-leak.py
+++ b/gdb/testsuite/gdb.python/py-read-memory-leak.py
@@ -13,81 +13,29 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import os
-import tracemalloc
+import sys
import gdb
-# A global variable in which we store a reference to the memory buffer
-# returned from gdb.Inferior.read_memory().
-mem_buf = None
+# Avoid generating
+# src/gdb/testsuite/gdb.python/__pycache__/gdb_leak_detector.cpython-<n>.pyc.
+sys.dont_write_bytecode = True
+import gdb_leak_detector # noqa: E402
-# A global filters list, we only care about memory allocations
-# originating from this script.
-filters = [tracemalloc.Filter(True, "*" + os.path.basename(__file__))]
+class read_leak_detector(gdb_leak_detector.gdb_leak_detector):
+ def __init__(self):
+ super().__init__(__file__)
+ self.mem_buf = None
+ self.addr = gdb.parse_and_eval("px")
+ self.inf = gdb.inferiors()[0]
-# Run the test. When CLEAR is True we clear the global INF variable
-# before comparing the before and after memory allocation traces.
-# When CLEAR is False we leave INF set to reference the gdb.Inferior
-# object, thus preventing the gdb.Inferior from being deallocated.
-def test(clear):
- global filters, mem_buf
+ def allocate(self):
+ self.mem_buf = self.inf.read_memory(self.addr, 4096)
- addr = gdb.parse_and_eval("px")
- inf = gdb.inferiors()[0]
+ def deallocate(self):
+ self.mem_buf = None
- # Start tracing, and take a snapshot of the current allocations.
- tracemalloc.start()
- snapshot1 = tracemalloc.take_snapshot()
- # Read from the inferior, this allocate a memory buffer object.
- mem_buf = inf.read_memory(addr, 4096)
-
- # Possibly clear the global INF variable.
- if clear:
- mem_buf = None
-
- # Now grab a second snapshot of memory allocations, and stop
- # tracing memory allocations.
- snapshot2 = tracemalloc.take_snapshot()
- tracemalloc.stop()
-
- # Filter the snapshots; we only care about allocations originating
- # from this file.
- snapshot1 = snapshot1.filter_traces(filters)
- snapshot2 = snapshot2.filter_traces(filters)
-
- # Compare the snapshots, this leaves only things that were
- # allocated, but not deallocated since the first snapshot.
- stats = snapshot2.compare_to(snapshot1, "traceback")
-
- # Total up all the allocated things.
- total = 0
- for stat in stats:
- total += stat.size_diff
- return total
-
-
-# The first time we run this some global state will be allocated which
-# shows up as memory that is allocated, but not released. So, run the
-# test once and discard the result.
-test(True)
-
-# Now run the test twice, the first time we clear our global reference
-# to the memory buffer object, which should allow Python to deallocate
-# the object. The second time we hold onto the global reference,
-# preventing Python from performing the deallocation.
-bytes_with_clear = test(True)
-bytes_without_clear = test(False)
-
-# The bug that used to exist in GDB was that even when we released the
-# global reference the gdb.Inferior object would not be deallocated.
-if bytes_with_clear > 0:
- raise gdb.GdbError("memory leak when memory buffer should be released")
-if bytes_without_clear == 0:
- raise gdb.GdbError("memory buffer object is no longer allocated")
-
-# Print a PASS message that the test script can see.
-print("PASS")
+read_leak_detector().run()
diff --git a/gdb/testsuite/gdb.python/py-record-btrace.exp b/gdb/testsuite/gdb.python/py-record-btrace.exp
index aff7c6c..207161d 100644
--- a/gdb/testsuite/gdb.python/py-record-btrace.exp
+++ b/gdb/testsuite/gdb.python/py-record-btrace.exp
@@ -23,7 +23,7 @@ load_lib gdb-python.exp
standard_testfile
-if [prepare_for_testing "failed to prepare" $testfile $srcfile] { return -1 }
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} { return -1 }
if {![runto_main]} {
return -1
@@ -66,8 +66,8 @@ with_test_prefix "prepare record" {
set v [linux_kernel_version]
if { $v != {} } {
set have_xfail \
- [expr [version_compare [list 5 5 0] <= $v] \
- && [version_compare $v < [list 6 1 0]]]
+ [expr {[version_compare [list 5 5 0] <= $v] \
+ && [version_compare $v < [list 6 1 0]]}]
}
set nonl_re \[^\r\n\]
set xfail_re \
diff --git a/gdb/testsuite/gdb.python/py-record-full.exp b/gdb/testsuite/gdb.python/py-record-full.exp
index 97d21ce..790e5b3 100644
--- a/gdb/testsuite/gdb.python/py-record-full.exp
+++ b/gdb/testsuite/gdb.python/py-record-full.exp
@@ -23,7 +23,7 @@ load_lib gdb-python.exp
standard_testfile
-if [prepare_for_testing "failed to prepare" $testfile $srcfile] { return -1 }
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} { return -1 }
if {![runto_main]} {
return -1
diff --git a/gdb/testsuite/gdb.python/py-recurse-unwind.exp b/gdb/testsuite/gdb.python/py-recurse-unwind.exp
index a1d1462..fbcb959 100644
--- a/gdb/testsuite/gdb.python/py-recurse-unwind.exp
+++ b/gdb/testsuite/gdb.python/py-recurse-unwind.exp
@@ -35,7 +35,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
gdb_test "source ${pyfile}" "Python script imported" \
- "import python scripts"
+ "import python scripts"
# The following tests require execution.
diff --git a/gdb/testsuite/gdb.python/py-recurse-unwind.py b/gdb/testsuite/gdb.python/py-recurse-unwind.py
index 244c693..51bc600 100644
--- a/gdb/testsuite/gdb.python/py-recurse-unwind.py
+++ b/gdb/testsuite/gdb.python/py-recurse-unwind.py
@@ -59,20 +59,15 @@ class TestUnwinder(Unwinder):
TestUnwinder.inc_count()
if TestUnwinder.test == "check_user_reg_pc":
- pc = pending_frame.read_register("pc")
- pc_as_int = int(pc.cast(gdb.lookup_type("int")))
- # gdb.write("In unwinder: pc=%x\n" % pc_as_int)
+ pending_frame.read_register("pc")
elif TestUnwinder.test == "check_pae_pc":
- pc = gdb.parse_and_eval("$pc")
- pc_as_int = int(pc.cast(gdb.lookup_type("int")))
- # gdb.write("In unwinder: pc=%x\n" % pc_as_int)
+ gdb.parse_and_eval("$pc")
elif TestUnwinder.test == "check_undefined_symbol":
try:
- val = gdb.parse_and_eval("undefined_symbol")
-
- except Exception as arg:
+ gdb.parse_and_eval("undefined_symbol")
+ except Exception:
pass
self.recurse_level -= 1
diff --git a/gdb/testsuite/gdb.python/py-section-script.exp b/gdb/testsuite/gdb.python/py-section-script.exp
index cc4425c..369c887 100644
--- a/gdb/testsuite/gdb.python/py-section-script.exp
+++ b/gdb/testsuite/gdb.python/py-section-script.exp
@@ -71,13 +71,13 @@ clean_restart
# Get the name of the binfile on the host; on a remote host this means
# stripping off any directory prefix.
-if [is_remote host] {
+if {[is_remote host]} {
set remote_binfile [file tail ${binfile}]
} else {
set remote_binfile ${binfile}
}
-if [ishost *-*-mingw*] {
+if {[ishost *-*-mingw*]} {
set remote_pathsep ";"
} else {
set remote_pathsep ":"
@@ -107,7 +107,7 @@ gdb_test "info auto-load python-scripts ${testfile}" "Yes.*${testfile}.py.*"
gdb_test "info auto-load python-scripts no-script-matches-this" \
"No auto-load scripts matching no-script-matches-this."
-if ![runto_main] {
+if {![runto_main]} {
return
}
@@ -126,7 +126,7 @@ gdb_test "test-cmd 1 2 3" "test-cmd output, arg = 1 2 3"
with_test_prefix "sepdebug" {
gdb_exit
- set result [catch "exec eu-strip -g -f ${binfile}.debug ${binfile}" output]
+ set result [catch {exec eu-strip -g -f ${binfile}.debug ${binfile}} output]
verbose "result is $result"
verbose "output is $output"
if {$result != 0 || $output != ""} {
diff --git a/gdb/testsuite/gdb.python/py-section-script.py b/gdb/testsuite/gdb.python/py-section-script.py
index d85221e..fb7bef3 100644
--- a/gdb/testsuite/gdb.python/py-section-script.py
+++ b/gdb/testsuite/gdb.python/py-section-script.py
@@ -17,6 +17,8 @@
import re
+import gdb
+
class pp_ss:
def __init__(self, val):
diff --git a/gdb/testsuite/gdb.python/py-send-packet.py b/gdb/testsuite/gdb.python/py-send-packet.py
index 0a0b359..7b852ed 100644
--- a/gdb/testsuite/gdb.python/py-send-packet.py
+++ b/gdb/testsuite/gdb.python/py-send-packet.py
@@ -65,7 +65,7 @@ def run_send_packet_test():
# find them, mark the ones we do find.
for thr in threads_xml:
id = thr.get("id")
- if not id in all_threads:
+ if id not in all_threads:
raise "found unexpected thread in remote thread list"
else:
all_threads[id] = True
@@ -144,7 +144,7 @@ def run_set_global_var_test():
res = conn.send_packet("X%x,4:\xff\xff\xff\xff" % addr)
except UnicodeError:
saw_error = True
- except:
+ except Exception:
assert False
assert saw_error
diff --git a/gdb/testsuite/gdb.python/py-source-styling-2.exp b/gdb/testsuite/gdb.python/py-source-styling-2.exp
index b13ee1f..ebf7f32 100644
--- a/gdb/testsuite/gdb.python/py-source-styling-2.exp
+++ b/gdb/testsuite/gdb.python/py-source-styling-2.exp
@@ -32,7 +32,9 @@ if { [build_executable "failed to build" $testfile $srcfile $opts] == -1 } {
return
}
-clean_restart
+with_ansi_styling_terminal {
+ clean_restart
+}
gdb_test_no_output "maint set gnu-source-highlight enabled off"
@@ -40,16 +42,14 @@ gdb_load $binfile
require {gdb_py_module_available pygments}
-with_ansi_styling_terminal {
- gdb_test_no_output "set style enabled on"
-
- gdb_test_multiple "list $line_number" "Styling of c++ keyword try" {
- -re -wrap " try\r\n.*" {
- # Unstyled.
- fail $gdb_test_name
- }
- -re -wrap "" {
- pass $gdb_test_name
- }
+gdb_test_no_output "set style enabled on"
+
+gdb_test_multiple "list $line_number" "Styling of c++ keyword try" {
+ -re -wrap " try\r\n.*" {
+ # Unstyled.
+ fail $gdb_test_name
+ }
+ -re -wrap "" {
+ pass $gdb_test_name
}
}
diff --git a/gdb/testsuite/gdb.python/py-source-styling.exp b/gdb/testsuite/gdb.python/py-source-styling.exp
index 308053c..e030768 100644
--- a/gdb/testsuite/gdb.python/py-source-styling.exp
+++ b/gdb/testsuite/gdb.python/py-source-styling.exp
@@ -62,7 +62,7 @@ proc check_source_listing_styling { cmd expect_styled { testname "" } } {
# highlighting when GNU source highlight is not available (or is
# disabled, as is done in this test).
proc test_pygments_styling {} {
- clean_restart $::binfile
+ clean_restart $::testfile
# Remote host boards disable styling via GDB's command line. Turn
# it back on now.
@@ -75,7 +75,7 @@ proc test_pygments_styling {} {
return
}
- if ![runto_main] {
+ if {![runto_main]} {
return
}
@@ -91,7 +91,7 @@ proc test_pygments_styling {} {
# string, then set the correct host encoding, and try again. This
# time the conversion should succeed.
proc test_gdb_execute_non_utf8_source {} {
- clean_restart $::binfile
+ clean_restart $::testfile
# The default host charset is utf-8, the source code contains a
# non-utf-8 character, so this will fail.
@@ -117,7 +117,7 @@ proc test_gdb_execute_non_utf8_source {} {
# output to be returned via a string, and in other cases we ask for
# the output to be sent straight to stdout.
proc_with_prefix test_source_cache_style_tracking {} {
- clean_restart $::binfile
+ clean_restart $::testfile
# Remote host boards disable styling via GDB's command line. Turn
# it back on now.
diff --git a/gdb/testsuite/gdb.python/py-startup-opt.exp b/gdb/testsuite/gdb.python/py-startup-opt.exp
index 7410706..929c64d 100644
--- a/gdb/testsuite/gdb.python/py-startup-opt.exp
+++ b/gdb/testsuite/gdb.python/py-startup-opt.exp
@@ -17,6 +17,7 @@
# initialized.
require allow_python_tests
+require {!is_remote host}
# Return a list containing two directory paths for newly created home
# directories.
diff --git a/gdb/testsuite/gdb.python/py-strfns.exp b/gdb/testsuite/gdb.python/py-strfns.exp
index 2b5dff19..13b8d2e 100644
--- a/gdb/testsuite/gdb.python/py-strfns.exp
+++ b/gdb/testsuite/gdb.python/py-strfns.exp
@@ -26,7 +26,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return 0
}
diff --git a/gdb/testsuite/gdb.python/py-style-parameter-set.exp b/gdb/testsuite/gdb.python/py-style-parameter-set.exp
new file mode 100644
index 0000000..73d94d1
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-style-parameter-set.exp
@@ -0,0 +1,366 @@
+# Copyright (C) 2025 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 file is part of the GDB testsuite. It tests gdb.StyleParameterSet.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+
+# Create a regexp that can be used to match the output of a 'show style
+# NAME' command. HAS_INTENSITY is a boolean and indicates if style NAME has
+# an intensity attribute.
+proc gen_show_style_re { name has_intensity } {
+ set output \
+ [list \
+ "style ${name} background: The \"${name}\" style background color is: none" \
+ "style ${name} foreground: The \"${name}\" style foreground color is: none"]
+
+ if { $has_intensity } {
+ lappend output \
+ "style ${name} intensity: The \"${name}\" style display intensity is: normal"
+ }
+
+ return [multi_line {*}$output]
+}
+
+# Create a regexp to match against the output of a 'set style NAME' command,
+# that is, a 'set' command that doesn't actually set an attribute of a
+# style, in this case GDB will print some useful help text. HAS_INTENSITY is
+# a boolean and indicates if style NAME has an intensity attribute or not.
+proc gen_set_style_re { name has_intensity } {
+ set output \
+ [list \
+ "List of \"set style $name\" subcommands:" \
+ "" \
+ "set style $name background -- Set the background color for this property\\." \
+ "set style $name foreground -- Set the foreground color for this property\\."]
+
+ if { $has_intensity } {
+ lappend output \
+ "set style $name intensity -- Set the display intensity for this property\\."
+ }
+
+ lappend output \
+ "" \
+ "Type \"help set style $name\" followed by subcommand name for full documentation\\." \
+ "Type \"apropos word\" to search for commands related to \"word\"\\." \
+ "Type \"apropos -v word\" for full documentation of commands related to \"word\"\\." \
+ "Command name abbreviations are allowed if unambiguous\\."
+
+ return [multi_line {*}$output]
+}
+
+# Create a regexp to match against the output of a 'help show style NAME'
+# command. HAS_INTENSITY is a boolean and indicates if style NAME has an
+# intensity attribute or not. DOC is a regexp that matches the doc string
+# for style NAME.
+proc gen_help_show_style_re { name has_intensity doc } {
+ set output \
+ [list \
+ $doc \
+ "" \
+ "List of \"show style ${name}\" subcommands:" \
+ "" \
+ "show style $name background -- Show the background color for this property\\." \
+ "show style $name foreground -- Show the foreground color for this property\\."]
+ if { $has_intensity } {
+ lappend output \
+ "show style $name intensity -- Show the display intensity for this property\\."
+ }
+
+ lappend output \
+ "" \
+ "Type \"help show style $name\" followed by subcommand name for full documentation\\." \
+ "Type \"apropos word\" to search for commands related to \"word\"\\." \
+ "Type \"apropos -v word\" for full documentation of commands related to \"word\"\\." \
+ "Command name abbreviations are allowed if unambiguous\\."
+
+ return [multi_line {*}$output]
+}
+
+# Create a regexp to match against the output of a 'help set style NAME'
+# command. HAS_INTENSITY is a boolean and indicates if style NAME has an
+# intensity attribute or not. DOC is a regexp that matches the doc string
+# for style NAME.
+proc gen_help_set_style_re { name has_intensity doc } {
+ return \
+ [multi_line \
+ $doc \
+ "" \
+ [gen_set_style_re $name $has_intensity]]
+}
+
+# Create styles with and without intensity. Use named and unnamed
+# argument passing, and vary the argument passing order. Create
+# styles with and without documentation.
+#
+# Confirm that the styles contain the expected sub-commands, and that
+# the documentation is as expected.
+proc_with_prefix test_basic_usage {} {
+ gdb_test_no_output \
+ "python style_1 = gdb.StyleParameterSet(\"style-1\")" \
+ "create style-1"
+
+ gdb_test_no_output \
+ "python style_2 = gdb.StyleParameterSet(add_intensity=True, name=\"style-2\")" \
+ "create style-2"
+
+ gdb_test_no_output \
+ "python style_3 = gdb.StyleParameterSet(name=\"style-3\", doc=\"Style-3 display styling.\\nThis is a multi-line documentation\\nstring describing style-3.\")" \
+ "create style-3"
+
+ gdb_test_no_output \
+ "python style_4 = gdb.StyleParameterSet(\"style-4\", add_intensity=False)" \
+ "create style-4"
+
+ foreach style { style-1 style-2 style-3 } {
+ gdb_test "show style $style" \
+ [gen_show_style_re $style true]
+ gdb_test "set style $style" \
+ [gen_set_style_re $style true]
+ }
+
+ gdb_test "show style style-4" \
+ [gen_show_style_re "style-4" false]
+
+ foreach style { style-1 style-2 } {
+ gdb_test "help show style $style" \
+ [gen_help_show_style_re $style true \
+ [multi_line \
+ "The $style display styling\\." \
+ "Configure $style colors and display intensity\\."]]
+
+
+ set out [gen_help_set_style_re $style true \
+ [multi_line \
+ "The $style display styling\\." \
+ "Configure $style colors and display intensity\\."]]
+
+ gdb_test "help set style $style" \
+ [gen_help_set_style_re $style true \
+ [multi_line \
+ "The $style display styling\\." \
+ "Configure $style colors and display intensity\\."]]
+ }
+
+ gdb_test "help show style style-3" \
+ [gen_help_show_style_re "style-3" true \
+ [multi_line \
+ "Style-3 display styling\\." \
+ "This is a multi-line documentation" \
+ "string describing style-3\\."]]
+
+ gdb_test "help show style style-4" \
+ [gen_help_show_style_re "style-4" false \
+ [multi_line \
+ "The style-4 display styling\\." \
+ "Configure style-4 colors and display intensity\\."]]
+
+ for { set i 1 } { $i < 5 } { incr i } {
+ gdb_test "python print(style_$i)" \
+ "<gdb.StyleParameterSet name='style-$i'>" \
+ "print repr of style_$i"
+ }
+
+ # There is no 'style-4 intensity' property.
+ gdb_test "show style style-4 foreground" \
+ "The \"style-4\" style foreground color is: none"
+ gdb_test "show style style-4 background" \
+ "The \"style-4\" style background color is: none"
+ gdb_test "show style style-4 intensity" \
+ "Undefined show style style-4 command: \"intensity\"\\. Try \"help show style style-4\"\\."
+
+ # There is a 'style-1 intensity' property.
+ gdb_test "show style style-1 foreground" \
+ "The \"style-1\" style foreground color is: none" \
+ "show style-1 foreground before changes"
+ gdb_test "show style style-1 background" \
+ "The \"style-1\" style background color is: none" \
+ "show style-1 background before changes"
+ gdb_test "show style style-1 intensity" \
+ "The \"style-1\" style display intensity is: normal" \
+ "show style-1 intensity before changes"
+
+ # Grab the gdb.Style objects from 'style-1'.
+ gdb_test_no_output "python s1 = style_1.style"
+ gdb_test_no_output "python s2 = style_1.value"
+
+ # Check both represent the same style.
+ gdb_test "python print(s1)" \
+ "<gdb.Style name='style-1', fg=none, bg=none, intensity=normal>" \
+ "print s1 style before changes"
+ gdb_test "python print(s2)" \
+ "<gdb.Style name='style-1', fg=none, bg=none, intensity=normal>" \
+ "print s2 style before changes"
+
+ gdb_test_no_output \
+ "python s1.foreground=gdb.Color('red')" "set foreground"
+ gdb_test_no_output \
+ "python s1.background=gdb.Color('blue')" "set background"
+ gdb_test_no_output \
+ "python s1.intensity=gdb.INTENSITY_DIM" "set intensity"
+
+ gdb_test "python print(s1)" \
+ "<gdb.Style name='style-1', fg=red, bg=blue, intensity=dim>" \
+ "print s1 style after first set of changes"
+ gdb_test "python print(s2)" \
+ "<gdb.Style name='style-1', fg=red, bg=blue, intensity=dim>" \
+ "print s2 style after first set of changes"
+
+ # Check the style properties have updated.
+ gdb_test "show style style-1 foreground" \
+ "The \"style-1\" style foreground color is: red" \
+ "show style-1 foreground after first set of changes"
+ gdb_test "show style style-1 background" \
+ "The \"style-1\" style background color is: blue" \
+ "show style-1 background after first set of changes"
+ gdb_test "show style style-1 intensity" \
+ "The \"style-1\" style display intensity is: dim" \
+ "show style-1 intensity after first set of changes"
+
+ # Change the style properties, check gdb.Style objects update.
+ gdb_test_no_output "set style style-1 foreground yellow"
+ gdb_test_no_output "set style style-1 background cyan"
+ gdb_test_no_output "set style style-1 intensity bold"
+
+ gdb_test "python print(s1)" \
+ "<gdb.Style name='style-1', fg=yellow, bg=cyan, intensity=bold>" \
+ "print s1 style after second set of changes"
+ gdb_test "python print(s2)" \
+ "<gdb.Style name='style-1', fg=yellow, bg=cyan, intensity=bold>" \
+ "print s2 style after second set of changes"
+
+ # Assign a gdb.Style to set 'style-1'. First create some unnamed
+ # style objects that can be used.
+ gdb_test_no_output \
+ "python uns1 = gdb.Style(foreground=gdb.Color('white'), background=gdb.Color('black'), intensity=gdb.INTENSITY_BOLD)" \
+ "create uns1"
+ gdb_test_no_output \
+ "python uns2 = gdb.Style(foreground=gdb.Color('black'), background=gdb.Color('white'), intensity=gdb.INTENSITY_DIM)" \
+ "create uns2"
+
+ gdb_test_no_output "python style_1.value = uns1"
+ gdb_test "show style style-1 foreground" \
+ "The \"style-1\" style foreground color is: white" \
+ "show style-1 foreground after assigning uns1"
+ gdb_test "show style style-1 background" \
+ "The \"style-1\" style background color is: black" \
+ "show style-1 background after assigning uns1"
+ gdb_test "show style style-1 intensity" \
+ "The \"style-1\" style display intensity is: bold" \
+ "show style-1 intensity after assigning uns1"
+
+ gdb_test_no_output "python style_1.style = uns2"
+ gdb_test "show style style-1 foreground" \
+ "The \"style-1\" style foreground color is: black" \
+ "show style-1 foreground after assigning uns2"
+ gdb_test "show style style-1 background" \
+ "The \"style-1\" style background color is: white" \
+ "show style-1 background after assigning uns2"
+ gdb_test "show style style-1 intensity" \
+ "The \"style-1\" style display intensity is: dim" \
+ "show style-1 intensity after assigning uns2"
+
+ # Assign a style with an intensity that is not 'NORMAL' to a
+ # StyleParameterSet that doesn't have an intensity. The new
+ # intensity setting should be ignored.
+ gdb_test_no_output "python style_4.style = uns1"
+ gdb_test "show style style-4 foreground" \
+ "The \"style-4\" style foreground color is: white" \
+ "show style-4 foreground after assigning uns1"
+ gdb_test "show style style-4 background" \
+ "The \"style-4\" style background color is: black" \
+ "show style-4 background after assigning uns1"
+ gdb_test "show style style-4 intensity" \
+ "Undefined show style style-4 command: \"intensity\"\\. Try \"help show style style-4\"\\." \
+ "show style-4 intensity after assigning uns1"
+
+ gdb_test "python print(style_4.style)" \
+ "<gdb.Style name='style-4', fg=white, bg=black, intensity=normal>" \
+ "print string repr of style_4's style"
+}
+
+# Test creating a style prefix with gdb.ParameterPrefix, then adding
+# some styles within the new prefix. Change the style through the CLI
+# and confirm that the associated Python object updated as expected.
+proc_with_prefix test_style_prefix {} {
+ gdb_test_no_output \
+ "python gdb.ParameterPrefix(\"style my-style-group\", gdb.COMMAND_NONE)"
+ gdb_test_no_output \
+ "python style_1 = gdb.StyleParameterSet(\"my-style-group style-1\")" \
+ "create style-1"
+ gdb_test_no_output \
+ "python style_2 = gdb.StyleParameterSet(\"my-style-group style-2\")" \
+ "create style-2"
+
+ gdb_test "python print(style_1.style)" \
+ "<gdb.Style name='my-style-group style-1', fg=none, bg=none, intensity=normal>" \
+ "print 'my-style-group style-1' style before changes"
+ gdb_test "python print(style_2.style)" \
+ "<gdb.Style name='my-style-group style-2', fg=none, bg=none, intensity=normal>" \
+ "print 'my-style-group style-2' style before changes"
+
+ gdb_test_no_output "set style my-style-group style-1 foreground red"
+ gdb_test_no_output "set style my-style-group style-1 background yellow"
+ gdb_test_no_output "set style my-style-group style-1 intensity bold"
+ gdb_test_no_output "set style my-style-group style-2 foreground black"
+ gdb_test_no_output "set style my-style-group style-2 background blue"
+ gdb_test_no_output "set style my-style-group style-2 intensity dim"
+
+ gdb_test "python print(style_1.style)" \
+ "<gdb.Style name='my-style-group style-1', fg=red, bg=yellow, intensity=bold>" \
+ "print 'my-style-group style-1' style after changes"
+ gdb_test "python print(style_2.style)" \
+ "<gdb.Style name='my-style-group style-2', fg=black, bg=blue, intensity=dim>" \
+ "print 'my-style-group style-2' style after changes"
+}
+
+# Test that gdb.StyleParameterSet.apply() works as expected.
+proc_with_prefix test_applying {} {
+ # Create a new StyleParameterSet, and adjust its settings.
+ gdb_test_no_output \
+ "python style_1 = gdb.StyleParameterSet(\"style-1\")" \
+ "create style-1"
+ gdb_test_no_output \
+ "python uns1 = gdb.Style(foreground=gdb.Color('red'), background=gdb.Color('blue'), intensity=gdb.INTENSITY_BOLD)" \
+ "create uns1"
+ gdb_test_no_output "python style_1 = uns1"
+
+ # When styling is off (which it currently is), no escape sequences
+ # should be added.
+ gdb_test \
+ "python print(style_1.apply('xxx'))" "^xxx" \
+ "apply StyleParameterSet to a string when styling is off"
+
+ # When styling is on, we should see an escape sequence added.
+ gdb_test "with style enabled on -- python print(style_1.apply('xxx'))" \
+ "\033\\\[31;44;1;23;24;27mxxx\033\\\[m" \
+ "apply a style when styling is on"
+}
+
+# Start GDB.
+with_ansi_styling_terminal {
+ clean_restart
+}
+
+# Turn styling off so that the output of 'show style ...' isn't styled, this
+# makes it easier to match the output.
+gdb_test_no_output "set style enabled off"
+
+# Run the tests.
+test_basic_usage
+test_style_prefix
+test_applying
diff --git a/gdb/testsuite/gdb.python/py-style.exp b/gdb/testsuite/gdb.python/py-style.exp
new file mode 100644
index 0000000..491e189
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-style.exp
@@ -0,0 +1,371 @@
+# Copyright (C) 2025 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 file is part of the GDB testsuite. It tests gdb.Style.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+
+# Start GDB, allow styling.
+with_ansi_styling_terminal {
+ clean_restart
+}
+
+# Check the error for unknown style names.
+foreach unknown_style { "unknown-style" "disassembler unknown-style" } {
+ gdb_test "python filename_style = gdb.Style('$unknown_style')" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: style '$unknown_style' cannot be found\\." \
+ "Error occurred in Python: style '$unknown_style' cannot be found\\."] \
+ "attempt to create named style for '$unknown_style'"
+}
+
+# Check we can create a style using an abbreviated style name.
+gdb_test_no_output "python abbrev_style = gdb.Style('high')" \
+ "create style using abbreviated name 'high'"
+gdb_test "python print(abbrev_style)" \
+ "^<gdb.Style name='highlight', fg=red, bg=none, intensity=normal>" \
+ "print the 'highlight' style"
+
+gdb_test_no_output "python abbrev_style = gdb.Style('disas mnem')" \
+ "create style using abbreviated name 'disas mnem'"
+gdb_test "python print(abbrev_style)" \
+ "^<gdb.Style name='disassembler mnemonic', fg=green, bg=none, intensity=normal>" \
+ "print the 'disassembler mnemonic' style"
+
+# Creating a style using an ambiguous abbreviated name will give an error.
+gdb_test "python abbrev_style = gdb.Style('f')" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: style 'f' cannot be found\\." \
+ "Error occurred in Python: style 'f' cannot be found\\."] \
+ "create style using abbreviated name 'f'"
+
+# Check a couple of different styles can be read. The 'tui-border' is
+# interesting as there is no 'intensity' for this one, the gdb.Style
+# object will show this as gdb.INTENSITY_NORMAL. The disassembler
+# styles are interesting because they are two word style names, and
+# the comment style has a foreground and intensity set.
+foreach style_check { { "filename" green none NORMAL } \
+ { "title" none none BOLD } \
+ { "tui-border" cyan none NORMAL } \
+ { "disassembler address" blue none NORMAL } \
+ { "disassembler comment" white none DIM } } {
+ set style_name [lindex $style_check 0]
+ set fg [lindex $style_check 1]
+ set bg [lindex $style_check 2]
+ set intensity [lindex $style_check 3]
+
+ with_test_prefix "check style $style_name" {
+ gdb_test_no_output "python style_obj = gdb.Style('$style_name')" \
+ "create named style for $style_name"
+
+ gdb_test "python print(style_obj.foreground)" "^$fg" \
+ "print foreground color"
+ gdb_test "python print(style_obj.background)" "^$bg" \
+ "print background color"
+ gdb_test "python print(style_obj.intensity == gdb.INTENSITY_$intensity)" \
+ "^True" "print intensity"
+
+ gdb_test "python print(style_obj)" \
+ "^<gdb.Style name='$style_name', fg=$fg, bg=$bg, intensity=[string tolower $intensity]>" \
+ "print string representation"
+ }
+}
+
+# Check that the intensity of a named style with no intensity
+# (tui-border) cannot be changed.
+gdb_test_no_output "python tui_border_style = gdb.Style('tui-border')" \
+ "create named style for 'tui-border'"
+gdb_test "python tui_border_style.intensity = gdb.INTENSITY_BOLD" \
+ [multi_line \
+ "Python Exception <class 'ValueError'>: the intensity of style 'tui-border' is not writable\\." \
+ "Error occurred in Python: the intensity of style 'tui-border' is not writable\\."]
+
+# Change the attributes of a named style, check the settings update as
+# expected.
+gdb_test_no_output "python filename_style = gdb.Style('filename')" \
+ "create named style for 'filename'"
+gdb_test_no_output "python filename_style.foreground = gdb.Color('blue')" \
+ "assign blue to filename foreground color"
+gdb_test_no_output "python filename_style.background = gdb.Color('red')" \
+ "assign red to filename background color"
+gdb_test_no_output "python filename_style.intensity = gdb.INTENSITY_BOLD"
+
+# Use 'with style enabled off' so that there are no escape sequences
+# in the output.
+gdb_test "with style enabled off -- show style filename" \
+ [multi_line \
+ "style filename background: The \"filename\" style background color is: red" \
+ "style filename foreground: The \"filename\" style foreground color is: blue" \
+ "style filename intensity: The \"filename\" style display intensity is: bold"]
+
+gdb_test "python print(filename_style)" \
+ "^<gdb.Style name='filename', fg=blue, bg=red, intensity=bold>" \
+ "print string representation of filename_style"
+
+# Check some attempts to set the gdb.Style attributes to invalid types.
+foreach attr { foreground background } {
+ gdb_test "python filename_style.$attr = None" \
+ [multi_line \
+ "Python Exception <class 'TypeError'>: value must be gdb.Color, not NoneType" \
+ "Error occurred in Python: value must be gdb.Color, not NoneType"]
+
+ gdb_test "python filename_style.$attr = list()" \
+ [multi_line \
+ "Python Exception <class 'TypeError'>: value must be gdb.Color, not list" \
+ "Error occurred in Python: value must be gdb.Color, not list"]
+
+ gdb_test "python filename_style.$attr = 'red'" \
+ [multi_line \
+ "Python Exception <class 'TypeError'>: value must be gdb.Color, not str" \
+ "Error occurred in Python: value must be gdb.Color, not str"]
+}
+
+gdb_test "python filename_style.intensity = None" \
+ [multi_line \
+ "Python Exception <class 'TypeError'>: value must be a Long \\(a gdb.INTENSITY constant\\), not NoneType" \
+ "Error occurred in Python: value must be a Long \\(a gdb.INTENSITY constant\\), not NoneType"]
+
+gdb_test "python filename_style.intensity = 'dim'" \
+ [multi_line \
+ "Python Exception <class 'TypeError'>: value must be a Long \\(a gdb.INTENSITY constant\\), not str" \
+ "Error occurred in Python: value must be a Long \\(a gdb.INTENSITY constant\\), not str"]
+
+# Check attempts to set the intensity to an integer value work as
+# expected. This is mostly about testing invalid integer values, but
+# we do also check that 0, 1, and 2 work as expected, though it is bad
+# practice to use the raw integer value rather than the defined
+# constants.
+set intensity_str { NORMAL BOLD DIM }
+for { set i -3 } { $i < 6 } { incr i } {
+ if { $i < 0 || $i > 2 } {
+ gdb_test "python filename_style.intensity = $i" \
+ [multi_line \
+ "Python Exception <class 'ValueError'>: invalid 'intensity' value $i\\." \
+ "Error occurred in Python: invalid 'intensity' value $i\\."]
+ } else {
+ gdb_test_no_output "python filename_style.intensity = $i"
+
+ set str [lindex $intensity_str $i]
+ gdb_test "python print(filename_style.intensity == gdb.INTENSITY_$str)" \
+ "^True" "check filename_style intensity is $str"
+ }
+}
+
+# Check the filename style has changed as expected.
+gdb_test "python print(filename_style)" \
+ "^<gdb.Style name='filename', fg=blue, bg=red, intensity=dim>" \
+ "check filename_style is now dim"
+
+# Check Style.escape_sequence and Style.apply when styling is disabled.
+gdb_test_no_output "with style enabled off -- python print(filename_style.escape_sequence(), end='')" \
+ "print escape sequence when styling is off"
+gdb_test "with style enabled off -- python print(filename_style.apply('xxx'))" "^xxx" \
+ "apply style to a string when styling is off"
+
+# Now check the escape sequences are emitted as expected.
+gdb_test "python print(filename_style.escape_sequence())" \
+ "\033\\\[34;41;2;23;24;27m" \
+ "print escape sequence when styling is on"
+gdb_test "python print(filename_style.apply('xxx'))" \
+ "\033\\\[34;41;2;23;24;27mxxx\033\\\[m" \
+ "apply a style when styling is on"
+
+# Test creating a style from component parts.
+gdb_test_no_output "python my_style_1 = gdb.Style(gdb.Color('red'), gdb.Color('blue'), gdb.INTENSITY_BOLD)" \
+ "create my_style_1"
+gdb_test "python print(my_style_1)" \
+ "^<gdb.Style fg=red, bg=blue, intensity=bold>" \
+ "check my_style_1"
+
+gdb_test_no_output "python my_style_2 = gdb.Style(background = gdb.Color('blue'))" \
+ "create my_style_2"
+gdb_test "python print(my_style_2)" \
+ "^<gdb.Style fg=none, bg=blue, intensity=normal>" \
+ "check my_style_2"
+
+gdb_test_no_output "python my_style_3 = gdb.Style(intensity = gdb.INTENSITY_DIM)" \
+ "create my_style_3"
+gdb_test "python print(my_style_3)" \
+ "^<gdb.Style fg=none, bg=none, intensity=dim>" \
+ "check my_style_3"
+
+# The precise error message, about 'None' not being an integer, varies
+# with Python version. We just check that we get a TypeError and
+# assume that this is related to the argument type.
+gdb_test "python my_style_4 = gdb.Style(intensity = None)" \
+ [multi_line \
+ "Python Exception <class 'TypeError'>: \[^\r\n\]+" \
+ "Error occurred in Python: \[^\r\n\]+"] \
+ "attempt to create my_style_4"
+
+gdb_test "python my_style_5 = gdb.Style(foreground = list())" \
+ [multi_line \
+ "Python Exception <class 'TypeError'>: 'foreground' argument must be gdb.Color or None, not list\\." \
+ "Error occurred in Python: 'foreground' argument must be gdb.Color or None, not list\\."] \
+ "attempt to create my_style_5"
+
+gdb_test "python my_style_6 = gdb.Style(background = list())" \
+ [multi_line \
+ "Python Exception <class 'TypeError'>: 'background' argument must be gdb.Color or None, not list\\." \
+ "Error occurred in Python: 'background' argument must be gdb.Color or None, not list\\."] \
+ "attempt to create my_style_6"
+
+# Adjust the attributes of an unnamed style.
+gdb_test_no_output "python my_style_1.foreground = gdb.Color('green')" \
+ "change my_style_1.foreground to green"
+gdb_test_no_output "python my_style_1.background = gdb.Color('cyan')" \
+ "change my_style_1.background to cyan"
+gdb_test_no_output "python my_style_1.intensity = gdb.INTENSITY_DIM" \
+ "change my_style_1.intensity to dim"
+gdb_test "python print(my_style_1)" \
+ "^<gdb.Style fg=green, bg=cyan, intensity=dim>" \
+ "check my_style_1 after changes."
+
+# Setup some prefix commands under 'set/show style ...'. Each prefix
+# command is called 'new-style-X' where X is an integer; 1, 2, 3, or 4.
+for { set i 1 } { $i < 5 } { incr i } {
+ gdb_test_no_output "python gdb.Command('set style new-style-$i', gdb.COMMAND_NONE, prefix = True)" \
+ "create set style new-style-$i"
+ gdb_test_no_output "python gdb.Command('show style new-style-$i', gdb.COMMAND_NONE, prefix = True)" \
+ "create show style new-style-$i"
+}
+
+# A helper class for creating color settings under the 'new-style-X'
+# prefix commands. The NUM to the __init__ supplies the value of
+# 'X', and NAME is either 'foreground' or 'background'.
+gdb_test_multiline "Class to create color parameters" \
+ "python" "" \
+ "class color_param(gdb.Parameter):" "" \
+ " def __init__(self, num, name):" "" \
+ " super().__init__(f\"style new-style-{num} {name}\", gdb.COMMAND_NONE, gdb.PARAM_COLOR)" "" \
+ " self.value = gdb.Color()" "" \
+ "end" ""
+
+# A helper class for creating intensity settings under the new
+# 'new-style-X' prefix commands. The NUM in the __init__ supplies the
+# value of 'X'.
+gdb_test_multiline "Class to create intensity parameters" \
+ "python" "" \
+ "class intensity_param(gdb.Parameter):" "" \
+ " def __init__(self, num):" "" \
+ " super().__init__(f\"style new-style-{num} intensity\", gdb.COMMAND_NONE, gdb.PARAM_ENUM," "" \
+ " \[\"normal\", \"bold\", \"dim\"\])" "" \
+ " self.value = \"normal\"" "" \
+ "end" ""
+
+# Within 'style new-style-1' we only have a 'foreground' setting.
+# This will not be usable as a gdb.Style.
+gdb_test_no_output "python color_param(1, 'foreground')" \
+ "setup new-style-1 foreground"
+
+# Within 'style new-style-2' we only have a 'background' setting.
+# This will not be usable as a gdb.Style.
+gdb_test_no_output "python color_param(2, 'background')" \
+ "setup new-style-2 background"
+
+# Within 'style new-style-3' we have both a 'foreground' and
+# 'background' setting. Even though 'intensity' is missing, this is
+# still usable as a style.
+gdb_test_no_output "python color_param(3, 'foreground')" \
+ "setup new-style-3 foreground"
+gdb_test_no_output "python color_param(3, 'background')" \
+ "setup new-style-3 background"
+
+# Within 'style new-style-4' we have a 'foreground', 'background', and
+# 'intensity' setting. This is a complete style setting group.
+gdb_test_no_output "python color_param(4, 'foreground')" \
+ "setup new-style-4 foreground"
+gdb_test_no_output "python color_param(4, 'background')" \
+ "setup new-style-4 background"
+gdb_test_no_output "python intensity_param(4)" \
+ "setup new-style-4 intensity"
+
+# Trying to create a style for 'new-style-1' should fail.
+gdb_test "python my_style_7 = gdb.Style('new-style-1')" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: style 'new-style-1' missing 'background' component\\." \
+ "Error occurred in Python: style 'new-style-1' missing 'background' component\\."] \
+ "try to create style for new-style-1"
+
+# Trying to create a style for 'new-style-2' should fail.
+gdb_test "python my_style_8 = gdb.Style('new-style-2')" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: style 'new-style-2' missing 'foreground' component\\." \
+ "Error occurred in Python: style 'new-style-2' missing 'foreground' component\\."] \
+ "try to create style for new-style-2"
+
+# Trying to create a style for 'new-style-3' should succeed.
+gdb_test_no_output "python my_style_9 = gdb.Style('new-style-3')" \
+ "create a style for new-style-3"
+gdb_test "python print(my_style_9)" \
+ "^<gdb.Style name='new-style-3', fg=none, bg=none, intensity=normal>" \
+ "print my_style_9"
+
+# Trying to create a style for 'new-style-4' should succeed too.
+gdb_test_no_output "python my_style_10 = gdb.Style('new-style-4')" \
+ "create a style for new-style-4"
+gdb_test "python print(my_style_10)" \
+ "^<gdb.Style name='new-style-4', fg=none, bg=none, intensity=normal>" \
+ "print my_style_10"
+
+# Adjust the settings directly, and check the gdb.Style updates.
+gdb_test_no_output "set style new-style-4 intensity bold"
+gdb_test_no_output "set style new-style-4 foreground red"
+gdb_test_no_output "set style new-style-4 background blue"
+gdb_test "python print(my_style_10)" \
+ "^<gdb.Style name='new-style-4', fg=red, bg=blue, intensity=bold>" \
+ "print my_style_10, intensity updated"
+
+# Check the reference counting on 'gdb.Style.apply' when global styling is disabled.
+gdb_test_no_output "python input_text = \"this is a unique string that is unlikely to appear elsewhere 12345\"" \
+ "setup an input string"
+gdb_test_no_output "with style enabled off -- python output_text = filename_style.apply(input_text)" \
+ "create an ouput string by applying filename_style"
+gdb_test_no_output "python input_text = \"a totally different string that is also, hopefully, unique\"" \
+ "replace the input string"
+gdb_test "python print(output_text)" \
+ "^this is a unique string that is unlikely to appear elsewhere 12345" \
+ "check the output_text is still valid"
+
+# Test gdb.write passing in a style. Define a helper function to
+# ensure all output is flushed before we return to the prompt.
+gdb_test_multiline "create function to call gdb.write then flush" \
+ "python" "" \
+ "def write_and_flush(*args, **kwargs):" "" \
+ " gdb.write(*args, **kwargs)" "" \
+ " gdb.write(\"\\n\")" "" \
+ " gdb.flush(gdb.STDOUT)" "" \
+ "end" ""
+
+gdb_test "python write_and_flush(\"some text\")" \
+ "^some text" "unstyled text, no style passed"
+
+gdb_test "python write_and_flush(\"some text\", style=None)" \
+ "^some text" "unstyled text, pass style as None"
+
+gdb_test "python write_and_flush(\"some text\", style=filename_style)" \
+ "^\033\\\[34;41;2;23;24;27msome text\033\\\[m" \
+ "styled output, pass style by keyword"
+
+gdb_test "python write_and_flush(\"some text\", gdb.STDOUT, filename_style)" \
+ "^\033\\\[34;41;2;23;24;27msome text\033\\\[m" \
+ "styled output, pass style by position"
+
+gdb_test "python write_and_flush(\"some text\", style='filename')" \
+ [multi_line \
+ "Python Exception <class 'TypeError'>: 'style' argument must be gdb\\.Style or None, not str\\." \
+ "Error occurred in Python: 'style' argument must be gdb\\.Style or None, not str\\."]
diff --git a/gdb/testsuite/gdb.python/py-styled-execute.exp b/gdb/testsuite/gdb.python/py-styled-execute.exp
index 0b27c63..198dab5 100644
--- a/gdb/testsuite/gdb.python/py-styled-execute.exp
+++ b/gdb/testsuite/gdb.python/py-styled-execute.exp
@@ -17,6 +17,7 @@
# on the value of the third argument passed to gdb.execute.
require allow_python_tests
+require {!is_remote host}
load_lib gdb-python.exp
diff --git a/gdb/testsuite/gdb.python/py-sym-artificial.exp b/gdb/testsuite/gdb.python/py-sym-artificial.exp
index e26e9d2..831ebd2 100644
--- a/gdb/testsuite/gdb.python/py-sym-artificial.exp
+++ b/gdb/testsuite/gdb.python/py-sym-artificial.exp
@@ -27,21 +27,21 @@ set asm_file [standard_output_file ${srcfile2}]
Dwarf::assemble $asm_file {
cu {} {
compile_unit {
- {language @DW_LANG_C}
- {name py-sym-artificial.c}
+ DW_AT_language @DW_LANG_C
+ DW_AT_name py-sym-artificial.c
} {
declare_labels signed
signed: DW_TAG_base_type {
- {DW_AT_byte_size 1 DW_FORM_sdata}
- {DW_AT_encoding @DW_ATE_signed}
- {DW_AT_name bool}
+ DW_AT_byte_size 1 DW_FORM_sdata
+ DW_AT_encoding @DW_ATE_signed
+ DW_AT_name bool
}
DW_TAG_variable {
- {name the_variable}
- {DW_AT_type :$signed}
- {artificial 1 DW_FORM_flag_present}
+ DW_AT_name the_variable
+ DW_AT_type :$signed
+ DW_AT_artificial 1 DW_FORM_flag_present
}
}
}
diff --git a/gdb/testsuite/gdb.python/py-symbol.exp b/gdb/testsuite/gdb.python/py-symbol.exp
index 55cdebe..6f0fcee 100644
--- a/gdb/testsuite/gdb.python/py-symbol.exp
+++ b/gdb/testsuite/gdb.python/py-symbol.exp
@@ -44,7 +44,7 @@ if {!$readnow_p} {
}
# Restart so we don't have expanded symtabs after the previous test.
-clean_restart ${binfile}
+clean_restart ${::testfile}
# Test looking up a global symbol before we runto_main as this is the
# point where we don't have a current frame, and we don't want to
@@ -70,37 +70,14 @@ gdb_test "python print (gdb.lookup_global_symbol('qq').needs_frame)" \
"print whether qq needs a frame"
# Similarly, test looking up a static symbol before we runto_main.
-set rr_line [gdb_get_line_number "line of rr"]
-set rr_line_alt [gdb_get_line_number "line of other rr" py-symbol-2.c]
gdb_test "python print (gdb.lookup_global_symbol ('qqrr') is None)" "True" \
"lookup_global_symbol for static var"
-set cmd "python print (gdb.lookup_static_symbol ('rr').line)"
-gdb_test_multiple $cmd "print line number of rr" {
- -re -wrap "$rr_line" {
- pass $gdb_test_name
- }
- -re -wrap "$rr_line_alt" {
- if { $readnow_p } {
- setup_kfail "symtab/25857" *-*-*
- }
- fail $gdb_test_name
- }
-}
-
-set cmd "python print (gdb.lookup_static_symbol ('rr').value ())"
-gdb_test_multiple $cmd "print value of rr" {
- -re -wrap "42" {
- pass $gdb_test_name
- }
- -re -wrap "99" {
- if { $readnow_p } {
- setup_kfail "symtab/25857" *-*-*
- }
- fail $gdb_test_name
- }
-}
-
+# Either "rr" static symbol is a valid result.
+set rr_line_1 [gdb_get_line_number "line of rr"]
+set rr_line_2 [gdb_get_line_number "line of other rr" py-symbol-2.c]
+gdb_test "python print (gdb.lookup_static_symbol ('rr').line)" "($rr_line_1|$rr_line_2)"
+gdb_test "python print (gdb.lookup_static_symbol ('rr').value ())" "(42|99)"
gdb_test "python print (gdb.lookup_static_symbol ('rr').needs_frame)" \
"False" \
@@ -215,8 +192,10 @@ gdb_test "python print (t\[0\].symtab)" "${py_symbol_c}" "get symtab"
# C++ tests
# Recompile binary.
lappend opts c++
-if {[prepare_for_testing "failed to prepare" "${binfile}-cxx" \
- [list $srcfile $srcfile2] $opts]} {
+set testfile $testfile-cxx
+set binfile [standard_output_file $testfile]
+if { [prepare_for_testing "failed to prepare" $testfile \
+ [list $srcfile $srcfile2] $opts] } {
return -1
}
@@ -252,7 +231,7 @@ gdb_test "python print (cplusfunc.addr_class == gdb.SYMBOL_LOC_BLOCK)" "True" "t
# Test is_valid when the objfile is unloaded. This must be the last
# test as it unloads the object file in GDB.
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
}
diff --git a/gdb/testsuite/gdb.python/py-template.exp b/gdb/testsuite/gdb.python/py-template.exp
index a0f9d80..251b478 100644
--- a/gdb/testsuite/gdb.python/py-template.exp
+++ b/gdb/testsuite/gdb.python/py-template.exp
@@ -31,7 +31,7 @@ proc test_template_arg {exefile type} {
global testfile srcdir subdir srcfile
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${exefile}" \
executable \
- [list debug c++ additional_flags="-DTYPE=$type"]] != "" } {
+ [list debug c++ additional_flags="-DTYPE=$type"]] != "" } {
untested $type
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-thread-exited.exp b/gdb/testsuite/gdb.python/py-thread-exited.exp
index dcacb11..0f47ce0 100644
--- a/gdb/testsuite/gdb.python/py-thread-exited.exp
+++ b/gdb/testsuite/gdb.python/py-thread-exited.exp
@@ -32,7 +32,7 @@ gdb_test_no_output "source ${pyfile}" "load python file"
gdb_test "test-events" "Event testers registered."
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-thread-exited.py b/gdb/testsuite/gdb.python/py-thread-exited.py
index ef5a244..f725bd5 100644
--- a/gdb/testsuite/gdb.python/py-thread-exited.py
+++ b/gdb/testsuite/gdb.python/py-thread-exited.py
@@ -26,6 +26,8 @@ def thread_exited_handler(event):
global threadOneExit, threadTwoExit, mainThreadExit
print("{}".format(event))
assert isinstance(event, gdb.ThreadExitedEvent)
+ # Also check the inheritance.
+ assert isinstance(event, gdb.ThreadEvent)
if threadOneExit == "":
threadOneExit = "event type: thread-exited. global num: {}".format(
event.inferior_thread.global_num
diff --git a/gdb/testsuite/gdb.python/py-thrhandle.exp b/gdb/testsuite/gdb.python/py-thrhandle.exp
index 343bf4b..599473c 100644
--- a/gdb/testsuite/gdb.python/py-thrhandle.exp
+++ b/gdb/testsuite/gdb.python/py-thrhandle.exp
@@ -29,17 +29,17 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
runto_main
gdb_test "break after_mc_barrier" \
"Breakpoint 2 at .*: file .*${srcfile}, line .*" \
- "breakpoint on after_mc_barrier"
+ "breakpoint on after_mc_barrier"
gdb_test "break do_something" \
"Breakpoint 3 at .*: file .*${srcfile}, line .*" \
- "breakpoint on do_something"
+ "breakpoint on do_something"
gdb_test "continue" \
"Breakpoint 2, after_mc_barrier .*" \
@@ -90,19 +90,19 @@ gdb_test "python print(gdb.selected_inferior().thread_from_handle(gdb.parse_and_
# We should see an exception when passing an object of the wrong type.
gdb_test "python print(gdb.selected_inferior().thread_from_handle(gdb.lookup_symbol('main')))" \
- ".*TypeError.*: Argument 'handle' must be a thread handle object.*" \
+ ".*TypeError.*: Argument 'handle' must be a thread handle object.*" \
"TypeError when passing a symbol object to thread_from_handle"
# We should see an exception when passing too large of an object.
gdb_test "python print(gdb.selected_inferior().thread_from_handle(gdb.parse_and_eval('thrs')))" \
- ".*Thread handle size mismatch.*" \
+ ".*Thread handle size mismatch.*" \
"Pass overly large object to thread_from_handle"
# We should see an exception when passing too small of an object.
gdb_test "python print(gdb.selected_inferior().thread_from_handle(gdb.parse_and_eval('\"S\"')))" \
- ".*Thread handle size mismatch.*" \
+ ".*Thread handle size mismatch.*" \
"Pass too small of an object to thread_from_handle"
# Test the thread_handle method
@@ -134,8 +134,8 @@ foreach thrN {0 1 2} {
# object into a gdb.value by calling the two argument form of
# its constructor.
- gdb_test "python print(gdb.Value(hand_bytes, tp) == hand)" \
- "True" \
- "verify that handles are the same"
+ gdb_test "python print(gdb.Value(hand_bytes, tp) == hand)" \
+ "True" \
+ "verify that handles are the same"
}
}
diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp
index 0bc4556..4cef150 100644
--- a/gdb/testsuite/gdb.python/py-type.exp
+++ b/gdb/testsuite/gdb.python/py-type.exp
@@ -33,8 +33,9 @@ proc build_inferior {exefile lang} {
}
# Restart GDB.
-proc restart_gdb {exefile} {
- clean_restart $exefile
+proc restart_gdb {exefile} {
+ clean_restart
+ gdb_load $exefile
if {![runto_main]} {
return
@@ -53,7 +54,7 @@ proc test_fields {lang} {
# .fields() of a typedef should still return the underlying field list
gdb_test "python print (len(gdb.parse_and_eval('ts').type.fields()))" "2" \
- "$lang typedef field list"
+ "$lang typedef field list"
if {$lang == "c++"} {
# Test usage with a class
@@ -134,7 +135,7 @@ proc test_fields {lang} {
# Test conversion to bool on scalar types
gdb_test "python print (not not st.type\['a'\].type)" "True"
-
+
# Test regression PR python/10805
gdb_py_test_silent_cmd "print (ar)" "print value(ar)" 1
gdb_py_test_silent_cmd "python ar = gdb.history (0)" "get value (ar) from history" 1
@@ -144,9 +145,9 @@ proc test_fields {lang} {
# Test gdb.Type.array.
gdb_test "python print (ar\[0\].cast(ar\[0\].type.array(1)))" \
- ".1, 2." "cast to array with one argument"
+ ".1, 2." "cast to array with one argument"
gdb_test "python print (ar\[0\].cast(ar\[0\].type.array(0, 1)))" \
- ".1, 2." "cast to array with two arguments"
+ ".1, 2." "cast to array with two arguments"
gdb_test "python print (ar\[0\].type == ar\[0\].type)" "True"
@@ -253,9 +254,9 @@ proc test_template {} {
|| [test_compiler_info {gcc-4-[0-4]-*}]} {
set have_older_gcc 1
}
- if $have_older_gcc { setup_xfail *-*-* }
+ if {$have_older_gcc} { setup_xfail *-*-* }
gdb_test "python print (ttype.template_argument(1))" "23"
- if $have_older_gcc { setup_xfail *-*-* }
+ if {$have_older_gcc} { setup_xfail *-*-* }
gdb_test "python print (isinstance(ttype.template_argument(1), gdb.Value))" \
"True"
@@ -391,6 +392,12 @@ if { [build_inferior "${binfile}" "c"] == 0 } {
test_type_equality
test_type_identity
}
+
+ gdb_test "python print(gdb.lookup_type('int').const().volatile())" \
+ "const volatile int"
+ gdb_test "python print(gdb.lookup_type('int').volatile().const())" \
+ "const volatile int" \
+ "volatile const int"
}
# Perform C++ Tests.
diff --git a/gdb/testsuite/gdb.python/py-typeprint.py b/gdb/testsuite/gdb.python/py-typeprint.py
index dc13210..208b368 100644
--- a/gdb/testsuite/gdb.python/py-typeprint.py
+++ b/gdb/testsuite/gdb.python/py-typeprint.py
@@ -14,6 +14,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import gdb
+import gdb.types
class StringRecognizer(object):
@@ -57,6 +58,4 @@ class OtherTypePrinter(object):
return OtherRecognizer()
-import gdb.types
-
gdb.types.register_type_printer(gdb.objfiles()[0], OtherTypePrinter())
diff --git a/gdb/testsuite/gdb.python/py-unwind-inline.exp b/gdb/testsuite/gdb.python/py-unwind-inline.exp
index 74d4ead..b0b06b2 100644
--- a/gdb/testsuite/gdb.python/py-unwind-inline.exp
+++ b/gdb/testsuite/gdb.python/py-unwind-inline.exp
@@ -37,7 +37,7 @@ set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
gdb_breakpoint "foo"
gdb_test "source ${pyfile}" "Python script imported" \
- "import python scripts"
+ "import python scripts"
gdb_continue_to_breakpoint "foo"
diff --git a/gdb/testsuite/gdb.python/py-unwind-inline.py b/gdb/testsuite/gdb.python/py-unwind-inline.py
index ca6b16e..95310b7 100644
--- a/gdb/testsuite/gdb.python/py-unwind-inline.py
+++ b/gdb/testsuite/gdb.python/py-unwind-inline.py
@@ -58,8 +58,8 @@ class dummy_unwinder(Unwinder):
to see if the unwinder should claim it, which is never does."""
try:
for r in self.get_regs(pending_frame):
- v = pending_frame.read_register(r).cast(self.void_ptr_t)
- except:
+ pending_frame.read_register(r).cast(self.void_ptr_t)
+ except Exception:
print("Dummy unwinder, exception")
raise
diff --git a/gdb/testsuite/gdb.python/py-unwind-maint.py b/gdb/testsuite/gdb.python/py-unwind-maint.py
index 4a109d5..b6b621b 100644
--- a/gdb/testsuite/gdb.python/py-unwind-maint.py
+++ b/gdb/testsuite/gdb.python/py-unwind-maint.py
@@ -15,10 +15,8 @@
# This file is part of the GDB testsuite. It tests python unwinders.
-import re
-
import gdb.types
-from gdb.unwinder import Unwinder, register_unwinder
+from gdb.unwinder import Unwinder
class TestGlobalUnwinder(Unwinder):
diff --git a/gdb/testsuite/gdb.python/py-unwind.c b/gdb/testsuite/gdb.python/py-unwind.c
index f785c5e..318458f 100644
--- a/gdb/testsuite/gdb.python/py-unwind.c
+++ b/gdb/testsuite/gdb.python/py-unwind.c
@@ -33,8 +33,8 @@ static void
bad_layout(void **variable_ptr, void *fp)
{
fprintf (stderr, "First variable should be allocated one word below "
- "the frame. Got variable's address %p, frame at %p instead.\n",
- variable_ptr, fp);
+ "the frame. Got variable's address %p, frame at %p instead.\n",
+ variable_ptr, fp);
abort();
}
diff --git a/gdb/testsuite/gdb.python/py-unwind.exp b/gdb/testsuite/gdb.python/py-unwind.exp
index 80eac28..b416c2f 100644
--- a/gdb/testsuite/gdb.python/py-unwind.exp
+++ b/gdb/testsuite/gdb.python/py-unwind.exp
@@ -245,6 +245,13 @@ with_test_prefix "frame-id 'pc' is invalid" {
"Python Exception <class 'ValueError'>: invalid literal for int\\(\\) with base 10: 'xyz'\r\n.*"
}
+with_test_prefix "bad object unwinder" {
+ gdb_test_no_output "python obj = bad_object_unwinder(\"bad-object\")"
+ gdb_test_no_output "python gdb.unwinder.register_unwinder(None, obj, replace=True)"
+ gdb_test "backtrace" \
+ "Python Exception <class 'gdb.error'>: an Unwinder should return gdb.UnwindInfo, not Blah\\.\r\n.*"
+}
+
# Gather information about every frame.
gdb_test_no_output "python capture_all_frame_information()"
gdb_test_no_output "python gdb.newest_frame().select()"
diff --git a/gdb/testsuite/gdb.python/py-unwind.py b/gdb/testsuite/gdb.python/py-unwind.py
index 8e65a1a..50c6d55 100644
--- a/gdb/testsuite/gdb.python/py-unwind.py
+++ b/gdb/testsuite/gdb.python/py-unwind.py
@@ -106,7 +106,6 @@ class TestUnwinder(Unwinder):
unwind_info.add_saved_register(value=previous_ip, register="rip")
unwind_info.add_saved_register(register="rsp", value=previous_sp)
- global add_saved_register_errors
try:
unwind_info.add_saved_register("nosuchregister", previous_sp)
except ValueError as ve:
@@ -230,7 +229,6 @@ def capture_all_frame_information():
# Assert that every entry in the global ALL_FRAME_INFORMATION list was
# matched by the validating_unwinder.
def check_all_frame_information_matched():
- global all_frame_information
for entry in all_frame_information:
assert entry["matched"]
@@ -245,8 +243,6 @@ class validating_unwinder(Unwinder):
def __call__(self, pending_frame):
info = capture_frame_information(pending_frame)
level = info["level"]
-
- global all_frame_information
old_info = all_frame_information[level]
assert old_info is not None
@@ -254,7 +250,7 @@ class validating_unwinder(Unwinder):
for key, value in info.items():
assert key in old_info, key + " not in old_info"
- assert type(value) == type(old_info[key])
+ assert type(value) is type(old_info[key])
if isinstance(value, gdb.Block):
assert value.start == old_info[key].start
assert value.end == old_info[key].end
@@ -267,4 +263,24 @@ class validating_unwinder(Unwinder):
return None
+class bad_object_unwinder(Unwinder):
+ def __init__(self, name):
+ super().__init__(name)
+
+ def __call__(self, pending_frame):
+
+ if pending_frame.level() != 1:
+ return None
+
+ class Blah:
+ def __init__(self):
+ pass
+
+ @property
+ def __class__(self):
+ raise RuntimeError("error in Blah.__class__")
+
+ return Blah()
+
+
print("Python script imported")
diff --git a/gdb/testsuite/gdb.python/py-value-cc.exp b/gdb/testsuite/gdb.python/py-value-cc.exp
index 3d371bc..6d261fb 100644
--- a/gdb/testsuite/gdb.python/py-value-cc.exp
+++ b/gdb/testsuite/gdb.python/py-value-cc.exp
@@ -24,7 +24,7 @@ if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-value.c b/gdb/testsuite/gdb.python/py-value.c
index a822346..f6dbf55 100644
--- a/gdb/testsuite/gdb.python/py-value.c
+++ b/gdb/testsuite/gdb.python/py-value.c
@@ -19,6 +19,14 @@
#include <stdlib.h>
#include <string.h>
+int long_array[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49
+};
+
struct s
{
int a;
@@ -60,6 +68,7 @@ struct Derived : public Base {
Base *base = new Derived ();
Derived derived;
Base &base_ref = derived;
+struct str pod;
void ptr_ref(int*& rptr_int)
{
diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp
index 93985a9..ffc4b7c 100644
--- a/gdb/testsuite/gdb.python/py-value.exp
+++ b/gdb/testsuite/gdb.python/py-value.exp
@@ -297,9 +297,9 @@ proc test_value_in_inferior {} {
gdb_test "print argc" " = $argc_value" "sanity check argc"
gdb_test "python print (argc_lazy.is_lazy)" "\r\nTrue" \
"python print (argc_lazy.is_lazy) the second time"
- gdb_test_no_output "set argc=[expr $argc_value + 1]" "change argc"
+ gdb_test_no_output "set argc=[expr {$argc_value + 1}]" "change argc"
gdb_test "python print (argc_notlazy)" "\r\n$argc_value"
- gdb_test "python print (argc_lazy)" "\r\n[expr $argc_value + 1]"
+ gdb_test "python print (argc_lazy)" "\r\n[expr {$argc_value + 1}]"
gdb_test "python print (argc_lazy.is_lazy)" "False"
# Test string fetches, both partial and whole.
@@ -431,7 +431,8 @@ proc test_value_after_death {} {
proc test_subscript_regression {exefile lang} {
# Start with a fresh gdb.
- clean_restart ${exefile}
+ clean_restart
+ gdb_load $exefile
if {![runto_main]} {
return
@@ -457,6 +458,8 @@ proc test_subscript_regression {exefile lang} {
"Derived \[*\]"
gdb_test "python print (gdb.parse_and_eval('base_ref').dynamic_type)" \
"Derived \[&\]"
+ gdb_test "python print (gdb.parse_and_eval('pod').dynamic_type)" \
+ "str"
# A static type case.
gdb_test "python print (gdb.parse_and_eval('5').dynamic_type)" \
"int"
@@ -541,13 +544,13 @@ proc test_float_conversion {} {
proc prepare_type_and_buffer {} {
gdb_py_test_silent_cmd "python tp=gdb.lookup_type('int')" "look up int type" 0
gdb_py_test_silent_cmd "python size_a=gdb.parse_and_eval('sizeof(a)')" \
- "find size of a" 0
+ "find size of a" 0
gdb_py_test_silent_cmd "python size_a0=gdb.parse_and_eval('sizeof(a\[0\])')" \
- "find size of element of a" 0
+ "find size of element of a" 0
gdb_py_test_silent_cmd "python addr=gdb.parse_and_eval('&a')" \
- "find address of a" 0
+ "find address of a" 0
gdb_py_test_silent_cmd "python b=gdb.selected_inferior().read_memory(addr,size_a)" \
- "read buffer from memory" 0
+ "read buffer from memory" 0
}
proc test_value_from_buffer {} {
@@ -567,23 +570,23 @@ proc test_value_from_buffer {} {
prepare_type_and_buffer
gdb_test "python v=gdb.Value(b,tp); print(v)" "1" \
- "construct value from buffer"
+ "construct value from buffer"
gdb_test_no_output { python compare_value_bytes_to_mem(v, addr, size_a0) }
gdb_test "python v=gdb.Value(b\[size_a0:\],tp); print(v)" "2" \
- "convert 2nd elem of buffer to value"
+ "convert 2nd elem of buffer to value"
gdb_test_no_output \
{ python compare_value_bytes_to_mem(v, (int(addr) + size_a0), size_a0) }
gdb_test "python v=gdb.Value(b\[2*size_a0:\],tp); print(v)" "3" \
- "convert 3rd elem of buffer to value"
+ "convert 3rd elem of buffer to value"
gdb_test_no_output \
{ python compare_value_bytes_to_mem(v, (int(addr) + (2 * size_a0)), size_a0) }
gdb_test "python v=gdb.Value(b\[2*size_a0+1:\],tp); print(v)" \
- "ValueError.*: Size of type is larger than that of buffer object\..*" \
+ "ValueError.*: Size of type is larger than that of buffer object\..*" \
"attempt to convert smaller buffer than size of type"
gdb_py_test_silent_cmd "python atp=tp.array(2) ; print(atp)" \
- "make array type" 0
+ "make array type" 0
gdb_py_test_silent_cmd "python va=gdb.Value(b,atp)" \
- "construct array value from buffer" 0
+ "construct array value from buffer" 0
gdb_test_no_output \
{ python compare_value_bytes_to_mem(va, addr, size_a0 * 3) }
gdb_test "python print(va)" "\\{1, 2, 3\\}" "print array value"
@@ -591,16 +594,16 @@ proc test_value_from_buffer {} {
gdb_test "python print(va\[1\])" "2" "print second array element"
gdb_test "python print(va\[2\])" "3" "print third array element"
gdb_test "python print(va\[3\])" "gdb\.error.*: no such vector element.*" \
- "print out of bounds array element"
+ "print out of bounds array element"
gdb_py_test_silent_cmd "python atpbig=tp.array(3)" "make bigger array type" 0
gdb_test "python vabig=gdb.Value(b,atpbig)" \
- "ValueError.*: Size of type is larger than that of buffer object\..*" \
- "attempt to construct large value with small buffer"
+ "ValueError.*: Size of type is larger than that of buffer object\..*" \
+ "attempt to construct large value with small buffer"
gdb_test "python v=gdb.Value(2048,tp)" \
- "TypeError.*: Object must support the python buffer protocol\..*" \
- "attempt to construct value from buffer with non-buffer object"
+ "TypeError.*: Object must support the python buffer protocol\..*" \
+ "attempt to construct value from buffer with non-buffer object"
gdb_test "python v=gdb.Value(b,'int'); print(v)" \
- "TypeError.*: type argument must be a gdb\.Type\..*" \
+ "TypeError.*: type argument must be a gdb\.Type\..*" \
"attempt to construct value with string as type"
}
@@ -680,6 +683,7 @@ proc_with_prefix test_value_bytes { } {
"python" "" \
"def check_value_bytes(var_name):" "" \
" val = gdb.parse_and_eval(var_name)" "" \
+ " assert not val.is_unavailable" "" \
" addr = val.address" "" \
" len = val.type.sizeof" "" \
" mem = gdb.selected_inferior().read_memory(addr, len)" "" \
@@ -762,13 +766,45 @@ proc test_assign {} {
"cannot assign to integer"
}
+# Test Value.is_unavailable
+proc test_unavailable {} {
+ set elem_size [get_valueof "/d" "sizeof(long_array\[0\])" "UNKNOWN" \
+ "get size of long_array element"]
+ set max [expr {$elem_size * 10}]
+
+ with_set "print elements" 5 {
+ with_max_value_size $max {
+ gdb_test "p long_array"
+
+ gdb_test_no_output "set print elements 15"
+
+ gdb_test_no_output "python v = gdb.history(0)"
+
+ gdb_test "python print(v.is_unavailable)" "^True" \
+ "overall object shows as unavailable"
+ for { set i 0 } { $i < 10 } { incr i } {
+ gdb_test "python print(v\[$i\].is_unavailable)" "^False" \
+ "array element $i is available"
+ gdb_test "python print(v\[$i\])" "^$i" \
+ "array element $i has correct value"
+ }
+ for { set i 10 } { $i < 15 } { incr i } {
+ gdb_test "python print(v\[$i\].is_unavailable)" "^True" \
+ "array element $i is unavailable"
+ gdb_test "python print(v\[$i\])" "^<unavailable>" \
+ "array element $i shows as unavailable"
+ }
+ }
+ }
+}
+
# Build C version of executable. C++ is built later.
if { [build_inferior "${binfile}" "c"] < 0 } {
return -1
}
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart ${::testfile}
test_history_count
test_value_creation
@@ -788,6 +824,7 @@ if {![runto_main]} {
return 0
}
+test_unavailable
test_value_in_inferior
test_value_from_buffer
test_value_sub_classes
@@ -797,7 +834,7 @@ test_assign
test_value_bytes
test_value_after_death
-# Test either C or C++ values.
+# Test either C or C++ values.
test_subscript_regression "${binfile}" "c"
@@ -809,3 +846,15 @@ if {[allow_cplus_tests]} {
test_subscript_regression "${binfile}-cxx" "c++"
}
}
+
+if {[allow_rust_tests]} {
+ gdb_test "set lang rust"
+
+ set cst 0x80000000000000000000000000000000
+ gdb_test "python print(int(gdb.parse_and_eval('${cst}u128')))" \
+ "170141183460469231731687303715884105728" \
+ "convert 128 bit unsigned constant to python int"
+ gdb_test "python print(int(gdb.parse_and_eval('${cst}i128')))" \
+ "-170141183460469231731687303715884105728" \
+ "convert 128 bit signed constant to python int"
+}
diff --git a/gdb/testsuite/gdb.python/py-varobj.exp b/gdb/testsuite/gdb.python/py-varobj.exp
index 7fb45f9..cf6a662 100644
--- a/gdb/testsuite/gdb.python/py-varobj.exp
+++ b/gdb/testsuite/gdb.python/py-varobj.exp
@@ -25,7 +25,7 @@ if {[gdb_compile "$srcdir/$subdir/$srcfile" $binfile executable {debug}] != ""}
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
mi_gdb_test "source ${pyfile}" \
diff --git a/gdb/testsuite/gdb.python/py-warning.exp b/gdb/testsuite/gdb.python/py-warning.exp
new file mode 100644
index 0000000..6b26a4e
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-warning.exp
@@ -0,0 +1,63 @@
+# Copyright (C) 2025 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/>.
+
+# Test the gdb.warning() function.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+
+clean_restart
+
+# Basic usage.
+gdb_test "python gdb.warning(\"some text\")" \
+ "warning: some text"
+
+# Basic usage with named argument.
+gdb_test "python gdb.warning(text=\"a warning message\")" \
+ "warning: a warning message"
+
+# Make sure GDB prints format specifiers correctly.
+gdb_test "python gdb.warning(\"%s %d %p\")" \
+ "warning: %s %d %p"
+
+# Empty string gives an error.
+gdb_test "python gdb.warning(\"\")" \
+ [multi_line \
+ "Python Exception <class 'ValueError'>: Empty text string passed to gdb\\.warning" \
+ "Error occurred in Python: Empty text string passed to gdb\\.warning"]
+
+# Missing argument gives an error.
+set re1 \
+ [multi_line \
+ [string_to_regexp \
+ [concat \
+ "Python Exception <class 'TypeError'>:" \
+ "function missing required argument 'text' (pos 1)"]] \
+ [string_to_regexp \
+ [concat \
+ "Error occurred in Python:" \
+ "function missing required argument 'text' (pos 1)"]]]
+set re2 \
+ [multi_line \
+ [string_to_regexp \
+ [concat \
+ "Python Exception <class 'TypeError'>:" \
+ "Required argument 'text' (pos 1) not found"]] \
+ [string_to_regexp \
+ [concat \
+ "Error occurred in Python:" \
+ "Required argument 'text' (pos 1) not found"]]]
+gdb_test "python gdb.warning()" $re1|$re2
diff --git a/gdb/testsuite/gdb.python/py-watchpoint.py b/gdb/testsuite/gdb.python/py-watchpoint.py
index d25826f..9d1ea5e 100644
--- a/gdb/testsuite/gdb.python/py-watchpoint.py
+++ b/gdb/testsuite/gdb.python/py-watchpoint.py
@@ -14,6 +14,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import gdb
+
+
class MyBreakpoint(gdb.Breakpoint):
def __init__(self):
super().__init__("i", gdb.BP_WATCHPOINT)
diff --git a/gdb/testsuite/gdb.python/py-xmethods.exp b/gdb/testsuite/gdb.python/py-xmethods.exp
index 3dafe0e..5863ec5 100644
--- a/gdb/testsuite/gdb.python/py-xmethods.exp
+++ b/gdb/testsuite/gdb.python/py-xmethods.exp
@@ -26,7 +26,7 @@ if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} {
return -1
}
-if ![runto_main] {
+if {![runto_main]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp
index 6b2f671..020fc66 100644
--- a/gdb/testsuite/gdb.python/python.exp
+++ b/gdb/testsuite/gdb.python/python.exp
@@ -152,29 +152,17 @@ gdb_test_no_output "set height $lines"
set test "verify pagination beforehand"
gdb_test_multiple "python print (\"\\n\" * $lines)" $test {
- -re "--Type <RET>" {
- exp_continue
- }
- -re " for more, q to quit" {
- exp_continue
- }
- -re ", c to continue without paging--$" {
+ -re "$pagination_prompt$" {
pass $test
}
}
gdb_test "q" "Quit.*" "verify pagination beforehand: q"
-gdb_test "python if gdb.execute('python print (\"\\\\n\" * $lines)', to_string=True) == \"\\n\" * [expr $lines + 1]: print (\"yes\")" "yes" "gdb.execute does not page"
+gdb_test "python if gdb.execute('python print (\"\\\\n\" * $lines)', to_string=True) == \"\\n\" * [expr {$lines + 1}]: print (\"yes\")" "yes" "gdb.execute does not page"
set test "verify pagination afterwards"
gdb_test_multiple "python print (\"\\n\" * $lines)" $test {
- -re "--Type <RET>" {
- exp_continue
- }
- -re " for more, q to quit" {
- exp_continue
- }
- -re ", c to continue without paging--$" {
+ -re "$pagination_prompt$" {
pass $test
}
}
@@ -300,7 +288,7 @@ gdb_test "python gdb.write(\"Foo\\n\")" "Foo" "test default write"
gdb_test "python gdb.write(\"Error stream\\n\", stream=gdb.STDERR)" "Error stream" "test stderr write"
gdb_test "python gdb.write(\"Normal stream\\n\", stream=gdb.STDOUT)" "Normal stream" "test stdout write"
-if ![gdb_debug_enabled] {
+if {![gdb_debug_enabled]} {
gdb_test "python gdb.write(\"Log stream\\n\", stream=gdb.STDLOG)" "Log stream" "test stdlog write"
}
diff --git a/gdb/testsuite/gdb.python/source2.py b/gdb/testsuite/gdb.python/source2.py
index 7ca0bb2..59ac6f6 100644
--- a/gdb/testsuite/gdb.python/source2.py
+++ b/gdb/testsuite/gdb.python/source2.py
@@ -16,6 +16,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Make sure __file__ is defined.
-assert type(__file__) == str
+assert type(__file__) is str
print("y%ss" % "e")
diff --git a/gdb/testsuite/gdb.python/tui-window-disabled.py b/gdb/testsuite/gdb.python/tui-window-disabled.py
index 8d140c4..e7195ea 100644
--- a/gdb/testsuite/gdb.python/tui-window-disabled.py
+++ b/gdb/testsuite/gdb.python/tui-window-disabled.py
@@ -46,9 +46,6 @@ class EventWindow:
self._win.write("Hello world...")
def close(self):
- global cleanup_properly
- global titles_at_the_close
-
# Ensure that window properties can be read within the close method.
titles_at_the_close[self._win.title] = dict(
width=self._win.width, height=self._win.height
@@ -70,9 +67,6 @@ class EventWindow:
self._exit_listener = None
def _event(self, type, event):
- global perform_valid_check
- global update_title
-
self._count += 1
self._events.insert(0, type)
if not perform_valid_check or self._win.is_valid():
@@ -83,7 +77,6 @@ class EventWindow:
def render(self):
self._win.erase()
- w = self._win.width
h = self._win.height
for i in range(min(h, len(self._events))):
self._win.write(self._events[i] + "\n")
diff --git a/gdb/testsuite/gdb.python/tui-window-factory.py b/gdb/testsuite/gdb.python/tui-window-factory.py
index 7593214..9ad75f7 100644
--- a/gdb/testsuite/gdb.python/tui-window-factory.py
+++ b/gdb/testsuite/gdb.python/tui-window-factory.py
@@ -14,6 +14,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import gdb
+
+
class TestWindow:
def __init__(self, tui_win, msg):
self.msg = msg