aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/testsuite')
-rw-r--r--gdb/testsuite/boards/cc-with-dwz-5.exp28
-rw-r--r--gdb/testsuite/gdb.ada/scalar_storage.exp28
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c205
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.exp106
-rw-r--r--gdb/testsuite/gdb.base/bg-execution-repeat.c2
-rw-r--r--gdb/testsuite/gdb.base/corefile3.c118
-rw-r--r--gdb/testsuite/gdb.base/corefile3.exp71
-rw-r--r--gdb/testsuite/gdb.base/dlmopen-ns-ids.exp20
-rw-r--r--gdb/testsuite/gdb.base/printcmds.exp7
-rw-r--r--gdb/testsuite/gdb.cp/cplusfuncs.exp3
-rw-r--r--gdb/testsuite/gdb.dwarf2/dwzbuildid.exp159
-rw-r--r--gdb/testsuite/gdb.dwarf2/dwzbuildid.tcl184
-rw-r--r--gdb/testsuite/gdb.dwarf2/dwzbuildid5.exp17
-rw-r--r--gdb/testsuite/gdb.dwarf2/dwznolink.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/fission-with-type-unit.exp4
-rw-r--r--gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp2
-rw-r--r--gdb/testsuite/gdb.python/gdb_leak_detector.py120
-rw-r--r--gdb/testsuite/gdb.python/py-breakpoint.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-color-leak.exp28
-rw-r--r--gdb/testsuite/gdb.python/py-color-leak.py31
-rw-r--r--gdb/testsuite/gdb.python/py-color.exp3
-rw-r--r--gdb/testsuite/gdb.python/py-inferior-leak.exp14
-rw-r--r--gdb/testsuite/gdb.python/py-inferior-leak.py108
-rw-r--r--gdb/testsuite/gdb.python/py-read-memory-leak.exp14
-rw-r--r--gdb/testsuite/gdb.python/py-read-memory-leak.py84
-rw-r--r--gdb/testsuite/gdb.threads/clone-attach-detach.exp2
-rw-r--r--gdb/testsuite/lib/dwarf.exp18
-rw-r--r--gdb/testsuite/lib/gdb-python.exp21
28 files changed, 1039 insertions, 362 deletions
diff --git a/gdb/testsuite/boards/cc-with-dwz-5.exp b/gdb/testsuite/boards/cc-with-dwz-5.exp
new file mode 100644
index 0000000..b254f91
--- /dev/null
+++ b/gdb/testsuite/boards/cc-with-dwz-5.exp
@@ -0,0 +1,28 @@
+# 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/>.
+
+# This file is a dejagnu "board file" and is used to run the testsuite
+# with contrib/cc-with-tweaks.sh -5.
+#
+# NOTE: We assume dwz is in $PATH.
+#
+# Example usage:
+# bash$ cd $objdir
+# bash$ make check-gdb \
+# RUNTESTFLAGS='--target_board=cc-with-dwz-5'
+#
+
+set CC_WITH_TWEAKS_FLAGS "-5"
+load_board_description "cc-with-tweaks"
diff --git a/gdb/testsuite/gdb.ada/scalar_storage.exp b/gdb/testsuite/gdb.ada/scalar_storage.exp
index 6b29226..52a85cd 100644
--- a/gdb/testsuite/gdb.ada/scalar_storage.exp
+++ b/gdb/testsuite/gdb.ada/scalar_storage.exp
@@ -45,10 +45,30 @@ if {![runto "storage.adb:$bp_location"]} {
return
}
-gdb_test "print V_LE" "= \\(value => 126, another_value => 12, color => green\\)"
+set re "value => 126, another_value => 12, color => green"
# This requires a compiler fix that is in GCC 14.
-if { ![gnat_version_compare >= 14] } {
- setup_kfail "DW_AT_endianity on enum types" *-*-*
+set have_xfail [expr ![gnat_version_compare >= 14]]
+set re_color "(red|green|blue|$decimal)"
+set re_xfail \
+ "value => $decimal, another_value => $decimal, color => $re_color"
+
+set re_pre [string_to_regexp " = ("]
+set re_post [string_to_regexp ")"]
+set re $re_pre$re$re_post
+set re_xfail $re_pre$re_xfail$re_post
+
+foreach var { V_LE V_BE } {
+ gdb_test_multiple "print $var" "" {
+ -re -wrap $re {
+ pass $gdb_test_name
+ }
+ -re -wrap $re_xfail {
+ if { $have_xfail } {
+ xfail $gdb_test_name
+ } else {
+ fail $gdb_test_name
+ }
+ }
+ }
}
-gdb_test "print V_BE" "= \\(value => 126, another_value => 12, color => green\\)"
diff --git a/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c b/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c
new file mode 100644
index 0000000..c86beaf
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c
@@ -0,0 +1,205 @@
+/* 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/>. */
+
+/* Exercise unwinding AArch64's SVE registers from a signal frame. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+
+static int second_vl = 0;
+
+static void
+initialize_sve_state_main ()
+{
+ __asm __volatile ("dup z0.b, -1");
+ __asm __volatile ("dup z1.b, -1");
+ __asm __volatile ("dup z2.b, -1");
+ __asm __volatile ("dup z3.b, -1");
+ __asm __volatile ("dup z4.b, -1");
+ __asm __volatile ("dup z5.b, -1");
+ __asm __volatile ("dup z6.b, -1");
+ __asm __volatile ("dup z7.b, -1");
+ __asm __volatile ("dup z8.b, -1");
+ __asm __volatile ("dup z9.b, -1");
+ __asm __volatile ("dup z10.b, -1");
+ __asm __volatile ("dup z11.b, -1");
+ __asm __volatile ("dup z12.b, -1");
+ __asm __volatile ("dup z13.b, -1");
+ __asm __volatile ("dup z14.b, -1");
+ __asm __volatile ("dup z15.b, -1");
+ __asm __volatile ("dup z16.b, -1");
+ __asm __volatile ("dup z17.b, -1");
+ __asm __volatile ("dup z18.b, -1");
+ __asm __volatile ("dup z19.b, -1");
+ __asm __volatile ("dup z20.b, -1");
+ __asm __volatile ("dup z21.b, -1");
+ __asm __volatile ("dup z22.b, -1");
+ __asm __volatile ("dup z23.b, -1");
+ __asm __volatile ("dup z24.b, -1");
+ __asm __volatile ("dup z25.b, -1");
+ __asm __volatile ("dup z26.b, -1");
+ __asm __volatile ("dup z27.b, -1");
+ __asm __volatile ("dup z28.b, -1");
+ __asm __volatile ("dup z29.b, -1");
+ __asm __volatile ("dup z30.b, -1");
+ __asm __volatile ("dup z31.b, -1");
+ __asm __volatile ("ptrue p0.d");
+ __asm __volatile ("ptrue p1.d");
+ __asm __volatile ("ptrue p2.d");
+ __asm __volatile ("ptrue p3.d");
+ __asm __volatile ("ptrue p4.d");
+ __asm __volatile ("ptrue p5.d");
+ __asm __volatile ("ptrue p6.d");
+ __asm __volatile ("ptrue p7.d");
+ __asm __volatile ("ptrue p8.d");
+ __asm __volatile ("ptrue p9.d");
+ __asm __volatile ("ptrue p10.d");
+ __asm __volatile ("ptrue p11.d");
+ __asm __volatile ("ptrue p12.d");
+ __asm __volatile ("ptrue p13.d");
+ __asm __volatile ("ptrue p14.d");
+ __asm __volatile ("ptrue p15.d");
+ __asm __volatile ("setffr");
+}
+
+static void
+initialize_sve_state_sighandler ()
+{
+ __asm __volatile ("dup z0.b, -2");
+ __asm __volatile ("dup z1.b, -2");
+ __asm __volatile ("dup z2.b, -2");
+ __asm __volatile ("dup z3.b, -2");
+ __asm __volatile ("dup z4.b, -2");
+ __asm __volatile ("dup z5.b, -2");
+ __asm __volatile ("dup z6.b, -2");
+ __asm __volatile ("dup z7.b, -2");
+ __asm __volatile ("dup z8.b, -2");
+ __asm __volatile ("dup z9.b, -2");
+ __asm __volatile ("dup z10.b, -2");
+ __asm __volatile ("dup z11.b, -2");
+ __asm __volatile ("dup z12.b, -2");
+ __asm __volatile ("dup z13.b, -2");
+ __asm __volatile ("dup z14.b, -2");
+ __asm __volatile ("dup z15.b, -2");
+ __asm __volatile ("dup z16.b, -2");
+ __asm __volatile ("dup z17.b, -2");
+ __asm __volatile ("dup z18.b, -2");
+ __asm __volatile ("dup z19.b, -2");
+ __asm __volatile ("dup z20.b, -2");
+ __asm __volatile ("dup z21.b, -2");
+ __asm __volatile ("dup z22.b, -2");
+ __asm __volatile ("dup z23.b, -2");
+ __asm __volatile ("dup z24.b, -2");
+ __asm __volatile ("dup z25.b, -2");
+ __asm __volatile ("dup z26.b, -2");
+ __asm __volatile ("dup z27.b, -2");
+ __asm __volatile ("dup z28.b, -2");
+ __asm __volatile ("dup z29.b, -2");
+ __asm __volatile ("dup z30.b, -2");
+ __asm __volatile ("dup z31.b, -2");
+ __asm __volatile ("pfalse p0.b");
+ __asm __volatile ("pfalse p1.b");
+ __asm __volatile ("pfalse p2.b");
+ __asm __volatile ("pfalse p3.b");
+ __asm __volatile ("pfalse p4.b");
+ __asm __volatile ("pfalse p5.b");
+ __asm __volatile ("pfalse p6.b");
+ __asm __volatile ("pfalse p7.b");
+ __asm __volatile ("pfalse p8.b");
+ __asm __volatile ("pfalse p9.b");
+ __asm __volatile ("pfalse p10.b");
+ __asm __volatile ("pfalse p11.b");
+ __asm __volatile ("pfalse p12.b");
+ __asm __volatile ("pfalse p13.b");
+ __asm __volatile ("pfalse p14.b");
+ __asm __volatile ("pfalse p15.b");
+ __asm __volatile ("setffr");
+}
+
+/* Set new value for the SVE vector length.
+ Return the value that was set. */
+
+static int
+set_vl (int vl)
+{
+ int rc;
+
+ rc = prctl (PR_SVE_SET_VL, vl, 0, 0, 0);
+ if (rc < 0)
+ {
+ perror ("FAILED to PR_SVE_SET_VL");
+ exit (EXIT_FAILURE);
+ }
+
+ return rc & PR_SVE_VL_LEN_MASK;
+}
+
+static void
+sighandler (int sig, siginfo_t *info, void *ucontext)
+{
+ /* Set vector length to the second value. */
+ second_vl = set_vl (second_vl);
+ initialize_sve_state_sighandler ();
+ printf ("sighandler: second_vl = %d\n", second_vl); /* Break here. */
+}
+
+int
+main (int argc, char *argv[])
+{
+ if (argc != 3)
+ {
+ fprintf (stderr, "Usage: %s <first vl> <second vl>\n", argv[0]);
+ return 1;
+ }
+
+ int first_vl = atoi (argv[1]);
+ second_vl = atoi (argv[2]);
+
+ if (first_vl == 0 || second_vl == 0)
+ {
+ fprintf (stderr, "Invalid vector length.\n");
+ return 1;
+ }
+
+ /* Set vector length to the first value. */
+ first_vl = set_vl (first_vl);
+
+ printf ("main: first_vl = %d\n", first_vl);
+
+ unsigned char buf[256];
+
+ /* Use an SVE register to make the kernel start saving the SVE bank. */
+ asm volatile ("mov z0.b, #255\n\t"
+ "str z0, %0"
+ :
+ : "m" (buf)
+ : "z0", "memory");
+
+ initialize_sve_state_main ();
+
+ struct sigaction sigact;
+ sigact.sa_sigaction = sighandler;
+ sigact.sa_flags = SA_SIGINFO;
+ sigaction (SIGUSR1, &sigact, NULL);
+
+ kill (getpid (), SIGUSR1);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.exp b/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.exp
new file mode 100644
index 0000000..32340bb
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.exp
@@ -0,0 +1,106 @@
+# 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/>.
+
+# Exercise unwinding AArch64's SVE registers from a signal frame.
+
+require allow_aarch64_sve_tests
+# Remote targets can't communicate vector length changes to GDB via the RSP.
+require !gdb_protocol_is_remote
+
+set first_vl 0
+set second_vl 0
+
+# Find two valid VL values to use in the test.
+# The minimum supported VL is 16 bytes, maximum is 256 bytes, and VL can change
+# in increments of at least 16 bytes.
+for {set i 16} {$i <= 256} {incr i 16} {
+ if {![aarch64_supports_sve_vl $i]} {
+ continue
+ }
+
+ if {$first_vl == 0} {
+ set first_vl $i
+ } elseif {$second_vl == 0} {
+ set second_vl $i
+ break
+ }
+}
+
+if {$first_vl == 0 || $second_vl == 0} {
+ untested "test needs to support at least two vector lengths"
+ return
+}
+
+standard_testfile
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
+ [list debug additional_flags=-march=armv9-a]] } {
+ return
+}
+
+# We want SIGUSR1 to be delivered normally.
+gdb_test "handle SIGUSR1 nostop" \
+ [multi_line {Signal Stop Print Pass to program Description} \
+ {SIGUSR1 No Yes Yes User defined signal 1}] \
+ "don't stop for SIGUSR1"
+
+set linespec ${srcfile}:[gdb_get_line_number "Break here."]
+gdb_test_no_output "set args $first_vl $second_vl"
+
+if ![runto ${linespec}] {
+ return
+}
+
+set first_vg [expr $first_vl/8]
+set second_vg [expr $second_vl/8]
+
+gdb_test "print \$vg" ". = $second_vg" "vg was changed"
+
+for {set row 0} {$row < 32} {incr row} {
+ set register_name "\$z${row}\.b\.u"
+ gdb_test "print sizeof $register_name" " = $second_vl" \
+ "size of $register_name in the signal handler"
+ gdb_test "print $register_name" ". = \\{254 <repeats $second_vl times>\\}" \
+ "$register_name contents in signal handler"
+}
+
+for {set row 0} {$row < 16} {incr row} {
+ set register_name "\$p${row}"
+ gdb_test "print $register_name" ". = \\{(0, ){[expr $second_vl/8 - 1]}0\\}" \
+ "$register_name contents in signal handler"
+}
+gdb_test "print \$ffr" ". = \\{(255, ){[expr $second_vl/8 - 1]}255\\}" \
+ "ffr contents in signal handler"
+
+gdb_test "frame function main" \
+ [multi_line "#$decimal $hex in main \[^\r\n\]+" \
+ "$decimal\[ \t\]+kill \\(getpid \\(\\), SIGUSR1\\);"]
+
+gdb_test "print \$vg" ". = $first_vg" "vg was correctly unwound"
+
+for {set row 0} {$row < 32} {incr row} {
+ set register_name "\$z${row}\.b\.u"
+ gdb_test "print sizeof $register_name" " = $first_vl" \
+ "size of $register_name was correctly unwound"
+ gdb_test "print $register_name" ". = \\{255 <repeats $first_vl times>\\}" \
+ "$register_name contents were correctly unwound"
+}
+
+for {set row 0} {$row < 16} {incr row} {
+ set register_name "\$p${row}"
+ gdb_test "print $register_name" ". = \\{(1, ){[expr $first_vl/8 - 1]}1\\}" \
+ "$register_name contents were correctly unwound"
+}
+gdb_test "print \$ffr" ". = \\{(255, ){[expr $first_vl/8 - 1]}255\\}" \
+ "ffr contents were correctly unwound"
diff --git a/gdb/testsuite/gdb.base/bg-execution-repeat.c b/gdb/testsuite/gdb.base/bg-execution-repeat.c
index 8e9bae4..3c0cc76 100644
--- a/gdb/testsuite/gdb.base/bg-execution-repeat.c
+++ b/gdb/testsuite/gdb.base/bg-execution-repeat.c
@@ -37,9 +37,9 @@ main (void)
{
alarm (60);
+ do_wait = 1;
foo ();
- do_wait = 1;
wait ();
/* do_wait set to 0 externally. */
diff --git a/gdb/testsuite/gdb.base/corefile3.c b/gdb/testsuite/gdb.base/corefile3.c
new file mode 100644
index 0000000..16030dd
--- /dev/null
+++ b/gdb/testsuite/gdb.base/corefile3.c
@@ -0,0 +1,118 @@
+/* Copyright 1992-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/>. */
+
+/* This file is based on coremaker.c. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#define MAPSIZE (8 * 1024)
+
+/* Global pointers so it's easier to access them from GDB. */
+
+char *rw_mapping = NULL;
+char *malloc_buffer = NULL;
+char *anon_mapping = NULL;
+char *shm_mapping = NULL;
+
+/* Create mappings within this process. */
+
+void
+mmapdata ()
+{
+ /* Allocate and initialize a buffer that will be used to write the file
+ that is later mapped in. */
+
+ malloc_buffer = (char *) malloc (MAPSIZE);
+ for (int j = 0; j < MAPSIZE; ++j)
+ malloc_buffer[j] = j;
+
+ /* Write the file to map in. */
+
+ int fd = open ("coremmap.data", O_CREAT | O_RDWR, 0666);
+ assert (fd != -1);
+ write (fd, malloc_buffer, MAPSIZE);
+
+ /* Now map the file into our address space as RW_MAPPING. */
+
+ rw_mapping
+ = (char *) mmap (0, MAPSIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ assert (rw_mapping != (char *) MAP_FAILED);
+
+ /* Verify that the original data and the mapped data are identical. If
+ not, we'd rather fail now than when trying to access the mapped data
+ from the core file. */
+
+ for (int j = 0; j < MAPSIZE; ++j)
+ assert (malloc_buffer[j] == rw_mapping[j]);
+
+ /* Touch RW_MAPPING so the kernel writes it out into 'core'. */
+ rw_mapping[0] = malloc_buffer[0];
+
+ /* Create yet another region which is allocated, but not written to. */
+ anon_mapping = mmap (NULL, MAPSIZE, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ assert (anon_mapping != MAP_FAILED);
+
+ /* Create a shared memory mapping. */
+ int sid = shmget (IPC_PRIVATE, MAPSIZE, IPC_CREAT | IPC_EXCL | 0777);
+ assert (sid != -1);
+ shm_mapping = (char *) shmat (sid, NULL, 0);
+ int res = shmctl (sid, IPC_RMID, NULL);
+ assert (res == 0);
+ assert (shm_mapping != MAP_FAILED);
+}
+
+void
+func2 ()
+{
+#ifdef SA_FULLDUMP
+ /* Force a corefile that includes the data section for AIX. */
+ {
+ struct sigaction sa;
+
+ sigaction (SIGABRT, (struct sigaction *)0, &sa);
+ sa.sa_flags |= SA_FULLDUMP;
+ sigaction (SIGABRT, &sa, (struct sigaction *)0);
+ }
+#endif
+
+ abort ();
+}
+
+void
+func1 ()
+{
+ func2 ();
+}
+
+int
+main (void)
+{
+ mmapdata ();
+ func1 ();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/corefile3.exp b/gdb/testsuite/gdb.base/corefile3.exp
new file mode 100644
index 0000000..57b2300
--- /dev/null
+++ b/gdb/testsuite/gdb.base/corefile3.exp
@@ -0,0 +1,71 @@
+# 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/>.
+
+# Create a core file with some mapped file regions, but ensure that
+# the the kernel should write the regions into the core file (e.g. r/w
+# file backed mapping).
+#
+# We then delete the file that backed the mapping and load the core
+# file into GDB.
+#
+# GDB shouldn't warn about the file being missing. It doesn't matter;
+# the file contents can all be found in the core file itself.
+
+require isnative
+require {!is_remote host}
+
+standard_testfile
+
+if {[build_executable $testfile.exp $testfile $srcfile] == -1} {
+ return
+}
+
+set corefile [core_find $binfile {}]
+if {$corefile == ""} {
+ return
+}
+
+# Move the coremap.data file out of the way, so it cannot be found
+# when we later load the core file into GDB. This file was generated
+# by the inferior as it was running.
+set data_filename \
+ [standard_output_file coredir.[getpid]/coremmap.data]
+set backup_filename \
+ [standard_output_file coredir.[getpid]/coremmap.data.backup]
+remote_exec host "mv ${data_filename} ${backup_filename}"
+
+clean_restart $binfile
+
+# Load the core file. The 'coremap.data' file cannot be found by GDB,
+# but all the mappings for that file are r/w and should be present in
+# the core file, so we shouldn't get any warnings from GDB about it.
+set warnings_seen 0
+gdb_test_multiple "core-file $corefile" "core-file command" {
+ -re "^warning: Can't open file \[^\r\n\]+ during file-backed mapping note processing\r\n" {
+ incr warnings_seen
+ exp_continue
+ }
+ -re "^$gdb_prompt $" {
+ gdb_assert { $warnings_seen == 0 } $gdb_test_name
+ }
+ -re "^\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+}
+
+# Check the mappings are all readable.
+foreach label { rw_mapping malloc_buffer anon_mapping shm_mapping } {
+ gdb_test "x/1wd $label" "^$hex:\\s+$decimal"
+}
diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
index 03b7a52..3ddc07e 100644
--- a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
+++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
@@ -24,7 +24,8 @@ require allow_dlmopen_tests
standard_testfile -main.c -lib.c
set srcfile_lib $srcfile2
-set binfile_lib [standard_output_file dlmopen-lib.so]
+set so_name dlmopen-lib.so
+set binfile_lib [standard_output_file $so_name]
if { [build_executable "build shlib" $binfile_lib $srcfile_lib \
[list debug shlib]] == -1 } {
@@ -41,18 +42,19 @@ if { [build_executable "failed to build" $testfile $srcfile \
# for the so
proc get_first_so_ns {} {
set ns -1
- gdb_test_multiple "info sharedlibrary" "get SO namespace" -lbl {
- -re "From\\s+To\\s+\(NS\\s+\)?Syms\\s+Read\\s+Shared Object Library\r\n" {
+ set lib_regexp [string_to_regexp ${::binfile_lib}]
+ gdb_test_multiple "info sharedlibrary $::so_name" "get SO namespace" -lbl {
+ -re "\r\nFrom\\s+To\\s+\(NS\\s+\)?Syms\\s+Read\\s+Shared Object Library(?=\r\n)" {
exp_continue
}
- -re "^$::hex\\s+$::hex\\s+\\\[\\\[($::decimal)\\\]\\\]\\s+\[^\r\n]+$::binfile_lib.*" {
- set ns $expect_out(1,string)
- }
- -re "^$::gdb_prompt $" {
- }
- -re "^\[^\r\n\]+\r\n" {
+ -re "\r\n$::hex\\s+$::hex\\s+\\\[\\\[($::decimal)\\\]\\\]\\s+\[^\r\n]+${lib_regexp}(?=\r\n)" {
+ if {$ns == -1} {
+ set ns $expect_out(1,string)
+ }
exp_continue
}
+ -re -wrap "" {
+ }
}
return $ns
}
diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp
index e1c996e..8634668 100644
--- a/gdb/testsuite/gdb.base/printcmds.exp
+++ b/gdb/testsuite/gdb.base/printcmds.exp
@@ -744,6 +744,12 @@ proc test_print_char_arrays {} {
gdb_test_no_output "set print address off" "address off char arrays"
}
+proc test_print_arrays_negative {} {
+ # Check whether correct error messages are printed
+ gdb_test "p 1 == { }" "size of the array element must not be zero"
+ gdb_test "p 1 == { 1, 'a' }" "array elements must all be the same size"
+}
+
proc test_print_nibbles {} {
gdb_test_no_output "set print nibbles on"
foreach lang_line {
@@ -1235,6 +1241,7 @@ test_print_int_arrays
test_print_typedef_arrays
test_artificial_arrays
test_print_char_arrays
+test_print_arrays_negative
test_print_nibbles
# We used to do the runto main here.
test_print_string_constants
diff --git a/gdb/testsuite/gdb.cp/cplusfuncs.exp b/gdb/testsuite/gdb.cp/cplusfuncs.exp
index 94d9df3..e785909 100644
--- a/gdb/testsuite/gdb.cp/cplusfuncs.exp
+++ b/gdb/testsuite/gdb.cp/cplusfuncs.exp
@@ -579,7 +579,8 @@ proc do_tests {} {
gdb_test_no_output "set width 0"
- runto_main
+ # Don't run to main, to avoid loading and expanding debug info for
+ # libstdc++.
gdb_test_no_output "set language c++"
probe_demangler
diff --git a/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp b/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp
index 055e69c..080e999 100644
--- a/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp
+++ b/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp
@@ -13,160 +13,5 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-load_lib dwarf.exp
-
-# This test can only be run on targets which support DWARF-2 and use gas.
-require dwarf2_support
-
-# No remote host testing either.
-require {!is_remote host}
-
-
-# Lots of source files since we test a few cases and make new files
-# for each.
-# The tests are:
-# ok - the main file refers to a dwz and the buildids match
-# mismatch - the buildids do not match
-# fallback - the buildids do not match but a match is found via buildid
-standard_testfile main.c \
- dwzbuildid-ok-base.S dwzbuildid-ok-sep.S \
- dwzbuildid-mismatch-base.S dwzbuildid-mismatch-sep.S \
- dwzbuildid-fallback-base.S dwzbuildid-fallback-sep.S \
- dwzbuildid-fallback-ok.S
-
-# Write some assembly that just has a .gnu_debugaltlink section.
-proc write_just_debugaltlink {filename dwzname buildid} {
- set asm_file [standard_output_file $filename]
-
- Dwarf::assemble $asm_file {
- upvar dwzname dwzname
- upvar buildid buildid
-
- gnu_debugaltlink $dwzname $buildid
-
- # Only the DWARF reader checks .gnu_debugaltlink, so make sure
- # there is a bit of DWARF in here.
- cu { label cu_start } {
- compile_unit {{language @DW_LANG_C}} {
- }
- }
- aranges {} cu_start {
- arange {} 0 0
- }
- }
-}
-
-# Write some DWARF that also sets the buildid.
-proc write_dwarf_file {filename buildid {value 99}} {
- set asm_file [standard_output_file $filename]
-
- Dwarf::assemble $asm_file {
- declare_labels int_label int_label2
-
- upvar buildid buildid
- upvar value value
-
- build_id $buildid
-
- cu { label cu_start } {
- compile_unit {{language @DW_LANG_C}} {
- int_label2: base_type {
- {name int}
- {byte_size 4 sdata}
- {encoding @DW_ATE_signed}
- }
-
- constant {
- {name the_int}
- {type :$int_label2}
- {const_value $value data1}
- }
- }
- }
-
- aranges {} cu_start {
- arange {} 0 0
- }
- }
-}
-
-if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile}1.o \
- object {nodebug}] != "" } {
- return -1
-}
-
-# The values don't really matter, just whether they are equal.
-set ok_prefix 01
-set ok_suffix 02030405060708091011121314151617181920
-set ok_suffix2 020304050607080910111213141516171819ff
-set ok_buildid ${ok_prefix}${ok_suffix}
-set ok_buildid2 ${ok_prefix}${ok_suffix2}
-set bad_buildid [string repeat ff 20]
-
-set debugdir [standard_output_file {}]
-set basedir $debugdir/.build-id
-file mkdir $basedir $basedir/$ok_prefix
-
-# Test where the separate debuginfo's buildid matches.
-write_just_debugaltlink $srcfile2 ${binfile}3.o $ok_buildid
-write_dwarf_file $srcfile3 $ok_buildid
-
-# Test where the separate debuginfo's buildid does not match.
-write_just_debugaltlink $srcfile4 ${binfile}5.o $ok_buildid
-write_dwarf_file $srcfile5 $bad_buildid
-
-# Test where the separate debuginfo's buildid does not match, but then
-# we find a match in the .build-id directory.
-write_just_debugaltlink $srcfile6 ${binfile}7.o $ok_buildid2
-# Use 77 as the value so that if we load the bad debuginfo, we will
-# see the wrong result.
-write_dwarf_file $srcfile7 $bad_buildid 77
-write_dwarf_file $srcfile8 $ok_buildid2
-
-# Compile everything.
-for {set i 2} {$i <= 8} {incr i} {
- if {[gdb_compile [standard_output_file [set srcfile$i]] \
- ${binfile}$i.o object nodebug] != ""} {
- return -1
- }
-}
-
-# Copy a file into the .build-id place for the "fallback" test.
-file copy -force -- ${binfile}8.o $basedir/$ok_prefix/$ok_suffix2.debug
-
-proc do_test {} {
- clean_restart
-
- gdb_test_no_output "set debug-file-directory $::debugdir" \
- "set debug-file-directory"
-
- gdb_load ${::binfile}-${::testname}
-
- if {![runto_main]} {
- return
- }
-
- if {$::testname == "mismatch"} {
- gdb_test "print the_int" \
- "(No symbol table is loaded|No symbol \"the_int\" in current context).*"
- } else {
- gdb_test "print the_int" " = 99"
- }
-}
-
-foreach_with_prefix testname { ok mismatch fallback } {
- if { $testname == "ok" } {
- set objs [list ${binfile}1.o ${binfile}2.o]
- } elseif { $testname == "mismatch" } {
- set objs [list ${binfile}1.o ${binfile}4.o]
- } elseif { $testname == "fallback" } {
- set objs [list ${binfile}1.o ${binfile}6.o]
- }
-
- if {[gdb_compile $objs ${binfile}-$testname executable {quiet}] != ""} {
- unsupported "compilation failed"
- continue
- }
-
- do_test
-}
+set scenario gnu
+source $srcdir/$subdir/dwzbuildid.tcl
diff --git a/gdb/testsuite/gdb.dwarf2/dwzbuildid.tcl b/gdb/testsuite/gdb.dwarf2/dwzbuildid.tcl
new file mode 100644
index 0000000..a9077eb
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dwzbuildid.tcl
@@ -0,0 +1,184 @@
+# Copyright 2013-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/>.
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+require dwarf2_support
+
+# No remote host testing either.
+require {!is_remote host}
+
+
+# Lots of source files since we test a few cases and make new files
+# for each.
+# The tests are:
+# ok - the main file refers to a dwz and the buildids match
+# mismatch - the buildids do not match
+# fallback - the buildids do not match but a match is found via buildid
+standard_testfile main.c \
+ dwzbuildid-ok-base.S dwzbuildid-ok-sep.S \
+ dwzbuildid-mismatch-base.S dwzbuildid-mismatch-sep.S \
+ dwzbuildid-fallback-base.S dwzbuildid-fallback-sep.S \
+ dwzbuildid-fallback-ok.S
+
+# Write some assembly that just has a .gnu_debugaltlink section.
+proc write_just_debugaltlink {filename dwzname buildid} {
+ set asm_file [standard_output_file $filename]
+
+ Dwarf::assemble $asm_file {
+ upvar dwzname dwzname
+ upvar buildid buildid
+
+ if {$::scenario == "gnu"} {
+ gnu_debugaltlink $dwzname $buildid
+ } else {
+ debug_sup 0 $dwzname $buildid
+ }
+
+ # Only the DWARF reader checks .gnu_debugaltlink, so make sure
+ # there is a bit of DWARF in here.
+ cu { label cu_start } {
+ compile_unit {{language @DW_LANG_C}} {
+ }
+ }
+ aranges {} cu_start {
+ arange {} 0 0
+ }
+ }
+}
+
+# Write some DWARF that also sets the buildid.
+proc write_dwarf_file {filename buildid {value 99}} {
+ set asm_file [standard_output_file $filename]
+
+ Dwarf::assemble $asm_file {
+ declare_labels int_label int_label2
+
+ upvar buildid buildid
+ upvar value value
+
+ if {$::scenario == "gnu"} {
+ build_id $buildid
+ } else {
+ debug_sup 1 "" $buildid
+ }
+
+ cu { label cu_start } {
+ compile_unit {{language @DW_LANG_C}} {
+ int_label2: base_type {
+ {name int}
+ {byte_size 4 sdata}
+ {encoding @DW_ATE_signed}
+ }
+
+ constant {
+ {name the_int}
+ {type :$int_label2}
+ {const_value $value data1}
+ }
+ }
+ }
+
+ aranges {} cu_start {
+ arange {} 0 0
+ }
+ }
+}
+
+if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile}1.o \
+ object {nodebug}] != "" } {
+ return -1
+}
+
+# The values don't really matter, just whether they are equal.
+set ok_prefix 01
+set ok_suffix 02030405060708091011121314151617181920
+set ok_suffix2 020304050607080910111213141516171819ff
+set ok_buildid ${ok_prefix}${ok_suffix}
+set ok_buildid2 ${ok_prefix}${ok_suffix2}
+set bad_buildid [string repeat ff 20]
+
+set debugdir [standard_output_file {}]
+set basedir $debugdir/.build-id
+file mkdir $basedir $basedir/$ok_prefix
+
+# Test where the separate debuginfo's buildid matches.
+write_just_debugaltlink $srcfile2 ${binfile}3.o $ok_buildid
+write_dwarf_file $srcfile3 $ok_buildid
+
+# Test where the separate debuginfo's buildid does not match.
+write_just_debugaltlink $srcfile4 ${binfile}5.o $ok_buildid
+write_dwarf_file $srcfile5 $bad_buildid
+
+# Test where the separate debuginfo's buildid does not match, but then
+# we find a match in the .build-id directory.
+write_just_debugaltlink $srcfile6 ${binfile}7.o $ok_buildid2
+# Use 77 as the value so that if we load the bad debuginfo, we will
+# see the wrong result.
+write_dwarf_file $srcfile7 $bad_buildid 77
+write_dwarf_file $srcfile8 $ok_buildid2
+
+# Compile everything.
+for {set i 2} {$i <= 8} {incr i} {
+ if {[gdb_compile [standard_output_file [set srcfile$i]] \
+ ${binfile}$i.o object nodebug] != ""} {
+ return -1
+ }
+}
+
+# Copy a file into the .build-id place for the "fallback" test.
+file copy -force -- ${binfile}8.o $basedir/$ok_prefix/$ok_suffix2.debug
+
+proc do_test {} {
+ clean_restart
+
+ gdb_test_no_output "set debug-file-directory $::debugdir" \
+ "set debug-file-directory"
+
+ gdb_load ${::binfile}-${::testname}
+
+ if {![runto_main]} {
+ return
+ }
+
+ if {$::testname == "mismatch"} {
+ gdb_test "print the_int" \
+ "(No symbol table is loaded|No symbol \"the_int\" in current context).*"
+ } else {
+ gdb_test "print the_int" " = 99"
+ }
+}
+
+set tests {ok mismatch}
+if {$scenario == "gnu"} {
+ lappend tests fallback
+}
+foreach_with_prefix testname $tests {
+ if { $testname == "ok" } {
+ set objs [list ${binfile}1.o ${binfile}2.o]
+ } elseif { $testname == "mismatch" } {
+ set objs [list ${binfile}1.o ${binfile}4.o]
+ } elseif { $testname == "fallback" } {
+ set objs [list ${binfile}1.o ${binfile}6.o]
+ }
+
+ if {[gdb_compile $objs ${binfile}-$testname executable {quiet}] != ""} {
+ unsupported "compilation failed"
+ continue
+ }
+
+ do_test
+}
diff --git a/gdb/testsuite/gdb.dwarf2/dwzbuildid5.exp b/gdb/testsuite/gdb.dwarf2/dwzbuildid5.exp
new file mode 100644
index 0000000..047626c
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dwzbuildid5.exp
@@ -0,0 +1,17 @@
+# 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/>.
+
+set scenario dwarf5
+source $srcdir/$subdir/dwzbuildid.tcl
diff --git a/gdb/testsuite/gdb.dwarf2/dwznolink.exp b/gdb/testsuite/gdb.dwarf2/dwznolink.exp
index 91fe369..0c486ea 100644
--- a/gdb/testsuite/gdb.dwarf2/dwznolink.exp
+++ b/gdb/testsuite/gdb.dwarf2/dwznolink.exp
@@ -49,5 +49,5 @@ if {[build_executable $testfile.exp $testfile \
clean_restart
gdb_test "file -readnow $binfile" \
- "could not read '.gnu_debugaltlink' section" \
+ "could not find supplementary DWARF file" \
"file $testfile"
diff --git a/gdb/testsuite/gdb.dwarf2/fission-with-type-unit.exp b/gdb/testsuite/gdb.dwarf2/fission-with-type-unit.exp
index a1b3bb7..0a02f7c 100644
--- a/gdb/testsuite/gdb.dwarf2/fission-with-type-unit.exp
+++ b/gdb/testsuite/gdb.dwarf2/fission-with-type-unit.exp
@@ -91,6 +91,10 @@ if { [gdb_compile_shlib $dwo_asm_file $dwo_file nodebug] != "" } {
return
}
+if { [is_remote host] } {
+ gdb_remote_download host $dwo_file
+}
+
clean_restart ${testfile}
# This would cause an internal error.
diff --git a/gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp b/gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp
index 7475d7a..05e625f 100644
--- a/gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp
+++ b/gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp
@@ -38,7 +38,7 @@ if { [build_executable $testfile.exp $testfile [list $srcfile $asm_file]] } {
clean_restart
gdb_test_no_output "maint set dwarf synchronous on"
-set msg "\r\nwarning: could not find '\.gnu_debugaltlink' file for \[^\r\n\]*"
+set msg "\r\nwarning: could not find supplementary DWARF file \[^\r\n\]*"
gdb_test "file $binfile" "$msg" "file command"
set question "Load new symbol table from .*\? .y or n. "
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..b0f6d47
--- /dev/null
+++ b/gdb/testsuite/gdb.python/gdb_leak_detector.py
@@ -0,0 +1,120 @@
+# 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/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-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..50dc315
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-color-leak.py
@@ -0,0 +1,31 @@
+# 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_leak_detector
+
+
+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.exp b/gdb/testsuite/gdb.python/py-color.exp
index c6f1041..1b8e0c5 100644
--- a/gdb/testsuite/gdb.python/py-color.exp
+++ b/gdb/testsuite/gdb.python/py-color.exp
@@ -13,8 +13,7 @@
# 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
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..38f33c3 100644
--- a/gdb/testsuite/gdb.python/py-inferior-leak.py
+++ b/gdb/testsuite/gdb.python/py-inferior-leak.py
@@ -14,99 +14,31 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
-import tracemalloc
+import gdb_leak_detector
-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
+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)
+ def __del__(self):
+ gdb.events.new_inferior.disconnect(self.__handler)
-# Register the new_inferior event handler.
-def new_inferior_handler(event):
- global inf
- inf = event.inferior
+ 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")
+ gdb.execute("remove-inferiors %s" % num)
-gdb.events.new_inferior.connect(new_inferior_handler)
+ def deallocate(self):
+ self.inferior = None
-# A global filters list, we only care about memory allocations
-# originating from this script.
-filters = [tracemalloc.Filter(True, "*py-inferior-leak.py")]
-
-# 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
-
-
-# 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-read-memory-leak.exp b/gdb/testsuite/gdb.python/py-read-memory-leak.exp
index 0015a57..9ae5eb8 100644
--- a/gdb/testsuite/gdb.python/py-read-memory-leak.exp
+++ b/gdb/testsuite/gdb.python/py-read-memory-leak.exp
@@ -30,15 +30,5 @@ 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..71edf47 100644
--- a/gdb/testsuite/gdb.python/py-read-memory-leak.py
+++ b/gdb/testsuite/gdb.python/py-read-memory-leak.py
@@ -13,81 +13,21 @@
# 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 gdb_leak_detector
-import gdb
-# A global variable in which we store a reference to the memory buffer
-# returned from gdb.Inferior.read_memory().
-mem_buf = None
+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]
+ def allocate(self):
+ self.mem_buf = self.inf.read_memory(self.addr, 4096)
-# A global filters list, we only care about memory allocations
-# originating from this script.
-filters = [tracemalloc.Filter(True, "*" + os.path.basename(__file__))]
+ def deallocate(self):
+ self.mem_buf = 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, mem_buf
-
- addr = gdb.parse_and_eval("px")
- inf = gdb.inferiors()[0]
-
- # 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.threads/clone-attach-detach.exp b/gdb/testsuite/gdb.threads/clone-attach-detach.exp
index 0ae4281..3da2c3e 100644
--- a/gdb/testsuite/gdb.threads/clone-attach-detach.exp
+++ b/gdb/testsuite/gdb.threads/clone-attach-detach.exp
@@ -74,7 +74,7 @@ set attempts 3
for {set attempt 1} {$attempt <= $attempts} {incr attempt} {
with_test_prefix "bg attach $attempt" {
- gdb_test "attach $testpid &" \
+ gdb_test -no-prompt-anchor "attach $testpid &" \
"Attaching to program.*process $testpid.*" \
"attach"
diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index 46b39a1..7e8778a 100644
--- a/gdb/testsuite/lib/dwarf.exp
+++ b/gdb/testsuite/lib/dwarf.exp
@@ -3068,6 +3068,24 @@ namespace eval Dwarf {
}
}
+ # Emit a .debug_sup section with the given file name and build-id.
+ # The buildid should be represented as a hexadecimal string, like
+ # "ffeeddcc".
+ proc debug_sup {is_sup filename buildid} {
+ _defer_output .debug_sup {
+ # The version.
+ _op .2byte 0x5
+ # Supplementary marker.
+ _op .byte $is_sup
+ _op .ascii [_quote $filename]
+ set len [expr {[string length $buildid] / 2}]
+ _op .uleb128 $len
+ foreach {a b} [split $buildid {}] {
+ _op .byte 0x$a$b
+ }
+ }
+ }
+
proc _note {type name hexdata} {
set namelen [expr [string length $name] + 1]
set datalen [expr [string length $hexdata] / 2]
diff --git a/gdb/testsuite/lib/gdb-python.exp b/gdb/testsuite/lib/gdb-python.exp
index b4eb40d..e026c1b 100644
--- a/gdb/testsuite/lib/gdb-python.exp
+++ b/gdb/testsuite/lib/gdb-python.exp
@@ -77,3 +77,24 @@ proc gdb_py_module_available { name } {
return ${available}
}
+
+# Run a memory leak test within the Python script FILENAME. This proc
+# checks that the required Python modules are available, sets up the
+# syspath so that the helper module can be found (in the same
+# directory as FILENAME), then loads FILENAME to run the test.
+proc gdb_py_run_memory_leak_test { filename testname } {
+ if { ![gdb_py_module_available "tracemalloc"] } {
+ unsupported "$testname (tracemalloc module not available)"
+ }
+
+ gdb_test_no_output -nopass "python import sys"
+ gdb_test_no_output -nopass \
+ "python sys.path.insert(0, \"[file dirname $filename]\")" \
+ "setup sys.path"
+
+ set pyfile [gdb_remote_download host ${filename}]
+
+ # Source the Python script, this runs the test, and either prints
+ # PASS, or throws an exception.
+ gdb_test "source ${pyfile}" "^PASS" $testname
+}