aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/testsuite')
-rw-r--r--gdb/testsuite/Makefile.in5
-rwxr-xr-xgdb/testsuite/analyze-racy-logs.py3
-rw-r--r--gdb/testsuite/boards/cc-with-dwz-5.exp28
-rw-r--r--gdb/testsuite/gdb.ada/array_subscript_addr/p.adb5
-rw-r--r--gdb/testsuite/gdb.ada/bp_inlined_func.exp4
-rw-r--r--gdb/testsuite/gdb.ada/dyn-bit-offset.exp79
-rw-r--r--gdb/testsuite/gdb.ada/dyn-bit-offset/exam.adb45
-rw-r--r--gdb/testsuite/gdb.ada/finish-var-size.exp8
-rw-r--r--gdb/testsuite/gdb.ada/fixed_points.exp4
-rw-r--r--gdb/testsuite/gdb.ada/fixed_points/fixed_points.adb7
-rw-r--r--gdb/testsuite/gdb.ada/negative-bit-offset.exp36
-rw-r--r--gdb/testsuite/gdb.ada/negative-bit-offset/prog.adb36
-rw-r--r--gdb/testsuite/gdb.ada/null_overload/foo.adb4
-rw-r--r--gdb/testsuite/gdb.ada/null_overload/pck.adb23
-rw-r--r--gdb/testsuite/gdb.ada/null_overload/pck.ads22
-rw-r--r--gdb/testsuite/gdb.ada/packed_record_2.exp61
-rw-r--r--gdb/testsuite/gdb.ada/packed_record_2/exam.adb51
-rw-r--r--gdb/testsuite/gdb.ada/scalar_storage.exp28
-rw-r--r--gdb/testsuite/gdb.ada/task_switch_in_core.exp2
-rw-r--r--gdb/testsuite/gdb.ada/type-tick-size/prog.adb2
-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.arch/amd64-watchpoint-downgrade.exp2
-rw-r--r--gdb/testsuite/gdb.arch/i386-prologue-skip-cf-protection-stackalign.c27
-rw-r--r--gdb/testsuite/gdb.arch/i386-prologue-skip-cf-protection.exp70
-rw-r--r--gdb/testsuite/gdb.base/attach-deleted-exec.exp44
-rw-r--r--gdb/testsuite/gdb.base/bg-execution-repeat.c2
-rw-r--r--gdb/testsuite/gdb.base/bg-execution-repeat.exp11
-rw-r--r--gdb/testsuite/gdb.base/bp-cond-failure.exp4
-rw-r--r--gdb/testsuite/gdb.base/bp-permanent.c2
-rw-r--r--gdb/testsuite/gdb.base/bp-permanent.exp4
-rw-r--r--gdb/testsuite/gdb.base/break-dbg.cc31
-rw-r--r--gdb/testsuite/gdb.base/break-dbg.exp70
-rw-r--r--gdb/testsuite/gdb.base/break1.c8
-rw-r--r--gdb/testsuite/gdb.base/catch-fork-kill.exp2
-rw-r--r--gdb/testsuite/gdb.base/catch-fork-static.exp4
-rw-r--r--gdb/testsuite/gdb.base/catch-signal-fork.exp1
-rw-r--r--gdb/testsuite/gdb.base/coredump-filter-build-id.exp2
-rw-r--r--gdb/testsuite/gdb.base/corefile-shmem-zero-id-lib.c522
-rw-r--r--gdb/testsuite/gdb.base/corefile-shmem-zero-id.c63
-rw-r--r--gdb/testsuite/gdb.base/corefile-shmem-zero-id.exp228
-rw-r--r--gdb/testsuite/gdb.base/default.exp209
-rw-r--r--gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c6
-rw-r--r--gdb/testsuite/gdb.base/dlmopen-ns-ids.exp145
-rw-r--r--gdb/testsuite/gdb.base/exprs.exp18
-rw-r--r--gdb/testsuite/gdb.base/filename-completion.exp27
-rw-r--r--gdb/testsuite/gdb.base/foll-exec-c++.exp24
-rw-r--r--gdb/testsuite/gdb.base/foll-exec-c.exp23
-rw-r--r--gdb/testsuite/gdb.base/foll-exec.c33
-rw-r--r--gdb/testsuite/gdb.base/foll-exec.exp.tcl (renamed from gdb/testsuite/gdb.base/foll-exec.exp)90
-rw-r--r--gdb/testsuite/gdb.base/foll-fork-syscall.c35
-rw-r--r--gdb/testsuite/gdb.base/foll-fork-syscall.exp143
-rw-r--r--gdb/testsuite/gdb.base/foll-fork.exp2
-rw-r--r--gdb/testsuite/gdb.base/foll-vfork.exp7
-rw-r--r--gdb/testsuite/gdb.base/fork-no-detach-follow-child-dlopen.exp1
-rw-r--r--gdb/testsuite/gdb.base/fork-print-inferior-events.exp2
-rw-r--r--gdb/testsuite/gdb.base/fork-running-state.exp2
-rw-r--r--gdb/testsuite/gdb.base/gcore.exp1
-rw-r--r--gdb/testsuite/gdb.base/infcall-failure.exp16
-rw-r--r--gdb/testsuite/gdb.base/inferior-died.exp5
-rw-r--r--gdb/testsuite/gdb.base/info-shared.exp3
-rw-r--r--gdb/testsuite/gdb.base/interrupt-daemon.exp2
-rw-r--r--gdb/testsuite/gdb.base/jit-bfd-name.exp6
-rw-r--r--gdb/testsuite/gdb.base/jit-elf-fork.exp1
-rw-r--r--gdb/testsuite/gdb.base/jit-elf-solib.c2
-rw-r--r--gdb/testsuite/gdb.base/kill-detach-inferiors-cmd.exp1
-rw-r--r--gdb/testsuite/gdb.base/maint.exp43
-rw-r--r--gdb/testsuite/gdb.base/multi-forks.exp6
-rw-r--r--gdb/testsuite/gdb.base/options.exp19
-rw-r--r--gdb/testsuite/gdb.base/pie-fork.exp2
-rw-r--r--gdb/testsuite/gdb.base/print-symbol-loading.exp2
-rw-r--r--gdb/testsuite/gdb.base/ptype.exp8
-rw-r--r--gdb/testsuite/gdb.base/run-control-while-bg-execution.exp5
-rw-r--r--gdb/testsuite/gdb.base/sigall.exp9
-rw-r--r--gdb/testsuite/gdb.base/solib-search.exp2
-rw-r--r--gdb/testsuite/gdb.base/step-over-exit.exp7
-rw-r--r--gdb/testsuite/gdb.base/style.exp289
-rw-r--r--gdb/testsuite/gdb.base/tls-common.exp.tcl50
-rw-r--r--gdb/testsuite/gdb.base/tls-dlobj-lib.c87
-rw-r--r--gdb/testsuite/gdb.base/tls-dlobj.c311
-rw-r--r--gdb/testsuite/gdb.base/tls-dlobj.exp378
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj.c89
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj.exp230
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj1.c26
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj2.c26
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj3.c26
-rw-r--r--gdb/testsuite/gdb.base/tls-nothreads.c57
-rw-r--r--gdb/testsuite/gdb.base/tls-nothreads.exp248
-rw-r--r--gdb/testsuite/gdb.base/user-namespace-attach.c35
-rw-r--r--gdb/testsuite/gdb.base/user-namespace-attach.exp148
-rw-r--r--gdb/testsuite/gdb.base/vfork-follow-parent.exp2
-rw-r--r--gdb/testsuite/gdb.base/watch-before-fork.exp2
-rw-r--r--gdb/testsuite/gdb.base/watch-vfork.exp2
-rw-r--r--gdb/testsuite/gdb.base/watchpoint-hw-attach.exp21
-rw-r--r--gdb/testsuite/gdb.btrace/multi-inferior.exp2
-rw-r--r--gdb/testsuite/gdb.cp/chained-calls.cc17
-rw-r--r--gdb/testsuite/gdb.cp/chained-calls.exp3
-rw-r--r--gdb/testsuite/gdb.cp/cpexprs.exp.tcl36
-rw-r--r--gdb/testsuite/gdb.cp/cplusfuncs.exp3
-rw-r--r--gdb/testsuite/gdb.cp/templates.exp49
-rw-r--r--gdb/testsuite/gdb.dap/attach.exp4
-rw-r--r--gdb/testsuite/gdb.dap/log-message.exp9
-rw-r--r--gdb/testsuite/gdb.dap/threads.c67
-rw-r--r--gdb/testsuite/gdb.dap/threads.exp81
-rw-r--r--gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp2
-rw-r--r--gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp4
-rw-r--r--gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp2
-rw-r--r--gdb/testsuite/gdb.debuginfod/solib-with-soname.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/ada-array-bound.c29
-rw-r--r--gdb/testsuite/gdb.dwarf2/ada-array-bound.exp89
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw-form-strx-out-of-bounds.exp41
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw-form-strx.exp25
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw-form-strx.exp.tcl64
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-error.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-modula2-self-type.S6
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-ranges-psym-warning.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-simple-locdesc.S6
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-strp.S6
-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/dynamic-bit-offset.exp95
-rw-r--r--gdb/testsuite/gdb.dwarf2/fission-dw-form-strx.exp88
-rw-r--r--gdb/testsuite/gdb.dwarf2/intbits.c3
-rw-r--r--gdb/testsuite/gdb.dwarf2/intbits.exp19
-rw-r--r--gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw4.exp71
-rw-r--r--gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw5.exp75
-rw-r--r--gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld234-dw5.exp70
-rw-r--r--gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw4.exp70
-rw-r--r--gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw5.exp81
-rw-r--r--gdb/testsuite/gdb.dwarf2/macro-source-path.exp.tcl (renamed from gdb/testsuite/gdb.dwarf2/macro-source-path.exp)250
-rw-r--r--gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/pr11465.S6
-rw-r--r--gdb/testsuite/gdb.guile/scm-cmd.exp59
-rw-r--r--gdb/testsuite/gdb.guile/scm-color.exp10
-rw-r--r--gdb/testsuite/gdb.guile/scm-frame.exp2
-rw-r--r--gdb/testsuite/gdb.guile/scm-parameter.exp195
-rw-r--r--gdb/testsuite/gdb.linespec/linespec.exp6
-rw-r--r--gdb/testsuite/gdb.linespec/lspec.cc2
-rw-r--r--gdb/testsuite/gdb.mi/interrupt-thread-group.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-condbreak-throw.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-multi-commands.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-display.exp4
-rw-r--r--gdb/testsuite/gdb.mi/user-selected-context-sync.exp4
-rw-r--r--gdb/testsuite/gdb.multi/attach-no-multi-process.exp5
-rw-r--r--gdb/testsuite/gdb.multi/attach-while-running.exp3
-rw-r--r--gdb/testsuite/gdb.multi/bp-thread-specific.exp2
-rw-r--r--gdb/testsuite/gdb.multi/dummy-frame-restore.exp2
-rw-r--r--gdb/testsuite/gdb.multi/multi-arch.exp2
-rw-r--r--gdb/testsuite/gdb.multi/multi-attach.exp2
-rw-r--r--gdb/testsuite/gdb.multi/multi-exit.exp2
-rw-r--r--gdb/testsuite/gdb.multi/multi-kill.exp2
-rw-r--r--gdb/testsuite/gdb.multi/multi-re-run.exp2
-rw-r--r--gdb/testsuite/gdb.multi/multi-target.exp.tcl4
-rw-r--r--gdb/testsuite/gdb.multi/multi-term-settings.exp2
-rw-r--r--gdb/testsuite/gdb.multi/start-inferior-specific.exp2
-rw-r--r--gdb/testsuite/gdb.multi/stop-all-on-exit.exp2
-rw-r--r--gdb/testsuite/gdb.multi/tids-gid-reset.exp2
-rw-r--r--gdb/testsuite/gdb.multi/tids.exp7
-rw-r--r--gdb/testsuite/gdb.multi/watchpoint-multi-exit.exp2
-rw-r--r--gdb/testsuite/gdb.multi/watchpoint-multi.exp2
-rw-r--r--gdb/testsuite/gdb.opt/break-on-_exit.exp2
-rw-r--r--gdb/testsuite/gdb.pascal/integers.exp2
-rw-r--r--gdb/testsuite/gdb.python/gdb_leak_detector.py121
-rw-r--r--gdb/testsuite/gdb.python/py-breakpoint.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-cmd.exp85
-rw-r--r--gdb/testsuite/gdb.python/py-color-leak.exp28
-rw-r--r--gdb/testsuite/gdb.python/py-color-leak.py37
-rw-r--r--gdb/testsuite/gdb.python/py-color.exp75
-rw-r--r--gdb/testsuite/gdb.python/py-disasm.exp.tcl5
-rw-r--r--gdb/testsuite/gdb.python/py-disasm.py18
-rw-r--r--gdb/testsuite/gdb.python/py-frame.exp15
-rw-r--r--gdb/testsuite/gdb.python/py-inferior-leak.exp14
-rw-r--r--gdb/testsuite/gdb.python/py-inferior-leak.py111
-rw-r--r--gdb/testsuite/gdb.python/py-missing-objfile.exp10
-rw-r--r--gdb/testsuite/gdb.python/py-objfile.c2
-rw-r--r--gdb/testsuite/gdb.python/py-objfile.exp3
-rw-r--r--gdb/testsuite/gdb.python/py-parameter-prefix.exp382
-rw-r--r--gdb/testsuite/gdb.python/py-parameter.exp187
-rw-r--r--gdb/testsuite/gdb.python/py-read-memory-leak.exp14
-rw-r--r--gdb/testsuite/gdb.python/py-read-memory-leak.py86
-rw-r--r--gdb/testsuite/gdb.python/py-source-styling-2.exp24
-rw-r--r--gdb/testsuite/gdb.python/py-unwind.exp7
-rw-r--r--gdb/testsuite/gdb.python/py-unwind.py20
-rw-r--r--gdb/testsuite/gdb.python/py-warning.exp63
-rw-r--r--gdb/testsuite/gdb.replay/connect.exp2
-rw-r--r--gdb/testsuite/gdb.reverse/i386-avx-reverse.exp2
-rw-r--r--gdb/testsuite/gdb.reverse/solib-precsave.exp2
-rw-r--r--gdb/testsuite/gdb.reverse/solib-reverse.exp2
-rw-r--r--gdb/testsuite/gdb.reverse/time-reverse.exp43
-rw-r--r--gdb/testsuite/gdb.rocm/code-object-load-while-breakpoint-hit.cpp86
-rw-r--r--gdb/testsuite/gdb.rocm/code-object-load-while-breakpoint-hit.exp68
-rw-r--r--gdb/testsuite/gdb.rocm/fork-exec-gpu-to-non-gpu.exp1
-rw-r--r--gdb/testsuite/gdb.rocm/fork-exec-non-gpu-to-gpu.exp1
-rw-r--r--gdb/testsuite/gdb.rocm/mi-attach.exp3
-rw-r--r--gdb/testsuite/gdb.rocm/precise-memory-fork.exp1
-rw-r--r--gdb/testsuite/gdb.rocm/precise-memory.exp2
-rw-r--r--gdb/testsuite/gdb.server/build-id-seqno.exp6
-rw-r--r--gdb/testsuite/gdb.server/fileio-packets.exp66
-rw-r--r--gdb/testsuite/gdb.server/fileio-packets.py208
-rw-r--r--gdb/testsuite/gdb.server/no-thread-db.exp4
-rw-r--r--gdb/testsuite/gdb.server/pread-offset-size.S29
-rw-r--r--gdb/testsuite/gdb.server/pread-offset-size.exp49
-rw-r--r--gdb/testsuite/gdb.stabs/weird.def2
-rw-r--r--gdb/testsuite/gdb.testsuite/gdb_test_multiple-lbl.exp84
-rwxr-xr-xgdb/testsuite/gdb.testsuite/gdb_test_multiple-lbl.gdb25
-rw-r--r--gdb/testsuite/gdb.threads/access-mem-running-thread-exit.exp89
-rw-r--r--gdb/testsuite/gdb.threads/clone-attach-detach.exp2
-rw-r--r--gdb/testsuite/gdb.threads/current-lwp-dead.exp2
-rw-r--r--gdb/testsuite/gdb.threads/detach-step-over.exp2
-rw-r--r--gdb/testsuite/gdb.threads/foll-fork-other-thread.exp2
-rw-r--r--gdb/testsuite/gdb.threads/fork-child-threads.exp5
-rw-r--r--gdb/testsuite/gdb.threads/fork-plus-threads.exp2
-rw-r--r--gdb/testsuite/gdb.threads/fork-thread-pending.exp6
-rw-r--r--gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp2
-rw-r--r--gdb/testsuite/gdb.threads/inf-thr-count.exp57
-rw-r--r--gdb/testsuite/gdb.threads/info-threads-options.c77
-rw-r--r--gdb/testsuite/gdb.threads/info-threads-options.exp131
-rw-r--r--gdb/testsuite/gdb.threads/next-fork-exec-other-thread.exp2
-rw-r--r--gdb/testsuite/gdb.threads/next-fork-other-thread.exp2
-rw-r--r--gdb/testsuite/gdb.threads/pending-fork-event-detach-ns.exp2
-rw-r--r--gdb/testsuite/gdb.threads/pending-fork-event-detach.exp2
-rw-r--r--gdb/testsuite/gdb.threads/thread-bp-deleted.exp2
-rw-r--r--gdb/testsuite/gdb.threads/thread-execl.c10
-rw-r--r--gdb/testsuite/gdb.threads/threadapply.exp6
-rw-r--r--gdb/testsuite/gdb.threads/tls.exp2
-rw-r--r--gdb/testsuite/gdb.threads/vfork-follow-child-exec.exp2
-rw-r--r--gdb/testsuite/gdb.threads/vfork-follow-child-exit.exp2
-rw-r--r--gdb/testsuite/gdb.threads/vfork-multi-inferior.exp4
-rw-r--r--gdb/testsuite/gdb.threads/vfork-multi-thread.exp2
-rw-r--r--gdb/testsuite/gdb.threads/watchpoint-fork.exp2
-rw-r--r--gdb/testsuite/gdb.trace/tspeed.exp2
-rw-r--r--gdb/testsuite/gdb.tui/corefile-run.exp2
-rw-r--r--gdb/testsuite/gdb.tui/pr30056.exp4
-rw-r--r--gdb/testsuite/gdb.tui/tui-focus.exp2
-rw-r--r--gdb/testsuite/gdb.tui/tui-layout-asm.exp106
-rw-r--r--gdb/testsuite/gdb.xml/bad-include.xml2
-rw-r--r--gdb/testsuite/gdb.xml/tdesc-xinclude.exp2
-rw-r--r--gdb/testsuite/lib/dwarf.exp86
-rw-r--r--gdb/testsuite/lib/gdb-python.exp21
-rw-r--r--gdb/testsuite/lib/gdb.exp114
-rw-r--r--gdb/testsuite/lib/gdbserver-support.exp2
-rwxr-xr-xgdb/testsuite/make-check-all.sh4
244 files changed, 8590 insertions, 1044 deletions
diff --git a/gdb/testsuite/Makefile.in b/gdb/testsuite/Makefile.in
index 0d5ad90..4a6665d 100644
--- a/gdb/testsuite/Makefile.in
+++ b/gdb/testsuite/Makefile.in
@@ -440,14 +440,15 @@ expect-read1 expect-readmore:
# function, making it read one byte at a time. Running the testsuite
# with this catches racy tests.
read1.so: lib/read1.c
- $(ECHO_CC) $(CC) -o $@ ${srcdir}/lib/read1.c -Wall -g -shared -fPIC $(CFLAGS)
+ $(ECHO_CC) $(CC) -o $@ ${srcdir}/lib/read1.c -Wall -g -shared -fPIC \
+ $(filter-out -fsanitize=%,$(CFLAGS))
# Build the readmore.so preload library. This overrides the `read'
# function, making it try harder to read more at a time. Running the
# testsuite with this catches racy tests.
readmore.so: lib/read1.c
$(ECHO_CC) $(CC) -o $@ ${srcdir}/lib/read1.c -Wall -g -shared -fPIC \
- $(CFLAGS) -DREADMORE
+ $(filter-out -fsanitize=%,$(CFLAGS)) -DREADMORE
# Build the read1 machinery.
.PHONY: read1 readmore
diff --git a/gdb/testsuite/analyze-racy-logs.py b/gdb/testsuite/analyze-racy-logs.py
index e7c5647..f24bea9 100755
--- a/gdb/testsuite/analyze-racy-logs.py
+++ b/gdb/testsuite/analyze-racy-logs.py
@@ -62,7 +62,6 @@ sum_matcher = re.compile("^(.?(PASS|FAIL)): (.*)$")
def parse_sum_line(line: str, dic: dict[str, set[str]]):
"""Parse a single LINE from a sumfile, and store the results in the
dictionary referenced by DIC."""
- global sum_matcher
line = line.rstrip()
m = re.match(sum_matcher, line)
@@ -96,7 +95,6 @@ def read_sum_files(files: list[str]):
"""Read the sumfiles (passed as a list in the FILES variable), and
process each one, filling the FILES_AND_TESTS global dictionary with
information about them."""
- global files_and_tests
for x in files:
with open(x, "r") as f:
@@ -115,7 +113,6 @@ def identify_racy_tests():
This function does that for all sets (PASS, FAIL, KPASS, KFAIL, etc.),
and then print a sorted list (without duplicates) of all the tests
that were found to be racy."""
- global files_and_tests
# First, construct two dictionaries that will hold one set of
# testcases for each state (PASS, FAIL, etc.).
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/array_subscript_addr/p.adb b/gdb/testsuite/gdb.ada/array_subscript_addr/p.adb
index eaa35c5..057d7a0 100644
--- a/gdb/testsuite/gdb.ada/array_subscript_addr/p.adb
+++ b/gdb/testsuite/gdb.ada/array_subscript_addr/p.adb
@@ -14,11 +14,12 @@
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
procedure P is
- type Table is array (1 .. 3) of Integer;
+ -- Make this large enough to force it into memory with gnat-llvm.
+ type Table is array (1 .. 15) of Integer;
function Create (I : Integer) return Table is
begin
- return (4 + I, 8 * I, 7 * I + 4);
+ return (4 + I, 8 * I, 7 * I + 4, others => 72);
end Create;
A : Table := Create (7);
diff --git a/gdb/testsuite/gdb.ada/bp_inlined_func.exp b/gdb/testsuite/gdb.ada/bp_inlined_func.exp
index 6593d1e..04cf755 100644
--- a/gdb/testsuite/gdb.ada/bp_inlined_func.exp
+++ b/gdb/testsuite/gdb.ada/bp_inlined_func.exp
@@ -41,8 +41,10 @@ gdb_test "break read_small" \
for {set i 0} {$i < 4} {incr i} {
with_test_prefix "iteration $i" {
+ # gnat-llvm may emit a call to an out-of-line copy, so allow
+ # for this here.
gdb_test "continue" \
- "Breakpoint $bkptno_num_re, b\\.read_small \\(\\).*" \
+ "Breakpoint $bkptno_num_re, ($hex in )?b\\.read_small \\(\\).*" \
"stopped in read_small"
}
}
diff --git a/gdb/testsuite/gdb.ada/dyn-bit-offset.exp b/gdb/testsuite/gdb.ada/dyn-bit-offset.exp
new file mode 100644
index 0000000..f8a4363
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/dyn-bit-offset.exp
@@ -0,0 +1,79 @@
+# 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/>.
+
+load_lib "ada.exp"
+
+require allow_ada_tests
+
+standard_ada_testfile exam
+
+set flags {debug}
+if {[ada_minimal_encodings]} {
+ lappend flags additional_flags=-fgnat-encodings=minimal
+}
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $flags] != ""} {
+ return -1
+}
+
+# GCC needs to have fixes:
+# - 809b46d2ccc ("Partially lift restriction from loc_list_from_tree_1")
+# - d7f24e37d4b ("Fix oversight about big-endian targets in latest change")
+set have_xfail [gnat_version_compare <= {16 1}]
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/exam.adb]
+runto "exam.adb:$bp_location"
+
+set re_pass \
+ [string_to_regexp \
+ " = (discr => 3, array_field => (-5, -6, -7), field => -5, another_field => -6)"]
+set re_xfail_le \
+ [string_to_regexp \
+ " = (discr => 3, array_field => (-5, -6, -7), field => -4, another_field => -4)"]
+set re_xfail_be \
+ [string_to_regexp \
+ " = (discr => 3, array_field => (-5, -6, -7), field => -6, another_field => -6)"]
+
+gdb_test_multiple "print spr" "" {
+ -re -wrap $re_pass {
+ pass $gdb_test_name
+ }
+ -re -wrap $re_xfail_le|$re_xfail_be {
+ if { $have_xfail } {
+ xfail $gdb_test_name
+ } else {
+ fail $gdb_test_name
+ }
+ }
+}
+
+set re_pass " = -5"
+set re_xfail_le " = -4"
+set re_xfail_be " = -6"
+
+gdb_test_multiple "print spr.field" "" {
+ -re -wrap $re_pass {
+ pass $gdb_test_name
+ }
+ -re -wrap $re_xfail_le|$re_xfail_be {
+ if { $have_xfail } {
+ xfail $gdb_test_name
+ } else {
+ fail $gdb_test_name
+ }
+ }
+}
diff --git a/gdb/testsuite/gdb.ada/dyn-bit-offset/exam.adb b/gdb/testsuite/gdb.ada/dyn-bit-offset/exam.adb
new file mode 100644
index 0000000..5c7f70b
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/dyn-bit-offset/exam.adb
@@ -0,0 +1,45 @@
+-- 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/>.
+
+procedure Exam is
+ type Small is range -7 .. -4;
+ for Small'Size use 2;
+
+ type Packed_Array is array (Integer range <>) of Small;
+ pragma pack (Packed_Array);
+
+ subtype Range_Int is Natural range 0 .. 7;
+
+ type Some_Packed_Record (Discr : Range_Int := 3) is record
+ Array_Field : Packed_Array (1 .. Discr);
+ Field: Small;
+ case Discr is
+ when 3 =>
+ Another_Field : Small;
+ when others =>
+ null;
+ end case;
+ end record;
+ pragma Pack (Some_Packed_Record);
+ pragma No_Component_Reordering (Some_Packed_Record);
+
+ SPR : Some_Packed_Record := (Discr => 3,
+ Field => -5,
+ Another_Field => -6,
+ Array_Field => (-5, -6, -7));
+
+begin
+ null; -- STOP
+end Exam;
diff --git a/gdb/testsuite/gdb.ada/finish-var-size.exp b/gdb/testsuite/gdb.ada/finish-var-size.exp
index e038ed4..ae30086 100644
--- a/gdb/testsuite/gdb.ada/finish-var-size.exp
+++ b/gdb/testsuite/gdb.ada/finish-var-size.exp
@@ -22,7 +22,13 @@ require {expr [gcc_major_version] >= 12}
standard_ada_testfile p
-if {[gdb_compile_ada "${srcfile}" "${binfile}" executable debug] != ""} {
+set opts {}
+lappend opts debug
+if { [have_fvar_tracking] } {
+ lappend opts additional_flags=-fvar-tracking
+}
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $opts] != ""} {
return -1
}
diff --git a/gdb/testsuite/gdb.ada/fixed_points.exp b/gdb/testsuite/gdb.ada/fixed_points.exp
index 8bb9e10..0e65004 100644
--- a/gdb/testsuite/gdb.ada/fixed_points.exp
+++ b/gdb/testsuite/gdb.ada/fixed_points.exp
@@ -90,6 +90,10 @@ foreach_gnat_encoding scenario flags {all minimal} {
# This only started working in GCC 11.
if {$scenario == "minimal" && [gnat_version_compare >= 11]} {
gdb_test "print fp5_var" " = 3e-19"
+
+ gdb_test "print Float(Object_Fixed) = Float(Semicircle_Delta * 5)" \
+ " = true" \
+ "examine object_fixed"
}
# This failed before GCC 10.
diff --git a/gdb/testsuite/gdb.ada/fixed_points/fixed_points.adb b/gdb/testsuite/gdb.ada/fixed_points/fixed_points.adb
index adab614..94a41b9 100644
--- a/gdb/testsuite/gdb.ada/fixed_points/fixed_points.adb
+++ b/gdb/testsuite/gdb.ada/fixed_points/fixed_points.adb
@@ -64,6 +64,12 @@ procedure Fixed_Points is
for Another_Type'size use 64;
Another_Fixed : Another_Type := Another_Delta * 5;
+ Semicircle_Delta : constant := 1.0/(2**31);
+ type Semicircle_Type is delta Semicircle_Delta range -1.0 .. (1.0 - Semicircle_Delta);
+ for Semicircle_Type'small use Semicircle_Delta;
+ for Semicircle_Type'size use 32;
+ Object_Fixed : Semicircle_Type := Semicircle_Delta * 5;
+
begin
Base_Object := 1.0/16.0; -- Set breakpoint here
Subtype_Object := 1.0/16.0;
@@ -75,4 +81,5 @@ begin
Do_Nothing (FP4_Var'Address);
Do_Nothing (FP5_Var'Address);
Do_Nothing (Another_Fixed'Address);
+ Do_Nothing (Object_Fixed'Address);
end Fixed_Points;
diff --git a/gdb/testsuite/gdb.ada/negative-bit-offset.exp b/gdb/testsuite/gdb.ada/negative-bit-offset.exp
new file mode 100644
index 0000000..c5fcae1
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/negative-bit-offset.exp
@@ -0,0 +1,36 @@
+# 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/>.
+
+# Test negative DW_AT_bit_offset.
+
+load_lib "ada.exp"
+
+require allow_ada_tests
+
+standard_ada_testfile prog
+
+# This particular output is only generated with -gdwarf-4.
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable \
+ {debug additional_flags=-gdwarf-4}] != ""} {
+ return
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/prog.adb]
+runto "prog.adb:$bp_location"
+
+gdb_test "print xp" \
+ [string_to_regexp "(x => 21, y => (-1, -2, -3, -4, -5, -6, -7, -8, -9, -10))"]
diff --git a/gdb/testsuite/gdb.ada/negative-bit-offset/prog.adb b/gdb/testsuite/gdb.ada/negative-bit-offset/prog.adb
new file mode 100644
index 0000000..e3c1775
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/negative-bit-offset/prog.adb
@@ -0,0 +1,36 @@
+-- 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/>.
+
+procedure Prog is
+
+ type Small is range -32 .. 31;
+ for Small'Size use 6;
+
+ type SomeArray is array (POSITIVE range <>) of Small;
+
+ type SomePackedArray is array (POSITIVE range <>) of Small;
+ pragma Pack (SomePackedArray);
+
+ type SomePackedRecord is record
+ X: Small;
+ Y: SomePackedArray (1 .. 10);
+ end record;
+ pragma Pack (SomePackedRecord);
+
+ XP: SomePackedRecord := (21, (-1, -2, -3, -4, -5, -6, -7, -8, -9, -10));
+
+begin
+ null; -- STOP
+end;
diff --git a/gdb/testsuite/gdb.ada/null_overload/foo.adb b/gdb/testsuite/gdb.ada/null_overload/foo.adb
index 002238f..55d3fd6 100644
--- a/gdb/testsuite/gdb.ada/null_overload/foo.adb
+++ b/gdb/testsuite/gdb.ada/null_overload/foo.adb
@@ -13,6 +13,8 @@
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
+with pck; use pck;
+
procedure Foo is
type R_Type is null record;
@@ -38,5 +40,5 @@ procedure Foo is
U_Ptr : U_P_T := null;
begin
- null; -- START
+ Do_Nothing (U_Ptr'Address); -- START
end Foo;
diff --git a/gdb/testsuite/gdb.ada/null_overload/pck.adb b/gdb/testsuite/gdb.ada/null_overload/pck.adb
new file mode 100644
index 0000000..95bd90a
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/null_overload/pck.adb
@@ -0,0 +1,23 @@
+-- Copyright 2020-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/>.
+
+package body Pck is
+
+ procedure Do_Nothing (A : System.Address) is
+ begin
+ null;
+ end Do_Nothing;
+
+end Pck;
diff --git a/gdb/testsuite/gdb.ada/null_overload/pck.ads b/gdb/testsuite/gdb.ada/null_overload/pck.ads
new file mode 100644
index 0000000..114aee0
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/null_overload/pck.ads
@@ -0,0 +1,22 @@
+-- Copyright 2020-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/>.
+
+with System;
+
+package Pck is
+
+ procedure Do_Nothing (A : System.Address);
+
+end Pck;
diff --git a/gdb/testsuite/gdb.ada/packed_record_2.exp b/gdb/testsuite/gdb.ada/packed_record_2.exp
new file mode 100644
index 0000000..d0bcdbd
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/packed_record_2.exp
@@ -0,0 +1,61 @@
+# 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/>.
+
+load_lib "ada.exp"
+
+require allow_ada_tests
+
+standard_ada_testfile exam
+
+set flags {debug}
+if {[ada_minimal_encodings]} {
+ lappend flags additional_flags=-fgnat-encodings=minimal
+}
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $flags] != ""} {
+ return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/exam.adb]
+runto "exam.adb:$bp_location"
+
+set spr_contents "discr => 3, field => -4, array_field => \\(-5, -6, -7\\)"
+
+gdb_test "print spr" " = \\($spr_contents\\)"
+
+gdb_test "print spr.discr" " = 3"
+
+# See PR ada/32880 -- gdb should probably print array (1 .. 3) here,
+# but instead shows array (<>). However as this isn't totally
+# relevant to this test, we just accept it.
+gdb_test "ptype spr" \
+ [multi_line \
+ "type = tagged record" \
+ " discr: range 1 .. 8;" \
+ " field: range -7 .. -4;" \
+ " array_field: array \\(<>\\) of exam.small <packed: 2-bit elements>;" \
+ "end record"]
+
+gdb_test_multiple "print sc" "" {
+ -re " \\($spr_contents, outer => 2, another_array => \\(-7, -6\\)\\)" {
+ pass $gdb_test_name
+ }
+ -re " \\($spr_contents, outer => $decimal, another_array => \\(.*\\)\\)" {
+ # Other output is a known GCC bug.
+ xfail $gdb_test_name
+ }
+}
diff --git a/gdb/testsuite/gdb.ada/packed_record_2/exam.adb b/gdb/testsuite/gdb.ada/packed_record_2/exam.adb
new file mode 100644
index 0000000..e528ecf
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/packed_record_2/exam.adb
@@ -0,0 +1,51 @@
+-- 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/>.
+
+procedure Exam is
+ type Small is range -7 .. -4;
+ for Small'Size use 2;
+
+ type Range_Int is range 1 .. 8;
+ for Range_Int'Size use 3;
+
+ type Packed_Array is array (Range_Int range <>) of Small;
+ pragma pack (Packed_Array);
+
+ type Some_Packed_Record (Discr : Range_Int) is tagged record
+ Field: Small;
+ Array_Field : Packed_Array (1 .. Discr);
+ end record;
+ pragma Pack (Some_Packed_Record);
+
+ type Sub_Class (Inner, Outer : Range_Int)
+ is new Some_Packed_Record (Inner) with
+ record
+ Another_Array : Packed_Array (1 .. Outer);
+ end record;
+ pragma Pack (Sub_Class);
+
+ SPR : Some_Packed_Record := (Discr => 3,
+ Field => -4,
+ Array_Field => (-5, -6, -7));
+
+ SC : Sub_Class := (Inner => 3,
+ Outer => 2,
+ Field => -4,
+ Array_Field => (-5, -6, -7),
+ Another_Array => (-7, -6));
+
+begin
+ null; -- STOP
+end Exam;
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.ada/task_switch_in_core.exp b/gdb/testsuite/gdb.ada/task_switch_in_core.exp
index 3aafc2b..bded377 100644
--- a/gdb/testsuite/gdb.ada/task_switch_in_core.exp
+++ b/gdb/testsuite/gdb.ada/task_switch_in_core.exp
@@ -15,7 +15,7 @@
load_lib "ada.exp"
-require allow_ada_tests
+require allow_ada_tests gcore_cmd_available
standard_ada_testfile crash
diff --git a/gdb/testsuite/gdb.ada/type-tick-size/prog.adb b/gdb/testsuite/gdb.ada/type-tick-size/prog.adb
index 34a9fca..a7457fd 100644
--- a/gdb/testsuite/gdb.ada/type-tick-size/prog.adb
+++ b/gdb/testsuite/gdb.ada/type-tick-size/prog.adb
@@ -50,6 +50,8 @@ procedure Prog is
Rec_Type_Size : Integer := Rec'Object_Size;
begin
+ Do_Nothing (Simple_Val'Address);
+ Do_Nothing (Rec_Val'Address);
Do_Nothing (Static_Blob'Address);
Do_Nothing (Dynamic_Blob'Address);
null; -- STOP
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.arch/amd64-watchpoint-downgrade.exp b/gdb/testsuite/gdb.arch/amd64-watchpoint-downgrade.exp
index dcee040..5663b0d 100644
--- a/gdb/testsuite/gdb.arch/amd64-watchpoint-downgrade.exp
+++ b/gdb/testsuite/gdb.arch/amd64-watchpoint-downgrade.exp
@@ -58,7 +58,7 @@ gdb_test "starti" \
[multi_line \
"warning: watchpoint $num downgraded to software watchpoint" \
"" \
- "Program stopped\\." \
+ "(Program|Thread \[^\r\n\]) stopped\\." \
".*"]
# Watchpoint should now have downgraded to a s/w watchpoint.
diff --git a/gdb/testsuite/gdb.arch/i386-prologue-skip-cf-protection-stackalign.c b/gdb/testsuite/gdb.arch/i386-prologue-skip-cf-protection-stackalign.c
new file mode 100644
index 0000000..f55cee5
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/i386-prologue-skip-cf-protection-stackalign.c
@@ -0,0 +1,27 @@
+/* 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/>. */
+
+#include <alloca.h>
+
+int
+main (int argc, char **argv)
+{
+ volatile __attribute__ ((__aligned__ (64))) int a;
+ volatile char *p = (char *) alloca (argc * 12);
+ p[2] = 'b';
+ return 1;
+}
diff --git a/gdb/testsuite/gdb.arch/i386-prologue-skip-cf-protection.exp b/gdb/testsuite/gdb.arch/i386-prologue-skip-cf-protection.exp
index eb93127..06285ce 100644
--- a/gdb/testsuite/gdb.arch/i386-prologue-skip-cf-protection.exp
+++ b/gdb/testsuite/gdb.arch/i386-prologue-skip-cf-protection.exp
@@ -19,41 +19,65 @@
# This option places an `endbr32`/`endbr64` instruction at the start of
# all functions, which can interfere with prologue analysis.
-standard_testfile .c
-set binfile ${binfile}
+standard_testfile .c -stackalign.c
require {is_any_target x86_64-*-* i?86-*-*}
-
require supports_fcf_protection
-set opts {debug additional_flags=-fcf-protection=full}
+# Tests if breakpoint set on main is placed past main's entry.
+proc test_run {} {
+ # Get start address of function main.
+ set main_addr [get_integer_valueof &main -1]
+ gdb_assert {$main_addr != -1}
-if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable $opts] != "" } {
- untested "failed to compile"
- return
-}
+ set bp_addr -1
-clean_restart ${binfile}
+ # Put breakpoint on main, get the address where the breakpoint was installed.
+ gdb_test_multiple "break -q main" "break on main, get address" {
+ -re -wrap "Breakpoint $::decimal at ($::hex).*" {
+ set bp_addr $expect_out(1,string)
-# Get start address of function main.
-set main_addr [get_integer_valueof &main -1]
-gdb_assert {$main_addr != -1}
+ # Convert to decimal.
+ set bp_addr [expr $bp_addr]
-set bp_addr -1
+ pass $gdb_test_name
+ }
+ }
-# Put breakpoint on main, get the address where the breakpoint was installed.
-gdb_test_multiple "break -q main" "break on main, get address" {
- -re -wrap "Breakpoint $decimal at ($hex).*" {
- set bp_addr $expect_out(1,string)
+ # Make sure some prologue was skipped.
+ gdb_assert {$bp_addr != -1 && $bp_addr > $main_addr} \
+ "breakpoint placed past main's entry"
+}
- # Convert to decimal.
- set bp_addr [expr $bp_addr]
+with_test_prefix "skip-cf-protection" {
+ set opts {debug additional_flags=-fcf-protection=full}
- pass $gdb_test_name
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
+ $opts] != "" } {
+ untested "failed to compile"
+ return
}
+
+ clean_restart ${binfile}
+
+ test_run
}
-if { $bp_addr != -1 } {
- # Make sure some prologue was skipped.
- gdb_assert {$bp_addr > $main_addr}
+# Now, make sure that the prologue analysis does not end up at function's entry
+# when stack alignment sequence is generated right after 'endbr64'/'endbr32'.
+# That could happen if GDB handled those incorrectly - there was a bug that
+# checked for those two in incorrect order, which caused such issue.
+with_test_prefix "skip-cf-protection-stackalign" {
+ # gcc is easier to make it produce the sequence of interest.
+ if { ![is_c_compiler_gcc] } {
+ unsupported "stackalign test part requires gcc compiler"
+ return
+ }
+
+ if { [prepare_for_testing "failed to prepare" "${testfile}-stackalign" \
+ $srcfile2 [list optimize=-O0 additional_flags=-fcf-protection=full]] } {
+ return
+ }
+
+ test_run
}
diff --git a/gdb/testsuite/gdb.base/attach-deleted-exec.exp b/gdb/testsuite/gdb.base/attach-deleted-exec.exp
index 82a7bb4..45fac0d 100644
--- a/gdb/testsuite/gdb.base/attach-deleted-exec.exp
+++ b/gdb/testsuite/gdb.base/attach-deleted-exec.exp
@@ -67,5 +67,49 @@ if { [regexp $re_nfs $filename] } {
gdb_assert { [string equal $filename /proc/${testpid}/exe] } $test
}
+# Restart GDB.
+clean_restart
+
+# Setup an empty sysroot. GDB will fail to find the executable within
+# the sysroot. Additionally, the presence of a sysroot should prevent
+# GDB from trying to load the executable from /proc/PID/exe.
+set sysroot [standard_output_file "sysroot"]
+gdb_test_no_output "set sysroot $sysroot" \
+ "setup sysroot"
+
+# Attach to the inferior. GDB should complain about failing to find
+# the executable. It is the name of the executable that GDB doesn't
+# find that we're interesting in here. For native targets GDB should
+# be looking for BINFILE, not /proc/PID/exe.
+#
+# For extended-remote targets things are unfortunately harder. Native
+# GDB looks for BINFILE because it understands that GDB will be
+# looking in the sysroot. But remote GDB doesn't know if GDB is using
+# a sysroot or not. As such, gdbserver will return /proc/PID/exe if
+# it knows that the file has been deleted locally. This isn't great
+# if GDB then plans to look in a sysroot, but equally, if the remote
+# file has been deleted, then the name GDB will return, will have had
+# " (deleted" appended, so we're unlikely to get a hit in the sysroot
+# either way.
+if { [target_info gdb_protocol] == "extended-remote" } {
+ set filename_re "/proc/$testpid/exe"
+} else {
+ set filename_re "\[^\r\n\]+/${testfile} \\(deleted\\)"
+}
+
+verbose -log "APB: warning: No executable has been specified, and target executable $filename_re could not be found\\. Try using the \"file\" command\\."
+
+gdb_test "attach $testpid" \
+ [multi_line \
+ "Attaching to process $decimal" \
+ "warning: No executable has been specified, and target executable $filename_re could not be found\\. Try using the \"file\" command\\." \
+ ".*"] \
+ "attach to inferior"
+
+# Check GDB hasn't managed to load an executable.
+gdb_test "info inferior" \
+ "\\*\[^)\]+\\)\\s*" \
+ "confirm no executable is loaded."
+
# Cleanup.
kill_wait_spawned_process $test_spawn_id
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/bg-execution-repeat.exp b/gdb/testsuite/gdb.base/bg-execution-repeat.exp
index b1496ee..d5580fb 100644
--- a/gdb/testsuite/gdb.base/bg-execution-repeat.exp
+++ b/gdb/testsuite/gdb.base/bg-execution-repeat.exp
@@ -67,6 +67,17 @@ proc test {continue_cmd} {
# enable the "set var" command with an interrupt / continue& pair.
gdb_test -no-prompt-anchor "interrupt"
+ set test "interrupt received"
+ set re [string_to_regexp "Program received signal SIGINT, Interrupt."]
+ gdb_expect {
+ -re $re {
+ pass $test
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+ }
+
# Allow the breakpoint to trigger.
gdb_test -no-prompt-anchor "set var do_wait=0"
diff --git a/gdb/testsuite/gdb.base/bp-cond-failure.exp b/gdb/testsuite/gdb.base/bp-cond-failure.exp
index d645454..4d03e7b 100644
--- a/gdb/testsuite/gdb.base/bp-cond-failure.exp
+++ b/gdb/testsuite/gdb.base/bp-cond-failure.exp
@@ -75,7 +75,7 @@ proc run_test { cond_eval access_type bpexpr nloc } {
"Error in testing condition for breakpoint ${bp_num}.2:" \
"Cannot access memory at address 0x0" \
"" \
- "Breakpoint ${bp_num}.2, foo \\(c=49 ...\\) at \[^\r\n\]+:\[0-9\]+" \
+ "(Thread \[^\r\n\]+ hit )?Breakpoint ${bp_num}.2, foo \\(c=49 ...\\) at \[^\r\n\]+:\[0-9\]+" \
"${::decimal}\\s+\[^\r\n\]+ breakpoint here\\. \[^\r\n\]+"]
} else {
gdb_test "continue" \
@@ -84,7 +84,7 @@ proc run_test { cond_eval access_type bpexpr nloc } {
"Error in testing condition for breakpoint ${bp_num}:" \
"Cannot access memory at address 0x0" \
"" \
- "Breakpoint ${bp_num}, bar \\(\\) at \[^\r\n\]+:\[0-9\]+" \
+ "(Thread \[^\r\n\]+ hit )?Breakpoint ${bp_num}, bar \\(\\) at \[^\r\n\]+:\[0-9\]+" \
"${::decimal}\\s+\[^\r\n\]+ breakpoint here\\. \[^\r\n\]+"]
}
}
diff --git a/gdb/testsuite/gdb.base/bp-permanent.c b/gdb/testsuite/gdb.base/bp-permanent.c
index d586acc..72e5e8a 100644
--- a/gdb/testsuite/gdb.base/bp-permanent.c
+++ b/gdb/testsuite/gdb.base/bp-permanent.c
@@ -101,7 +101,7 @@ test_signal_no_handler (void)
}
static void
-test_signal_nested_handler ()
+test_signal_nested_handler (int sig)
{
test ();
}
diff --git a/gdb/testsuite/gdb.base/bp-permanent.exp b/gdb/testsuite/gdb.base/bp-permanent.exp
index 62ce3f6..c6c6269 100644
--- a/gdb/testsuite/gdb.base/bp-permanent.exp
+++ b/gdb/testsuite/gdb.base/bp-permanent.exp
@@ -134,7 +134,7 @@ proc test {always_inserted sw_watchpoint} {
unsupported "failed to stop at permanent breakpoint"
return
}
- -re "Program received signal SIGTRAP.*$gdb_prompt $" {
+ -re "received signal SIGTRAP.*$gdb_prompt $" {
pass $test
}
}
@@ -174,7 +174,7 @@ proc test {always_inserted sw_watchpoint} {
# disabled, it should act as if we hadn't created it in the first
# place. IOW, we should get a random signal, and, the breakpoint's
# command should not run.
- gdb_test "continue" "Program received signal SIGTRAP.*" \
+ gdb_test "continue" "received signal SIGTRAP.*" \
"disabled permanent breakpoint doesn't explain stop"
gdb_test "info breakpoints" \
diff --git a/gdb/testsuite/gdb.base/break-dbg.cc b/gdb/testsuite/gdb.base/break-dbg.cc
new file mode 100644
index 0000000..642ded0
--- /dev/null
+++ b/gdb/testsuite/gdb.base/break-dbg.cc
@@ -0,0 +1,31 @@
+/* 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/>. */
+
+volatile int global_var = 0;
+
+int
+foo ()
+{
+ return global_var;
+}
+
+int
+main ()
+{
+ int res = foo ();
+ return res;
+}
diff --git a/gdb/testsuite/gdb.base/break-dbg.exp b/gdb/testsuite/gdb.base/break-dbg.exp
new file mode 100644
index 0000000..3652b8e
--- /dev/null
+++ b/gdb/testsuite/gdb.base/break-dbg.exp
@@ -0,0 +1,70 @@
+# 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/>. */
+
+# Some basic testing of 'set debug breakpoint on'. At one point a bug
+# meant that some breakpoints would immediately trigger a segfault if
+# GDB tried to run with breakpoint debugging turned on.
+#
+# Test is compiled as C++ only so 'catch catch/throw/rethrow' have a
+# something to do. The original bug would trigger for any 'catch'
+# style breakpoint, so C++ isn't really a hard requirement.
+
+standard_testfile .cc
+
+require allow_cplus_tests
+
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
+ {debug c++}] } {
+ return
+}
+
+if {![runto_main]} {
+ return
+}
+
+gdb_test "catch catch" "^Catchpoint $decimal \\(catch\\)"
+gdb_test "catch throw" "^Catchpoint $decimal \\(throw\\)"
+gdb_test "catch rethrow" "^Catchpoint $decimal \\(rethrow\\)"
+
+gdb_test "catch exec" "^Catchpoint $decimal \\(exec\\)"
+gdb_test "catch fork" "^Catchpoint $decimal \\(fork\\)"
+gdb_test "catch vfork" "^Catchpoint $decimal \\(vfork\\)"
+
+gdb_test "catch load" "^Catchpoint $decimal \\(load\\)"
+gdb_test "catch unload" "^Catchpoint $decimal \\(unload\\)"
+
+gdb_test "catch signal" "^Catchpoint $decimal \\(standard signals\\)"
+gdb_test "catch syscall" "^Catchpoint $decimal \\(any syscall\\)"
+
+gdb_test "watch -l global_var" "\[Ww]atchpoint $decimal: -location global_var"
+
+gdb_test_no_output "set debug breakpoint on"
+
+set saw_bp_debug_line false
+gdb_test_multiple "step" "" {
+ -re "^step\r\n" {
+ exp_continue
+ }
+ -re "^\\\[breakpoint\\\] \[^\r\n\]+\r\n" {
+ set saw_bp_debug_line true
+ exp_continue
+ }
+ -re "^$gdb_prompt $" {
+ gdb_assert { $saw_bp_debug_line } $gdb_test_name
+ }
+ -re "^\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+}
diff --git a/gdb/testsuite/gdb.base/break1.c b/gdb/testsuite/gdb.base/break1.c
index 110341c..26c4663 100644
--- a/gdb/testsuite/gdb.base/break1.c
+++ b/gdb/testsuite/gdb.base/break1.c
@@ -23,7 +23,13 @@ struct some_struct
{
int a_field;
int b_field;
- union { int z_field; };
+ union
+ {
+ struct
+ {
+ int z_field;
+ };
+ };
};
struct some_struct values[50];
diff --git a/gdb/testsuite/gdb.base/catch-fork-kill.exp b/gdb/testsuite/gdb.base/catch-fork-kill.exp
index 0fd853b..224a8df 100644
--- a/gdb/testsuite/gdb.base/catch-fork-kill.exp
+++ b/gdb/testsuite/gdb.base/catch-fork-kill.exp
@@ -32,6 +32,8 @@
standard_testfile
+require allow_fork_tests
+
# Build two programs -- one for fork, and another for vfork.
set testfile_fork "${testfile}-fork"
set testfile_vfork "${testfile}-vfork"
diff --git a/gdb/testsuite/gdb.base/catch-fork-static.exp b/gdb/testsuite/gdb.base/catch-fork-static.exp
index b171a6d..9d50d5d 100644
--- a/gdb/testsuite/gdb.base/catch-fork-static.exp
+++ b/gdb/testsuite/gdb.base/catch-fork-static.exp
@@ -21,9 +21,7 @@
# ld.so probes before reaching main, and ptrace flags were set then. But a
# static executable would just keep running and never catch the fork.
-# Until "catch fork" is implemented on other targets...
-#
-require {is_any_target "*-*-linux*" "*-*-openbsd*"}
+require allow_fork_tests
# Reusing foll-fork.c since it's a simple forking program.
standard_testfile foll-fork.c
diff --git a/gdb/testsuite/gdb.base/catch-signal-fork.exp b/gdb/testsuite/gdb.base/catch-signal-fork.exp
index dea0cc4..2a33ee1 100644
--- a/gdb/testsuite/gdb.base/catch-signal-fork.exp
+++ b/gdb/testsuite/gdb.base/catch-signal-fork.exp
@@ -14,6 +14,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
require {!target_info exists gdb,nosignals}
+require allow_fork_tests
standard_testfile
diff --git a/gdb/testsuite/gdb.base/coredump-filter-build-id.exp b/gdb/testsuite/gdb.base/coredump-filter-build-id.exp
index 7594cc2..eb5b489 100644
--- a/gdb/testsuite/gdb.base/coredump-filter-build-id.exp
+++ b/gdb/testsuite/gdb.base/coredump-filter-build-id.exp
@@ -28,7 +28,7 @@ if { ![istarget *-*-linux*] } {
untested "$testfile.exp"
return -1
}
-require is_x86_64_m64_target
+require is_x86_64_m64_target gcore_cmd_available
if { [prepare_for_testing "failed to prepare" $testfile $srcfile {debug build-id}] } {
return -1
diff --git a/gdb/testsuite/gdb.base/corefile-shmem-zero-id-lib.c b/gdb/testsuite/gdb.base/corefile-shmem-zero-id-lib.c
new file mode 100644
index 0000000..58fdec6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/corefile-shmem-zero-id-lib.c
@@ -0,0 +1,522 @@
+/* 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/>. */
+
+/* This file contains a library that can be preloaded into GDB on Linux
+ using the LD_PRELOAD technique.
+
+ The library intercepts calls to OPEN, CLOSE, READ, and PREAD in order to
+ fake the inode number of a shared memory mapping.
+
+ When GDB creates a core file (e.g. with the 'gcore' command), then
+ shared memory mappings should be included in the generated core file.
+
+ The 'id' for the shared memory mapping shares the inode slot in the
+ /proc/PID/smaps file, which is what GDB consults to decide which
+ mappings should be included in the core file.
+
+ It is possible for a shared memory mapping to have an 'id' of zero.
+
+ At one point there was a bug in GDB where mappings with an inode of zero
+ would not be included in the generated core file. This meant that most
+ shared memory mappings would be included in the generated core file,
+ but, if a shared memory mapping happened to get an 'id' of zero, then,
+ because this would appear as a zero inode in the smaps file, this shared
+ memory mapping would be excluded from the generated core file.
+
+ This preload library spots when GDB opens a /proc/PID/smaps file and
+ immediately copies the contents of this file into an internal buffer.
+ The buffer is then scanned looking for a shared memory mapping, and, if
+ a shared memory mapping is found, its 'id' (in the inode position) is
+ changed to zero.
+
+ Calls to read/pread are intercepted, and attempts to read from the smaps
+ file are then served from the modified buffer contents.
+
+ The close calls are monitored and, when the smaps file is closed, the
+ internal buffer is released.
+
+ This works with GDB (currently) because the requirements for access to
+ the smaps file are pretty simple. GDB opens the file and grabs the
+ entire contents with a single pread call and a large buffer. There's no
+ seeking within the file or anything like that.
+
+ The intention is that this library is preloaded into a GDB session which
+ is then used to start an inferior and generate a core file. GDB will
+ then see the zero inode for the shared memory mapping and should, if the
+ bug is correctly fixed, still add the shared memory mapping to the
+ generated core file. */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdbool.h>
+#include <assert.h>
+
+/* Logging. */
+
+static void
+log_msg (const char *fmt, ...)
+{
+#ifdef LOGGING
+ va_list ap;
+
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+#endif /* LOGGING */
+}
+
+/* Error handling, message and exit. */
+
+static void
+error (const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+
+ exit (EXIT_FAILURE);
+}
+
+/* The type of the open() function. */
+typedef int (*open_func_type)(const char *pathname, int flags, ...);
+
+/* The type of the close() function. */
+typedef int (*close_func_type)(int fd);
+
+/* The type of the read() function. */
+typedef ssize_t (*read_func_type)(int fd, void *buf, size_t count);
+
+/* The type of the pread() function. */
+typedef ssize_t (*pread_func_type) (int fd, void *buf, size_t count, off_t offset);
+
+/* Structure that holds information about a /proc/PID/smaps file that has
+ been opened. */
+struct interesting_file
+{
+ /* The file descriptor for the opened file. */
+ int fd;
+
+ /* The read offset within the file. Set to zero when the file is
+ opened. Any 'read' calls will update this offset. */
+ size_t offset;
+
+ /* The size of the contents within the buffer. This is not the total
+ buffer size (which might be larger). Attempts to read beyond SIZE
+ indicate an attempt to read beyond the end of the file. */
+ size_t size;
+
+ /* The (possibly modified) contents of the file. */
+ char *content;
+};
+
+/* We only track a single interesting file. Currently, for the use case
+ we imagine, GDB will only ever open one /proc/PID/smaps file at once. */
+struct interesting_file the_file = { -1, 0, 0, NULL };
+
+/* Update the contents of the global THE_FILE buffer. It is assumed that
+ the file contents have already been loaded into THE_FILE's content
+ buffer.
+
+ Look for any lines that represent a shared memory mapping and modify
+ the inode field (which holds the shared memory id) to be zero. */
+static void
+update_file_content_buffer (void)
+{
+ assert (the_file.content != NULL);
+
+ char *start = the_file.content;
+ do
+ {
+ /* Every line, even the last one, ends with a newline. */
+ char *end = strchrnul (start, '\n');
+ assert (end != NULL);
+ assert (*end != '\0');
+
+ /* Attribute lines start with an uppercase letter. The lines we want
+ to modify should start with a lower case hex character,
+ i.e. [0-9a-f]. Also, every line that we want to consider should
+ be long enough, but just in case, check the longest possible
+ filename that we care about. */
+ if (isxdigit (*start) && (isdigit (*start) || islower (*start))
+ && (end - start) > 23)
+ {
+ /* There are two possible filenames that we look for:
+ /SYSV%08x
+ /SYSV%08x (deleted)
+ The END pointer is pointing to the first character after the
+ filename.
+
+ Setup OFFSET to be the offset from END to the start of the
+ filename. As we check the filename we set OFFSET to 0 if the
+ filename doesn't match one of the expected patterns. */
+ size_t offset;
+ if (strncmp ((end - 13), "/SYSV", 5) == 0)
+ offset = 13;
+ else if (strncmp ((end - 23), "/SYSV", 5) == 0)
+ {
+ if (strncmp ((end - 10), " (deleted)", 10) == 0)
+ offset = 23;
+ else
+ offset = 0;
+ }
+ else
+ offset = 0;
+
+ for (int i = 0; i < 8 && offset != 0; ++i)
+ {
+ if (!isdigit (*(end - offset + 5 + i)))
+ offset = 0;
+ }
+
+ /* If OFFSET is non-zero then the filename on this line looks
+ like a shared memory mapping, and OFFSET is the offset from
+ END to the first character of the filename. */
+ if (offset != 0)
+ {
+ log_msg ("[LD_PRELOAD] shared memory entry: %.*s\n",
+ offset, (end - offset));
+
+ /* Set PTR to the first character before the filename. This
+ should be a white space character. */
+ char *ptr = end - offset - 1;
+ assert (isspace (*ptr));
+
+ /* Walk backwards until we find the inode field. */
+ while (isspace (*ptr))
+ --ptr;
+
+ /* Now replace every character in the inode field, except the
+ first one, with a space character. */
+ while (!isspace (*(ptr - 1)))
+ {
+ assert (isdigit (*ptr));
+ *ptr = ' ';
+ --ptr;
+ }
+
+ /* Replace the first character with '0'. */
+ assert (isdigit (*ptr));
+ *ptr = '0';
+
+ /* This print is checked for from GDB. */
+ printf ("[LD_PRELOAD] updated a shared memory mapping\n");
+ }
+ }
+
+ /* Update START to point to the next line. The last line of the
+ file will be empty. */
+ assert (*end == '\n');
+ start = end;
+ while (*start == '\n')
+ ++start;
+ }
+ while (*start != '\0');
+}
+
+/* Return true if PATHNAME has for form "/proc/PID/smaps" (without the
+ quotes). Otherwise, return false. */
+
+static bool
+is_smaps_file (const char *pathname)
+{
+ if (strncmp (pathname, "/proc/", 6) == 0)
+ {
+ int idx = 6;
+ while (isdigit (pathname[idx]))
+ idx++;
+ if (idx > 6 && strcmp (&pathname[idx], "/smaps") == 0)
+ return true;
+ }
+
+ return false;
+}
+
+/* Return true if PATHNAME should be considered interesting. PATHNAME is
+ interesting if it has the form /proc/PID/smaps, and there is no
+ interesting file already opened. */
+
+static bool
+is_interesting_pathname (const char *pathname)
+{
+ return the_file.fd == -1 && is_smaps_file (pathname);
+}
+
+/* Read the contents of an interesting file from FD (and open file
+ descriptor) into the global THE_FILE variable, making the file FD the
+ current interesting file. There should be no already open interesting
+ file when this function is called.
+
+ The contents of the file FD are read into a memory buffer and updated so
+ that any shared memory mappings listed within FD (which will be an smaps
+ file) will have the id zero. */
+
+static void
+read_interesting_file_contents (int fd)
+{
+#define BLOCK_SIZE 1024
+ /* Slurp contents into a local buffer. */
+ size_t buffer_size = 1024;
+ size_t offset = 0;
+
+ assert (the_file.size == 0);
+ assert (the_file.content == NULL);
+ assert (the_file.fd == -1);
+ assert (the_file.offset == 0);
+
+ do
+ {
+ the_file.content = (char *) realloc (the_file.content, buffer_size);
+ if (the_file.content == NULL)
+ error ("[LD_PRELOAD] Failed allocating memory: %s\n", strerror (errno));
+
+ ssize_t bytes_read = read (fd, the_file.content + offset, BLOCK_SIZE);
+ if (bytes_read == -1)
+ error ("[LD_PRELOAD] Failed reading file: %s\n", strerror (errno));
+
+ the_file.size += bytes_read;
+
+ if (bytes_read < BLOCK_SIZE)
+ break;
+
+ offset += BLOCK_SIZE;
+ buffer_size += BLOCK_SIZE;
+ }
+ while (true);
+
+ /* Add a null terminator. This makes the update easier. We know
+ there will be space because we only break out of the loop above
+ when the last read returns less than BLOCK_SIZE bytes. This means
+ we allocated an extra BLOCK_SIZE bytes, but didn't fill them all.
+ This means there must be at least 1 byte available for the null. */
+ the_file.content[the_file.size] = '\0';
+
+ /* Reset the seek pointer. */
+ if (lseek (fd, 0, SEEK_SET) == (off_t) -1)
+ error ("[LD_PRELOAD] Failed to lseek in file: %s\n", strerror (errno));
+
+ /* Record the file descriptor, this is used in read, pread, and close
+ in order to spot when we need to intercept the call. */
+ the_file.fd = fd;
+
+ update_file_content_buffer ();
+#undef BLOCK_SIZE
+}
+
+/* Intercept calls to 'open'. If this is an attempt to open a
+ /proc/PID/smaps file then intercept it, load the file contents into a
+ buffer and update the file contents. For all other open requests, just
+ forward to the real open function. */
+int
+open (const char *pathname, int flags, ...)
+{
+ /* Pointer to the real open function. */
+ static open_func_type real_open = NULL;
+
+ /* Mode is only used if the O_CREAT flag is set in FLAGS. */
+ mode_t mode = 0;
+
+ /* Set true if this is a /proc/PID/smaps file. */
+ bool is_interesting = is_interesting_pathname (pathname);
+
+ /* Check if O_CREAT is in flags. If it is, get the mode. */
+ if (flags & O_CREAT)
+ {
+ va_list args;
+ va_start (args, flags);
+ mode = va_arg (args, mode_t);
+ va_end (args);
+ }
+
+ /* Debug. */
+ if (is_interesting)
+ log_msg ("[LD_PRELOAD] Opening file: %s\n", pathname);
+
+ /* Make sure we have a pointer to the real open() function. */
+ if (real_open == NULL)
+ {
+ /* Get the address of the real open() function. */
+ real_open = (open_func_type) dlsym (RTLD_NEXT, "open");
+ if (real_open == NULL)
+ error ("[LD_PRELOAD] dlsym() error for 'open': %s\n", dlerror ());
+ }
+
+ /* Call the original open() function with the provided arguments. */
+ int res = -1;
+ if (flags & O_CREAT)
+ res = real_open (pathname, flags, mode);
+ else
+ res = real_open (pathname, flags);
+
+ if (res != -1 && is_interesting)
+ read_interesting_file_contents (res);
+
+ return res;
+}
+
+/* Like above, but for open64. */
+
+int
+open64 (const char *pathname, int flags, ...)
+{
+ /* Pointer to the real open64 function. */
+ static open_func_type real_open64 = NULL;
+
+ /* Mode is only used if the O_CREAT flag is set in FLAGS. */
+ mode_t mode = 0;
+
+ /* Set true if this is a /proc/PID/smaps file. */
+ bool is_interesting = is_interesting_pathname (pathname);
+
+ /* Check if O_CREAT is in flags. If it is, get the mode. */
+ if (flags & O_CREAT)
+ {
+ va_list args;
+ va_start (args, flags);
+ mode = va_arg (args, mode_t);
+ va_end (args);
+ }
+
+ /* Debug. */
+ if (is_interesting)
+ log_msg ("[LD_PRELOAD] Opening file: %s\n", pathname);
+
+ /* Make sure we have a pointer to the real open64() function. */
+ if (real_open64 == NULL)
+ {
+ /* Get the address of the real open64() function. */
+ real_open64 = (open_func_type) dlsym (RTLD_NEXT, "open64");
+ if (real_open64 == NULL)
+ error ("[LD_PRELOAD] dlsym() error for 'open64': %s\n", dlerror ());
+ }
+
+ /* Call the original open64() function with the provided arguments. */
+ int res = -1;
+ if (flags & O_CREAT)
+ res = real_open64 (pathname, flags, mode);
+ else
+ res = real_open64 (pathname, flags);
+
+ if (res != -1 && is_interesting)
+ read_interesting_file_contents (res);
+
+ return res;
+}
+
+/* Intercept the 'close' function. If this is a previously opened
+ interesting file then clean up. Otherwise, forward to the normal close
+ function. */
+int
+close (int fd)
+{
+ static close_func_type real_close = NULL;
+
+ if (fd == the_file.fd)
+ {
+ the_file.fd = -1;
+ free (the_file.content);
+ the_file.content = NULL;
+ the_file.offset = 0;
+ the_file.size = 0;
+ log_msg ("[LD_PRELOAD] Closing file.\n");
+ }
+
+ /* Make sure we have a pointer to the real open() function. */
+ if (real_close == NULL)
+ {
+ /* Get the address of the real open() function. */
+ real_close = (close_func_type) dlsym (RTLD_NEXT, "close");
+ if (real_close == NULL)
+ error ("[LD_PRELOAD] dlsym() error for 'close': %s\n", dlerror ());
+ }
+
+ return real_close (fd);
+}
+
+/* Intercept 'pread' calls. If this is a pread from a previously opened
+ interesting file, then read from the in memory buffer. Otherwise,
+ forward to the real pread function. */
+ssize_t
+pread (int fd, void *buf, size_t count, off_t offset)
+{
+ static pread_func_type real_pread = NULL;
+
+ if (fd == the_file.fd)
+ {
+ size_t max;
+
+ if (offset > the_file.size)
+ max = 0;
+ else
+ max = the_file.size - offset;
+ if (count > max)
+ count = max;
+
+ memcpy (buf, the_file.content + offset, count);
+ log_msg ("[LD_PRELOAD] Read from file.\n");
+ return count;
+ }
+
+ if (real_pread == NULL)
+ {
+ /* Get the address of the real read() function. */
+ real_pread = (pread_func_type) dlsym (RTLD_NEXT, "pread");
+ if (real_pread == NULL)
+ error ("[LD_PRELOAD] dlsym() error for 'pread': %s\n", dlerror ());
+ }
+
+ return real_pread (fd, buf, count, offset);
+}
+
+/* Intercept 'read' calls. If this is a read from a previously opened
+ interesting file, then read from the in memory buffer. Otherwise,
+ forward to the real read function. */
+ssize_t
+read (int fd, void *buf, size_t count)
+{
+ static read_func_type real_read = NULL;
+
+ if (fd == the_file.fd)
+ {
+ ssize_t bytes_read = pread (fd, buf, count, the_file.offset);
+ if (bytes_read > 0)
+ the_file.offset += bytes_read;
+ return bytes_read;
+ }
+
+ if (real_read == NULL)
+ {
+ /* Get the address of the real read() function. */
+ real_read = (read_func_type) dlsym (RTLD_NEXT, "read");
+ if (real_read == NULL)
+ error ("[LD_PRELOAD] dlsym() error for 'read': %s\n", dlerror ());
+ }
+
+ return real_read (fd, buf, count);
+}
diff --git a/gdb/testsuite/gdb.base/corefile-shmem-zero-id.c b/gdb/testsuite/gdb.base/corefile-shmem-zero-id.c
new file mode 100644
index 0000000..92d2edf
--- /dev/null
+++ b/gdb/testsuite/gdb.base/corefile-shmem-zero-id.c
@@ -0,0 +1,63 @@
+/* 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/>. */
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <time.h>
+
+void
+breakpt (void)
+{
+ /* Nothing. */
+}
+
+int
+main (void)
+{
+ /* Create a shared memory mapping. */
+ int sid = shmget (IPC_PRIVATE, 0x1000, IPC_CREAT | IPC_EXCL | 0777);
+ if (sid == -1)
+ {
+ perror ("shmget");
+ exit (1);
+ }
+
+ /* Attach the shared memory mapping. */
+ void *addr = shmat (sid, NULL, SHM_RND);
+ if (addr == (void *) -1L)
+ {
+ perror ("shmat");
+ exit (1);
+ }
+
+ breakpt ();
+
+ /* Mark the shared memory mapping as deleted -- once the last user
+ has finished with it. */
+ if (shmctl (sid, IPC_RMID, NULL) != 0)
+ {
+ perror ("shmctl");
+ exit (1);
+ }
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/corefile-shmem-zero-id.exp b/gdb/testsuite/gdb.base/corefile-shmem-zero-id.exp
new file mode 100644
index 0000000..57c665e
--- /dev/null
+++ b/gdb/testsuite/gdb.base/corefile-shmem-zero-id.exp
@@ -0,0 +1,228 @@
+# 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 test script tries to check GDB's ability to create a core file
+# (e.g. with 'gcore' command) when there's a shared memory mapping
+# with the id zero.
+#
+# Testing this case is hard. Older kernels don't even seem to give
+# out the shared memory id zero. And on new kernels you still cannot
+# guarantee to grab the zero id for testing; the id might be in use by
+# some other process, or the kernel might just not give out that id
+# for some other reason.
+#
+# To figure out which mappings to include in the core file, GDB reads
+# the /proc/PID/smaps file. There is a field in this file which for
+# file backed mappings, holds the inode of the file. But for shared
+# memory mappings this field holds the shared memory id. The problem
+# was that GDB would ignore any entry in /proc/PID/smaps with an inode
+# entry of zero, which would catch the shared memory mapping with a
+# zero id.
+#
+# There was an attempt to write a test which spammed out requests for
+# shared memory mappings and tried to find the one with id zero, but
+# this was still really unreliable.
+#
+# This test takes a different approach. We compile a library which we
+# preload into the GDB process. This library intercepts calls to
+# open, close, read, and pread, and watches for an attempt to open the
+# /proc/PID/smaps file.
+#
+# When we see that file being opened, we copy the file contents into a
+# memory buffer and modify the buffer so that the inode field for any
+# shared memory mappings is set to zero. We then intercept calls to
+# read and pread and return results from that in memory buffer.
+#
+# The test executable itself create a shared memory mapping (which
+# might have any id).
+#
+# GDB, with the pre-load library in place, start the inferior and then
+# uses the 'gcore' command to dump a core file. When GDB opens the
+# smaps file and reads from it, the preload library ensures that GDB
+# sees an inode of zero.
+#
+
+# This test only works on Linux
+require isnative
+require {!is_remote host}
+require {!is_remote target}
+require {istarget *-linux*}
+require gcore_cmd_available
+
+standard_testfile .c -lib.c
+
+set libfile ${testfile}-lib
+set libobj [standard_output_file ${libfile}.so]
+
+# Compile the preload library. We only get away with this as we
+# limit this test to running when ISNATIVE is true.
+if { [build_executable "build preload lib" $libobj $srcfile2 \
+ {debug shlib libs=-ldl}] == -1 } {
+ return
+}
+
+# Now compile the inferior executable.
+if {[build_executable "build executable" $testfile $srcfile] == -1} {
+ return
+}
+
+# Spawn GDB with LIBOBJ preloaded using LD_PRELOAD.
+save_vars { env(LD_PRELOAD) env(ASAN_OPTIONS) } {
+ if { ![info exists env(LD_PRELOAD) ]
+ || $env(LD_PRELOAD) == "" } {
+ set env(LD_PRELOAD) "$libobj"
+ } else {
+ append env(LD_PRELOAD) ":$libobj"
+ }
+
+ # Prevent address sanitizer error:
+ # ASan runtime does not come first in initial library list; you should
+ # either link runtime to your application or manually preload it with
+ # LD_PRELOAD.
+ append_environment_default ASAN_OPTIONS verify_asan_link_order 0
+
+ clean_restart $binfile
+
+ # Start GDB with the modified environment, this means that, when
+ # using remote targets, gdbserver will also use the preload
+ # library.
+ if {![runto_main]} {
+ return
+ }
+}
+
+gdb_breakpoint breakpt
+gdb_continue_to_breakpoint "run to breakpt"
+
+# Check the /proc/PID/smaps file itself. The call to 'cat' should
+# inherit the preload library, so should see the modified file
+# contents. Check that the shared memory mapping line has an id of
+# zero. This confirms that the preload library is working. If the
+# preload library breaks then we'll start seeing non-zero shared
+# memory ids, which always worked, so we'd never know that this test
+# is broken!
+#
+# This check ensures the test is working as expected.
+set shmem_line_count 0
+set fixup_line_count 0
+set inf_pid [get_inferior_pid]
+gdb_test_multiple "shell cat /proc/${inf_pid}/smaps" "check smaps" {
+ -re "^\\\[LD_PRELOAD\\\] updated a shared memory mapping\r\n" {
+ incr fixup_line_count
+ exp_continue
+ }
+ -re "^\[^\r\n\]+($decimal)\\s+/SYSV\[0-9\]{8}(?: \\(deleted\\))?\r\n" {
+ set id $expect_out(1,string)
+ if { $id == 0 } {
+ incr shmem_line_count
+ }
+ exp_continue
+ }
+ -re "^$gdb_prompt $" {
+ with_test_prefix $gdb_test_name {
+ gdb_assert { $shmem_line_count == 1 } \
+ "single shared memory mapping found"
+ gdb_assert { $fixup_line_count == 1 } \
+ "single fixup line found"
+ }
+ }
+ -re "^\[^\r\n\]+\r\n" {
+ exp_continue
+ }
+}
+
+# Now generate a core file. This will use the preload library to read
+# the smaps file. The code below is copied from 'proc gdb_gcore_cmd',
+# but we don't use that as we also look for a message that is printed
+# by the LD_PRELOAD library. This is an extra level of check that the
+# preload library is triggering when needed.
+set corefile [standard_output_file ${testfile}.core]
+set saw_ld_preload_msg false
+set saw_saved_msg false
+with_timeout_factor 3 {
+ gdb_test_multiple "gcore $corefile" "save core file" {
+ -re "^\\\[LD_PRELOAD\\\] updated a shared memory mapping\r\n" {
+ # GDB actually reads the smaps file multiple times when
+ # creating a core file, so we'll see multiple of these
+ # fixup lines.
+ set saw_ld_preload_msg true
+ exp_continue
+ }
+ -re "^Saved corefile \[^\r\n\]+\r\n" {
+ set saw_saved_msg true
+ exp_continue
+ }
+ -re "^$gdb_prompt $" {
+ with_test_prefix $gdb_test_name {
+ gdb_assert { $saw_saved_msg } \
+ "saw 'Saved corefile' message"
+
+ # If we're using a remote target then the message from
+ # the preload library will go to gdbservers stdout,
+ # not GDB's, so don't check for it.
+ if { [gdb_protocol_is_native] } {
+ gdb_assert { $saw_ld_preload_msg } \
+ "saw LD_PRELOAD message from library"
+ }
+ }
+ }
+ -re "^\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+ }
+}
+
+# Restart GDB. This time we are _not_ using the preload library. We
+# no longer need it as we are only analysing the core file now.
+clean_restart $binfile
+
+# Load the core file.
+gdb_test "core-file $corefile" \
+ "Program terminated with signal SIGTRAP, Trace/breakpoint trap\\..*" \
+ "load core file"
+
+# Look through the mappings. We _should_ see the shared memory
+# mapping. We _should_not_ see any of the special '[blah]' style
+# mappings, e.g. [vdso], [vstack], [vsyscalls], etc.
+set saw_special_mapping false
+set saw_shmem_mapping false
+gdb_test_multiple "info proc mappings" "" {
+ -re "\r\nStart Addr\[^\r\n\]+File\\s*\r\n" {
+ exp_continue
+ }
+
+ -re "^$hex\\s+$hex\\s+$hex\\s+$hex\\s+\\\[\\S+\\\]\\s*\r\n" {
+ set saw_special_mapping true
+ exp_continue
+ }
+
+ -re "^$hex\\s+$hex\\s+$hex\\s+$hex\\s+/SYSV\[0-9\]+ \\(deleted\\)\\s*\r\n" {
+ set saw_shmem_mapping true
+ exp_continue
+ }
+
+ -re "^$hex\\s+$hex\\s+$hex\\s+$hex\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+
+ -re "^$gdb_prompt $" {
+ with_test_prefix $gdb_test_name {
+ gdb_assert { $saw_shmem_mapping } \
+ "check shared memory mapping exists"
+ gdb_assert { !$saw_special_mapping } \
+ "check no special mappings added"
+ }
+ }
+}
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index d4d6b20..01e3cc1 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -253,10 +253,39 @@ gdb_test "h" "List of classes of commands:(\[^\r\n\]*\[\r\n\])+aliases -- User-d
gdb_test "help" "List of classes of commands:(\[^\r\n\]*\[\r\n\])+aliases -- User-defined aliases of other commands(\[^\r\n\]*\[\r\n\])+breakpoints -- Making program stop at certain points(\[^\r\n\]*\[\r\n\])+data -- Examining data(\[^\r\n\]*\[\r\n\])+files -- Specifying and examining files(\[^\r\n\]*\[\r\n\])+obscure -- Obscure features(\[^\r\n\]*\[\r\n\])+running -- Running the program(\[^\r\n\]*\[\r\n\])+stack -- Examining the stack(\[^\r\n\]*\[\r\n\])+status -- Status inquiries(\[^\r\n\]*\[\r\n\])+support -- Support facilities(\[^\r\n\]*\[\r\n\])+user-defined -- User-defined commands(\[^\r\n\]*\[\r\n\])+Type \"help\" followed by a class name for a list of commands in that class.(\[^\r\n\]*\[\r\n\])+Type \"help\" followed by command name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous."
#test handle
gdb_test "handle" "Argument required .signal to handle.*"
-#test info "i" abbreviation
-gdb_test "i" "List of \"info\" subcommands:(\[^\r\n\]*\[\r\n\])+Type \"help info\" followed by subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "info \"i\" abbreviation"
+
+proc test_info_command { command message } {
+ set saw_info_header 0
+ set saw_help_info 0
+ set saw_command_abbrev 0
+ gdb_test_multiple $command $message -lbl {
+ -re "\r\nList of \"info\" subcommands:" {
+ verbose "Info header displayed"
+ set saw_info_header 1
+ exp_continue
+ }
+ -re "Type \"help info\" followed by subcommand name for full documentation\\." {
+ verbose "Help info displayed"
+ set saw_help_info 1
+ exp_continue
+ }
+ -re "\r\nCommand name abbreviations are allowed if unambiguous\\." {
+ verbose "Command name abbreviations displayed"
+ set saw_command_abbrev 1
+ exp_continue
+ }
+ -re -wrap "" {
+ gdb_assert { $saw_info_header && $saw_help_info
+ && $saw_command_abbrev } $gdb_test_name
+ }
+ }
+}
+
+#test info "i" abbreviation
+test_info_command "i" "info \"i\" abbreviation"
#test info
-gdb_test "info" "List of \"info\" subcommands:(\[^\r\n\]*\[\r\n\])+Type \"help info\" followed by subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous."
+test_info_command "info" "info"
+
#test ignore
gdb_test "ignore" "Argument required .a breakpoint number.*"
#test info address
@@ -379,38 +408,52 @@ gdb_test "info registers" "The program has no registers now."
gdb_test "info s" "No stack." "info stack \"s\" abbreviation"
#test info stack
gdb_test "info stack" "No stack."
-#test info set
-# Test improved to check three parts:
-# 1) confirm
-# 2) prompt
-# 3) write
-# And only succeed if all three are matched.
-# This should fix an old problem on native solaris 2.8,
-# where this test fails due to this line:
+
+#test "info set" and "show" commands
+# The test needs to match the "prompt: ..." part to fix an old problem on native
+# Solaris 2.8, where this test fails due to this line:
# prompt: Gdb's prompt is "(gdb) ".^M
-set set_confirm_seen 0
-set set_prompt_seen 0
-gdb_test_multiple "info set" "info set" {
- -re "confirm: Whether to confirm potentially dangerous operations is o\[a-z\]*.(\[^\r\n\]*\[\r\n\])+history filename: The filename in which to record the command history is (\[^\r\n\]*\[\r\n\])+listsize: Number of source lines gdb will list by default is 10" {
- verbose "Confirm dislayed"
- set set_confirm_seen 1
- exp_continue
- }
- -re "Gdb's prompt is \"$gdb_prompt \"" {
- verbose "GDB prompt displayed"
- set set_prompt_seen 1
- exp_continue
- }
- -re "Writing into executable.*$gdb_prompt $" {
- verbose "write displayed"
- if { $set_prompt_seen && $set_confirm_seen } {
- pass "info set"
- } else {
- verbose "prompt $set_prompt_seen confirm $set_confirm_seen"
- fail "info set (incomplete output)"
+proc test_info_set_show { command } {
+ set set_confirm_seen 0
+ set set_history_filename_seen 0
+ set set_listsize_seen 0
+ set set_prompt_seen 0
+ set set_write_seen 0
+ gdb_test_multiple $command $command -lbl {
+ -re "\r\nconfirm: Whether to confirm potentially dangerous operations is o\[a-z\]+\\." {
+ verbose "Confirm displayed"
+ set set_confirm_seen 1
+ exp_continue
+ }
+ -re "\r\nhistory filename: The filename in which to record the command history is \[^\r\n\]+\\." {
+ verbose "History filename displayed"
+ set set_history_filename_seen 1
+ exp_continue
+ }
+ -re "\r\nlistsize: Number of source lines gdb will list by default is 10\\." {
+ verbose "Listsize displayed"
+ set set_listsize_seen 1
+ exp_continue
+ }
+ -re "\r\nprompt: Gdb's prompt is \"$::gdb_prompt \"" {
+ verbose "GDB prompt displayed"
+ set set_prompt_seen 1
+ exp_continue
+ }
+ -re "write: Writing into executable and core files is o\[a-z\]+\\." {
+ verbose "Write displayed"
+ set set_write_seen 1
+ exp_continue
+ }
+ -re -wrap "" {
+ gdb_assert { $set_confirm_seen && $set_history_filename_seen
+ && $set_listsize_seen && $set_prompt_seen
+ && $set_write_seen } $gdb_test_name
}
}
}
+test_info_set_show "info set"
+
gdb_test "info symbol" "Argument required .address.."
#test info source
gdb_test "info source" "No current source file..*"
@@ -591,12 +634,41 @@ gdb_test "set history" "List of \"set history\" subcommands:(\[^\r\n\]*\[\r\n\])
gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, asm, c, c.., d, fortran, go, minimal, modula-2, objective-c, opencl, pascal, rust."
#test set listsize
gdb_test "set listsize" "Argument required .integer to set it to.*"
+
+proc test_set_print { command message } {
+ set saw_info_header 0
+ set saw_help_info 0
+ set saw_command_abbrev 0
+ gdb_test_multiple $command $message -lbl {
+ -re "\r\nList of \"set print\" subcommands:" {
+ verbose "Info header displayed"
+ set saw_info_header 1
+ exp_continue
+ }
+ -re "Type \"help set print\" followed by subcommand name for full documentation\\." {
+ verbose "Help info displayed"
+ set saw_help_info 1
+ exp_continue
+ }
+ -re "\r\nCommand name abbreviations are allowed if unambiguous\\." {
+ verbose "Command name abbreviations displayed"
+ set saw_command_abbrev 1
+ exp_continue
+ }
+ -re -wrap "" {
+ gdb_assert { $saw_info_header && $saw_help_info
+ && $saw_command_abbrev } $gdb_test_name
+ }
+ }
+}
+
#test set print "p" abbreviation
-gdb_test "set p" "List of \"set print\" subcommands:(\[^\r\n\]*\[\r\n\])+Type \"help set print\" followed by subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "set print \"p\" abbreviation"
+test_set_print "set p" "set print \"p\" abbreviation"
#test set print "pr" abbreviation
-gdb_test "set pr" "List of \"set print\" subcommands:(\[^\r\n\]*\[\r\n\])+Type \"help set print\" followed by subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "set print \"pr\" abbreviation"
+test_set_print "set pr" "set print \"pr\" abbreviation"
#test set print
-gdb_test "set print" "List of \"set print\" subcommands:(\[^\r\n\]*\[\r\n\])+Type \"help set print\" followed by subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous."
+test_set_print "set print" "set print"
+
#test set print address
gdb_test_no_output "set print address" "set print address"
#test set print array
@@ -699,6 +771,8 @@ set show_conv_list \
{$_gdb_minor = 1} \
{$_shell_exitsignal = void} \
{$_shell_exitcode = 0} \
+ {$_active_linker_namespaces = 1} \
+ {$_linker_namespace = <error: No registers.>}\
}
if [allow_python_tests] {
append show_conv_list \
@@ -739,12 +813,47 @@ gdb_test "show history" "history expansion: *History expansion on command input
gdb_test "show language" "The current source language is \"auto; currently c\"."
#test show listsize
gdb_test "show listsize" "Number of source lines gdb will list by default is 10."
+
+proc test_show_print { command } {
+ set saw_print_address 0
+ set saw_print_frame_args 0
+ set saw_print_symbol 0
+ set saw_print_vtbl 0
+ gdb_test_multiple $command $command -lbl {
+ -re "\r\nprint address: Printing of addresses is o\[a-z\]+\\." {
+ verbose "Print address displayed"
+ set saw_print_address 1
+ exp_continue
+ }
+ -re "\r\nprint frame-arguments: Printing of non-scalar frame arguments is \[^\r\n\]+\\." {
+ verbose "Print frame-arguments displayed"
+ set saw_print_frame_args 1
+ exp_continue
+ }
+ -re "\r\nprint symbol: Printing of symbols when printing pointers is o\[a-z\]+\\." {
+ verbose "Print symbol displayed"
+ set saw_print_symbol 1
+ exp_continue
+ }
+ -re "\r\nprint vtbl: Printing of C\\+\\+ virtual function tables is o\[a-z\]+\\." {
+ verbose "Print vtbl displayed"
+ set saw_print_vtbl 1
+ exp_continue
+ }
+ -re -wrap "" {
+ gdb_assert { $saw_print_address && $saw_print_frame_args
+ && $saw_print_symbol && $saw_print_vtbl } $gdb_test_name
+ }
+ }
+}
+
#test show print "p" abbreviation
-gdb_test "show p" ".*"
+test_show_print "show p"
#test show print "pr" abbreviation
-gdb_test "show pr" ".*"
+test_show_print "show pr"
#test show print
-gdb_test "show print" ".*"
+test_show_print "show print"
+
#test show paths
gdb_test "show paths" "Executable and object file path:.*"
#test show print address
@@ -790,30 +899,10 @@ gdb_test "show width" "Number of characters gdb thinks are in a line is.*"
#test show write
# This is only supported on targets which use exec.o.
gdb_test "show write" "Writing into executable and core files is o.*"
+
#test show
-set show_confirm_seen 0
-set show_prompt_seen 0
-gdb_test_multiple "show" "show" {
- -re "confirm: *Whether to confirm potentially dangerous operations is on.(\[^\r\n\]*\[\r\n\])+history filename: *The filename in which to record the command history is (\[^\r\n\]*\[\r\n\])+history save: *Saving of the history record on exit is on.(\[^\r\n\]*\[\r\n\])+history size: *The size of the command history is(\[^\r\n\]*\[\r\n\])+listsize: *Number of source lines gdb will list by default is 10(\[^\r\n]*\[\r\n\])+print elements: *Limit on string chars or array elements to print is 200." {
- verbose "Confirm displayed"
- set show_confirm_seen 1
- exp_continue
- }
- -re "Gdb's prompt is \"$gdb_prompt \"" {
- verbose "GDB prompt displayed"
- set show_prompt_seen 1
- exp_continue
- }
- -re "Writing into executable.*$gdb_prompt $" {
- verbose "write displayed"
- if { $show_prompt_seen && $show_confirm_seen } {
- pass "show"
- } else {
- verbose "prompt $show_prompt_seen confirm $show_confirm_seen"
- fail "show (incomplete output)"
- }
- }
-}
+test_info_set_show "show"
+
#history saving should stay disabled
gdb_test_no_output "set history save off" "set history save off"
#test stepi "si" abbreviation
diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c b/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c
index 3bcd819..c7c038a 100644
--- a/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c
+++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c
@@ -41,6 +41,12 @@ main (void)
handle[2] = dlmopen (LM_ID_NEWLM, DSO_NAME, RTLD_LAZY | RTLD_LOCAL);
assert (handle[2] != NULL);
+ for (dl = 2; dl >= 0; dl--)
+ {
+ fun = dlsym (handle[dl], "inc");
+ fun (dl);
+ }
+
dlclose (handle[0]); /* TAG: first dlclose */
dlclose (handle[1]); /* TAG: second dlclose */
dlclose (handle[2]); /* TAG: third dlclose */
diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
index 3ddc07e..4d3e8eb 100644
--- a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
+++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
@@ -105,4 +105,149 @@ proc test_info_shared {} {
"after unloading everything"
}
+# Run all tests related to the linkage namespaces convenience
+# variables, _active_namespaces and _current_namespaces.
+proc_with_prefix test_conv_vars {} {
+ clean_restart $::binfile
+
+ gdb_test "print \$_active_linker_namespaces" "1" \
+ "1 namespace before starting inferior"
+ gdb_test "print \$_linker_namespace" "No registers." \
+ "No current namespace before starting inferior"
+
+ if { ![runto_main] } {
+ return
+ }
+
+ gdb_test "print \$_active_linker_namespaces" "1" \
+ "Before activating namespaces"
+ gdb_test "print \$_linker_namespace" ".* = 0" \
+ "Still in the default namespace"
+
+ gdb_breakpoint "inc" allow-pending
+ gdb_breakpoint [gdb_get_line_number "TAG: first dlclose"]
+
+ foreach_with_prefix dl {3 2 1} {
+ gdb_continue_to_breakpoint "inc"
+
+ gdb_test "print \$_linker_namespace" ".* = $dl" \
+ "Verify we're in namespace $dl"
+ }
+
+ # Check that we display the namespace of the selected
+ # frame, not the lowermost one.
+ gdb_test "up" "\#1.*in main.*"
+ gdb_test "print \$_linker_namespace" ".* = 0" \
+ "print namespace of selected frame"
+
+ gdb_continue_to_breakpoint "first dlclose"
+ gdb_test "print \$_active_linker_namespaces" "4" "all SOs loaded"
+
+ gdb_test "next" ".*second dlclose.*" "close one SO"
+ gdb_test "print \$_active_linker_namespaces" "3" "one SOs unloaded"
+ gdb_test "next" ".*third dlclose.*" "close another SO"
+ gdb_test "print \$_active_linker_namespaces" "2" "two SOs unloaded"
+
+ # Restarting GDB so that we can test setting a breakpoint
+ # using the convenience variable, while a proper bp syntax
+ # isn't implemented for namespaces
+ clean_restart $::binfile
+ if {![runto_main]} {
+ return
+ }
+
+ # We need to load one SO because you can't have confitional
+ # breakpoints and pending breakpoints at the same time with
+ # gdb_breakpoint.
+ gdb_test "next" ".*assert.*" "load the first SO"
+ gdb_breakpoint "inc if \$_linker_namespace == 2"
+ gdb_continue_to_breakpoint "inc"
+ gdb_continue_to_end "" continue 1
+}
+
+# Run several tests relating to the command "info namespaces".
+proc test_info_linker_namespaces {} {
+ clean_restart $::binfile
+
+ # Check that "info linker-namespaces" while the inferior is not running
+ # doesn't crash.
+ gdb_test "info linker-namespaces" \
+ "Current inferior does not support linker namespaces\\. Use \"info sharedlibrary\" instead\\." \
+ "info linker-namespaces before running"
+
+ if { ![runto_main] } {
+ return
+ }
+
+ with_test_prefix "info linker-namespaces" {
+ gdb_breakpoint [gdb_get_line_number "TAG: first dlclose"]
+ gdb_continue_to_breakpoint "TAG: first dlclose"
+ }
+
+ # First, test printing a single namespace, and ensure all of
+ # them are correct, using both syntaxes.
+ set found_all_libs false
+ gdb_test_multiple "info linker-namespaces \[\[0\]\]" "print namespace 0" -lbl {
+ -re "^\r\nThere are ($::decimal) libraries loaded in linker namespace \\\[\\\[0\\\]\\\]" {
+ # Some systems may add libc and libm to every loaded namespace,
+ # others may load only one or neither, because the SO doesn't
+ # actually use either library. The best we can do is check if
+ # we found the dynamic linker, and up to 2 more libraries.
+ set libs $expect_out(1,string)
+ set found_all_libs [expr $libs - 1 <= 2]
+ exp_continue
+ }
+ -re "^\r\n$::gdb_prompt $" {
+ gdb_assert $found_all_libs "the correct number of libraries was reported"
+ }
+ -re "(^\r\n)?\[^\r\n\]+(?=\r\n)" {
+ exp_continue
+ }
+ }
+ foreach_with_prefix ns {1 2 3} {
+ set found_test_so false
+ set found_all_libs false
+ gdb_test_multiple "info linker-namespaces $ns" "print namespace $ns" -lbl {
+ -re "^\r\nThere are ($::decimal) libraries loaded in linker namespace \\\[\\\[$ns\\\]\\\]" {
+ set libs $expect_out(1,string)
+ # Some systems may add libc and libm to every loaded namespace,
+ # others may load only one or neither, because the SO doesn't
+ # actually use either library. The best we can do is check if
+ # we found the dynamic linker, the test SO, and maybe up to 2
+ # more libraries.
+ set found_all_libs [expr $libs - 2 <= 2]
+ exp_continue
+ }
+ -re "^\r\n\[^\r\n\]+${::binfile_lib}\[^\r\n\]*(?=\r\n)" {
+ set found_test_so true
+ exp_continue
+ }
+ -re "^\r\n$::gdb_prompt $" {
+ gdb_assert $found_test_so "this testfle's SO was reported"
+ gdb_assert $found_all_libs "the correct number of libraries was reported"
+ }
+ -re "(^\r\n)?\[^\r\n\]+(?=\r\n)" {
+ exp_continue
+ }
+ }
+ }
+
+ # These patterns are simpler, and purposefully glob multiple lines.
+ # The point is to ensure that we find and display all the namespaces,
+ # without worrying about the libraries printed, since that was tested
+ # above.
+ gdb_test "info linker-namespaces" \
+ [multi_line "There are 4 linker namespaces loaded" \
+ "There are $::decimal libraries loaded in linker namespace ..0.." \
+ ".*" \
+ "There are $::decimal libraries loaded in linker namespace ..1.." \
+ ".*" \
+ "There are $::decimal libraries loaded in linker namespace ..2.." \
+ ".*" \
+ "There are $::decimal libraries loaded in linker namespace ..3.." \
+ ".*" ] "print namespaces with no argument"
+}
+
test_info_shared
+test_conv_vars
+test_info_linker_namespaces
diff --git a/gdb/testsuite/gdb.base/exprs.exp b/gdb/testsuite/gdb.base/exprs.exp
index eb2d0e4..f703c18 100644
--- a/gdb/testsuite/gdb.base/exprs.exp
+++ b/gdb/testsuite/gdb.base/exprs.exp
@@ -284,3 +284,21 @@ gdb_test "print v_short + " \
# Test for a syntax error in the middle of an expression.
gdb_test "print v_short =}{= 3" \
"A syntax error in expression, near `\\}\\{= 3'\\."
+
+gdb_test_no_output "set debug parse 1"
+set saw_start 0
+set saw_val 0
+gdb_test_multiple "print 23" "print with debugging" -lbl {
+ -re "\r\nStarting parse(?=\r\n)" {
+ set saw_start 1
+ exp_continue
+ }
+ -re "\r\n.$decimal = 23(?=\r\n)" {
+ set saw_val 1
+ exp_continue
+ }
+
+ -re -wrap "" {
+ gdb_assert {$saw_start && $saw_val} $gdb_test_name
+ }
+}
diff --git a/gdb/testsuite/gdb.base/filename-completion.exp b/gdb/testsuite/gdb.base/filename-completion.exp
index cb3fc90..c10941c 100644
--- a/gdb/testsuite/gdb.base/filename-completion.exp
+++ b/gdb/testsuite/gdb.base/filename-completion.exp
@@ -385,7 +385,7 @@ proc run_quoting_and_escaping_tests { root } {
remove-symbol-file \
"target core" "target exec" "target tfile" \
"maint print c-tdesc" "save gdb-index"
- "save gdb-index -dwarf-5" }
+ "save gdb-index -dwarf-5" "shell ls"}
if { [allow_compile_tests] } {
lappend all_cmds "compile file"
}
@@ -408,6 +408,31 @@ proc run_quoting_and_escaping_tests { root } {
run_quoting_and_escaping_tests_1 $root $cmd
}
}
+
+ # Some additional testing of shell command. Test 'shell' and '!'
+ # when there are multiple filenames on the command line. This
+ # focuses on completion of the final filename. There is also some
+ # testing of the shell command above, this tests completion within
+ # the line.
+ foreach_with_prefix shell_cmd { "shell " "!" "pipe print 1 | " } {
+ foreach suffix { "aaa/aa bb" "bb2/dir 1/unique file" } {
+ set dir $root/$suffix
+
+ regsub -all " " "$dir" "\\ " dir_with_backslash
+
+ with_test_prefix "suffix='$suffix'" {
+ with_test_prefix "with_backslash" {
+ run_quoting_and_escaping_tests_1 $root "${shell_cmd}ls $dir_with_backslash"
+ }
+ with_test_prefix "with double quotes" {
+ run_quoting_and_escaping_tests_1 $root "${shell_cmd}ls \"$dir\""
+ }
+ with_test_prefix "with single quotes" {
+ run_quoting_and_escaping_tests_1 $root "${shell_cmd}ls '$dir'"
+ }
+ }
+ }
+ }
}
# Helper for run_unquoted_tests. ROOT is the root directory as setup
diff --git a/gdb/testsuite/gdb.base/foll-exec-c++.exp b/gdb/testsuite/gdb.base/foll-exec-c++.exp
new file mode 100644
index 0000000..d96310b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/foll-exec-c++.exp
@@ -0,0 +1,24 @@
+# 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 part of the gdb testsuite
+
+# See foll-exec.exp.tcl for test details. This file runs the test
+# using the C++ compiler.
+
+require allow_cplus_tests
+set lang c++
+
+source $srcdir/$subdir/foll-exec.exp.tcl
diff --git a/gdb/testsuite/gdb.base/foll-exec-c.exp b/gdb/testsuite/gdb.base/foll-exec-c.exp
new file mode 100644
index 0000000..67f62cc
--- /dev/null
+++ b/gdb/testsuite/gdb.base/foll-exec-c.exp
@@ -0,0 +1,23 @@
+# 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 part of the gdb testsuite
+
+# See foll-exec.exp.tcl for test details. This file runs the test
+# using the C compiler.
+
+set lang c
+
+source $srcdir/$subdir/foll-exec.exp.tcl
diff --git a/gdb/testsuite/gdb.base/foll-exec.c b/gdb/testsuite/gdb.base/foll-exec.c
index a1c9b70..291f803 100644
--- a/gdb/testsuite/gdb.base/foll-exec.c
+++ b/gdb/testsuite/gdb.base/foll-exec.c
@@ -19,25 +19,38 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
-
+#include <libgen.h>
+#include <assert.h>
#include <limits.h>
int global_i = 100;
+#ifndef EXECD_PROG
+#define EXECD_PROG "execd-prog"
+#endif
+
int main (int argc, char ** argv)
{
int local_j = global_i + 1;
int local_k = local_j + 1;
char prog[PATH_MAX];
- int len;
+ size_t len = PATH_MAX - 1;
+
+ printf ("foll-exec is about to execlp(%s)...\n", EXECD_PROG);
+
+ prog [len] = '\0';
+
+ strncpy (prog, dirname (argv[0]), len);
+ len -= strlen (prog);
+ assert (len > 0);
- printf ("foll-exec is about to execlp(execd-prog)...\n");
+ strncat (prog, "/", len);
+ len -= 1;
+ assert (len > 0);
- strcpy (prog, argv[0]);
- len = strlen (prog);
- /* Replace "foll-exec" with "execd-prog". */
- memcpy (prog + len - 9, "execd-prog", 10);
- prog[len + 1] = 0;
+ strncat (prog, EXECD_PROG, len);
+ len -= strlen (EXECD_PROG);
+ assert (len > 0);
/* In the following function call, maximum line length exceed the limit 80.
This is intentional and required for clang compiler such that complete
@@ -45,7 +58,7 @@ int main (int argc, char ** argv)
multi-line. */
execlp (prog, /* tbreak-execlp */ prog, "execlp arg1 from foll-exec", (char *) 0);
- printf ("foll-exec is about to execl(execd-prog)...\n");
+ printf ("foll-exec is about to execl(%s)...\n", EXECD_PROG);
/* In the following function call, maximum line length exceed the limit 80.
This is intentional and required for clang compiler such that complete
@@ -61,7 +74,7 @@ int main (int argc, char ** argv)
argv[0] = prog;
- printf ("foll-exec is about to execv(execd-prog)...\n");
+ printf ("foll-exec is about to execv(%s)...\n", EXECD_PROG);
execv (prog, argv); /* tbreak-execv */
}
diff --git a/gdb/testsuite/gdb.base/foll-exec.exp b/gdb/testsuite/gdb.base/foll-exec.exp.tcl
index ad4c3516..8f96a55 100644
--- a/gdb/testsuite/gdb.base/foll-exec.exp
+++ b/gdb/testsuite/gdb.base/foll-exec.exp.tcl
@@ -22,33 +22,55 @@ require {istarget "*-linux*"}
standard_testfile foll-exec.c
-set testfile2 "execd-prog"
-set srcfile2 ${testfile2}.c
-set binfile2 [standard_output_file ${testfile2}]
+# Compile a program that performs an exec as EXECER_LANG, and a
+# program that will be exec'd as EXECEE_LANG. Either language can be
+# 'c' or 'c++'. Then run various test associated with 'catch exec'
+# using the compiled programs.
+proc do_exec_tests { execer_lang execee_lang } {
+ global srcfile testfile
+ global gdb_prompt
-set compile_options debug
+ # First compile the program to be exec'd, the execee.
+ set execee_base_filename "execd-prog"
+ set srcfile2 ${execee_base_filename}.c
+ set execee_testfile "execd-prog-${execee_lang}"
+ set execee_testfile_re [string_to_regexp $execee_testfile]
+ set execee_binfile [standard_output_file $execee_testfile]
-# build the first test case
-if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable $compile_options] != "" } {
- untested "failed to compile"
- return -1
-}
+ set execee_flags debug
+ if { $execee_lang == "c++" } {
+ lappend execee_flags "c++"
+ }
-if { [is_remote target] } {
- gdb_remote_download target $binfile2
-}
+ if { [build_executable "failed to build $execee_testfile" $execee_testfile \
+ $srcfile2 $execee_flags] == -1 } {
+ return
+ }
-if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable $compile_options] != "" } {
- untested "failed to compile"
- return -1
-}
+ if { [is_remote target] } {
+ gdb_remote_download target $execee_binfile
+ }
-proc do_exec_tests {} {
- global binfile srcfile srcfile2 testfile testfile2
- global gdb_prompt
+
+ # Now compile the program to do the exec, the execer.
+ set execer_testfile "$testfile-${execee_lang}"
+ set execer_binfile [standard_output_file $execer_testfile]
+
+ set execer_flags debug
+ if { $execer_lang == "c++" } {
+ lappend execer_flags "c++"
+ }
+ lappend execer_flags "additional_flags=-DEXECD_PROG=\"${execee_testfile}\""
+
+ if { [build_executable "failed to build $execer_testfile" $execer_testfile \
+ $srcfile $execer_flags] == -1 } {
+ return
+ }
+
+ # Now we can start running the tests.
+ clean_restart $execer_binfile
# Start the program running, and stop at main.
- #
if {![runto_main]} {
return
}
@@ -71,7 +93,7 @@ proc do_exec_tests {} {
return
}
- clean_restart $binfile
+ clean_restart $execer_binfile
# Start the program running, and stop at main.
#
@@ -120,7 +142,7 @@ proc do_exec_tests {} {
set execd_line [gdb_get_line_number "after-exec" $srcfile2]
send_gdb "next\n"
gdb_expect {
- -re ".*xecuting new program: .*${testfile2}.*${srcfile2}:${execd_line}.*int local_j = argc;.*$gdb_prompt $"\
+ -re ".*xecuting new program: .*${execee_testfile_re}.*${srcfile2}:${execd_line}.*int local_j = argc;.*$gdb_prompt $"\
{pass "step through execlp call"}
-re "$gdb_prompt $" {fail "step through execlp call"}
timeout {fail "(timeout) step through execlp call"}
@@ -160,7 +182,7 @@ proc do_exec_tests {} {
# Explicitly kill this program, or a subsequent rerun actually runs
# the exec'd program, not the original program...
- clean_restart $binfile
+ clean_restart $execer_binfile
# Start the program running, and stop at main.
#
@@ -193,7 +215,7 @@ proc do_exec_tests {} {
send_gdb "continue\n"
gdb_expect {
- -re ".*xecuting new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*$gdb_prompt $"\
+ -re ".*xecuting new program:.*${execee_testfile_re}.*Catchpoint .*(exec\'d .*${execee_testfile_re}).*$gdb_prompt $"\
{pass "hit catch exec"}
-re "$gdb_prompt $" {fail "hit catch exec"}
timeout {fail "(timeout) hit catch exec"}
@@ -210,7 +232,7 @@ proc do_exec_tests {} {
#
set msg "info shows catchpoint exec pathname"
gdb_test_multiple "info breakpoints" $msg {
- -re ".*catchpoint.*keep y.*exec, program \".*${testfile2}\".*$gdb_prompt $" {
+ -re ".*catchpoint.*keep y.*exec, program \".*${execee_testfile_re}\".*$gdb_prompt $" {
pass $msg
}
}
@@ -228,7 +250,7 @@ proc do_exec_tests {} {
# Explicitly kill this program, or a subsequent rerun actually runs
# the exec'd program, not the original program...
- clean_restart $binfile
+ clean_restart $execer_binfile
# Start the program running, and stop at main.
#
@@ -269,7 +291,7 @@ proc do_exec_tests {} {
#
send_gdb "next 2\n"
gdb_expect {
- -re ".*xecuting new program: .*${testfile2}.*${srcfile2}:${execd_line}.*int local_j = argc;.*$gdb_prompt $"\
+ -re ".*xecuting new program: .*${execee_testfile_re}.*${srcfile2}:${execd_line}.*int local_j = argc;.*$gdb_prompt $"\
{pass "step through execl call"}
-re "$gdb_prompt $" {fail "step through execl call"}
timeout {fail "(timeout) step through execl call"}
@@ -295,7 +317,7 @@ proc do_exec_tests {} {
# Explicitly kill this program, or a subsequent rerun actually runs
# the exec'd program, not the original program...
- clean_restart $binfile
+ clean_restart $execer_binfile
# Start the program running, and stop at main.
#
@@ -330,7 +352,7 @@ proc do_exec_tests {} {
}
send_gdb "next\n"
gdb_expect {
- -re ".*xecuting new program: .*${testfile2}.*${srcfile2}:${execd_line}.*int local_j = argc;.*$gdb_prompt $"\
+ -re ".*xecuting new program: .*${execee_testfile_re}.*${srcfile2}:${execd_line}.*int local_j = argc;.*$gdb_prompt $"\
{pass "step through execv call"}
-re "$gdb_prompt $" {fail "step through execv call"}
timeout {fail "(timeout) step through execv call"}
@@ -356,7 +378,7 @@ proc do_exec_tests {} {
# Explicitly kill this program, or a subsequent rerun actually runs
# the exec'd program, not the original program...
- clean_restart $binfile
+ clean_restart $execer_binfile
# Start the program running, and stop at main.
#
@@ -370,13 +392,13 @@ proc do_exec_tests {} {
#
send_gdb "continue\n"
gdb_expect {
- -re ".*xecuting new program: .*${testfile2}.*${srcfile2}:${execd_line}.*int local_j = argc;.*$gdb_prompt $"\
+ -re ".*xecuting new program: .*${execee_testfile_re}.*${srcfile2}:${execd_line}.*int local_j = argc;.*$gdb_prompt $"\
{pass "continue through exec"}
-re "$gdb_prompt $" {fail "continue through exec"}
timeout {fail "(timeout) continue through exec"}
}
}
-clean_restart $binfile
-
-do_exec_tests
+foreach_with_prefix execee_lang { c c++ } {
+ do_exec_tests $lang $execee_lang
+}
diff --git a/gdb/testsuite/gdb.base/foll-fork-syscall.c b/gdb/testsuite/gdb.base/foll-fork-syscall.c
new file mode 100644
index 0000000..ef695f5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/foll-fork-syscall.c
@@ -0,0 +1,35 @@
+/* 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/>. */
+
+#include <unistd.h>
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+ int pid, x = 0;
+
+ pid = fork ();
+ if (pid == 0) /* set breakpoint here */
+ printf ("I am the child\n");
+ else
+ printf ("I am the parent\n");
+
+ chdir (".");
+ ++x; /* set exit breakpoint here */
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/foll-fork-syscall.exp b/gdb/testsuite/gdb.base/foll-fork-syscall.exp
new file mode 100644
index 0000000..21ef334
--- /dev/null
+++ b/gdb/testsuite/gdb.base/foll-fork-syscall.exp
@@ -0,0 +1,143 @@
+# 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/>.
+
+# Test catching syscalls with all permutations of follow-fork parent/child
+# and detach-on-fork on/off.
+
+# Test relies on checking follow-fork output. Do not run if gdb debug is
+# enabled because it will be redirected to the log.
+require !gdb_debug_enabled
+require {is_any_target "i?86-*-*" "x86_64-*-*"}
+require allow_fork_tests
+
+standard_testfile
+
+if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
+ return -1
+}
+
+proc setup_gdb {} {
+ global testfile
+
+ clean_restart $testfile
+
+ if {![runto_main]} {
+ return false
+ }
+
+ # Set a breakpoint after the fork is "complete."
+ if {![gdb_breakpoint [gdb_get_line_number "set breakpoint here"]]} {
+ return false
+ }
+
+ # Set exit breakpoint (to prevent inferior from exiting).
+ if {![gdb_breakpoint [gdb_get_line_number "set exit breakpoint here"]]} {
+ return false
+ }
+ return true
+}
+
+# Check that fork catchpoints are supported, as an indicator for whether
+# fork-following is supported. Return 1 if they are, else 0.
+
+proc_with_prefix check_fork_catchpoints {} {
+ global gdb_prompt
+
+ if { ![setup_gdb] } {
+ return false
+ }
+
+ # Verify that the system supports "catch fork".
+ gdb_test "catch fork" "Catchpoint \[0-9\]* \\(fork\\)" "insert first fork catchpoint"
+ set has_fork_catchpoints false
+ gdb_test_multiple "continue" "continue to first fork catchpoint" {
+ -re ".*Your system does not support this type\r\nof catchpoint.*$gdb_prompt $" {
+ unsupported "continue to first fork catchpoint"
+ }
+ -re ".*Catchpoint.*$gdb_prompt $" {
+ set has_fork_catchpoints true
+ pass "continue to first fork catchpoint"
+ }
+ }
+
+ return $has_fork_catchpoints
+}
+
+proc_with_prefix test_catch_syscall {follow-fork-mode detach-on-fork} {
+ # Start with shiny new gdb instance.
+ if {![setup_gdb]} {
+ return
+ }
+
+ # The "Detaching..." and "Attaching..." messages may be hidden by
+ # default.
+ gdb_test_no_output "set verbose"
+
+ # Setup modes to test.
+ gdb_test_no_output "set follow-fork-mode ${follow-fork-mode}"
+ gdb_test_no_output "set detach-on-fork ${detach-on-fork}"
+
+ gdb_test "catch fork" "Catchpoint . \\(fork\\)"
+ gdb_test "catch syscall chdir" "Catchpoint . \\(syscall 'chdir'.*\\)"
+
+ # Which inferior we're expecting to follow. Assuming the parent
+ # will be inferior #1, and the child will be inferior #2.
+ if {${follow-fork-mode} == "parent"} {
+ set following_inf 1
+ } else {
+ set followin_inf 2
+ }
+ # Next stop should be the fork catchpoint.
+ set expected_re ""
+ append expected_re "Catchpoint . \\(forked process.*"
+ gdb_test "continue" $expected_re "continue to fork catchpoint"
+
+ # Next stop should be the breakpoint after the fork.
+ set expected_re ".*"
+ if {${follow-fork-mode} == "child" || ${detach-on-fork} == "off"} {
+ append expected_re "\\\[New inferior.*"
+ }
+ if {${detach-on-fork} == "on"} {
+ append expected_re "\\\[Detaching after fork from "
+ if {${follow-fork-mode} == "parent"} {
+ append expected_re "child"
+ } else {
+ append expected_re "parent"
+ }
+ append expected_re " process.*"
+ }
+ append expected_re "Breakpoint .*set breakpoint here.*"
+ gdb_test "continue" $expected_re "continue to breakpoint after fork"
+
+ # Next stop should be the syscall catchpoint.
+ set expected_re ".*Catchpoint . \\(call to syscall chdir\\).*"
+ gdb_test continue $expected_re "continue to chdir syscall"
+}
+
+# Check for follow-fork support.
+if {![check_fork_catchpoints]} {
+ untested "follow-fork not supported"
+ return
+}
+
+# Test all permutations.
+foreach_with_prefix follow-fork-mode {"parent" "child"} {
+
+ # Do not run tests when not detaching from the parent.
+ # See breakpoints/13457 for discussion.
+ foreach_with_prefix detach-on-fork {"on"} {
+ test_catch_syscall ${follow-fork-mode} ${detach-on-fork}
+ }
+}
diff --git a/gdb/testsuite/gdb.base/foll-fork.exp b/gdb/testsuite/gdb.base/foll-fork.exp
index 94755c6..12db516 100644
--- a/gdb/testsuite/gdb.base/foll-fork.exp
+++ b/gdb/testsuite/gdb.base/foll-fork.exp
@@ -17,6 +17,8 @@
# enabled as it will be redirected to the log.
require !gdb_debug_enabled
+require allow_fork_tests
+
standard_testfile
if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
diff --git a/gdb/testsuite/gdb.base/foll-vfork.exp b/gdb/testsuite/gdb.base/foll-vfork.exp
index 266df46..6ca7711 100644
--- a/gdb/testsuite/gdb.base/foll-vfork.exp
+++ b/gdb/testsuite/gdb.base/foll-vfork.exp
@@ -18,12 +18,7 @@
# either execs or exits --- since those events take somewhat different
# code paths in GDB, both variants are exercised.
-# Until "set follow-fork-mode" and "catch vfork" are implemented on
-# other targets...
-#
-if {![istarget "*-linux*"]} {
- continue
-}
+require allow_fork_tests
standard_testfile .c -exit.c vforked-prog.c
diff --git a/gdb/testsuite/gdb.base/fork-no-detach-follow-child-dlopen.exp b/gdb/testsuite/gdb.base/fork-no-detach-follow-child-dlopen.exp
index 311d7ba..2d47d5d 100644
--- a/gdb/testsuite/gdb.base/fork-no-detach-follow-child-dlopen.exp
+++ b/gdb/testsuite/gdb.base/fork-no-detach-follow-child-dlopen.exp
@@ -23,6 +23,7 @@
# in the source of the shlib, and "list" should display the source where
# the program stopped.
+require allow_fork_tests
require allow_shlib_tests
standard_testfile .c -shlib.c
diff --git a/gdb/testsuite/gdb.base/fork-print-inferior-events.exp b/gdb/testsuite/gdb.base/fork-print-inferior-events.exp
index 26ed2f9..19ace00 100644
--- a/gdb/testsuite/gdb.base/fork-print-inferior-events.exp
+++ b/gdb/testsuite/gdb.base/fork-print-inferior-events.exp
@@ -19,6 +19,8 @@
# inferior-events [on,off]', 'set follow-fork-mode [child,parent]' and
# 'set detach-on-fork [on,off]' are the correct ones.
+require allow_fork_tests
+
# This test relies on "run", so it cannot run on target remote stubs.
require !use_gdb_stub
diff --git a/gdb/testsuite/gdb.base/fork-running-state.exp b/gdb/testsuite/gdb.base/fork-running-state.exp
index 4b810a6..c446800 100644
--- a/gdb/testsuite/gdb.base/fork-running-state.exp
+++ b/gdb/testsuite/gdb.base/fork-running-state.exp
@@ -17,6 +17,8 @@
# in non-stop). GDB used to miss updating the parent/child running
# states after a fork.
+require allow_fork_tests
+
standard_testfile
# The test proper.
diff --git a/gdb/testsuite/gdb.base/gcore.exp b/gdb/testsuite/gdb.base/gcore.exp
index 5251e3f..0a9f099 100644
--- a/gdb/testsuite/gdb.base/gcore.exp
+++ b/gdb/testsuite/gdb.base/gcore.exp
@@ -16,6 +16,7 @@
# This file was written by Michael Snyder (msnyder@redhat.com)
# This is a test for the gdb command "generate-core-file".
+require gcore_cmd_available
standard_testfile
diff --git a/gdb/testsuite/gdb.base/infcall-failure.exp b/gdb/testsuite/gdb.base/infcall-failure.exp
index 66bccd1..e7aeac1 100644
--- a/gdb/testsuite/gdb.base/infcall-failure.exp
+++ b/gdb/testsuite/gdb.base/infcall-failure.exp
@@ -131,7 +131,13 @@ proc_with_prefix run_cond_hits_segfault_test { async_p non_stop_p } {
[multi_line \
"Continuing\\." \
"" \
- "Program received signal SIGSEGV, Segmentation fault\\." \
+ [string cat \
+ [string_to_regexp \
+ "Program received signal SIGSEGV, Segmentation fault."] \
+ "("] \
+ [string cat \
+ [string_to_regexp "Address not mapped to object."] \
+ ")?"] \
"${::hex} in func_segfault \\(\\) at \[^\r\n\]+:${::segv_line}" \
"${::decimal}\\s+\[^\r\n\]+Segfault here\[^\r\n\]+" \
"Error in testing condition for breakpoint ${bp_1_num}:" \
@@ -161,7 +167,13 @@ proc_with_prefix run_call_hits_segfault_test { async_p non_stop_p } {
gdb_test "call func_segfault ()" \
[multi_line \
"" \
- "Program received signal SIGSEGV, Segmentation fault\\." \
+ [string cat \
+ [string_to_regexp \
+ "Program received signal SIGSEGV, Segmentation fault."] \
+ "("] \
+ [string cat \
+ [string_to_regexp "Address not mapped to object."] \
+ ")?"] \
"${::hex} in func_segfault \\(\\) at \[^\r\n\]+:${::segv_line}" \
"${::decimal}\\s+\[^\r\n\]+Segfault here\[^\r\n\]+" \
"The program being debugged was signaled while in a function called from GDB\\." \
diff --git a/gdb/testsuite/gdb.base/inferior-died.exp b/gdb/testsuite/gdb.base/inferior-died.exp
index 3992561..764a88d 100644
--- a/gdb/testsuite/gdb.base/inferior-died.exp
+++ b/gdb/testsuite/gdb.base/inferior-died.exp
@@ -13,10 +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/>.
-# Until "set follow-fork-mode" and "catch fork" are implemented on
-# other targets...
-#
-require {istarget "*-*-linux*"}
+require allow_fork_tests
require support_displaced_stepping
diff --git a/gdb/testsuite/gdb.base/info-shared.exp b/gdb/testsuite/gdb.base/info-shared.exp
index 6f1b2d6..e81b28e 100644
--- a/gdb/testsuite/gdb.base/info-shared.exp
+++ b/gdb/testsuite/gdb.base/info-shared.exp
@@ -79,6 +79,9 @@ proc check_info_shared { test expect1 expect2 } {
}
}
+# Check that "info shared" before running doesn't crash.
+check_info_shared "info sharedlibrary before running" 0 0
+
# Start the inferior, and check neither of the libraries are loaded at
# the start.
if ![runto_main] {
diff --git a/gdb/testsuite/gdb.base/interrupt-daemon.exp b/gdb/testsuite/gdb.base/interrupt-daemon.exp
index 161f854..8b8c61d 100644
--- a/gdb/testsuite/gdb.base/interrupt-daemon.exp
+++ b/gdb/testsuite/gdb.base/interrupt-daemon.exp
@@ -16,6 +16,8 @@
# Make sure that we can interrupt an inferior that forks and moves to
# its own session.
+require allow_fork_tests
+
standard_testfile
if {[build_executable "failed to build" $testfile $srcfile {debug}]} {
diff --git a/gdb/testsuite/gdb.base/jit-bfd-name.exp b/gdb/testsuite/gdb.base/jit-bfd-name.exp
index 9e4daa1..219929b 100644
--- a/gdb/testsuite/gdb.base/jit-bfd-name.exp
+++ b/gdb/testsuite/gdb.base/jit-bfd-name.exp
@@ -67,11 +67,13 @@ gdb_breakpoint [gdb_get_line_number "break here 1" $::main_srcfile]
gdb_continue_to_breakpoint "break here 1"
# Confirm that the two expected functions are available.
+set re_f1 [string_to_regexp "int jit_function_0001(void)"]
+set re_f2 [string_to_regexp "int jit_function_0002(void)"]
gdb_test "info function ^jit_function" \
[multi_line \
"File \[^\r\n\]+jit-elf-solib.c:" \
- "${decimal}:\\s+int jit_function_0001\\(\\);" \
- "${decimal}:\\s+int jit_function_0002\\(\\);"]
+ "${decimal}:\\s+$re_f1;" \
+ "${decimal}:\\s+$re_f2;"]
# Capture the addresses of each JIT symfile.
set symfile_addrs {}
diff --git a/gdb/testsuite/gdb.base/jit-elf-fork.exp b/gdb/testsuite/gdb.base/jit-elf-fork.exp
index 81d3350..c1fa428 100644
--- a/gdb/testsuite/gdb.base/jit-elf-fork.exp
+++ b/gdb/testsuite/gdb.base/jit-elf-fork.exp
@@ -15,6 +15,7 @@
# Test fork handling of an inferior that has JIT-ed objfiles.
+require allow_fork_tests
require allow_shlib_tests
load_lib jit-elf-helpers.exp
diff --git a/gdb/testsuite/gdb.base/jit-elf-solib.c b/gdb/testsuite/gdb.base/jit-elf-solib.c
index 690d7a0..c6fcb89 100644
--- a/gdb/testsuite/gdb.base/jit-elf-solib.c
+++ b/gdb/testsuite/gdb.base/jit-elf-solib.c
@@ -22,4 +22,4 @@
#error "Must define the FUNCTION_NAME macro to set a jited function name"
#endif
-int FUNCTION_NAME() { return 42; }
+int FUNCTION_NAME(void) { return 42; }
diff --git a/gdb/testsuite/gdb.base/kill-detach-inferiors-cmd.exp b/gdb/testsuite/gdb.base/kill-detach-inferiors-cmd.exp
index ef4bb88..57ec330 100644
--- a/gdb/testsuite/gdb.base/kill-detach-inferiors-cmd.exp
+++ b/gdb/testsuite/gdb.base/kill-detach-inferiors-cmd.exp
@@ -19,6 +19,7 @@
# commands.
require can_spawn_for_attach
+require allow_multi_inferior_tests
standard_testfile
set executable $testfile
diff --git a/gdb/testsuite/gdb.base/maint.exp b/gdb/testsuite/gdb.base/maint.exp
index e006d55..7936e53 100644
--- a/gdb/testsuite/gdb.base/maint.exp
+++ b/gdb/testsuite/gdb.base/maint.exp
@@ -52,6 +52,40 @@ if {[prepare_for_testing "failed to prepare" $testfile \
return -1
}
+# Check "maint set per-command" warnings. We do this early so that
+# the following tests don't need to expect them, as GDB only warns
+# once.
+
+with_test_prefix "warnings" {
+ # Potential warning given by "maint set per-command time".
+ set maybe_per_command_warning \
+ "(?:warning: per-thread run time information not available on this platform)?"
+
+ # This one should not issue the "per-command time" warning.
+ with_test_prefix "per-command space" {
+ gdb_test_no_output "mt set per-command space on"
+ gdb_test_no_output "mt set per-command space off"
+ }
+
+ # These might warn. "per-command on" enables all sub commands, so
+ # might trigger the "per-command time" warning.
+ foreach cmd {"per-command" "per-command time"} {
+ with_test_prefix $cmd {
+ # GDB only warns once, so restart between commands.
+ clean_restart $binfile
+ gdb_test "mt set $cmd on" "$maybe_per_command_warning"
+ gdb_test "mt set $cmd off" "command started"
+ gdb_test_no_output "mt set $cmd on" \
+ "mt set $cmd on, again"
+ gdb_test "mt set $cmd off" "command started" \
+ "mt set $cmd off, again"
+ }
+ }
+
+ # We've already warned once above, so the following tests don't
+ # need to expect the warning.
+}
+
set readnow_p [readnow]
# The commands we test here produce many lines of output; disable "press
@@ -205,8 +239,8 @@ set re \
"( Number of \"partial\" symbols read: $decimal" \
")?( Number of psym tables \\(not yet expanded\\): $decimal" \
")?( Total memory used for psymbol cache: $decimal" \
- ")?( Number of read CUs: $decimal" \
- " Number of unread CUs: $decimal" \
+ ")?( Number of read units: $decimal" \
+ " Number of unread units: $decimal" \
")? Total memory used for objfile obstack: $decimal" \
" Total memory used for BFD obstack: $decimal" \
" Total memory used for string cache: $decimal" \
@@ -513,4 +547,9 @@ gdb_test_no_output "maint print symbols"
gdb_test_no_output "maint print msymbols"
gdb_test_no_output "maint print psymbols"
+gdb_test "maint canonicalize int short" "canonical = short"
+gdb_test "maint canonicalize fn<ty<int>>" \
+ "canonical = fn<ty<int> >"
+gdb_test "maint canonical unsigned int" "No change\\."
+
gdb_exit
diff --git a/gdb/testsuite/gdb.base/multi-forks.exp b/gdb/testsuite/gdb.base/multi-forks.exp
index 61a240f..3facccb 100644
--- a/gdb/testsuite/gdb.base/multi-forks.exp
+++ b/gdb/testsuite/gdb.base/multi-forks.exp
@@ -13,11 +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/>.
-# Until "set follow-fork-mode" and "catch fork" are implemented on
-# other targets...
-#
-require {istarget "*-*-linux*"}
-
+require allow_fork_tests
standard_testfile .c
diff --git a/gdb/testsuite/gdb.base/options.exp b/gdb/testsuite/gdb.base/options.exp
index f32d258..a0947e2 100644
--- a/gdb/testsuite/gdb.base/options.exp
+++ b/gdb/testsuite/gdb.base/options.exp
@@ -62,8 +62,7 @@ proc check_completion_result {expected test} {
# just checking whether GDB recognizes the option and auto-appends a
# space.
proc test_completer_recognizes {res input_line} {
- set expected_re [string_to_regexp $input_line]
- test_gdb_complete_unique $input_line $expected_re
+ test_gdb_complete_unique $input_line $input_line
check_completion_result $res $input_line
}
@@ -509,12 +508,26 @@ proc_with_prefix test-thread-apply {} {
proc_with_prefix test-info-threads {} {
test_gdb_complete_multiple "info threads " "" "" {
"-gid"
+ "-running"
+ "-stopped"
"ID"
}
+ test_gdb_complete_multiple "info threads " "-" "" {
+ "-gid"
+ "-running"
+ "-stopped"
+ }
+
test_gdb_complete_unique \
- "info threads -" \
+ "info threads -g" \
"info threads -gid"
+ test_gdb_complete_unique \
+ "info threads -r" \
+ "info threads -running"
+ test_gdb_complete_unique \
+ "info threads -s" \
+ "info threads -stopped"
# "ID" isn't really something the user can type.
test_gdb_complete_none "info threads I"
diff --git a/gdb/testsuite/gdb.base/pie-fork.exp b/gdb/testsuite/gdb.base/pie-fork.exp
index 48c01d9..86407b4 100644
--- a/gdb/testsuite/gdb.base/pie-fork.exp
+++ b/gdb/testsuite/gdb.base/pie-fork.exp
@@ -16,6 +16,8 @@
# Test that we can follow forks properly when the executable is
# position-independent.
+require allow_fork_tests
+
standard_testfile
set opts [list debug pie]
diff --git a/gdb/testsuite/gdb.base/print-symbol-loading.exp b/gdb/testsuite/gdb.base/print-symbol-loading.exp
index 15f2c19..c9e2480 100644
--- a/gdb/testsuite/gdb.base/print-symbol-loading.exp
+++ b/gdb/testsuite/gdb.base/print-symbol-loading.exp
@@ -15,7 +15,7 @@
# Test the "print symbol-loading" option.
-require allow_shlib_tests
+require allow_shlib_tests gcore_cmd_available
standard_testfile print-symbol-loading-main.c
set libfile print-symbol-loading-lib
diff --git a/gdb/testsuite/gdb.base/ptype.exp b/gdb/testsuite/gdb.base/ptype.exp
index 788cdfc..6971f4c 100644
--- a/gdb/testsuite/gdb.base/ptype.exp
+++ b/gdb/testsuite/gdb.base/ptype.exp
@@ -544,10 +544,10 @@ proc ptype_maybe_prototyped { id prototyped plain { overprototyped "NO-MATCH" }
fail "ptype $id (compiler doesn't emit prototyped types)"
}
-re "type = $overprototyped\[\r\n\]+$gdb_prompt $" {
- if { [test_compiler_info "armcc-*"] } {
- setup_xfail "*-*-*"
- }
- fail "ptype $id (compiler doesn't emit unprototyped types)"
+ # C23 no longer supports non-prototype function declaration, in which
+ # case the overprototyped regexp is the expected one. Simply pass
+ # in all cases.
+ pass "ptype $id (overprototyped)"
}
}
}
diff --git a/gdb/testsuite/gdb.base/run-control-while-bg-execution.exp b/gdb/testsuite/gdb.base/run-control-while-bg-execution.exp
index 22913ca..eaee010 100644
--- a/gdb/testsuite/gdb.base/run-control-while-bg-execution.exp
+++ b/gdb/testsuite/gdb.base/run-control-while-bg-execution.exp
@@ -49,6 +49,11 @@ if {[build_executable "failed to prepare" $testfile $srcfile]} {
# - run: use the run command
# - attach: start a process outside of GDB and attach it
proc do_test { action1 action2 } {
+
+ if {$action1 == "add" && ![allow_multi_inferior_tests]} {
+ return
+ }
+
save_vars { ::GDBFLAGS } {
append ::GDBFLAGS " -ex \"maintenance set target-non-stop on\""
clean_restart $::binfile
diff --git a/gdb/testsuite/gdb.base/sigall.exp b/gdb/testsuite/gdb.base/sigall.exp
index b23e3c5..461a92b 100644
--- a/gdb/testsuite/gdb.base/sigall.exp
+++ b/gdb/testsuite/gdb.base/sigall.exp
@@ -41,13 +41,14 @@ proc test_one_sig {nextsig} {
setup_xfail "i*86-pc-linuxoldld-gnu" "i*86-pc-linuxaout-gnu"
}
# On Linux SPARC64 systems SIGLOST==SIGPWR and gdb identifies
- # the raised signal as PWR.
- if {$thissig == "LOST" && [istarget "sparc64-*-linux*"]} {
+ # the raised signal as PWR. Same for Cygwin.
+ if {$thissig == "LOST"
+ && ([istarget "sparc64-*-linux*"] || [istarget "*-*-cygwin*"])} {
set esig "PWR"
}
gdb_test "continue" \
- "Continuing.*Program received signal SIG$esig.*" \
+ "Continuing.* received signal SIG$esig.*" \
"get signal $esig"
}
@@ -177,7 +178,7 @@ gdb_test "handle SIGTERM stop print" \
"SIGTERM\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*Yes.*"
gdb_test "b handle_TERM" "Breakpoint \[0-9\]+ .*"
gdb_test "continue" \
- "Continuing.*Program received signal SIGTERM.*" \
+ "Continuing.* received signal SIGTERM.*" \
"get signal TERM"
gdb_test "continue" "Breakpoint.*handle_TERM.*" "send signal TERM"
gdb_continue_to_end "continue to sigall exit"
diff --git a/gdb/testsuite/gdb.base/solib-search.exp b/gdb/testsuite/gdb.base/solib-search.exp
index 2efad18..35b0314 100644
--- a/gdb/testsuite/gdb.base/solib-search.exp
+++ b/gdb/testsuite/gdb.base/solib-search.exp
@@ -16,7 +16,7 @@
# Test solib-search-path, and in the case of solib-svr4.c whether l_addr_p
# is properly reset when the path is changed.
-require allow_shlib_tests
+require allow_shlib_tests gcore_cmd_available
require {!is_remote target}
# Build "wrong" and "right" versions of the libraries in separate directories.
diff --git a/gdb/testsuite/gdb.base/step-over-exit.exp b/gdb/testsuite/gdb.base/step-over-exit.exp
index 2370f97..6dfa7bb 100644
--- a/gdb/testsuite/gdb.base/step-over-exit.exp
+++ b/gdb/testsuite/gdb.base/step-over-exit.exp
@@ -13,11 +13,14 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-standard_testfile
-
# Test a thread is doing step-over a syscall instruction which is exit,
# and GDBserver should cleanup its state of step-over properly.
+# The testcase relies on follow-fork-mode child.
+require allow_fork_tests
+
+standard_testfile
+
set syscall_insn ""
# Define the syscall instruction for each target.
diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
index 59c93ee..503671b 100644
--- a/gdb/testsuite/gdb.base/style.exp
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -329,6 +329,18 @@ proc run_style_tests { } {
"The \033\\\[38;2;254;210;16;48;5;255;22;27m.*\".*version.*\".*style.*\033\\\[m foreground color is: #FED210" \
"Version's TrueColor foreground style"
}
+
+ gdb_test_no_output "set host-charset UTF-8"
+ # Chosen since it will print an error.
+ gdb_test "maint translate-address" \
+ "❌️ requires argument.*" \
+ "emoji output"
+
+ gdb_test_no_output "set style error-prefix abcd:" \
+ "set the error prefix"
+ gdb_test "maint translate-address" \
+ "abcd:requires argument.*" \
+ "error prefix"
}
}
@@ -739,6 +751,280 @@ proc test_enable_styling_warning { } {
}
}
+# Run an 'apropos' command. Each line of output starts with a
+# non-default style (command style). Ensure that pagination triggers
+# during the 'apropos' output such that, at the point pagination kicks
+# in, a non-default style is in effect.
+#
+# Then, at the pagination prompt, quit the command.
+#
+# Next, run a command which switches to a different style, and then
+# back to the current style.
+#
+# At one point, a bug in the pagination code would leave the
+# non-default style from the 'apropos' command recorded as the current
+# style, such that the second command would switch back to the earlier
+# style.
+proc test_pagination_cmd_after_quit_styling {} {
+ with_ansi_styling_terminal {
+ clean_restart
+ }
+
+ # We're going to use 'apropos time'. Check that with a height of
+ # 12 lines, each line starts with a non-default style, and that we
+ # do see the pagination prompt. This means that there are more
+ # than 12 lines for this command.
+ with_test_prefix "validate apropos output" {
+ gdb_test_no_output "set height 12"
+
+ set saw_pagination_prompt false
+ gdb_test_multiple "apropos time" "" {
+ -re "^apropos time\r\n" {
+ exp_continue
+ }
+ -re "^\033\\\[39;49;1;27m\[^\r\n\]+\r\n" {
+ exp_continue
+ }
+ -re "^$::pagination_prompt$" {
+ set saw_pagination_prompt true
+ send_gdb "q\n"
+ exp_continue
+ }
+ -re "^q\r\n" {
+ exp_continue
+ }
+ -re "^Quit\r\n" {
+ exp_continue
+ }
+ -re "^$::gdb_prompt $" {
+ gdb_assert { $saw_pagination_prompt } $gdb_test_name
+ }
+ -re "^\[^\r\n\]+\r\n" {
+ exp_continue
+ }
+ }
+ }
+
+ # Now reduce the height to 10 and re-run 'apropos time'. Based on
+ # the previous check, we know that this is going to present the
+ # pagination prompt when a non-default style is in use.
+ gdb_test_no_output "set height 10"
+
+ set saw_pagination_prompt false
+ gdb_test_multiple "apropos time" "" {
+ -re "$::pagination_prompt" {
+ set saw_pagination_prompt true
+ send_gdb "q\n"
+ exp_continue
+ }
+ -re "\r\n$::gdb_prompt $" {
+ gdb_assert { $saw_pagination_prompt } $gdb_test_name
+ }
+ }
+
+ # The help output for this maintenance command switches to a
+ # different style, and then back to the default. If the
+ # pagination bug still exists, then this would switch back to the
+ # non-default style that was in use when pagination kicked in
+ # above.
+ gdb_test "maintenance time" \
+ "^\"\033\\\[39;49;1;27mmaintenance time\033\\\[m\" takes a numeric argument\\."
+}
+
+# Helper for test_pagination_prompt_styling. Return false if STR, a
+# line that appears immediately before a pagination prompt, matches
+# the pattern for needing a style reset at the end, but does not have
+# the style reset.
+#
+# In all other cases, return true. So lines that don't match the
+# known pattern for neededing a style reset will always return true,
+# as will lines that match the pattern, and do have the style reset.
+proc previous_line_is_ok { str } {
+
+ # Create a copy of STR with all the '\033' characters removed.
+ # Then compare string lengths to get a count of the '\033'
+ # charactes present in STR.
+ regsub -all "\033" $str {} stripped
+ set count [expr [string length $str] - [string length $stripped]]
+
+ # If STR switched styles, then it _must_ switch back again,
+ # otherwise the pagination prompt will be in the wrong style.
+ # This means that there _must_ be an even number of '\033'
+ # characters in STR. If there is not then we switched style, but
+ # failed to switch back.
+ if { [expr $count % 2] != 0 } {
+ return false
+ }
+
+ # For lines that don't match this pattern, we cannot comment on
+ # where the style reset should occur, so lets just claim the line
+ # is fine.
+ if { ![regexp "\\s+$::hex - $::hex is \[^\r\n\]+ in " $str] } {
+ return true
+ }
+
+ # This line did match the above pattern, so we know that a style
+ # reset _must_ occur at the end of the line. If it doesn't then
+ # this line is not OK.
+ if { ![regexp "\033\\\[m$" $str] } {
+ return false
+ }
+
+ # All tests passed, this line looks OK.
+ return true
+}
+
+# Test that the pagination prompt is displayed unstyled. This is done
+# by looking at the 'info files' output and selecting a width that
+# will mean we should get a pagination prompt part way through a
+# styled filename.
+#
+# Then, re-run 'info files' and check that for every pagination
+# prompt, the previous line disables styling as expected.
+proc test_pagination_prompt_styling {} {
+ with_ansi_styling_terminal {
+ clean_restart $::binfile
+ }
+
+ if {![runto_main]} {
+ return
+ }
+
+ # Set height so we actually get a pagination prompt.
+ gdb_test_no_output "set height 3"
+
+ # Scan the 'info files' output and set DESIRED_WIDTH such that it
+ # will trigger pagination part-way through a styled filename.
+ set desired_width 0
+ gdb_test_multiple "info files" "find good test width" {
+ -re "^info files\r\n" {
+ exp_continue
+ }
+
+ -re "^$::pagination_prompt$" {
+ send_gdb "\n"
+ exp_continue
+ }
+
+ -re "^$::gdb_prompt $" {
+ }
+
+ -re "^((\\s+$::hex - $::hex is \[^\r\n\]+ in )\[^\r\n\]+)\r\n" {
+ if { $desired_width == 0 } {
+ set full_line $expect_out(1,string)
+ set inner_line $expect_out(2,string)
+ set desired_width [expr [string length $inner_line] + ([string length $full_line] - [string length $inner_line]) / 2]
+ }
+ exp_continue
+ }
+
+ -re "^\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+ }
+
+ # Now setup the screen width.
+ gdb_test_no_output "set width $desired_width"
+
+ # Re-run 'info files'. Check that the content before any
+ # pagination prompt correctly disables styling.
+ set saw_bad_line false
+ set prev_line ""
+ gdb_test_multiple "info files" "check pagination prompt styling" {
+ -re "^info files\r\n" {
+ exp_continue
+ }
+
+ -re "^$::pagination_prompt$" {
+ if { ![previous_line_is_ok $prev_line] } {
+ set saw_bad_line true
+ }
+ send_gdb "\n"
+ exp_continue
+ }
+
+ -re "^(\[^\r\n\]+)$::pagination_prompt$" {
+ set prev_line $expect_out(1,string)
+ if { ![previous_line_is_ok $prev_line] } {
+ set saw_bad_line true
+ }
+ send_gdb "\n"
+ exp_continue
+ }
+
+ -re "^$::gdb_prompt $" {
+ gdb_assert { !$saw_bad_line } $gdb_test_name
+ }
+
+ -re "^(\[^\r\n\]*)\r\n" {
+ set prev_line $expect_out(1,string)
+ exp_continue
+ }
+ }
+}
+
+# Test that GDB can correctly restore the current style after a
+# pagination prompt.
+#
+# Set the logging file to a garbage string based on LENGTH (is
+# actually 2x LENGTH), then 'show logging file'. Press return at the
+# pagination prompt, and check that the reset of the filename is
+# styled correctly, and that GDB correctly switches back to the
+# default style once the logging file has finished.
+proc test_pagination_continue_styling_1 { length } {
+ with_ansi_styling_terminal {
+ clean_restart $::binfile
+ }
+
+ set filename [string repeat "ax" $length]
+
+ gdb_test_no_output "set logging file $filename"
+
+ gdb_test_no_output "set height 3"
+ gdb_test_no_output "set width 80"
+
+ set saw_bad_styling false
+ gdb_test_multiple "show logging file" "" {
+ -re "^show logging file\r\n" {
+ exp_continue
+ }
+
+ -re "^The current logfile is \"\033\\\[32;49;22;27m(?:ax)+\033\\\[m" {
+ exp_continue
+ }
+
+ -re "^\r\n\033\\\[32;49;22;27m(?:ax)+\033\\\[m(?=--)" {
+ exp_continue
+ }
+
+ -re "^\r\n\033\\\[32;49;22;27m(?:ax)+(?=--)" {
+ set saw_bad_styling true
+ exp_continue
+ }
+
+ -re "^\r\n\033\\\[32;49;22;27m(?:ax)+\033\\\[m\"\\.\r\n" {
+ exp_continue
+ }
+
+ -re "^$::gdb_prompt $" {
+ gdb_assert { !$saw_bad_styling } $gdb_test_name
+ }
+
+ -re "^$::pagination_prompt$$" {
+ send_gdb "\n"
+ exp_continue
+ }
+ }
+}
+
+# Wrapper around test_pagination_continue_styling_1, calls that
+# function with different lengths.
+proc test_pagination_continue_styling { } {
+ foreach_with_prefix length { 80 160 } {
+ test_pagination_continue_styling_1 $length
+ }
+}
+
# Check to see if the Python styling of disassembler output is
# expected or not, this styling requires Python support in GDB, and
# the Python pygments module to be available.
@@ -781,3 +1067,6 @@ test_colorsupport_truecolor
test_colorsupport_truecolor_only
test_enable_styling_warning
+test_pagination_cmd_after_quit_styling
+test_pagination_prompt_styling
+test_pagination_continue_styling
diff --git a/gdb/testsuite/gdb.base/tls-common.exp.tcl b/gdb/testsuite/gdb.base/tls-common.exp.tcl
new file mode 100644
index 0000000..7aa7f46
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-common.exp.tcl
@@ -0,0 +1,50 @@
+# Copyright 2024 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.
+
+# Require statement, variables and procs used by tls-nothreads.exp,
+# tls-multiobj.exp, and tls-dlobj.exp.
+
+# The tests listed above are known to work for the targets listed on
+# the 'require' line, below.
+#
+# At the moment, only the Linux target is listed, but, ideally, these
+# tests should be run on other targets too. E.g, testing on FreeBSD
+# shows many failures which should be addressed in some fashion before
+# enabling it for that target.
+
+require {is_any_target "*-*-linux*"}
+
+# These are the targets which have support for internal TLS lookup:
+
+set internal_tls_linux_targets {"x86_64-*-linux*" "aarch64-*-linux*"
+ "riscv*-*-linux*" "powerpc64*-*-linux*"
+ "s390x*-*-linux*"}
+
+# The "maint set force-internal-tls-address-lookup" command is only
+# available for certain Linux architectures. Don't attempt to force
+# use of internal TLS support for architectures which don't support
+# it.
+
+if [is_any_target {*}$internal_tls_linux_targets] {
+ set internal_tls_iters { false true }
+} else {
+ set internal_tls_iters { false }
+}
+
+# Set up a kfail with message KFAIL_MSG when KFAIL_COND holds, then
+# issue gdb_test with command CMD and regular expression RE.
+
+proc gdb_test_with_kfail {cmd re kfail_cond kfail_msg} {
+ if [uplevel 1 [list expr $kfail_cond]] {
+ setup_kfail $kfail_msg *-*-*
+ }
+ gdb_test $cmd $re
+}
diff --git a/gdb/testsuite/gdb.base/tls-dlobj-lib.c b/gdb/testsuite/gdb.base/tls-dlobj-lib.c
new file mode 100644
index 0000000..c69bab7
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-dlobj-lib.c
@@ -0,0 +1,87 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 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 program needs to be compiled with preprocessor symbol set to
+ a small integer, e.g. "gcc -DN=1 ..." With N defined, the CONCAT2
+ and CONCAT3 macros will construct suitable names for the global
+ variables and functions. */
+
+#define CONCAT2(a,b) CONCAT2_(a,b)
+#define CONCAT2_(a,b) a ## b
+
+#define CONCAT3(a,b,c) CONCAT3_(a,b,c)
+#define CONCAT3_(a,b,c) a ## b ## c
+
+/* For N=1, this ends up being...
+ __thread int tls_lib1_tbss_1;
+ __thread int tls_lib1_tbss_2;
+ __thread int tls_lib1_tdata_1 = 196;
+ __thread int tls_lib1_tdata_2 = 197; */
+
+__thread int CONCAT3(tls_lib, N, _tbss_1);
+__thread int CONCAT3(tls_lib, N, _tbss_2);
+__thread int CONCAT3(tls_lib, N, _tdata_1) = CONCAT2(N, 96);
+__thread int CONCAT3(tls_lib, N, _tdata_2) = CONCAT2(N, 97);
+
+/* Substituting for N, define function:
+
+ int get_tls_libN_var (int which) . */
+
+int
+CONCAT3(get_tls_lib, N, _var) (int which)
+{
+ switch (which)
+ {
+ case 0:
+ return -1;
+ case 1:
+ return CONCAT3(tls_lib, N, _tbss_1);
+ case 2:
+ return CONCAT3(tls_lib, N, _tbss_2);
+ case 3:
+ return CONCAT3(tls_lib, N, _tdata_1);
+ case 4:
+ return CONCAT3(tls_lib, N, _tdata_2);
+ }
+ return -1;
+}
+
+/* Substituting for N, define function:
+
+ void set_tls_libN_var (int which, int val) . */
+
+void
+CONCAT3(set_tls_lib, N, _var) (int which, int val)
+{
+ switch (which)
+ {
+ case 0:
+ break;
+ case 1:
+ CONCAT3(tls_lib, N, _tbss_1) = val;
+ break;
+ case 2:
+ CONCAT3(tls_lib, N, _tbss_2) = val;
+ break;
+ case 3:
+ CONCAT3(tls_lib, N, _tdata_1) = val;
+ break;
+ case 4:
+ CONCAT3(tls_lib, N, _tdata_2) = val;
+ break;
+ }
+}
diff --git a/gdb/testsuite/gdb.base/tls-dlobj.c b/gdb/testsuite/gdb.base/tls-dlobj.c
new file mode 100644
index 0000000..322bdda
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-dlobj.c
@@ -0,0 +1,311 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 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/>. */
+
+#include <dlfcn.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+typedef void (*setter_ftype) (int which, int val);
+
+__thread int tls_main_tbss_1;
+__thread int tls_main_tbss_2;
+__thread int tls_main_tdata_1 = 96;
+__thread int tls_main_tdata_2 = 97;
+
+extern void set_tls_lib10_var (int which, int val);
+extern void set_tls_lib11_var (int which, int val);
+
+volatile int data;
+
+static void
+set_tls_main_var (int which, int val)
+{
+ switch (which)
+ {
+ case 1:
+ tls_main_tbss_1 = val;
+ break;
+ case 2:
+ tls_main_tbss_2 = val;
+ break;
+ case 3:
+ tls_main_tdata_1 = val;
+ break;
+ case 4:
+ tls_main_tdata_2 = val;
+ break;
+ }
+}
+
+void
+use_it (int a)
+{
+ data = a;
+}
+
+static void *
+load_dso (char *dso_name, int n, setter_ftype *setterp)
+{
+ char buf[80];
+ void *sym;
+ void *handle = dlopen (dso_name, RTLD_NOW | RTLD_GLOBAL);
+ if (handle == NULL)
+ {
+ fprintf (stderr, "dlopen of DSO '%s' failed: %s\n", dso_name, dlerror ());
+ exit (1);
+ }
+ sprintf (buf, "set_tls_lib%d_var", n);
+ sym = dlsym (handle, buf);
+ assert (sym != NULL);
+ *setterp = sym;
+
+ /* Some libc implementations (for some architectures) refuse to
+ initialize TLS data structures (specifically, the DTV) without
+ first calling dlsym on one of the TLS symbols. */
+ sprintf (buf, "tls_lib%d_tdata_1", n);
+ assert (dlsym (handle, buf) != NULL);
+
+ return handle;
+}
+
+int
+main (int argc, char **argv)
+{
+ int i, status;
+ setter_ftype s0, s1, s2, s3, s4, s10, s11;
+ void *h1 = load_dso (OBJ1, 1, &s1);
+ void *h2 = load_dso (OBJ2, 2, &s2);
+ void *h3 = load_dso (OBJ3, 3, &s3);
+ void *h4 = load_dso (OBJ4, 4, &s4);
+ s0 = set_tls_main_var;
+ s10 = set_tls_lib10_var;
+ s11 = set_tls_lib11_var;
+
+ use_it (0); /* main-breakpoint-1 */
+
+ /* Set TLS variables in main program and all libraries. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 10 + i);
+ for (i = 1; i <= 4; i++)
+ s1 (i, 110 + i);
+ for (i = 1; i <= 4; i++)
+ s2 (i, 210 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 310 + i);
+ for (i = 1; i <= 4; i++)
+ s4 (i, 410 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1010 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1110 + i);
+
+ use_it (0); /* main-breakpoint-2 */
+
+ /* Unload lib2 and lib3. */
+ status = dlclose (h2);
+ assert (status == 0);
+ status = dlclose (h3);
+ assert (status == 0);
+
+ /* Set TLS variables in main program and in libraries which are still
+ loaded. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 20 + i);
+ for (i = 1; i <= 4; i++)
+ s1 (i, 120 + i);
+ for (i = 1; i <= 4; i++)
+ s4 (i, 420 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1020 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1120 + i);
+
+ use_it (0); /* main-breakpoint-3 */
+
+ /* Load lib3. */
+ h3 = load_dso (OBJ3, 3, &s3);
+
+ /* Set TLS vars again; currently, only lib2 is not loaded. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 30 + i);
+ for (i = 1; i <= 4; i++)
+ s1 (i, 130 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 330 + i);
+ for (i = 1; i <= 4; i++)
+ s4 (i, 430 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1030 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1130 + i);
+
+ use_it (0); /* main-breakpoint-4 */
+
+ /* Unload lib1 and lib4; load lib2. */
+ status = dlclose (h1);
+ assert (status == 0);
+ status = dlclose (h4);
+ assert (status == 0);
+ h2 = load_dso (OBJ2, 2, &s2);
+
+ /* Set TLS vars; currently, lib2 and lib3 are loaded,
+ lib1 and lib4 are not. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 40 + i);
+ for (i = 1; i <= 4; i++)
+ s2 (i, 240 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 340 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1040 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1140 + i);
+
+ use_it (0); /* main-breakpoint-5 */
+
+ /* Load lib4 and lib1. Unload lib2. */
+ h4 = load_dso (OBJ4, 4, &s4);
+ h1 = load_dso (OBJ1, 1, &s1);
+ status = dlclose (h2);
+ assert (status == 0);
+
+ /* Set TLS vars; currently, lib1, lib3, and lib4 are loaded;
+ lib2 is not loaded. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 50 + i);
+ for (i = 1; i <= 4; i++)
+ s1 (i, 150 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 350 + i);
+ for (i = 1; i <= 4; i++)
+ s4 (i, 450 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1050 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1150 + i);
+
+ use_it (0); /* main-breakpoint-6 */
+
+ /* Load lib2, unload lib1, lib3, and lib4; then load lib3 again. */
+ h2 = load_dso (OBJ2, 2, &s2);
+ status = dlclose (h1);
+ assert (status == 0);
+ status = dlclose (h3);
+ assert (status == 0);
+ status = dlclose (h4);
+ assert (status == 0);
+ h3 = load_dso (OBJ3, 3, &s3);
+
+ /* Set TLS vars; currently, lib2 and lib3 are loaded;
+ lib1 and lib4 are not loaded. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 60 + i);
+ for (i = 1; i <= 4; i++)
+ s2 (i, 260 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 360 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1060 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1160 + i);
+
+ use_it (0); /* main-breakpoint-7 */
+
+ /* Unload lib3 and lib2, then (re)load lib4, lib3, lib2, and lib1,
+ in that order. */
+ status = dlclose (h3);
+ assert (status == 0);
+ status = dlclose (h2);
+ assert (status == 0);
+ h4 = load_dso (OBJ4, 4, &s4);
+ h3 = load_dso (OBJ3, 3, &s3);
+ h2 = load_dso (OBJ2, 2, &s2);
+ h1 = load_dso (OBJ1, 1, &s1);
+
+ /* Set TLS vars; currently, lib1, lib2, lib3, and lib4 are all
+ loaded. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 70 + i);
+ for (i = 1; i <= 4; i++)
+ s1 (i, 170 + i);
+ for (i = 1; i <= 4; i++)
+ s2 (i, 270 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 370 + i);
+ for (i = 1; i <= 4; i++)
+ s4 (i, 470 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1070 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1170 + i);
+
+ use_it (0); /* main-breakpoint-8 */
+
+ /* Unload lib3, lib1, and lib4. */
+ status = dlclose (h3);
+ assert (status == 0);
+ status = dlclose (h1);
+ assert (status == 0);
+ status = dlclose (h4);
+ assert (status == 0);
+
+ /* Set TLS vars; currently, lib2 is loaded; lib1, lib3, and lib4 are
+ not. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 80 + i);
+ for (i = 1; i <= 4; i++)
+ s2 (i, 280 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1080 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1180 + i);
+
+ use_it (0); /* main-breakpoint-9 */
+
+ /* Load lib3, unload lib2, load lib4. */
+ h3 = load_dso (OBJ3, 3, &s3);
+ status = dlclose (h2);
+ assert (status == 0);
+ h4 = load_dso (OBJ4, 4, &s4);
+
+ /* Set TLS vars; currently, lib3 and lib4 are loaded; lib1 and lib2
+ are not. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 90 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 390 + i);
+ for (i = 1; i <= 4; i++)
+ s4 (i, 490 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1090 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1190 + i);
+
+ use_it (0); /* main-breakpoint-10 */
+
+ /* Attempt to keep variables in the main program from being optimized
+ away. */
+ use_it (tls_main_tbss_1);
+ use_it (tls_main_tbss_2);
+ use_it (tls_main_tdata_1);
+ use_it (tls_main_tdata_2);
+
+ use_it (100); /* main-breakpoint-last */
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/tls-dlobj.exp b/gdb/testsuite/gdb.base/tls-dlobj.exp
new file mode 100644
index 0000000..02f2ff8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-dlobj.exp
@@ -0,0 +1,378 @@
+# Copyright 2024 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.
+
+# Test that the GDB-internal TLS link map to module id mapping code
+# works correctly when debugging a program which is linked against
+# shared objects and which also loads and unloads other shared objects
+# in different orders. For targets which have GDB-internal TLS
+# support, it'll check both GDB-internal TLS support as well as that
+# provided by a helper library such as libthread_db.
+
+source $srcdir/$subdir/tls-common.exp.tcl
+
+require allow_shlib_tests
+
+standard_testfile
+
+set libsrc "${srcdir}/${subdir}/${testfile}-lib.c"
+
+# These will be dlopen'd:
+set lib1obj [standard_output_file "${testfile}1-lib.so"]
+set lib2obj [standard_output_file "${testfile}2-lib.so"]
+set lib3obj [standard_output_file "${testfile}3-lib.so"]
+set lib4obj [standard_output_file "${testfile}4-lib.so"]
+
+# These will be dynamically linked with the main program:
+set lib10obj [standard_output_file "${testfile}10-lib.so"]
+set lib11obj [standard_output_file "${testfile}11-lib.so"]
+
+# Due to problems with some versions of glibc, we expect some tests to
+# fail due to TLS storage not being allocated/initialized. Test
+# command CMD using regular expression RE, and use XFAIL instead of
+# FAIL when the relevant RE is matched and COND is true when evaluated
+# in the upper level.
+
+proc gdb_test_with_xfail { cmd re cond} {
+ gdb_test_multiple $cmd $cmd {
+ -re -wrap $re {
+ pass $gdb_test_name
+ }
+ -re -wrap "The inferior has not yet allocated storage for thread-local variables.*" {
+ if [ uplevel 1 [list expr $cond]] {
+ xfail $gdb_test_name
+ } else {
+ fail $gdb_test_name
+ }
+ }
+ }
+}
+
+proc do_tests {force_internal_tls} {
+ clean_restart $::binfile
+ if ![runto_main] {
+ return
+ }
+
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-1"]
+ gdb_continue_to_breakpoint "main-breakpoint-1"
+
+ with_test_prefix "before assignments" {
+ gdb_test "print tls_main_tbss_1" ".* = 0"
+ gdb_test "print tls_main_tbss_2" ".* = 0"
+ gdb_test "print tls_main_tdata_1" ".* = 96"
+ gdb_test "print tls_main_tdata_2" ".* = 97"
+
+ # For these tests, where we're attempting to access TLS vars
+ # in a dlopen'd library, but before assignment to any of the
+ # vars, so it could happen that storage hasn't been allocated
+ # yet. But it might also work. (When testing against MUSL,
+ # things just work; GLIBC ends to produce the TLS error.) So
+ # accept either the right answer or a TLS error message.
+
+ set tlserr "The inferior has not yet allocated storage for thread-local variables.*"
+ foreach n {1 2 3 4} {
+ gdb_test "print tls_lib${n}_tbss_1" \
+ "0|${tlserr}"
+ gdb_test "print tls_lib${n}_tbss_2" \
+ "0|${tlserr}"
+ gdb_test "print tls_lib${n}_tdata_1" \
+ "96|${tlserr}"
+ gdb_test "print tls_lib${n}_tdata_2" \
+ "97|${tlserr}"
+ }
+ foreach n {10 11} {
+ gdb_test "print tls_lib${n}_tbss_1" ".* = 0"
+ gdb_test "print tls_lib${n}_tbss_2" ".* = 0"
+ gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}96"
+ gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}97"
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-2"]
+ gdb_continue_to_breakpoint "main-breakpoint-2"
+
+ with_test_prefix "at main-breakpoint-2" {
+ gdb_test "print tls_main_tbss_1" ".* = 11"
+ gdb_test "print tls_main_tbss_2" ".* = 12"
+ gdb_test "print tls_main_tdata_1" ".* = 13"
+ gdb_test "print tls_main_tdata_2" ".* = 14"
+
+ foreach n {1 2 3 4 10 11} {
+ gdb_test "print tls_lib${n}_tbss_1" ".* = ${n}11"
+ gdb_test "print tls_lib${n}_tbss_2" ".* = ${n}12"
+ gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}13"
+ gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}14"
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-3"]
+ gdb_continue_to_breakpoint "main-breakpoint-3"
+
+ # At this point lib2 and lib3 have been unloaded. Also, TLS vars
+ # in remaining libraries have been changed.
+
+ with_test_prefix "at main-breakpoint-3" {
+ gdb_test "print tls_main_tbss_1" ".* = 21"
+ gdb_test "print tls_main_tbss_2" ".* = 22"
+ gdb_test "print tls_main_tdata_1" ".* = 23"
+ gdb_test "print tls_main_tdata_2" ".* = 24"
+
+ foreach n {1 4 10 11} {
+ gdb_test "print tls_lib${n}_tbss_1" ".* = ${n}21"
+ gdb_test "print tls_lib${n}_tbss_2" ".* = ${n}22"
+ gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}23"
+ gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}24"
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-4"]
+ gdb_continue_to_breakpoint "main-breakpoint-4"
+
+ # lib3 has been loaded again; lib2 is the only one not loaded.
+
+ with_test_prefix "at main-breakpoint-4" {
+ gdb_test "print tls_main_tbss_1" ".* = 31"
+ gdb_test "print tls_main_tbss_2" ".* = 32"
+ gdb_test "print tls_main_tdata_1" ".* = 33"
+ gdb_test "print tls_main_tdata_2" ".* = 34"
+
+ set cond { $n == 3 }
+ foreach n {1 3 4 10 11} {
+ gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}31" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}32" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}33" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}34" $cond
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-5"]
+ gdb_continue_to_breakpoint "main-breakpoint-5"
+
+ # lib2 and lib3 are loaded; lib1 and lib4 are not.
+
+ with_test_prefix "at main-breakpoint-5" {
+ gdb_test "print tls_main_tbss_1" ".* = 41"
+ gdb_test "print tls_main_tbss_2" ".* = 42"
+ gdb_test "print tls_main_tdata_1" ".* = 43"
+ gdb_test "print tls_main_tdata_2" ".* = 44"
+
+ set cond { $n == 2 || $n == 3 }
+ foreach n {2 3 10 11} {
+ gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}41" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}42" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}43" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}44" $cond
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-6"]
+ gdb_continue_to_breakpoint "main-breakpoint-6"
+
+ # lib1, lib3 and lib4 are loaded; lib2 is not loaded.
+
+ with_test_prefix "at main-breakpoint-6" {
+ gdb_test "print tls_main_tbss_1" ".* = 51"
+ gdb_test "print tls_main_tbss_2" ".* = 52"
+ gdb_test "print tls_main_tdata_1" ".* = 53"
+ gdb_test "print tls_main_tdata_2" ".* = 54"
+
+ set cond { $n == 1 || $n == 3 || $n == 4}
+ foreach n {1 3 4 10 11} {
+ gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}51" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}52" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}53" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}54" $cond
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-7"]
+ gdb_continue_to_breakpoint "main-breakpoint-7"
+
+ # lib2 and lib3 are loaded; lib1 and lib4 are not.
+
+ with_test_prefix "at main-breakpoint-7" {
+ gdb_test "print tls_main_tbss_1" ".* = 61"
+ gdb_test "print tls_main_tbss_2" ".* = 62"
+ gdb_test "print tls_main_tdata_1" ".* = 63"
+ gdb_test "print tls_main_tdata_2" ".* = 64"
+
+ set cond { $n == 2 || $n == 3 }
+ foreach n {2 3 10 11} {
+ gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}61" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}62" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}63" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}64" $cond
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-8"]
+ gdb_continue_to_breakpoint "main-breakpoint-8"
+
+ # lib1, lib2, lib3, and lib4 are all loaded.
+
+ with_test_prefix "at main-breakpoint-8" {
+ gdb_test "print tls_main_tbss_1" ".* = 71"
+ gdb_test "print tls_main_tbss_2" ".* = 72"
+ gdb_test "print tls_main_tdata_1" ".* = 73"
+ gdb_test "print tls_main_tdata_2" ".* = 74"
+
+ foreach n {1 2 3 4 10 11} {
+ gdb_test "print tls_lib${n}_tbss_1" ".* = ${n}71"
+ gdb_test "print tls_lib${n}_tbss_2" ".* = ${n}72"
+ gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}73"
+ gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}74"
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-9"]
+ gdb_continue_to_breakpoint "main-breakpoint-9"
+
+ # lib2 is loaded; lib1, lib3, and lib4 are not.
+
+ with_test_prefix "at main-breakpoint-9" {
+ gdb_test "print tls_main_tbss_1" ".* = 81"
+ gdb_test "print tls_main_tbss_2" ".* = 82"
+ gdb_test "print tls_main_tdata_1" ".* = 83"
+ gdb_test "print tls_main_tdata_2" ".* = 84"
+
+ foreach n {2 10 11} {
+ gdb_test "print tls_lib${n}_tbss_1" ".* = ${n}81"
+ gdb_test "print tls_lib${n}_tbss_2" ".* = ${n}82"
+ gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}83"
+ gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}84"
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-10"]
+ gdb_continue_to_breakpoint "main-breakpoint-10"
+
+ # lib3 and lib4 are loaded; lib1 and lib2 are not.
+
+ with_test_prefix "at main-breakpoint-10" {
+ gdb_test "print tls_main_tbss_1" ".* = 91"
+ gdb_test "print tls_main_tbss_2" ".* = 92"
+ gdb_test "print tls_main_tdata_1" ".* = 93"
+ gdb_test "print tls_main_tdata_2" ".* = 94"
+
+ set cond { $n == 3 || $n == 4 }
+ foreach n {3 4 10 11} {
+ gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}91" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}92" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}93" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}94" $cond
+ }
+ }
+
+ # gdb_interact
+
+ set corefile ${::binfile}.core
+ set core_supported 0
+ if { ![is_remote host] } {
+ set core_supported [gdb_gcore_cmd $corefile "save corefile"]
+ }
+
+ # Finish test early if no core file was made.
+ if !$core_supported {
+ return
+ }
+
+ clean_restart $::binfile
+
+ set core_loaded [gdb_core_cmd $corefile "load corefile"]
+ if { $core_loaded == -1 } {
+ return
+ }
+
+ with_test_prefix "core file" {
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ gdb_test "print tls_main_tbss_1" ".* = 91"
+ gdb_test "print tls_main_tbss_2" ".* = 92"
+ gdb_test "print tls_main_tdata_1" ".* = 93"
+ gdb_test "print tls_main_tdata_2" ".* = 94"
+
+ set cond { $n == 3 || $n == 4 }
+ foreach n {3 4 10 11} {
+ gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}91" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}92" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}93" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}94" $cond
+ }
+ }
+}
+
+# Build shared objects for dlopen:
+if { [gdb_compile_shlib $libsrc $lib1obj [list debug additional_flags=-DN=1]] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+if { [gdb_compile_shlib $libsrc $lib2obj [list debug additional_flags=-DN=2]] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+if { [gdb_compile_shlib $libsrc $lib3obj [list debug additional_flags=-DN=3]] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+if { [gdb_compile_shlib $libsrc $lib4obj [list debug additional_flags=-DN=4]] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+
+# Build shared objects to link against main program:
+if { [gdb_compile_shlib $libsrc $lib10obj [list debug additional_flags=-DN=10]] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+if { [gdb_compile_shlib $libsrc $lib11obj [list debug additional_flags=-DN=11]] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+
+# Use gdb_compile_pthreads to build and link the main program for
+# testing. It's also possible to run the tests using plain old
+# gdb_compile, but this adds complexity with setting up additional
+# KFAILs. (When run using GLIBC versions earlier than 2.34, a program
+# that's not dynamically linked against libpthread will lack a working
+# libthread_db, and, therefore, won't be able to access thread local
+# storage without GDB-internal TLS support. Additional complications
+# arise from when testing on x86_64 with -m32, which tends to work
+# okay on GLIBC 2.34 and newer, but not older versions. It gets messy
+# to properly sort out all of these cases.)
+#
+# This test was originally written to do it both ways, i.e. with both
+# both gdb_compile and gdb_compile_pthreads, but the point of this
+# test is to check that the link map address to TLS module id mapping
+# code works correctly in programs which use lots of dlopen and
+# dlclose calls in various orders - and that can be done using just
+# gdb_compile_pthreads.
+
+if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
+ [list debug shlib_load \
+ shlib=${lib10obj} \
+ shlib=${lib11obj} \
+ additional_flags=-DOBJ1=\"${lib1obj}\" \
+ additional_flags=-DOBJ2=\"${lib2obj}\" \
+ additional_flags=-DOBJ3=\"${lib3obj}\" \
+ additional_flags=-DOBJ4=\"${lib4obj}\" \
+ ]] != "" } {
+ untested "failed to compile"
+} else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ do_tests $force_internal_tls
+ }
+}
diff --git a/gdb/testsuite/gdb.base/tls-multiobj.c b/gdb/testsuite/gdb.base/tls-multiobj.c
new file mode 100644
index 0000000..10e67da
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-multiobj.c
@@ -0,0 +1,89 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 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/>. */
+
+__thread int tls_main_tbss_1;
+__thread int tls_main_tbss_2;
+__thread int tls_main_tdata_1 = 96;
+__thread int tls_main_tdata_2 = 97;
+
+extern __thread int tls_lib1_tbss_1;
+extern __thread int tls_lib1_tbss_2;
+extern __thread int tls_lib1_tdata_1;
+extern __thread int tls_lib1_tdata_2;
+
+extern __thread int tls_lib2_tbss_1;
+extern __thread int tls_lib2_tbss_2;
+extern __thread int tls_lib2_tdata_1;
+extern __thread int tls_lib2_tdata_2;
+
+extern __thread int tls_lib3_tbss_1;
+extern __thread int tls_lib3_tbss_2;
+extern __thread int tls_lib3_tdata_1;
+extern __thread int tls_lib3_tdata_2;
+
+extern void lib1_func ();
+extern void lib2_func ();
+extern void lib3_func ();
+
+volatile int data;
+
+void
+use_it (int a)
+{
+ data = a;
+}
+
+int
+main (int argc, char **argv)
+{
+ use_it (-1);
+
+ tls_main_tbss_1 = 51; /* main-breakpoint-1 */
+ tls_main_tbss_2 = 52;
+ tls_main_tdata_1 = 53;
+ tls_main_tdata_2 = 54;
+
+ tls_lib1_tbss_1 = 151;
+ tls_lib1_tbss_2 = 152;
+ tls_lib1_tdata_1 = 153;
+ tls_lib1_tdata_2 = 154;
+
+ tls_lib2_tbss_1 = 251;
+ tls_lib2_tbss_2 = 252;
+ tls_lib2_tdata_1 = 253;
+ tls_lib2_tdata_2 = 254;
+
+ tls_lib3_tbss_1 = 351;
+ tls_lib3_tbss_2 = 352;
+ tls_lib3_tdata_1 = 353;
+ tls_lib3_tdata_2 = 354;
+
+ lib1_func ();
+ lib2_func ();
+ lib3_func ();
+
+ /* Attempt to keep variables in the main program from being optimized
+ away. */
+ use_it (tls_main_tbss_1);
+ use_it (tls_main_tbss_2);
+ use_it (tls_main_tdata_1);
+ use_it (tls_main_tdata_2);
+
+ use_it (100); /* main-breakpoint-2 */
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/tls-multiobj.exp b/gdb/testsuite/gdb.base/tls-multiobj.exp
new file mode 100644
index 0000000..97acb33
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-multiobj.exp
@@ -0,0 +1,230 @@
+# Copyright 2024 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.
+
+# Using different compilation/linking scenarios, attempt to access
+# thread-local variables in a non-threaded program using multiple
+# shared objects.
+
+source $srcdir/$subdir/tls-common.exp.tcl
+
+standard_testfile
+
+set lib1src "${srcdir}/${subdir}/${testfile}1.c"
+set lib2src "${srcdir}/${subdir}/${testfile}2.c"
+set lib3src "${srcdir}/${subdir}/${testfile}3.c"
+
+set lib1obj [standard_output_file "${testfile}1-lib.so"]
+set lib2obj [standard_output_file "${testfile}2-lib.so"]
+set lib3obj [standard_output_file "${testfile}3-lib.so"]
+
+proc do_tests {force_internal_tls {do_kfail_tls_access 0}} {
+ clean_restart $::binfile
+ if ![runto_main] {
+ return
+ }
+
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ if { $do_kfail_tls_access && [istarget "*-*-linux*"] } {
+ # Turn off do_kfail_tls_access when libthread_db is loaded.
+ # This can happen for the default case when testing x86_64
+ # w/ -m32 using glibc versions 2.34 or newer.
+ gdb_test_multiple "maint check libthread-db" "Check for loaded libthread_db" {
+ -re -wrap "libthread_db integrity checks passed." {
+ set do_kfail_tls_access 0
+ pass $gdb_test_name
+ }
+ -re -wrap "No libthread_db loaded" {
+ pass $gdb_test_name
+ }
+ }
+ # Also turn off do_kfail_tls_access when connected to a
+ # gdbserver and we observe that accessing a TLS variable
+ # works.
+ if [target_is_gdbserver] {
+ gdb_test_multiple "print tls_main_tbss_1" \
+ "Check TLS accessibility when connected to a gdbserver" {
+ -re -wrap "= 0" {
+ set do_kfail_tls_access 0
+ pass $gdb_test_name
+ }
+ -re -wrap "Remote target failed to process qGetTLSAddr request" {
+ pass $gdb_test_name
+ }
+ }
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-1"]
+ gdb_continue_to_breakpoint "main-breakpoint-1"
+
+ set t $do_kfail_tls_access
+ set m "tls not available"
+ with_test_prefix "before assignments" {
+ gdb_test_with_kfail "print tls_main_tbss_1" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_main_tbss_2" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_main_tdata_1" ".* = 96" $t $m
+ gdb_test_with_kfail "print tls_main_tdata_2" ".* = 97" $t $m
+
+ gdb_test_with_kfail "print tls_lib1_tbss_1" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_lib1_tbss_2" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_lib1_tdata_1" ".* = 196" $t $m
+ gdb_test_with_kfail "print tls_lib1_tdata_2" ".* = 197" $t $m
+
+ gdb_test_with_kfail "print tls_lib2_tbss_1" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_lib2_tbss_2" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_lib2_tdata_1" ".* = 296" $t $m
+ gdb_test_with_kfail "print tls_lib2_tdata_2" ".* = 297" $t $m
+
+ gdb_test_with_kfail "print tls_lib3_tbss_1" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_lib3_tbss_2" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_lib3_tdata_1" ".* = 396" $t $m
+ gdb_test_with_kfail "print tls_lib3_tdata_2" ".* = 397" $t $m
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-2"]
+ gdb_continue_to_breakpoint "main-breakpoint-2"
+
+ with_test_prefix "after assignments" {
+ gdb_test_with_kfail "print tls_main_tbss_1" ".* = 51" $t $m
+ gdb_test_with_kfail "print tls_main_tbss_2" ".* = 52" $t $m
+ gdb_test_with_kfail "print tls_main_tdata_1" ".* = 53" $t $m
+ gdb_test_with_kfail "print tls_main_tdata_2" ".* = 54" $t $m
+
+ gdb_test_with_kfail "print tls_lib1_tbss_1" ".* = 151" $t $m
+ gdb_test_with_kfail "print tls_lib1_tbss_2" ".* = 152" $t $m
+ gdb_test_with_kfail "print tls_lib1_tdata_1" ".* = 153" $t $m
+ gdb_test_with_kfail "print tls_lib1_tdata_2" ".* = 154" $t $m
+
+ gdb_test_with_kfail "print tls_lib2_tbss_1" ".* = 251" $t $m
+ gdb_test_with_kfail "print tls_lib2_tbss_2" ".* = 252" $t $m
+ gdb_test_with_kfail "print tls_lib2_tdata_1" ".* = 253" $t $m
+ gdb_test_with_kfail "print tls_lib2_tdata_2" ".* = 254" $t $m
+
+ gdb_test_with_kfail "print tls_lib3_tbss_1" ".* = 351" $t $m
+ gdb_test_with_kfail "print tls_lib3_tbss_2" ".* = 352" $t $m
+ gdb_test_with_kfail "print tls_lib3_tdata_1" ".* = 353" $t $m
+ gdb_test_with_kfail "print tls_lib3_tdata_2" ".* = 354" $t $m
+ }
+
+ set corefile ${::binfile}.core
+ set core_supported 0
+ if { ![is_remote host] } {
+ set core_supported [gdb_gcore_cmd $corefile "save corefile"]
+ }
+
+ # Finish test early if no core file was made.
+ if !$core_supported {
+ return
+ }
+
+ clean_restart $::binfile
+
+ set core_loaded [gdb_core_cmd $corefile "load corefile"]
+ if { $core_loaded == -1 } {
+ return
+ }
+
+ with_test_prefix "core file" {
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ gdb_test_with_kfail "print tls_main_tbss_1" ".* = 51" $t $m
+ gdb_test_with_kfail "print tls_main_tbss_2" ".* = 52" $t $m
+ gdb_test_with_kfail "print tls_main_tdata_1" ".* = 53" $t $m
+ gdb_test_with_kfail "print tls_main_tdata_2" ".* = 54" $t $m
+
+ gdb_test_with_kfail "print tls_lib1_tbss_1" ".* = 151" $t $m
+ gdb_test_with_kfail "print tls_lib1_tbss_2" ".* = 152" $t $m
+ gdb_test_with_kfail "print tls_lib1_tdata_1" ".* = 153" $t $m
+ gdb_test_with_kfail "print tls_lib1_tdata_2" ".* = 154" $t $m
+
+ gdb_test_with_kfail "print tls_lib2_tbss_1" ".* = 251" $t $m
+ gdb_test_with_kfail "print tls_lib2_tbss_2" ".* = 252" $t $m
+ gdb_test_with_kfail "print tls_lib2_tdata_1" ".* = 253" $t $m
+ gdb_test_with_kfail "print tls_lib2_tdata_2" ".* = 254" $t $m
+
+ gdb_test_with_kfail "print tls_lib3_tbss_1" ".* = 351" $t $m
+ gdb_test_with_kfail "print tls_lib3_tbss_2" ".* = 352" $t $m
+ gdb_test_with_kfail "print tls_lib3_tdata_1" ".* = 353" $t $m
+ gdb_test_with_kfail "print tls_lib3_tdata_2" ".* = 354" $t $m
+ }
+}
+
+if { [gdb_compile_shlib $lib1src $lib1obj {debug}] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+if { [gdb_compile_shlib $lib2src $lib2obj {debug}] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+if { [gdb_compile_shlib $lib3src $lib3obj {debug}] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+
+# Certain linux target architectures implement support for internal
+# TLS lookup which is used when thread stratum support (via
+# libthread_db) is missing or when the linux-only GDB maintenance
+# setting 'force-internal-tls-address-lookup' is 'on'. Thus for some
+# of the testing scenarios, such as statically linked executables,
+# this internal support will be used. Set 'do_kfail_tls_access' to 1
+# for those architectures which don't implement internal tls support.
+if {[istarget *-*-linux*]
+ && ![is_any_target {*}$internal_tls_linux_targets]} {
+ set do_kfail_tls_access 1
+} elseif {[istarget *-*-linux*] && [is_x86_like_target]} {
+ # This covers the case of x86_64 with -m32:
+ set do_kfail_tls_access 1
+} else {
+ set do_kfail_tls_access 0
+}
+
+set binprefix $binfile
+
+with_test_prefix "default" {
+ set binfile $binprefix-default
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
+ [list debug shlib=${lib1obj} \
+ shlib=${lib2obj} \
+ shlib=${lib3obj}]] != "" } {
+ untested "failed to compile"
+ } else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ # Depending on glibc version, it might not be appropriate
+ # for do_kfail_tls_access to be set here. That will be
+ # handled in 'do_tests', disabling it if necessary.
+ #
+ # Specifically, glibc versions 2.34 and later have the
+ # thread library (and libthread_db availability) in
+ # programs not linked against libpthread.so
+ do_tests $force_internal_tls $do_kfail_tls_access
+ }
+ }
+}
+
+with_test_prefix "pthreads" {
+ set binfile $binprefix-pthreads
+ if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
+ [list debug shlib=${lib1obj} \
+ shlib=${lib2obj} \
+ shlib=${lib3obj}]] != "" } {
+ untested "failed to compile"
+ } else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ do_tests $force_internal_tls
+ }
+ }
+}
diff --git a/gdb/testsuite/gdb.base/tls-multiobj1.c b/gdb/testsuite/gdb.base/tls-multiobj1.c
new file mode 100644
index 0000000..86e7222
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-multiobj1.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 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/>. */
+
+__thread int tls_lib1_tbss_1;
+__thread int tls_lib1_tbss_2;
+__thread int tls_lib1_tdata_1 = 196;
+__thread int tls_lib1_tdata_2 = 197;
+
+void
+lib1_func ()
+{
+}
diff --git a/gdb/testsuite/gdb.base/tls-multiobj2.c b/gdb/testsuite/gdb.base/tls-multiobj2.c
new file mode 100644
index 0000000..cea0709
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-multiobj2.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 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/>. */
+
+__thread int tls_lib2_tbss_1;
+__thread int tls_lib2_tbss_2;
+__thread int tls_lib2_tdata_1 = 296;
+__thread int tls_lib2_tdata_2 = 297;
+
+void
+lib2_func ()
+{
+}
diff --git a/gdb/testsuite/gdb.base/tls-multiobj3.c b/gdb/testsuite/gdb.base/tls-multiobj3.c
new file mode 100644
index 0000000..bb0f239
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-multiobj3.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 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/>. */
+
+__thread int tls_lib3_tbss_1;
+__thread int tls_lib3_tbss_2;
+__thread int tls_lib3_tdata_1 = 396;
+__thread int tls_lib3_tdata_2 = 397;
+
+void
+lib3_func ()
+{
+}
diff --git a/gdb/testsuite/gdb.base/tls-nothreads.c b/gdb/testsuite/gdb.base/tls-nothreads.c
new file mode 100644
index 0000000..b3aaa33
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-nothreads.c
@@ -0,0 +1,57 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 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/>. */
+
+__thread int tls_tbss_1;
+__thread int tls_tbss_2;
+__thread int tls_tbss_3;
+
+__thread int tls_tdata_1 = 21;
+__thread int tls_tdata_2 = 22;
+__thread int tls_tdata_3 = 23;
+
+volatile int data;
+
+void
+use_it (int a)
+{
+ data = a;
+}
+
+int
+main (int argc, char **argv)
+{
+ use_it (-1);
+
+ tls_tbss_1 = 24; /* main-breakpoint-1 */
+ tls_tbss_2 = 25;
+ tls_tbss_3 = 26;
+
+ tls_tdata_1 = 42;
+ tls_tdata_2 = 43;
+ tls_tdata_3 = 44;
+
+ use_it (tls_tbss_1);
+ use_it (tls_tbss_2);
+ use_it (tls_tbss_3);
+ use_it (tls_tdata_1);
+ use_it (tls_tdata_2);
+ use_it (tls_tdata_3);
+
+ use_it (100); /* main-breakpoint-2 */
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/tls-nothreads.exp b/gdb/testsuite/gdb.base/tls-nothreads.exp
new file mode 100644
index 0000000..92a5cd9
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-nothreads.exp
@@ -0,0 +1,248 @@
+# Copyright 2024 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.
+
+# Using different compilation/linking scenarios, attempt to access
+# thread-local variables in a non-threaded program. Also test that
+# GDB internal TLS lookup works correctly.
+
+source $srcdir/$subdir/tls-common.exp.tcl
+
+standard_testfile
+
+proc do_tests {force_internal_tls {do_kfail_tls_access 0}} {
+ clean_restart $::binfile
+ if ![runto_main] {
+ return
+ }
+
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ if { $do_kfail_tls_access && [istarget "*-*-linux*"] } {
+ # Turn off do_kfail_tls_access when libthread_db is loaded.
+ # This can happen for the default case when testing x86_64
+ # w/ -m32 using glibc versions 2.34 or newer.
+ gdb_test_multiple "maint check libthread-db" "Check for loaded libthread_db" {
+ -re -wrap "libthread_db integrity checks passed." {
+ set do_kfail_tls_access 0
+ pass $gdb_test_name
+ }
+ -re -wrap "No libthread_db loaded" {
+ pass $gdb_test_name
+ }
+ }
+ # Also turn off do_kfail_tls_access when connected to a
+ # gdbserver and we observe that accessing a TLS variable
+ # works.
+ if [target_is_gdbserver] {
+ gdb_test_multiple "print tls_tbss_1" "Check TLS accessibility when connected to a gdbserver" {
+ -re -wrap "= 0" {
+ set do_kfail_tls_access 0
+ pass $gdb_test_name
+ }
+ -re -wrap "Remote target failed to process qGetTLSAddr request" {
+ pass $gdb_test_name
+ }
+ }
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-1"]
+ gdb_continue_to_breakpoint "main-breakpoint-1"
+
+ set t $do_kfail_tls_access
+ set m "tls not available"
+ with_test_prefix "before assignments" {
+ gdb_test_with_kfail "print tls_tbss_1" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_tbss_2" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_tbss_3" ".* = 0" $t $m
+
+ gdb_test_with_kfail "print tls_tdata_1" ".* = 21" $t $m
+ gdb_test_with_kfail "print tls_tdata_2" ".* = 22" $t $m
+ gdb_test_with_kfail "print tls_tdata_3" ".* = 23" $t $m
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-2"]
+ gdb_continue_to_breakpoint "main-breakpoint-2"
+
+ with_test_prefix "after assignments" {
+ gdb_test_with_kfail "print tls_tbss_1" ".* = 24" $t $m
+ gdb_test_with_kfail "print tls_tbss_2" ".* = 25" $t $m
+ gdb_test_with_kfail "print tls_tbss_3" ".* = 26" $t $m
+
+ gdb_test_with_kfail "print tls_tdata_1" ".* = 42" $t $m
+ gdb_test_with_kfail "print tls_tdata_2" ".* = 43" $t $m
+ gdb_test_with_kfail "print tls_tdata_3" ".* = 44" $t $m
+ }
+
+ # Make a core file now, but save testing using it until the end
+ # in case core files are not supported.
+ set corefile ${::binfile}.core
+ set core_supported 0
+ if { ![is_remote host] } {
+ set core_supported [gdb_gcore_cmd $corefile "save corefile"]
+ }
+
+ # Now continue to end and see what happens when attempting to
+ # access a TLS variable when the program is no longer running.
+ gdb_continue_to_end
+ with_test_prefix "after exit" {
+ gdb_test "print tls_tbss_1" \
+ "Cannot (?:read|find address of TLS symbol) `tls_tbss_1' without registers"
+ }
+
+ with_test_prefix "stripped" {
+ set binfile_stripped "${::binfile}.stripped"
+ set objcopy [gdb_find_objcopy]
+ set cmd "$objcopy --strip-debug ${::binfile} $binfile_stripped"
+ if ![catch "exec $cmd" cmd_output] {
+ clean_restart $binfile_stripped
+ if ![runto_main] {
+ return
+ }
+
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ # While there are no debug (e.g. DWARF) symbols, there
+ # are minimal symbols, so we should be able to place a
+ # breakpoint in use_it and continue to it. Continuing
+ # twice should put us past the assignments, at which point
+ # we can see if the TLS variables are still accessible.
+ gdb_test "break use_it" "Breakpoint 2 at $::hex"
+ gdb_test "continue" "Breakpoint 2, $::hex in use_it.*"
+ gdb_test "continue" "Breakpoint 2, $::hex in use_it.*" "continue 2"
+
+ # Note that a cast has been added in order to avoid the
+ # "...has unknown type; cast it to its declared type"
+ # problem.
+ gdb_test_with_kfail "print (int) tls_tbss_1" ".* = 24" $t $m
+ gdb_test_with_kfail "print (int) tls_tbss_2" ".* = 25" $t $m
+ gdb_test_with_kfail "print (int) tls_tbss_3" ".* = 26" $t $m
+
+ gdb_test_with_kfail "print (int) tls_tdata_1" ".* = 42" $t $m
+ gdb_test_with_kfail "print (int) tls_tdata_2" ".* = 43" $t $m
+ gdb_test_with_kfail "print (int) tls_tdata_3" ".* = 44" $t $m
+
+ # Get rid of the "use_it" breakpoint
+ gdb_test_no_output "del 2"
+
+ # Continue to program exit
+ gdb_continue_to_end
+
+ # TLS variables should not be accessible after program exit
+ # (This case initially caused GDB to crash during development
+ # of GDB-internal TLS lookup support.)
+ with_test_prefix "after exit" {
+ gdb_test "print (int) tls_tbss_1" \
+ "Cannot find address of TLS symbol `tls_tbss_1' without registers"
+ }
+ }
+ }
+
+ # Finish test early if no core file was made.
+ if !$core_supported {
+ return
+ }
+
+ clean_restart $::binfile
+
+ set core_loaded [gdb_core_cmd $corefile "load corefile"]
+ if { $core_loaded == -1 } {
+ return
+ }
+
+ with_test_prefix "core file" {
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ gdb_test_with_kfail "print tls_tbss_1" ".* = 24" $t $m
+ gdb_test_with_kfail "print tls_tbss_2" ".* = 25" $t $m
+ gdb_test_with_kfail "print tls_tbss_3" ".* = 26" $t $m
+
+ gdb_test_with_kfail "print tls_tdata_1" ".* = 42" $t $m
+ gdb_test_with_kfail "print tls_tdata_2" ".* = 43" $t $m
+ gdb_test_with_kfail "print tls_tdata_3" ".* = 44" $t $m
+ }
+}
+
+# Certain linux target architectures implement support for internal
+# TLS lookup which is used when thread stratum support (via
+# libthread_db) is missing or when the linux-only GDB maintenance
+# setting 'force-internal-tls-address-lookup' is 'on'. Thus for some
+# of the testing scenarios, such as statically linked executables,
+# this internal support will be used. Set 'do_kfail_tls_access' to 1
+# for those architectures which don't implement internal TLS support.
+if {[istarget *-*-linux*]
+ && ![is_any_target {*}$internal_tls_linux_targets]} {
+ set do_kfail_tls_access 1
+} elseif {[istarget *-*-linux*] && [is_x86_like_target]} {
+ # This covers the case of x86_64 with -m32:
+ set do_kfail_tls_access 1
+} else {
+ set do_kfail_tls_access 0
+}
+
+set binprefix $binfile
+
+with_test_prefix "default" {
+ set binfile $binprefix-default
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ untested "failed to compile"
+ } else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ # Depending on glibc version, it might not be appropriate
+ # for do_kfail_tls_access to be set here. That will be
+ # handled in 'do_tests', disabling it if necessary.
+ #
+ # Specifically, glibc versions 2.34 and later have the
+ # thread library (and libthread_db availability) in
+ # programs not linked against libpthread.so
+ do_tests $force_internal_tls $do_kfail_tls_access
+ }
+ }
+}
+
+with_test_prefix "static" {
+ set binfile $binprefix-static
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug "additional_flags=-static"}] != "" } {
+ untested "failed to compile"
+ } else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ do_tests $force_internal_tls $do_kfail_tls_access
+ }
+ }
+}
+
+with_test_prefix "pthreads" {
+ set binfile $binprefix-pthreads
+ if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ untested "failed to compile"
+ } else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ do_tests $force_internal_tls
+ }
+ }
+}
+
+with_test_prefix "pthreads-static" {
+ set binfile $binprefix-pthreads-static
+ if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug "additional_flags=-static"}] != "" } {
+ untested "failed to compile"
+ } else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ do_tests $force_internal_tls $do_kfail_tls_access
+ }
+ }
+}
diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.c b/gdb/testsuite/gdb.base/user-namespace-attach.c
new file mode 100644
index 0000000..684ce1c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/user-namespace-attach.c
@@ -0,0 +1,35 @@
+/* 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/>. */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+
+volatile int spin_p = 1;
+
+int
+main ()
+{
+ alarm (60);
+
+ printf ("pid = %lld\n", ((long long) getpid ()));
+
+ while (spin_p)
+ sleep (1);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp b/gdb/testsuite/gdb.base/user-namespace-attach.exp
new file mode 100644
index 0000000..741093c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
@@ -0,0 +1,148 @@
+# 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/>.
+
+# Check that GDB can attach to a process started using 'unshare'. The
+# inferior is started in a separate mnt namespace.
+
+require can_spawn_for_attach
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile] == -1} {
+ return
+}
+
+# This test relies (at least in some parts) on the sysroot being
+# 'target:'. Grab the current sysroot now so we can skip those tests
+# if the board file has changed the sysroot.
+set sysroot ""
+set test "show sysroot"
+gdb_test_multiple $test $test {
+ -re -wrap "The current system root is \"(.*)\"\\." {
+ set sysroot $expect_out(1,string)
+ }
+}
+
+# Start a process using 'unshare FLAGS', then attach to the process
+# from GDB. Check that the attach worked as expected.
+proc run_test { flags } {
+
+ # If FLAGS contains '--mount' then a separate mnt namespace will
+ # be created, in which case the executable will have been read
+ # from the 'target:'. Otherwise, the executable will have been
+ # read from the local filesystem, and there will be no prefix.
+ #
+ # Of course, this only applies if the sysroot is 'target:', some
+ # boards change this, so skip these tests on those boards.
+ if { [lsearch -exact [split $flags " "] "--mount"] != -1 } {
+ if { $::sysroot ne "target:" } {
+ return
+ }
+
+ set prefix "target:"
+ } else {
+ set prefix ""
+ }
+
+ set unshare_cmd "unshare $flags"
+
+ # Run '/bin/true' using UNSHARE_CMD. If the flags in UNSHARE_CMD
+ # aren't supported then this will fail, this means we shouldn't
+ # spawn the command with our test executable and try attaching.
+ #
+ # This will also fail if /bin/true isn't present, or doesn't work
+ # as we expect. But this should be fine for many targets.
+ set res [remote_exec target "$unshare_cmd /bin/true"]
+ if { [lindex $res 0] != 0 } {
+ unsupported "unshare flags not supported"
+ return
+ }
+
+ set inferior_spawn_id \
+ [spawn_wait_for_attach [list "$unshare_cmd $::binfile"]]
+ if { $inferior_spawn_id == -1 } {
+ unsupported "failed to spawn for attach"
+ return
+ }
+
+ set inferior_pid [spawn_id_get_pid $inferior_spawn_id]
+
+ clean_restart
+
+ set saw_bad_warning false
+ gdb_test_multiple "attach $inferior_pid" "attach to inferior" {
+ -re "^attach $::decimal\r\n" {
+ exp_continue
+ }
+
+ -re "^warning: \[^\r\n\]+: could not open as an executable file: \[^\r\n\]+\r\n" {
+ set saw_bad_warning true
+ exp_continue
+ }
+
+ -re "^warning: \[^\r\n\]+: can't open to read symbols: \[^\r\n\]+\r\n" {
+ set saw_bad_warning true
+ exp_continue
+ }
+
+ -re "^warning: Could not load vsyscall page because no executable was specified\r\n" {
+ # This warning is a secondary consequence of the above bad
+ # warnings, so don't count this as a bad warnings, ignore
+ # it instead.
+ exp_continue
+ }
+
+ -re "^warning:\\s+$::decimal\\s*\[^\r\n\]+: No such file or directory\r\n" {
+ # This unrelated warning is seen when GDB stops in libc,
+ # and the source code for libc is not available.
+ exp_continue
+ }
+
+ -re "^warning: \[^\r\n\]+\r\n" {
+ # If we ignore "other" warnings then, should the above
+ # warnings strings change we'll start ignoring the bad
+ # warnings, and the test will appear to pass.
+ #
+ # If you are seeing a warning here that really has nothing
+ # to do with the test failing, then the correct solution
+ # is to add a new regexp to specifically match _that_
+ # warning, and ignore it.
+ set saw_bad_warning true
+ exp_continue
+ }
+
+ -re "^$::gdb_prompt $" {
+ gdb_assert { !$saw_bad_warning } $gdb_test_name
+ }
+
+ -re "^\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+ }
+
+ # Ensure GDB could access the executable.
+ set binfile_re [string_to_regexp $::binfile]
+ gdb_test "info inferiors" \
+ "\r\n\\*\\s+$::decimal\\s+\[^\r\n\]+\\s+${prefix}${binfile_re}\\s*"
+}
+
+set test_flags [list \
+ "--mount --map-root-user" \
+ "--user" \
+ "--user --map-root-user"]
+
+foreach_with_prefix flags $test_flags {
+ run_test $flags
+}
diff --git a/gdb/testsuite/gdb.base/vfork-follow-parent.exp b/gdb/testsuite/gdb.base/vfork-follow-parent.exp
index fca2993..8cb785d 100644
--- a/gdb/testsuite/gdb.base/vfork-follow-parent.exp
+++ b/gdb/testsuite/gdb.base/vfork-follow-parent.exp
@@ -19,6 +19,8 @@
# schedule-multiple on" or "set detach-on-fork on". Test these two resolution
# methods.
+require allow_fork_tests
+
standard_testfile .c vforked-prog.c
set binfile ${testfile}-exit
diff --git a/gdb/testsuite/gdb.base/watch-before-fork.exp b/gdb/testsuite/gdb.base/watch-before-fork.exp
index 074cfbd..509561e 100644
--- a/gdb/testsuite/gdb.base/watch-before-fork.exp
+++ b/gdb/testsuite/gdb.base/watch-before-fork.exp
@@ -20,6 +20,8 @@
# This test uses "awatch".
require allow_hw_watchpoint_access_tests
+require allow_fork_tests
+
standard_testfile
if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
diff --git a/gdb/testsuite/gdb.base/watch-vfork.exp b/gdb/testsuite/gdb.base/watch-vfork.exp
index 1bc61bc..503727d 100644
--- a/gdb/testsuite/gdb.base/watch-vfork.exp
+++ b/gdb/testsuite/gdb.base/watch-vfork.exp
@@ -17,6 +17,8 @@
standard_testfile .c
+require allow_fork_tests
+
if { [build_executable ${testfile}.exp ${testfile} $srcfile {debug}] } {
untested "failed to compile"
return -1
diff --git a/gdb/testsuite/gdb.base/watchpoint-hw-attach.exp b/gdb/testsuite/gdb.base/watchpoint-hw-attach.exp
index b3892f3..fa63edb 100644
--- a/gdb/testsuite/gdb.base/watchpoint-hw-attach.exp
+++ b/gdb/testsuite/gdb.base/watchpoint-hw-attach.exp
@@ -26,29 +26,18 @@ if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} {
return -1
}
-if ![runto_main] {
- return -1
-}
+set test_spawn_id [spawn_wait_for_attach $binfile]
+set testpid [spawn_id_get_pid $test_spawn_id]
-# Run to the point where mypid in the test program has been
-# populated.
-gdb_breakpoint [gdb_get_line_number "pidacquired"]
-gdb_continue_to_breakpoint "pidacquired"
-
-# Get the PID of the test process.
-set testpid [get_integer_valueof "mypid" 0]
+gdb_test "attach $testpid" "Attaching to program: .*, process $testpid.*" "attach once"
gdb_test "detach" "Detaching from program: .*, process $testpid\r\n\\\[Inferior $decimal \\(process $testpid\\) detached\\\]"
-if {$testpid == ""} {
- return -1
-}
-
# A clean restart is needed to force the hardware watchpoint setup
# logic to run post attach rather than post inferior launch.
clean_restart $binfile
-gdb_test "attach $testpid" "Attaching to program: .*, process $testpid.*" "attach"
+gdb_test "attach $testpid" "Attaching to program: .*, process $testpid.*" "attach twice"
# Ensure the test program is in the top frame so the required
# variables are in scope.
@@ -62,3 +51,5 @@ gdb_test "watch watched_variable" \
gdb_test "continue" \
"continue.*Continuing.*\.Hardware watchpoint $decimal: watched_variable.*Old value = 0.*New value = 4.*watched_variable\\);"
+
+kill_wait_spawned_process $test_spawn_id
diff --git a/gdb/testsuite/gdb.btrace/multi-inferior.exp b/gdb/testsuite/gdb.btrace/multi-inferior.exp
index ed2acb2..d87a941 100644
--- a/gdb/testsuite/gdb.btrace/multi-inferior.exp
+++ b/gdb/testsuite/gdb.btrace/multi-inferior.exp
@@ -24,6 +24,8 @@
require allow_btrace_tests
+require allow_multi_inferior_tests
+
require !use_gdb_stub
standard_testfile
diff --git a/gdb/testsuite/gdb.cp/chained-calls.cc b/gdb/testsuite/gdb.cp/chained-calls.cc
index 9d12c98..9358c71 100644
--- a/gdb/testsuite/gdb.cp/chained-calls.cc
+++ b/gdb/testsuite/gdb.cp/chained-calls.cc
@@ -23,6 +23,8 @@ public:
S operator+ (const S &s);
+ int get ();
+
int a;
};
@@ -41,6 +43,12 @@ S::operator+ (const S &s)
return res;
}
+int
+S::get ()
+{
+ return a;
+}
+
S
f (int i)
{
@@ -162,6 +170,8 @@ public:
U (type t);
type get_type ();
+ int get ();
+
int a;
char c;
type tp[2];
@@ -191,6 +201,12 @@ U::get_type ()
}
int
+U::get ()
+{
+ return a;
+}
+
+int
main ()
{
int i = g(f(0));
@@ -198,6 +214,7 @@ main ()
B b = makeb ();
C c;
+ int z = f (42).get ();
return i + getb(b, 0); /* Break here */
}
diff --git a/gdb/testsuite/gdb.cp/chained-calls.exp b/gdb/testsuite/gdb.cp/chained-calls.exp
index 4f0597a..d34162c 100644
--- a/gdb/testsuite/gdb.cp/chained-calls.exp
+++ b/gdb/testsuite/gdb.cp/chained-calls.exp
@@ -42,3 +42,6 @@ gdb_test "p *c" ".* = {a = 5678}" "*c"
gdb_test "p *c + *c" ".* = {a = 11356}" "*c + *c"
gdb_test "p q(*c + *c)" ".* = {a = 11356}" "q(*c + *c)"
gdb_test "p make_int().get_type ()" ".* = INT" "make_int().get_type ()"
+gdb_test "p f(42).get()" " = 42" "f().get()"
+gdb_test "ptype f(42).get()" "type = int" "ptype f().get()"
+gdb_test "ptype make_int().get()" "type = int" "make_int().get()"
diff --git a/gdb/testsuite/gdb.cp/cpexprs.exp.tcl b/gdb/testsuite/gdb.cp/cpexprs.exp.tcl
index 1ac35af..5c3dfd6 100644
--- a/gdb/testsuite/gdb.cp/cpexprs.exp.tcl
+++ b/gdb/testsuite/gdb.cp/cpexprs.exp.tcl
@@ -28,17 +28,33 @@ proc test_breakpoint {func} {
delete_breakpoints
if { ! [gdb_breakpoint test_function] } {
fail "set test_function breakpoint for $func"
- } elseif { [gdb_test "continue" \
- "Continuing.\r\n\r\nBreakpoint $DEC+,.*test_function.*" \
- "continue to test_function for $func"] != 0 } {
- } else {
- gdb_breakpoint "$func"
- set i [expr {[string last : $func] + 1}]
- set efunc [string_to_regexp [string range $func $i end]]
- gdb_test "continue" \
- "Continuing.\r\n\r\nBreakpoint $DEC+,.*$efunc.*" \
- "continue to $func"
+ return
+ }
+
+ # Accept any input between "Continuing" and the breakpoint hit, as
+ # on Cygwin, we may see a "New Thread" notification. This is the
+ # Cygwin runtime spawning its own internal threads.
+ if { [gdb_test "continue" \
+ "Continuing.\r\n.*Breakpoint $DEC+,.*test_function.*" \
+ "continue to test_function for $func"] != 0 } {
+ return
}
+
+ # On some systems, the in-charge and not-in-charge dtors of a
+ # class may end up with the same address, so setting a breakpoint
+ # at a dtor like base::~base only finds one location. On other
+ # systems (e.g. Cygwin), the two dtors for the same class may have
+ # different addresses, so we find two locations for the
+ # breakpoint. Thus, expect that the breakpoint hit may or may not
+ # report a location number.
+ set bp_re "$DEC+(\.$DEC+)?"
+
+ gdb_breakpoint "$func"
+ set i [expr {[string last : $func] + 1}]
+ set efunc [string_to_regexp [string range $func $i end]]
+ gdb_test "continue" \
+ "Continuing.\r\n.*Breakpoint $bp_re,.*$efunc.*" \
+ "continue to $func"
}
# Add a function to the list of tested functions
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.cp/templates.exp b/gdb/testsuite/gdb.cp/templates.exp
index 74e4a92..52d0229 100644
--- a/gdb/testsuite/gdb.cp/templates.exp
+++ b/gdb/testsuite/gdb.cp/templates.exp
@@ -58,9 +58,9 @@ proc test_ptype_of_templates {} {
xfail "ptype T5<int> (obsolescent gcc or gdb)"
}
-re "type = class T5<int> \{${ws}public:${ws}static int X;${ws}int x;${ws}int val;${ws}void T5\\(int\\);${ws}void T5\\((T5<int> const|const T5<int>) ?&\\);${ws}~T5\\(\\);${ws}static void \\* operator new\\((size_t|unsigned( int| long|))\\);${ws}static void operator delete\\(void ?\\*\\);${ws}int value\\((void|)\\);${ws}\}\r\n$gdb_prompt $" {
- # This also triggers gdb/1113...
- kfail "gdb/1111" "ptype T5<int>"
- # Add here a PASS case when PR gdb/1111 gets fixed.
+ # This also triggers gdb/8218...
+ kfail "gdb/8216" "ptype T5<int>"
+ # Add here a PASS case when PR gdb/8216 gets fixed.
# These are really:
# http://sourceware.org/bugzilla/show_bug.cgi?id=8216
# http://sourceware.org/bugzilla/show_bug.cgi?id=8218
@@ -98,9 +98,9 @@ proc test_ptype_of_templates {} {
xfail "ptype t5i (obsolescent gcc or gdb) -- without size_t"
}
-re "type = class T5<int> \{${ws}public:${ws}static int X;${ws}int x;${ws}int val;${ws}void T5\\(int\\);${ws}void T5\\((T5<int> const|const T5<int>) ?&\\);${ws}~T5\\(\\);${ws}static void \\* operator new\\((size_t|unsigned( int| long|))\\);${ws}static void operator delete\\(void ?\\*\\);${ws}int value\\((void|)\\);${ws}\}\r\n$gdb_prompt $" {
- # This also triggers gdb/1113...
- kfail "gdb/1111" "ptype t5i"
- # Add here a PASS case when PR gdb/1111 gets fixed.
+ # This also triggers gdb/8218...
+ kfail "gdb/8216" "ptype t5i"
+ # Add here a PASS case when PR gdb/8216 gets fixed.
# These are really:
# http://sourceware.org/bugzilla/show_bug.cgi?id=8216
# http://sourceware.org/bugzilla/show_bug.cgi?id=8218
@@ -132,7 +132,7 @@ proc test_template_breakpoints {} {
"constructor breakpoint"
}
-re "0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2. T5 at .*\[\r\n\]*.3. T5 at .*\[\r\n\]*> $" {
- setup_kfail "gdb/1062" "*-*-*"
+ setup_kfail "gdb/8167" "*-*-*"
gdb_test "0" \
"nonsense intended to insure that this test fails" \
"constructor breakpoint"
@@ -151,7 +151,7 @@ proc test_template_breakpoints {} {
}
-re "the class `T5<int>' does not have destructor defined\r\nHint: try 'T5<int>::~T5<TAB> or 'T5<int>::~T5<ESC-\\?>\r\n\\(Note leading single quote.\\)\r\n$gdb_prompt $"
{
- kfail "gdb/1112" "destructor breakpoint"
+ kfail "gdb/8217" "destructor breakpoint"
}
}
@@ -307,7 +307,7 @@ gdb_test_multiple "ptype/r Foo" "ptype Foo" {
}
-re "type = class Foo<int> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int foo\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" {
# GCC 3.1, DWARF-2 output.
- kfail "gdb/57" "ptype Foo"
+ kfail "gdb/7162" "ptype Foo"
}
-re "No symbol \"Foo\" in current context.\r\n$gdb_prompt $" {
# GCC 2.95.3, stabs+ output.
@@ -342,28 +342,25 @@ gdb_test_multiple "ptype/r fchar" "ptype fchar" {
# ptype Foo<volatile char *>
gdb_test_multiple "ptype/r fvpchar" "ptype fvpchar" {
- -re "type = (class |)Foo<volatile char ?\\*> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*.*char.*\\*t;\r\n\r\n\[ \t\]*.*char \\* foo\\(int,.*char.*\\*\\);\r\n\\}\r\n$gdb_prompt $" {
- pass "ptype fvpchar"
- }
- -re "type = (class |)Foo<volatile char ?\\*> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*.*char.*\\*t;\r\n\r\n\[ \t\]*.*char \\* foo\\(int,.*char.*\\*\\);.*\r\n\\}\r\n$gdb_prompt $" {
+ -re "type = class Foo<char volatile\\*> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*volatile char \\*t;\r\n\r\n\[ \t\]*volatile char \\* foo\\(int, volatile char \\*\\);.*\r\n\\}\r\n$gdb_prompt $" {
pass "ptype fvpchar"
}
-re "type = (class |)Foo<char volatile ?\\*> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*.*char.*\\*t;\r\n\r\n\[ \t\]*.*char \\* foo\\(int,.*char.*\\*\\);\r\n\\}\r\n$gdb_prompt $" {
- kfail "gdb/1512" "ptype fvpchar"
+ kfail "gdb/8617" "ptype fvpchar"
}
}
# print a function from Foo<volatile char *>
# This test is sensitive to whitespace matching, so we'll do it twice,
-# varying the spacing, because of PR gdb/33.
+# varying the spacing, because of PR gdb/7138.
gdb_test_multiple "print Foo<volatile char *>::foo" "print Foo<volatile char *>::foo" {
-re "\\$\[0-9\]* = \\{.*char \\*\\((class |)Foo<(volatile char|char volatile) ?\\*> \\*(| const), int, .*char \\*\\)\\} $hex <Foo<.*char.*\\*>::foo\\(int, .*char.*\\*\\)>\r\n$gdb_prompt $" {
pass "print Foo<volatile char *>::foo"
}
-re "No symbol \"Foo<volatile char \\*>\" in current context.\r\n$gdb_prompt $" {
- # This used to be a kfail gdb/33 and then kfail gdb/931.
+ # This used to be a kfail gdb/7138 and then kfail gdb/8036.
fail "print Foo<volatile char *>::foo"
}
}
@@ -373,7 +370,7 @@ gdb_test_multiple "print Foo<volatile char*>::foo" "print Foo<volatile char*>::f
pass "print Foo<volatile char*>::foo"
}
-re "No symbol \"Foo<volatile char\\*>\" in current context.\r\n$gdb_prompt $" {
- # This used to be a kfail gdb/33 and then kfail gdb/931.
+ # This used to be a kfail gdb/7138 and then kfail gdb/8036.
fail "print Foo<volatile char*>::foo"
}
}
@@ -390,7 +387,7 @@ gdb_test_multiple "ptype/r Bar" "ptype Bar" {
}
-re "ptype Bar\r\ntype = class Bar<int, ?33> {\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int bar\\(int, int\\);\r\n}\r\n$gdb_prompt $" {
# GCC 3.1, DWARF-2 output.
- kfail "gdb/57" "ptype Bar"
+ kfail "gdb/7162" "ptype Bar"
}
-re "No symbol \"Bar\" in current context.\r\n$gdb_prompt $" {
# GCC 2.95.3, stabs+ output.
@@ -433,11 +430,11 @@ gdb_test_multiple "ptype/r Baz" "ptype Baz" {
}
-re "type = class Baz<int, ?'s'> {\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int baz\\(int, int\\);\r\n}\r\n$gdb_prompt $" {
# GCC 3.1, DWARF-2 output.
- kfail "gdb/57" "ptype Baz"
+ kfail "gdb/7162" "ptype Baz"
}
-re "type = class Baz<int, ?(\\(char\\))?115> {\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int baz\\(int, int\\);\r\n}\r\n$gdb_prompt $" {
- # GCC 3.x, DWARF-2 output, running into gdb/57 and gdb/1512.
- kfail "gdb/57" "ptype Baz"
+ # GCC 3.x, DWARF-2 output, running into gdb/7162 and gdb/8617.
+ kfail "gdb/7162" "ptype Baz"
}
-re "No symbol \"Baz\" in current context.\r\n$gdb_prompt $" {
# GCC 2.95.3, stabs+ output.
@@ -479,11 +476,11 @@ gdb_test_multiple "ptype/r Qux" "ptype Qux" {
}
-re "type = class Qux<char, ?&string> {\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*char t;\r\n\r\n\[ \t\]*char qux\\(int, char\\);\r\n}\r\n$gdb_prompt $" {
# GCC 3.1, DWARF-2 output.
- kfail "gdb/57" "ptype Qux"
+ kfail "gdb/7162" "ptype Qux"
}
-re "type = class Qux<char, ?&\\(string\\)> {\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*char t;\r\n\r\n\[ \t\]*char qux\\(int, char\\);\r\n}\r\n$gdb_prompt $" {
- # GCC 3.x, DWARF-2 output; gdb/57 + gdb/1512.
- kfail "gdb/57" "ptype Qux"
+ # GCC 3.x, DWARF-2 output; gdb/7162 + gdb/8617.
+ kfail "gdb/7162" "ptype Qux"
}
-re "No symbol \"Qux\" in current context.\r\n$gdb_prompt $" {
# GCC 2.95.3, stabs+ output.
@@ -507,7 +504,7 @@ gdb_test_multiple "ptype/r quxint" "ptype quxint" {
pass "ptype quxint"
}
-re "type = class Qux<int, ?& ?\\(string\\)> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int qux\\(int, int\\);.*\r\n\\}\r\n$gdb_prompt $" {
- kfail "gdb/1512" "ptype quxint"
+ kfail "gdb/8617" "ptype quxint"
}
}
@@ -524,7 +521,7 @@ gdb_test_multiple "ptype/r Spec" "ptype Spec" {
}
-re "type = class Spec<int, ?char> {\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\r\n\[ \t\]*int spec\\(char\\);\r\n}\r\n$gdb_prompt $" {
# GCC 3.1, DWARF-2 output.
- kfail "gdb/57" "ptype Spec"
+ kfail "gdb/7162" "ptype Spec"
}
-re "No symbol \"Spec\" in current context.\r\n$gdb_prompt $" {
# GCC 2.95.3, stabs+ output.
diff --git a/gdb/testsuite/gdb.dap/attach.exp b/gdb/testsuite/gdb.dap/attach.exp
index 37e867c..5e1f634 100644
--- a/gdb/testsuite/gdb.dap/attach.exp
+++ b/gdb/testsuite/gdb.dap/attach.exp
@@ -33,11 +33,11 @@ set attach_id [dap_attach $testpid $binfile]
dap_check_request_and_response "configurationDone" configurationDone
+dap_check_response "attach response" attach $attach_id
+
dap_wait_for_event_and_check "stopped" stopped \
"body reason" attach
-dap_check_response "attach response" attach $attach_id
-
dap_shutdown true
kill_wait_spawned_process $test_spawn_id
diff --git a/gdb/testsuite/gdb.dap/log-message.exp b/gdb/testsuite/gdb.dap/log-message.exp
index 421df14..cce367d 100644
--- a/gdb/testsuite/gdb.dap/log-message.exp
+++ b/gdb/testsuite/gdb.dap/log-message.exp
@@ -40,6 +40,15 @@ set obj [dap_check_request_and_response "set breakpoint" \
[list s $srcfile] $line]]
set fn_bpno [dap_get_breakpoint_number $obj]
+set eol {\n}
+dap_wait_for_event_and_check "set breakpoint output, part 1" output \
+ {body category} stdout \
+ {body output} "No source file named log-message.c.$eol"
+
+dap_wait_for_event_and_check "set breakpoint output, part 2" output \
+ {body category} stdout \
+ {body output} "Breakpoint 1 (-source log-message.c -line $line) pending.$eol"
+
dap_check_request_and_response "configurationDone" configurationDone
dap_check_response "launch response" launch $launch_id
diff --git a/gdb/testsuite/gdb.dap/threads.c b/gdb/testsuite/gdb.dap/threads.c
new file mode 100644
index 0000000..168f044
--- /dev/null
+++ b/gdb/testsuite/gdb.dap/threads.c
@@ -0,0 +1,67 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2019-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/>. */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#define NUM 2
+
+static pthread_barrier_t threads_started_barrier;
+
+static void *
+thread_function (void *arg)
+{
+ pthread_barrier_wait (&threads_started_barrier);
+
+ while (1)
+ sleep (1);
+
+ pthread_exit (NULL);
+}
+
+static void
+all_started (void)
+{
+}
+
+int
+main ()
+{
+ pthread_t threads[NUM];
+ long i;
+
+ pthread_barrier_init (&threads_started_barrier, NULL, NUM + 1);
+
+ for (i = 1; i <= NUM; i++)
+ {
+ int res;
+
+ res = pthread_create (&threads[i - 1], NULL, thread_function, NULL);
+ }
+
+ pthread_barrier_wait (&threads_started_barrier);
+
+ all_started ();
+
+ printf ("sleeping\n");
+ fflush (stdout);
+ sleep (180);
+
+ exit (EXIT_SUCCESS);
+}
diff --git a/gdb/testsuite/gdb.dap/threads.exp b/gdb/testsuite/gdb.dap/threads.exp
new file mode 100644
index 0000000..c91d107
--- /dev/null
+++ b/gdb/testsuite/gdb.dap/threads.exp
@@ -0,0 +1,81 @@
+# 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/>.
+
+# Test DAP "threads" request.
+
+require allow_shlib_tests allow_dap_tests
+
+load_lib dap-support.exp
+
+standard_testfile
+
+set libname $testfile-solib
+set srcfile_lib $srcdir/$subdir/$libname.c
+set binfile_lib [standard_output_file $libname.so]
+
+if {[build_executable "failed to prepare" $testfile $srcfile \
+ {debug pthreads}] == -1} {
+ return
+}
+
+if {[dap_initialize] == ""} {
+ return
+}
+
+set launch_id [dap_launch $testfile]
+
+set obj [dap_check_request_and_response "set breakpoint on all_started function" \
+ setFunctionBreakpoints \
+ {o breakpoints [a [o name [s all_started]]]}]
+set fn_bpno [dap_get_breakpoint_number $obj]
+
+dap_check_request_and_response "configurationDone" configurationDone
+
+dap_check_response "launch response" launch $launch_id
+
+lassign [dap_wait_for_event_and_check "stopped at function breakpoint" \
+ stopped \
+ "body reason" breakpoint \
+ "body hitBreakpointIds" $fn_bpno] \
+ ignore \
+ all_events
+
+# Verify that we saw the correct number of thread events.
+set count 0
+foreach event $all_events {
+ if {[dict get $event type] == "event"
+ && [dict get $event event] == "thread"
+ && [dict get $event body reason] == "started"} {
+ incr count
+ }
+}
+gdb_assert {$count == 3} "correct number of thread events"
+
+dap_check_request_and_response "continue" continue \
+ {o threadId [i 1]}
+
+# Make sure that the inferior has really re-started -- note that there
+# is no "continue" event, because the "continue" request suppresses
+# those.
+dap_wait_for_event_and_check "output from inferior" output \
+ {body output} "sleeping\\n"
+
+lassign [dap_check_request_and_response "threads request" threads] \
+ response ignore
+
+gdb_assert {[llength [dict get $response body threads]] == 3} \
+ "correct number of threads"
+
+dap_shutdown true
diff --git a/gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp b/gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp
index 93f8f92..35bb401 100644
--- a/gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp
+++ b/gdb/testsuite/gdb.debuginfod/build-id-no-debug-warning.exp
@@ -46,7 +46,7 @@ set build_id_debug_file \
[standard_output_file [build_id_debug_filename_get $binfile]]
# Get the BINFILE.debug filename. This is the file we should be
-# moving to the BUILD_ID_DEBUG_FILE location, but we wont, we're going
+# moving to the BUILD_ID_DEBUG_FILE location, but we won't, we're going
# to move something else there instead.
set debugfile [standard_output_file "${binfile}.debug"]
diff --git a/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp
index 78fa252..dac4e6c 100644
--- a/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp
+++ b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp
@@ -49,7 +49,7 @@
#
# This obviously needs fixing, but is a separate problem from the one being
# tested here, so this test deliberately checks the mapping using a file that
-# is mmaped rather than loaded as a shared library, as such the file is in the
+# is mmapped rather than loaded as a shared library, as such the file is in the
# core-files list of mapped files, but is not in the shared library list.
#
# Despite this test living in the gdb.debuginfod/ directory, only the last
@@ -260,7 +260,7 @@ proc load_core_file { testname { line_re "" } } {
# We expect RES to be 2 (TCL_RETURN) or 1 (TCL_ERROR). If we get
# here then somehow the 'catch' above finished without hitting
# either of those cases, which is .... weird.
- perror "unexepcted return value, code = $res, value = $string"
+ perror "unexpected return value, code = $res, value = $string"
return -1
}
}
diff --git a/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp b/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
index 7b36f65..4b3894e 100644
--- a/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
+++ b/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
@@ -152,7 +152,7 @@ proc_with_prefix no_url { } {
# Test that GDB cannot find dwz without debuginfod.
clean_restart
gdb_test "file ${binfile}_alt.o" \
- ".*could not find '.gnu_debugaltlink'.*" \
+ ".*could not find supplementary DWARF file .*" \
"file [file tail ${binfile}_alt.o]"
# Generate a core file and test that GDB cannot find the
diff --git a/gdb/testsuite/gdb.debuginfod/solib-with-soname.exp b/gdb/testsuite/gdb.debuginfod/solib-with-soname.exp
index 9f1842c..1008e46 100644
--- a/gdb/testsuite/gdb.debuginfod/solib-with-soname.exp
+++ b/gdb/testsuite/gdb.debuginfod/solib-with-soname.exp
@@ -89,7 +89,7 @@ if {[lindex $status 0] != 0} {
}
# Build the executable. This links against libfoo.so, which is
-# poining at libfoo_1.so. Just to confuse things even more, this
+# pointing at libfoo_1.so. Just to confuse things even more, this
# executable uses dlopen to load libfoo_2.so. Weird!
if { [build_executable "build executable" ${binfile} ${srcfile2} \
[list debug shlib=${library_filename} shlib_load]] == -1 } {
diff --git a/gdb/testsuite/gdb.dwarf2/ada-array-bound.c b/gdb/testsuite/gdb.dwarf2/ada-array-bound.c
new file mode 100644
index 0000000..5a7d397
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/ada-array-bound.c
@@ -0,0 +1,29 @@
+/* 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/>. */
+
+/* The data used for the structure. */
+
+unsigned char our_data[] = { 3, 7, 11, 13 };
+
+/* Dummy main function. */
+
+int
+main()
+{
+ asm ("main_label: .globl main_label");
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/ada-array-bound.exp b/gdb/testsuite/gdb.dwarf2/ada-array-bound.exp
new file mode 100644
index 0000000..f48df7b
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/ada-array-bound.exp
@@ -0,0 +1,89 @@
+# 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/>.
+
+# Test handling of an array type whose bound comes from the field of a
+# structure.
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+require dwarf2_support
+
+standard_testfile .c -debug.S
+
+# Set up the DWARF for the test.
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ global srcdir subdir srcfile
+
+ cu {} {
+ DW_TAG_compile_unit {
+ {DW_AT_language @DW_LANG_Ada95}
+ {DW_AT_name $srcfile}
+ } {
+ declare_labels byte array disc struct
+
+ byte: DW_TAG_base_type {
+ {DW_AT_byte_size 1 DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_unsigned}
+ {DW_AT_name byte}
+ }
+
+ array: DW_TAG_array_type {
+ {DW_AT_name array_type}
+ {DW_AT_type :$byte}
+ } {
+ DW_TAG_subrange_type {
+ {DW_AT_type :$byte}
+ {DW_AT_upper_bound :$disc}
+ }
+ }
+
+ struct: DW_TAG_structure_type {
+ {DW_AT_name discriminated}
+ {DW_AT_byte_size 4 DW_FORM_sdata}
+ } {
+ disc: DW_TAG_member {
+ {DW_AT_name disc}
+ {DW_AT_type :$byte}
+ {DW_AT_data_member_location 0 DW_FORM_sdata}
+ }
+ DW_TAG_member {
+ {DW_AT_name nums}
+ {DW_AT_type :$array}
+ {DW_AT_data_member_location 1 DW_FORM_sdata}
+ }
+ }
+
+ DW_TAG_variable {
+ {DW_AT_name "value"}
+ {DW_AT_type :$struct}
+ {DW_AT_external 1 DW_FORM_flag}
+ {DW_AT_location {DW_OP_addr [gdb_target_symbol "our_data"]}
+ SPECIAL_expr}
+ }
+ }
+ }
+}
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+ [list $srcfile $asm_file] {nodebug}] } {
+ return -1
+}
+
+gdb_test_no_output "set language ada"
+gdb_test "print value" \
+ [string_to_regexp " = (disc => 3, nums => (7, 11, 13))"]
diff --git a/gdb/testsuite/gdb.dwarf2/dw-form-strx-out-of-bounds.exp b/gdb/testsuite/gdb.dwarf2/dw-form-strx-out-of-bounds.exp
new file mode 100644
index 0000000..cb24b19
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw-form-strx-out-of-bounds.exp
@@ -0,0 +1,41 @@
+# 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/>.
+
+# Check that an out-of-bounds DW_FORM_strx attribute triggers a DWARF error.
+
+# Out of bounds index.
+set int_str_idx 1
+
+# With readnow, the dwarf error is printed during the file command, so skip
+# the test.
+require !readnow
+
+set prepare_for_testing_done 0
+source $srcdir/$subdir/dw-form-strx.exp.tcl
+require {expr $prepare_for_testing_done == 1}
+
+set re_dwarf_error \
+ [string_list_to_regexp \
+ "DWARF Error: Offset from DW_FORM_GNU_str_index or DW_FORM_strx" \
+ " pointing outside of .debug_str_offsets section in CU at offset"\
+ " "]$hex
+set re_in_module \
+ {in module [^\r\n]+}
+set re_in_module [string_to_regexp {[}]$re_in_module[string_to_regexp {]}]
+set re_no_symbol [string_to_regexp {No symbol "global_var" in current context.}]
+gdb_test "ptype global_var" \
+ [multi_line \
+ "$re_dwarf_error $re_in_module"\
+ $re_no_symbol]
diff --git a/gdb/testsuite/gdb.dwarf2/dw-form-strx.exp b/gdb/testsuite/gdb.dwarf2/dw-form-strx.exp
new file mode 100644
index 0000000..3f739c4
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw-form-strx.exp
@@ -0,0 +1,25 @@
+# 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/>.
+
+# Check that DW_FORM_strx works.
+
+# Correct index.
+set int_str_idx 0
+
+set prepare_for_testing_done 0
+source $srcdir/$subdir/dw-form-strx.exp.tcl
+require {expr $prepare_for_testing_done == 1}
+
+gdb_test "ptype global_var" "type = int"
diff --git a/gdb/testsuite/gdb.dwarf2/dw-form-strx.exp.tcl b/gdb/testsuite/gdb.dwarf2/dw-form-strx.exp.tcl
new file mode 100644
index 0000000..bc5a654
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw-form-strx.exp.tcl
@@ -0,0 +1,64 @@
+# 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/>.
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+require dwarf2_support
+
+standard_testfile main.c -dw.S
+
+set asm_file [standard_output_file $srcfile2]
+
+# Debug info in the main file.
+Dwarf::assemble $asm_file {
+ declare_labels base_offset_cu1
+
+ debug_str_offsets { base_offset base_offset_cu1 } int
+
+ cu {
+ version 5
+ } {
+ DW_TAG_compile_unit {
+ {DW_AT_str_offsets_base $base_offset_cu1 sec_offset}
+ } {
+ declare_labels int4_type
+
+ int4_type: DW_TAG_base_type {
+ {DW_AT_byte_size 4 DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_signed}
+ {DW_AT_name $::int_str_idx DW_FORM_strx_id}
+ }
+
+ DW_TAG_variable {
+ {DW_AT_name global_var}
+ {DW_AT_type :$int4_type}
+ {DW_AT_location {
+ DW_OP_const1u 12
+ DW_OP_stack_value
+ } SPECIAL_expr}
+ }
+ }
+ }
+}
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+ [list $srcfile $asm_file] {nodebug}] } {
+ return
+}
+
+# Let includers know prepare_for_testing was done, without having to check
+# source return status.
+set prepare_for_testing_done 1
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-error.exp b/gdb/testsuite/gdb.dwarf2/dw2-error.exp
index f1c8617..0701ec6 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-error.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-error.exp
@@ -37,7 +37,7 @@ set host_binfile [gdb_remote_download host $binfile]
# First test that reading symbols fails.
gdb_test "file $host_binfile" \
- {Reading symbols.*DWARF Error: wrong version in compilation unit header \(is 153, should be 2, 3, 4 or 5\).*} \
+ {Reading symbols.*DWARF Error: wrong version in unit header \(is 153, should be 2, 3, 4 or 5\).*} \
"file $testfile"
# We can't use proc readnow, because the PR makes it return 0.
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-modula2-self-type.S b/gdb/testsuite/gdb.dwarf2/dw2-modula2-self-type.S
index c09c6db..06a93ac 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-modula2-self-type.S
+++ b/gdb/testsuite/gdb.dwarf2/dw2-modula2-self-type.S
@@ -114,7 +114,11 @@ die221:
.byte 0x0
- .section .debug_str
+#ifdef __arm__
+ .section .debug_str,"MS",%progbits,1
+#else
+ .section .debug_str,"MS",@progbits,1
+#endif
.LASF1:
.string "2.mod"
.LASF0:
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-ranges-psym-warning.exp b/gdb/testsuite/gdb.dwarf2/dw2-ranges-psym-warning.exp
index ea0fc03..6120878 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-ranges-psym-warning.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-ranges-psym-warning.exp
@@ -117,7 +117,7 @@ if ![runto_main] {
# the hole is there in the symbol table, but not the partial symbol table,
# we run into:
# (gdb) bt
-# warning: (Internal error: pc 0x555555554619 in read in psymtab, \
+# warning: (Internal error: pc 0x555555554619 in read in psymtab,
# but not in symtab.)
# ...
# (gdb)
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-simple-locdesc.S b/gdb/testsuite/gdb.dwarf2/dw2-simple-locdesc.S
index cd999f4..551dda7 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-simple-locdesc.S
+++ b/gdb/testsuite/gdb.dwarf2/dw2-simple-locdesc.S
@@ -160,7 +160,11 @@ d:
.byte 0
.byte 0
.byte 0
- .section .debug_str
+#ifdef __arm__
+ .section .debug_str,"MS",%progbits,1
+#else
+ .section .debug_str,"MS",@progbits,1
+#endif
.LASF2:
.string "GNU C 4.7.0 20110727 (experimental)"
.LASF0:
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-strp.S b/gdb/testsuite/gdb.dwarf2/dw2-strp.S
index c7ede95..db3e64f 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-strp.S
+++ b/gdb/testsuite/gdb.dwarf2/dw2-strp.S
@@ -163,7 +163,11 @@
.byte 0x0 /* Terminator */
/* String table */
- .section .debug_str
+#ifdef __arm__
+ .section .debug_str,"MS",%progbits,1
+#else
+ .section .debug_str,"MS",@progbits,1
+#endif
.Lproducer:
.string "GNU C 3.3.3"
.Lchar_str:
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/dynamic-bit-offset.exp b/gdb/testsuite/gdb.dwarf2/dynamic-bit-offset.exp
new file mode 100644
index 0000000..f4e02da
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dynamic-bit-offset.exp
@@ -0,0 +1,95 @@
+# 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/>.
+
+# Test DW_AT_data_bit_offset with an expression. This is a DWARF
+# extension, but expected to be in DWARF 6. See
+# https://dwarfstd.org/issues/250501.1.html
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+require dwarf2_support
+
+standard_testfile ada-array-bound.c -debug.S
+
+# Set up the DWARF for the test.
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ global srcdir subdir srcfile
+
+ cu {} {
+ DW_TAG_compile_unit {
+ {DW_AT_language @DW_LANG_Ada95}
+ {DW_AT_name $srcfile}
+ } {
+ declare_labels byte array struct
+
+ byte: DW_TAG_base_type {
+ {DW_AT_byte_size 1 DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_unsigned}
+ {DW_AT_name byte}
+ }
+
+ array: DW_TAG_array_type {
+ {DW_AT_name array_type}
+ {DW_AT_type :$byte}
+ } {
+ DW_TAG_subrange_type {
+ {DW_AT_type :$byte}
+ {DW_AT_upper_bound 3 DW_FORM_sdata}
+ }
+ }
+
+ struct: DW_TAG_structure_type {
+ {DW_AT_name discriminated}
+ {DW_AT_byte_size 4 DW_FORM_sdata}
+ } {
+ DW_TAG_member {
+ {DW_AT_name disc}
+ {DW_AT_type :$byte}
+ {DW_AT_data_member_location 0 DW_FORM_sdata}
+ }
+
+ # We know this is always at offset 1 but use an
+ # expression just to test this code path. This is a
+ # DWARF extension. See
+ # https://dwarfstd.org/issues/250501.1.html.
+ DW_TAG_member {
+ {DW_AT_name nums}
+ {DW_AT_type :$array}
+ {DW_AT_data_bit_offset {DW_OP_lit8} SPECIAL_expr}
+ }
+ }
+
+ DW_TAG_variable {
+ {DW_AT_name "value"}
+ {DW_AT_type :$struct}
+ {DW_AT_external 1 DW_FORM_flag}
+ {DW_AT_location {DW_OP_addr [gdb_target_symbol "our_data"]}
+ SPECIAL_expr}
+ }
+ }
+ }
+}
+
+if {[prepare_for_testing "failed to prepare" ${testfile} \
+ [list $srcfile $asm_file] {nodebug}]} {
+ return -1
+}
+
+gdb_test_no_output "set language ada"
+gdb_test "print value" \
+ [string_to_regexp " = (disc => 3, nums => (7, 11, 13))"]
diff --git a/gdb/testsuite/gdb.dwarf2/fission-dw-form-strx.exp b/gdb/testsuite/gdb.dwarf2/fission-dw-form-strx.exp
new file mode 100644
index 0000000..4f5867c
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/fission-dw-form-strx.exp
@@ -0,0 +1,88 @@
+# 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/>.
+
+# Check support for a DW_FORM_strx attribute in a dwo file.
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+require dwarf2_support
+
+standard_testfile main.c -dw.S -dwo.S
+
+set main_asm_file [standard_output_file $srcfile2]
+set dwo_asm_file [standard_output_file $srcfile3]
+
+# Debug info in the main file.
+Dwarf::assemble $main_asm_file {
+ cu {
+ version 5
+ dwo_id 0xF00D
+ } {
+ compile_unit {
+ {DW_AT_dwo_name ${::gdb_test_file_name}.dwo DW_FORM_strp}
+ } {}
+ }
+}
+
+# Debug info in the DWO file.
+Dwarf::assemble $dwo_asm_file {
+ debug_str_offsets { dwo 1 } int
+
+ cu {
+ fission 1
+ version 5
+ dwo_id 0xF00D
+ } {
+ compile_unit {} {
+ declare_labels int4_type
+
+ int4_type: DW_TAG_base_type {
+ {DW_AT_byte_size 4 DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_signed}
+ {DW_AT_name 0 DW_FORM_strx_id}
+ }
+
+ DW_TAG_variable {
+ {DW_AT_name global_var}
+ {DW_AT_type :$int4_type}
+ {DW_AT_location {
+ DW_OP_const1u 12
+ DW_OP_stack_value
+ } SPECIAL_expr}
+ }
+ }
+ }
+}
+
+# Build main file.
+if { [build_executable "${testfile}.exp" $binfile \
+ [list ${srcfile} ${main_asm_file}] {nodebug}] } {
+ return
+}
+
+# Build DWO file.
+set dwo_file [standard_output_file ${testfile}.dwo]
+if { [gdb_compile_shlib $dwo_asm_file $dwo_file nodebug] != "" } {
+ return
+}
+
+if { [is_remote host] } {
+ gdb_remote_download host $dwo_file
+}
+
+clean_restart $binfile
+
+gdb_test "ptype global_var" "type = int"
diff --git a/gdb/testsuite/gdb.dwarf2/intbits.c b/gdb/testsuite/gdb.dwarf2/intbits.c
index 82e6ae8..909d283 100644
--- a/gdb/testsuite/gdb.dwarf2/intbits.c
+++ b/gdb/testsuite/gdb.dwarf2/intbits.c
@@ -41,6 +41,9 @@ unsigned char be30_1_off[4] = { 0x80, 0, 0, 2 };
here, to catch any situation where gdb tries to use the memory. */
unsigned char u32_0[4] = { 0xff, 0xff, 0xff, 0xff };
+/* An 8 bit slot holding a 3 bit value. */
+unsigned char just_bit_0 = 5;
+
int
main (void)
{
diff --git a/gdb/testsuite/gdb.dwarf2/intbits.exp b/gdb/testsuite/gdb.dwarf2/intbits.exp
index 7b50e15..ff1d69a 100644
--- a/gdb/testsuite/gdb.dwarf2/intbits.exp
+++ b/gdb/testsuite/gdb.dwarf2/intbits.exp
@@ -36,7 +36,7 @@ Dwarf::assemble ${asm_file} {
{DW_AT_language @DW_LANG_C_plus_plus}
} {
declare_labels i7_type u1_type u17_type u31_type \
- u31_1_type u32_0_type u0_0_type be30_1_type
+ u31_1_type u32_0_type u0_0_type be30_1_type just_bit_type
i7_type: DW_TAG_base_type {
{DW_AT_encoding @DW_ATE_signed}
@@ -167,6 +167,20 @@ Dwarf::assemble ${asm_file} {
{DW_AT_location {DW_OP_addr [gdb_target_symbol "u32_0"]}
SPECIAL_expr}
}
+
+ just_bit_type: DW_TAG_base_type {
+ {DW_AT_encoding @DW_ATE_unsigned}
+ {DW_AT_name "just_bit_type"}
+ {DW_AT_bit_size 3 DW_FORM_udata}
+ }
+
+ DW_TAG_variable {
+ {DW_AT_name "v_just_bit"}
+ {DW_AT_type :${just_bit_type}}
+ {DW_AT_external 1 DW_FORM_flag}
+ {DW_AT_location {DW_OP_addr [gdb_target_symbol "just_bit_0"]}
+ SPECIAL_expr}
+ }
}
}
}
@@ -197,3 +211,6 @@ gdb_test "x/4xb &v_u32_1_off" ":\t0x0e\t0x00\t0x00\t0x00"
gdb_test "print v_be30_1_off" "= 1"
gdb_test "print v_be30_1_off = 7" " = 7"
gdb_test "x/4xb &v_be30_1_off" ":\t0x00\t0x00\t0x00\t0x0e"
+
+gdb_test "print/x v_just_bit" " = 0x5"
+gdb_test "print/x (just_bit_type) 5" " = 0x5"
diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw4.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw4.exp
new file mode 100644
index 0000000..c0c2635
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw4.exp
@@ -0,0 +1,71 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2022-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/>.
+
+# Generate binaries imitating different ways source file paths can be passed to
+# compilers. Test printing macros from those binaries.
+
+# The do_test proc comes from macro-source-path.exp.tcl.
+source $srcdir/$subdir/macro-source-path.exp.tcl
+
+# When adding a test here, please consider adding an equivalent case to
+# `gdb.base/macro-source-path.exp`.
+
+# The following tests are based on the output of `clang-14 -gdwarf-4
+# -fdebug-macro -g3 <file>` (using its built-in assembler). With -gdwarf-4,
+# clang produces a .debug_macinfo section, not a .debug_macro section. But
+# this test still creates a .debug_macro section, that's good enough for what
+# we want to test.
+
+## test.c
+do_test filename 4 "test.c" 1 {
+} {
+ {"test.c" 0}
+}
+
+## ./test.c
+do_test dot-filename 4 "test.c" 1 {
+ "."
+} {
+ {"test.c" 1}
+}
+
+## ../cwd/test.c
+do_test dot-dot-cwd 4 "../cwd/test.c" 1 {
+ "../cwd"
+} {
+ {"test.c" 1}
+}
+
+## /tmp/cwd/test.c
+do_test absolute-cwd 4 "/tmp/cwd/test.c" 1 {
+} {
+ {"test.c" 0}
+}
+
+## ../other/test.c
+do_test dot-dot-other 4 "../other/test.c" 1 {
+ "../other"
+} {
+ {"test.c" 1}
+}
+
+## /tmp/other/test.c
+do_test absolute-other 4 "/tmp/other/test.c" 1 {
+ "/tmp"
+} {
+ {"other/test.c" 1}
+}
diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw5.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw5.exp
new file mode 100644
index 0000000..0b3239e
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw5.exp
@@ -0,0 +1,75 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2022-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/>.
+
+# Generate binaries imitating different ways source file paths can be passed to
+# compilers. Test printing macros from those binaries.
+
+# The do_test proc comes from macro-source-path.exp.tcl.
+source $srcdir/$subdir/macro-source-path.exp.tcl
+
+# When adding a test here, please consider adding an equivalent case to
+# `gdb.base/macro-source-path.exp`.
+
+# The following tests are based on the output of `clang-14 -gdwarf-5
+# -fdebug-macro -g3 <file>` (using its built-in assembler)
+
+## test.c
+do_test filename 5 "test.c" 0 {
+ "/tmp/cwd"
+} {
+ {"test.c" 0}
+}
+
+## ./test.c
+do_test dot-filename 5 "test.c" 1 {
+ "/tmp/cwd"
+ "."
+} {
+ {"test.c" 0}
+ {"test.c" 1}
+}
+
+## ../cwd/test.c
+do_test dot-dot-cwd 5 "../cwd/test.c" 0 {
+ "/tmp/cwd"
+} {
+ {"../cwd/test.c" 0}
+}
+
+## /tmp/cwd/test.c
+do_test absolute-cwd 5 "/tmp/cwd/test.c" 1 {
+ "/tmp/cwd"
+} {
+ {"/tmp/cwd/test.c" 0}
+ {"test.c" 0}
+}
+
+## ../other/test.c
+do_test dot-dot-other 5 "../other/test.c" 0 {
+ "/tmp/cwd"
+} {
+ {"../other/test.c" 0}
+}
+
+## /tmp/other/test.c
+do_test absolute-other 5 "/tmp/other/test.c" 1 {
+ "/tmp/cwd"
+ "/tmp"
+} {
+ {"/tmp/other/test.c" 0}
+ {"other/test.c" 1}
+}
diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld234-dw5.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld234-dw5.exp
new file mode 100644
index 0000000..940f997
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld234-dw5.exp
@@ -0,0 +1,70 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2022-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/>.
+
+# Generate binaries imitating different ways source file paths can be passed to
+# compilers. Test printing macros from those binaries.
+
+# The do_test proc comes from macro-source-path.exp.tcl.
+source $srcdir/$subdir/macro-source-path.exp.tcl
+
+# When adding a test here, please consider adding an equivalent case to
+# `gdb.base/macro-source-path.exp`.
+
+# The following tests are based on the output of `gcc -gdwarf-5 -g3 <file>`,
+# gcc 11 paired with gas from binutils 2.34 (Ubuntu 20.04). It generates a v5
+# .debug_macro section, but a v3 .debug_line section.
+
+## test.c
+do_test filename 3 "test.c" 1 {
+} {
+ {"test.c" 0}
+}
+
+## ./test.c
+do_test dot-filename 3 "./test.c" 1 {
+ "."
+} {
+ {"test.c" 1}
+}
+
+## ../cwd/test.c
+do_test dot-dot-cwd 3 "../cwd/test.c" 1 {
+ "../cwd"
+} {
+ {"test.c" 1}
+}
+
+## /tmp/cwd/test.c
+do_test absolute-cwd 3 "/tmp/cwd/test.c" 1 {
+ "/tmp/cwd"
+} {
+ {"test.c" 1}
+}
+
+## ../other/test.c
+do_test dot-dot-other 3 "../other/test.c" 1 {
+ "../other"
+} {
+ {"test.c" 1}
+}
+
+## /tmp/other/test.c
+do_test absolute-other 3 "/tmp/other/test.c" 1 {
+ "/tmp/other"
+} {
+ {"test.c" 1}
+}
diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw4.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw4.exp
new file mode 100644
index 0000000..dea0308
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw4.exp
@@ -0,0 +1,70 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2022-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/>.
+
+# Generate binaries imitating different ways source file paths can be passed to
+# compilers. Test printing macros from those binaries.
+
+# The do_test proc comes from macro-source-path.exp.tcl.
+source $srcdir/$subdir/macro-source-path.exp.tcl
+
+# When adding a test here, please consider adding an equivalent case to
+# `gdb.base/macro-source-path.exp`.
+
+# The following tests are based on the output of `gcc -gdwarf-4 -g3 <file>`,
+# gcc 11 paired with gas from binutils 2.38. With -gdwarf-4, gcc generates a
+# v4 (pre-standard) .debug_macro section.
+
+## test.c
+do_test filename 4 "test.c" 1 {
+} {
+ {"test.c" 0}
+}
+
+## ./test.c
+do_test dot-filename 4 "./test.c" 1 {
+ "."
+} {
+ {"test.c" 1}
+}
+
+## ../cwd/test.c
+do_test dot-dot-cwd 4 "../cwd/test.c" 1 {
+ "../cwd"
+} {
+ {"test.c" 1}
+}
+
+## /tmp/cwd/test.c
+do_test absolute-cwd 4 "/tmp/cwd/test.c" 1 {
+ "/tmp/cwd"
+} {
+ {"test.c" 1}
+}
+
+## ../other/test.c
+do_test dot-dot-other 4 "../other/test.c" 1 {
+ "../other"
+} {
+ {"test.c" 1}
+}
+
+## /tmp/other/test.c
+do_test absolute-other 4 "/tmp/other/test.c" 1 {
+ "/tmp/other"
+} {
+ {"test.c" 1}
+}
diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw5.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw5.exp
new file mode 100644
index 0000000..98a278e
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw5.exp
@@ -0,0 +1,81 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2022-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/>.
+
+# Generate binaries imitating different ways source file paths can be passed to
+# compilers. Test printing macros from those binaries.
+
+# The do_test proc comes from macro-source-path.exp.tcl.
+source $srcdir/$subdir/macro-source-path.exp.tcl
+
+# When adding a test here, please consider adding an equivalent case to
+# `gdb.base/macro-source-path.exp`.
+
+# The following tests are based on the output of `gcc -gdwarf-5 -g3 <file>`,
+# gcc 11 paired with gas from binutils 2.38.
+
+## test.c
+do_test filename 5 "test.c" 1 {
+ "/tmp/cwd"
+} {
+ {"test.c" 0}
+ {"test.c" 0}
+}
+
+## ./test.c
+do_test dot-filename 5 "./test.c" 1 {
+ "/tmp/cwd"
+ "."
+} {
+ {"test.c" 1}
+ {"test.c" 1}
+}
+
+## ../cwd/test.c
+do_test dot-dot-cwd 5 "../cwd/test.c" 1 {
+ "/tmp/cwd"
+ "../cwd"
+} {
+ {"test.c" 1}
+ {"test.c" 1}
+}
+
+## /tmp/cwd/test.c
+do_test absolute-cwd 5 "/tmp/cwd/test.c" 1 {
+ "/tmp/cwd"
+ "/tmp/cwd"
+} {
+ {"test.c" 1}
+ {"test.c" 0}
+}
+
+## ../other/test.c
+do_test dot-dot-other 5 "../other/test.c" 1 {
+ "/tmp/cwd"
+ "../other"
+} {
+ {"test.c" 1}
+ {"test.c" 1}
+}
+
+## /tmp/other/test.c
+do_test absolute-other 5 "/tmp/other/test.c" 1 {
+ "/tmp/cwd"
+ "/tmp/other"
+} {
+ {"test.c" 1}
+ {"test.c" 1}
+}
diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path.exp.tcl
index 1318f8e..ecaf685 100644
--- a/gdb/testsuite/gdb.dwarf2/macro-source-path.exp
+++ b/gdb/testsuite/gdb.dwarf2/macro-source-path.exp.tcl
@@ -17,12 +17,15 @@
# Generate binaries imitating different ways source file paths can be passed to
# compilers. Test printing macros from those binaries.
+#
+# The entry points for this test are in the various
+# gdb.dwarf2/macro-source-path-*.exp files.
load_lib dwarf.exp
require dwarf2_support
-standard_testfile .c
+standard_testfile macro-source-path.c
lassign [function_range main $srcdir/$subdir/$srcfile] \
main_start main_len
@@ -160,248 +163,3 @@ proc do_test { test_name lines_version DW_AT_name main_file_idx directories
}
}
}
-
-# When adding a test here, please consider adding an equivalent case to the test
-# of the same name in gdb.base.
-
-# The following tests are based on the output of `gcc -gdwarf-5 -g3 <file>`,
-# gcc 11 paired with gas from binutils 2.38.
-
-## test.c
-do_test gcc11-ld238-dw5-filename 5 "test.c" 1 {
- "/tmp/cwd"
-} {
- {"test.c" 0}
- {"test.c" 0}
-}
-
-## ./test.c
-do_test gcc11-ld238-dw5-dot-filename 5 "./test.c" 1 {
- "/tmp/cwd"
- "."
-} {
- {"test.c" 1}
- {"test.c" 1}
-}
-
-## ../cwd/test.c
-do_test gcc11-ld238-dw5-dot-dot-cwd 5 "../cwd/test.c" 1 {
- "/tmp/cwd"
- "../cwd"
-} {
- {"test.c" 1}
- {"test.c" 1}
-}
-
-## /tmp/cwd/test.c
-do_test gcc11-ld238-dw5-absolute-cwd 5 "/tmp/cwd/test.c" 1 {
- "/tmp/cwd"
- "/tmp/cwd"
-} {
- {"test.c" 1}
- {"test.c" 0}
-}
-
-## ../other/test.c
-do_test gcc11-ld238-dw5-dot-dot-other 5 "../other/test.c" 1 {
- "/tmp/cwd"
- "../other"
-} {
- {"test.c" 1}
- {"test.c" 1}
-}
-
-## /tmp/other/test.c
-do_test gcc11-ld238-dw5-absolute-other 5 "/tmp/other/test.c" 1 {
- "/tmp/cwd"
- "/tmp/other"
-} {
- {"test.c" 1}
- {"test.c" 1}
-}
-
-# The following tests are based on the output of `gcc -gdwarf-4 -g3 <file>`,
-# gcc 11 paired with gas from binutils 2.38. With -gdwarf-4, gcc generates a
-# v4 (pre-standard) .debug_macro section.
-
-## test.c
-do_test gcc11-ld238-dw4-filename 4 "test.c" 1 {
-} {
- {"test.c" 0}
-}
-
-## ./test.c
-do_test gcc11-ld238-dw4-dot-filename 4 "./test.c" 1 {
- "."
-} {
- {"test.c" 1}
-}
-
-## ../cwd/test.c
-do_test gcc11-ld238-dw4-dot-dot-cwd 4 "../cwd/test.c" 1 {
- "../cwd"
-} {
- {"test.c" 1}
-}
-
-## /tmp/cwd/test.c
-do_test gcc11-ld238-dw4-absolute-cwd 4 "/tmp/cwd/test.c" 1 {
- "/tmp/cwd"
-} {
- {"test.c" 1}
-}
-
-## ../other/test.c
-do_test gcc11-ld238-dw4-dot-dot-other 4 "../other/test.c" 1 {
- "../other"
-} {
- {"test.c" 1}
-}
-
-## /tmp/other/test.c
-do_test gcc11-ld238-dw4-absolute-other 4 "/tmp/other/test.c" 1 {
- "/tmp/other"
-} {
- {"test.c" 1}
-}
-
-# The following tests are based on the output of `clang-14 -gdwarf-5
-# -fdebug-macro -g3 <file>` (using its built-in assembler)
-
-## test.c
-do_test clang14-dw5-filename 5 "test.c" 0 {
- "/tmp/cwd"
-} {
- {"test.c" 0}
-}
-
-## ./test.c
-do_test clang14-dw5-dot-filename 5 "test.c" 1 {
- "/tmp/cwd"
- "."
-} {
- {"test.c" 0}
- {"test.c" 1}
-}
-
-## ../cwd/test.c
-do_test clang14-dw5-dot-dot-cwd 5 "../cwd/test.c" 0 {
- "/tmp/cwd"
-} {
- {"../cwd/test.c" 0}
-}
-
-## /tmp/cwd/test.c
-do_test clang14-dw5-absolute-cwd 5 "/tmp/cwd/test.c" 1 {
- "/tmp/cwd"
-} {
- {"/tmp/cwd/test.c" 0}
- {"test.c" 0}
-}
-
-## ../other/test.c
-do_test clang14-dw5-dot-dot-other 5 "../other/test.c" 0 {
- "/tmp/cwd"
-} {
- {"../other/test.c" 0}
-}
-
-## /tmp/other/test.c
-do_test clang14-dw5-absolute-other 5 "/tmp/other/test.c" 1 {
- "/tmp/cwd"
- "/tmp"
-} {
- {"/tmp/other/test.c" 0}
- {"other/test.c" 1}
-}
-
-# The following tests are based on the output of `clang-14 -gdwarf-4
-# -fdebug-macro -g3 <file>` (using its built-in assembler). With -gdwarf-4,
-# clang produces a .debug_macinfo section, not a .debug_macro section. But
-# this test still creates a .debug_macro section, that's good enough for what
-# we want to test.
-
-## test.c
-do_test clang14-dw4-filename 4 "test.c" 1 {
-} {
- {"test.c" 0}
-}
-
-## ./test.c
-do_test clang14-dw4-dot-filename 4 "test.c" 1 {
- "."
-} {
- {"test.c" 1}
-}
-
-## ../cwd/test.c
-do_test clang14-dw4-dot-dot-cwd 4 "../cwd/test.c" 1 {
- "../cwd"
-} {
- {"test.c" 1}
-}
-
-## /tmp/cwd/test.c
-do_test clang14-dw4-absolute-cwd 4 "/tmp/cwd/test.c" 1 {
-} {
- {"test.c" 0}
-}
-
-## ../other/test.c
-do_test clang14-dw4-dot-dot-other 4 "../other/test.c" 1 {
- "../other"
-} {
- {"test.c" 1}
-}
-
-## /tmp/other/test.c
-do_test clang14-dw4-absolute-other 4 "/tmp/other/test.c" 1 {
- "/tmp"
-} {
- {"other/test.c" 1}
-}
-
-# The following tests are based on the output of `gcc -gdwarf-5 -g3 <file>`,
-# gcc 11 paired with gas from binutils 2.34 (Ubuntu 20.04). It generates a v5
-# .debug_macro section, but a v3 .debug_line section.
-
-## test.c
-do_test gcc11-ld234-dw5-filename 3 "test.c" 1 {
-} {
- {"test.c" 0}
-}
-
-## ./test.c
-do_test gcc11-ld234-dw5-dot-filename 3 "./test.c" 1 {
- "."
-} {
- {"test.c" 1}
-}
-
-## ../cwd/test.c
-do_test gcc11-ld234-dw5-dot-dot-cwd 3 "../cwd/test.c" 1 {
- "../cwd"
-} {
- {"test.c" 1}
-}
-
-## /tmp/cwd/test.c
-do_test gcc11-ld234-dw5-absolute-cwd 3 "/tmp/cwd/test.c" 1 {
- "/tmp/cwd"
-} {
- {"test.c" 1}
-}
-
-## ../other/test.c
-do_test gcc11-ld234-dw5-dot-dot-other 3 "../other/test.c" 1 {
- "../other"
-} {
- {"test.c" 1}
-}
-
-## /tmp/other/test.c
-do_test gcc11-ld234-dw5-absolute-other 3 "/tmp/other/test.c" 1 {
- "/tmp/other"
-} {
- {"test.c" 1}
-}
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.dwarf2/pr11465.S b/gdb/testsuite/gdb.dwarf2/pr11465.S
index fed98bc..f3f2c57 100644
--- a/gdb/testsuite/gdb.dwarf2/pr11465.S
+++ b/gdb/testsuite/gdb.dwarf2/pr11465.S
@@ -344,7 +344,11 @@ die149: .uleb128 0x16 /* DW_TAG_variable */
.byte 0x0
.byte 0x0
.byte 0x0
- .section .debug_str
+#ifdef __arm__
+ .section .debug_str,"MS",%progbits,1
+#else
+ .section .debug_str,"MS",@progbits,1
+#endif
.LASF0:
.string "_ZN1N1fE"
.LASF7:
diff --git a/gdb/testsuite/gdb.guile/scm-cmd.exp b/gdb/testsuite/gdb.guile/scm-cmd.exp
index 9caca24..3709cb1 100644
--- a/gdb/testsuite/gdb.guile/scm-cmd.exp
+++ b/gdb/testsuite/gdb.guile/scm-cmd.exp
@@ -71,6 +71,65 @@ gdb_test_multiline "input subcommand" \
gdb_test "prefix-cmd subcmd ugh" "subcmd output, arg = ugh" "call subcmd"
+# Create a sub-command using a partial, but still unique, prefix.
+
+gdb_test_multiline "sub-command using partial prefix" \
+ "guile" "" \
+ "(register-command! (make-command \"prefix subcmd2\"" "" \
+ " #:command-class COMMAND_OBSCURE" "" \
+ " #:invoke (lambda (self arg from-tty)" "" \
+ " (display (format #f \"subcmd2 output, arg = ~a\\n\" arg)))))" "" \
+ "end" ""
+
+gdb_test "prefix-cmd subcmd2 ugh" "subcmd2 output, arg = ugh" "call subcmd2"
+
+# Now create a second prefix, similar to the first.
+
+gdb_test_multiline "create prefix-xxx prefix command" \
+ "guile" "" \
+ "(register-command! (make-command \"prefix-xxx\"" "" \
+ " #:command-class COMMAND_OBSCURE" "" \
+ " #:completer-class COMPLETE_NONE" "" \
+ " #:prefix? #t))" "" \
+ "end" ""
+
+# Now create a sub-command using an ambiguous prefix.
+
+gdb_test_multiline "sub-command using ambiguous partial prefix" \
+ "guile" "" \
+ "(register-command! (make-command \"prefix subcmd3\"" "" \
+ " #:command-class COMMAND_OBSCURE" "" \
+ " #:invoke (lambda (self arg from-tty)" "" \
+ " (display (format #f \"subcmd3 output, arg = ~a\\n\" arg)))))" "" \
+ "end" \
+ [multi_line \
+ "Out of range: could not find command prefix 'prefix' in position 1: \"prefix subcmd3\"" \
+ "Error while executing Scheme code\\."]
+
+# Check for errors when creating a command with an unknown prefix.
+
+gdb_test_multiline "try to create 'unknown-prefix subcmd'" \
+ "guile" "" \
+ "(register-command! (make-command \"unknown-prefix subcmd\"" "" \
+ " #:command-class COMMAND_OBSCURE" "" \
+ " #:invoke (lambda (self arg from-tty)" "" \
+ " (display \"called unknown-prefix subcmd\"))))" "" \
+ "end" \
+ [multi_line \
+ "Out of range: could not find command prefix 'unknown-prefix' in position 1: \"unknown-prefix subcmd\"" \
+ "Error while executing Scheme code\\."]
+
+gdb_test_multiline "try to create 'prefix-cmd unknown-prefix subcmd'" \
+ "guile" "" \
+ "(register-command! (make-command \"prefix-cmd unknown-prefix subcmd\"" "" \
+ " #:command-class COMMAND_OBSCURE" "" \
+ " #:invoke (lambda (self arg from-tty)" "" \
+ " (display \"called prefix-cmd unknown-prefix subcmd\"))))" "" \
+ "end" \
+ [multi_line \
+ "Out of range: could not find command prefix 'prefix-cmd unknown-prefix' in position 1: \"prefix-cmd unknown-prefix subcmd\"" \
+ "Error while executing Scheme code\\."]
+
# Test a subcommand in an existing GDB prefix.
gdb_test_multiline "input new subcommand" \
diff --git a/gdb/testsuite/gdb.guile/scm-color.exp b/gdb/testsuite/gdb.guile/scm-color.exp
index bbc9e71..578f712 100644
--- a/gdb/testsuite/gdb.guile/scm-color.exp
+++ b/gdb/testsuite/gdb.guile/scm-color.exp
@@ -20,7 +20,10 @@ load_lib gdb-guile.exp
require allow_guile_tests
-clean_restart
+# Start GDB with styling support.
+with_ansi_styling_terminal {
+ clean_restart
+}
gdb_install_guile_utils
gdb_install_guile_module
@@ -108,3 +111,8 @@ gdb_test [concat "guile " \
"\033\\\[31m\033\\\[42mred on green\033\\\[49m red on default\033\\\[39m" \
"escape sequences"
+# Ensure that turning styling off means no escape sequences.
+gdb_test_no_output "set style enabled off"
+gdb_test_no_output "guile (display (color-escape-sequence c_red #t))"
+gdb_test_no_output "guile (display (color-escape-sequence c_red #f))"
+gdb_test_no_output "set style enabled on"
diff --git a/gdb/testsuite/gdb.guile/scm-frame.exp b/gdb/testsuite/gdb.guile/scm-frame.exp
index b5ec73f..9a27c42 100644
--- a/gdb/testsuite/gdb.guile/scm-frame.exp
+++ b/gdb/testsuite/gdb.guile/scm-frame.exp
@@ -52,7 +52,7 @@ gdb_test "guile (print (frame-read-var bf1 \"b\"))" \
"\"bar\"" "test b"
# Test the read-var function in another block other than the current
-# block (in this case, the super block). Test thar read-var is reading
+# block (in this case, the super block). Test that read-var is reading
# the correct variables of i and f but they are the correct value and type.
gdb_scm_test_silent_cmd "guile (define sb (block-superblock (frame-block bf1)))" \
"get superblock"
diff --git a/gdb/testsuite/gdb.guile/scm-parameter.exp b/gdb/testsuite/gdb.guile/scm-parameter.exp
index 8ab5d93..e35428a 100644
--- a/gdb/testsuite/gdb.guile/scm-parameter.exp
+++ b/gdb/testsuite/gdb.guile/scm-parameter.exp
@@ -67,9 +67,19 @@ with_test_prefix "test-param" {
gdb_test_no_output "set print test-param off"
gdb_test "show print test-param" "The state of the Test Parameter is off." "show parameter off"
gdb_test "guile (print (parameter-value test-param))" "= #f" "parameter value, false"
- gdb_test "help show print test-param" "Show the state of the boolean test-param.*" "show help"
- gdb_test "help set print test-param" "Set the state of the boolean test-param.*" "set help"
- gdb_test "help set print" "set print test-param -- Set the state of the boolean test-param.*" "general help"
+ gdb_test "help show print test-param" \
+ [multi_line \
+ "^Show the state of the boolean test-param\\." \
+ "When enabled, test param does something useful\\. When disabled, does nothing\\."] \
+ "show help"
+ gdb_test "help set print test-param" \
+ [multi_line \
+ "^Set the state of the boolean test-param\\." \
+ "When enabled, test param does something useful\\. When disabled, does nothing\\."] \
+ "set help"
+ gdb_test "help set print" \
+ "set print test-param -- Set the state of the boolean test-param.*" \
+ "general help"
gdb_test "guile (print (parameter? test-param))" "= #t"
gdb_test "guile (print (parameter? 42))" "= #f"
@@ -314,9 +324,17 @@ with_test_prefix "test-undocumented-param" {
gdb_test "show print test-undoc-param" "The state of the Test Parameter is on." "show parameter on"
gdb_test_no_output "set print test-undoc-param off"
gdb_test "show print test-undoc-param" "The state of the Test Parameter is off." "show parameter off"
- gdb_test "help show print test-undoc-param" "This command is not documented." "show help"
- gdb_test "help set print test-undoc-param" "This command is not documented." "set help"
- gdb_test "help set print" "set print test-undoc-param -- This command is not documented.*" "general help"
+ gdb_test "help show print test-undoc-param" \
+ [multi_line \
+ "^Show the current value of 'print test-undoc-param'\\." \
+ "This command is not documented\\."] \
+ "show help"
+ gdb_test "help set print test-undoc-param" \
+ [multi_line \
+ "Set the current value of 'print test-undoc-param'\\." \
+ "This command is not documented\\."] \
+ "set help"
+ gdb_test "help set print" "set print test-undoc-param -- Set the current value of 'print test-undoc-param'\\..*" "general help"
}
# Test a parameter with a restricted range, where we need to notify the user
@@ -379,13 +397,168 @@ gdb_test_no_output "guile (register-parameter! prev-ambig)"
with_test_prefix "previously-ambiguous" {
gdb_test "guile (print (parameter-value prev-ambig))" "= #f" "parameter value, false"
- gdb_test "show print s" "Command is not documented is off." "show parameter off"
+ gdb_test "show print s" \
+ "The current value of 'print s' is off\\." "show parameter off"
gdb_test_no_output "set print s on"
- gdb_test "show print s" "Command is not documented is on." "show parameter on"
+ gdb_test "show print s" \
+ "The current value of 'print s' is on\\." "show parameter on"
gdb_test "guile (print (parameter-value prev-ambig))" "= #t" "parameter value, true"
- gdb_test "help show print s" "This command is not documented." "show help"
- gdb_test "help set print s" "This command is not documented." "set help"
- gdb_test "help set print" "set print s -- This command is not documented.*" "general help"
+ gdb_test "help show print s" \
+ [multi_line \
+ "^Show the current value of 'print s'\\." \
+ "This command is not documented\\."] \
+ "show help"
+ gdb_test "help set print s" \
+ [multi_line \
+ "Set the current value of 'print s'\\." \
+ "This command is not documented\\."] \
+ "set help"
+ gdb_test "help set print" \
+ "set print s -- Set the current value of 'print s'\\..*" \
+ "general help"
+}
+
+gdb_test_multiline "create set/show foo1 prefix commands" \
+ "guile" "" \
+ "(register-command! (make-command \"set foo1\"" "" \
+ " #:command-class COMMAND_OBSCURE" "" \
+ " #:prefix? #t))" "" \
+ "(register-command! (make-command \"show foo1\"" "" \
+ " #:command-class COMMAND_OBSCURE" "" \
+ " #:prefix? #t))" "" \
+ "end"
+
+gdb_test_multiline "create set/show foo1 baz1 prefix commands" \
+ "guile" "" \
+ "(register-command! (make-command \"set foo1 baz1\"" "" \
+ " #:command-class COMMAND_OBSCURE" "" \
+ " #:prefix? #t))" "" \
+ "(register-command! (make-command \"show foo1 baz1\"" "" \
+ " #:command-class COMMAND_OBSCURE" "" \
+ " #:prefix? #t))" "" \
+ "end"
+
+gdb_test_multiline "create 'foo bar' parameter" \
+ "guile" "" \
+ "(register-parameter! (make-parameter \"foo bar\"" "" \
+ " #:command-class COMMAND_OBSCURE" "" \
+ " #:parameter-type PARAM_BOOLEAN" "" \
+ " #:show-func (lambda (self value)" "" \
+ " (format #f \"The state of 'foo bar' is ~a.\" value))" "" \
+ " #:initial-value #t))" "" \
+ "end"
+
+gdb_test "show foo1 bar" "^The state of 'foo bar' is on\\." "show parameter 'foo bar'"
+
+gdb_test_multiline "create set/show foo2 prefix commands" \
+ "guile" "" \
+ "(register-command! (make-command \"set foo2\"" "" \
+ " #:command-class COMMAND_OBSCURE" "" \
+ " #:prefix? #t))" "" \
+ "(register-command! (make-command \"show foo2\"" "" \
+ " #:command-class COMMAND_OBSCURE" "" \
+ " #:prefix? #t))" "" \
+ "end" ""
+
+gdb_test_multiline "create ambiguous 'foo baz' parameter" \
+ "guile" "" \
+ "(register-parameter! (make-parameter \"foo baz\"" "" \
+ " #:command-class COMMAND_OBSCURE" "" \
+ " #:parameter-type PARAM_BOOLEAN" "" \
+ " #:show-func (lambda (self value)" "" \
+ " (format #f \"The state of 'foo baz' is ~a.\" value))" "" \
+ " #:initial-value #t))" "" \
+ "end" \
+ [multi_line \
+ "Out of range: could not find command prefix 'foo' in position 1: \"foo baz\"" \
+ "Error while executing Scheme code."]
+
+with_test_prefix "empty doc string" {
+ gdb_test_multiline "empty doc string parameter" \
+ "guile" "" \
+ "(register-parameter! (make-parameter \"empty-doc-string\"" "" \
+ " #:command-class COMMAND_NONE" "" \
+ " #:parameter-type PARAM_ZINTEGER" "" \
+ " #:doc \"\"" "" \
+ " #:set-doc \"Set doc string.\"" "" \
+ " #:show-doc \"Show doc string.\"))" "" \
+ "end"
+
+ gdb_test "help set empty-doc-string" "^Set doc string\\."
+ gdb_test "help show empty-doc-string" "^Show doc string\\."
+}
+
+with_test_prefix "set/show parameter" {
+ # 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" \
+ "guile" "" \
+ "(register-command! (make-command \"set test-prefix\"" "" \
+ " #:prefix? #t" "" \
+ " #:command-class COMMAND_NONE))" ""\
+ "(register-command! (make-command \"show test-prefix\"" "" \
+ " #:prefix? #t" "" \
+ " #:command-class COMMAND_NONE))" ""\
+ "(register-parameter! (make-parameter \"test-prefix param-1\"" "" \
+ " #:command-class COMMAND_NONE" "" \
+ " #:parameter-type PARAM_BOOLEAN))" "" \
+ "(register-parameter! (make-parameter \"test-prefix param-2\"" "" \
+ " #:command-class COMMAND_NONE" "" \
+ " #:parameter-type PARAM_UINTEGER))" "" \
+ "(register-parameter! (make-parameter \"test-prefix param-3\"" "" \
+ " #:command-class COMMAND_NONE" "" \
+ " #:parameter-type 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" \
+ "guile" "" \
+ "(register-command! (make-command \"set test-prefix-2\"" "" \
+ " #:prefix? #t" "" \
+ " #:command-class COMMAND_NONE" ""\
+ " #:invoke (lambda (self arg from-tty)" "" \
+ " (display \"invoke -- set\\n\"))))" "" \
+ "(register-command! (make-command \"show test-prefix-2\"" "" \
+ " #:prefix? #t" "" \
+ " #:command-class COMMAND_NONE" ""\
+ " #:invoke (lambda (self arg from-tty)" "" \
+ " (display \"invoke -- show\\n\"))))" "" \
+ "(register-parameter! (make-parameter \"test-prefix-2 param-1\"" "" \
+ " #:command-class COMMAND_NONE" "" \
+ " #:parameter-type PARAM_BOOLEAN))" "" \
+ "(register-parameter! (make-parameter \"test-prefix-2 param-2\"" "" \
+ " #:command-class COMMAND_NONE" "" \
+ " #:parameter-type PARAM_UINTEGER))" "" \
+ "(register-parameter! (make-parameter \"test-prefix-2 param-3\"" "" \
+ " #:command-class COMMAND_NONE" "" \
+ " #:parameter-type PARAM_STRING))" "" \
+ "end" ""
+
+ gdb_test "set test-prefix-2" "^invoke -- set"
+
+ gdb_test "show test-prefix-2" "^invoke -- show"
}
rename scm_param_test_maybe_no_output ""
diff --git a/gdb/testsuite/gdb.linespec/linespec.exp b/gdb/testsuite/gdb.linespec/linespec.exp
index 69744dd..86b55bb 100644
--- a/gdb/testsuite/gdb.linespec/linespec.exp
+++ b/gdb/testsuite/gdb.linespec/linespec.exp
@@ -194,6 +194,12 @@ gdb_test "break lspec.h:$line" \
"Breakpoint \[0-9\]+ at $hex: file .*lspec.h, line $line." \
"set breakpoint in f1"
+# This should only have a single location -- in no_multi_locs.
+set line [gdb_get_line_number no_multi_locs]
+gdb_test "break $line" \
+ "Breakpoint \[0-9\]+ at $hex: file .*$srcfile, line $line." \
+ "set breakpoint at no_multi_locs"
+
#
# Multi-inferior tests.
#
diff --git a/gdb/testsuite/gdb.linespec/lspec.cc b/gdb/testsuite/gdb.linespec/lspec.cc
index bb660fb..ab0a193 100644
--- a/gdb/testsuite/gdb.linespec/lspec.cc
+++ b/gdb/testsuite/gdb.linespec/lspec.cc
@@ -13,6 +13,8 @@ int body_elsewhere()
#include "body.h"
}
+void no_multi_locs () { {int var = 0;} }
+
int main()
{
return dupname(0) + m(0) + n(0) + f1() + f2() + body_elsewhere();
diff --git a/gdb/testsuite/gdb.mi/interrupt-thread-group.exp b/gdb/testsuite/gdb.mi/interrupt-thread-group.exp
index ff35109..869fb1c 100644
--- a/gdb/testsuite/gdb.mi/interrupt-thread-group.exp
+++ b/gdb/testsuite/gdb.mi/interrupt-thread-group.exp
@@ -54,7 +54,7 @@ mi_send_resuming_command "exec-continue --thread-group i1" \
# We can't run a second inferior on stub targets. We can still test with one
# inferior and ensure that the command has the desired effect.
-set use_second_inferior [expr {![use_gdb_stub]}]
+set use_second_inferior [expr {![use_gdb_stub] && [allow_multi_inferior_tests]}]
if { $use_second_inferior } {
mi_gdb_test "-add-inferior" \
diff --git a/gdb/testsuite/gdb.mi/mi-condbreak-throw.exp b/gdb/testsuite/gdb.mi/mi-condbreak-throw.exp
index 9897b2b..0a89a8a 100644
--- a/gdb/testsuite/gdb.mi/mi-condbreak-throw.exp
+++ b/gdb/testsuite/gdb.mi/mi-condbreak-throw.exp
@@ -16,7 +16,7 @@
# Check that when GDB fails to evaluate the condition of a conditional
# breakpoint we only get one *stopped notification. In this test case
# the breakpoint condition fails due to throwing an uncaught C++
-# excpetion.
+# exception.
require allow_cplus_tests
diff --git a/gdb/testsuite/gdb.mi/mi-multi-commands.exp b/gdb/testsuite/gdb.mi/mi-multi-commands.exp
index 20b8d46..3bc63eb 100644
--- a/gdb/testsuite/gdb.mi/mi-multi-commands.exp
+++ b/gdb/testsuite/gdb.mi/mi-multi-commands.exp
@@ -90,7 +90,7 @@ proc run_test { args } {
# looking for. However, due to the unpredictable
# intermingling, it's much easier if we drop the ^ anchor.
# However, with this gone dejagnu would sometimes match the
- # second comand output before the first commands output.
+ # second command output before the first commands output.
#
# This approach just looks for the first command output, then,
# once that has been found, we start looking for the second
diff --git a/gdb/testsuite/gdb.mi/mi-var-display.exp b/gdb/testsuite/gdb.mi/mi-var-display.exp
index 61b3894..5535368 100644
--- a/gdb/testsuite/gdb.mi/mi-var-display.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-display.exp
@@ -96,7 +96,7 @@ mi_gdb_test "-var-evaluate-expression bar" \
# Desc: change value of bar
mi_gdb_test "-var-assign bar 3" \
"\\^done,value=\"0x3\"" \
- "assing to variable bar"
+ "assign to variable bar"
mi_gdb_test "-var-set-format bar decimal" \
"\\^done,format=\"decimal\",value=\"3\"" \
@@ -152,7 +152,7 @@ mi_gdb_test "-var-evaluate-expression foo" \
# Desc: change value of foo
mi_gdb_test "-var-assign foo 3" \
"\\^done,value=\"03\"" \
- "assing to variable foo"
+ "assign to variable foo"
mi_gdb_test "-var-set-format foo decimal" \
"\\^done,format=\"decimal\",value=\"3\"" \
diff --git a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
index 9198cfb..f85e108 100644
--- a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
+++ b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
@@ -40,6 +40,8 @@ standard_testfile
# gdbserver modes are supported.
require !use_gdb_stub
+require allow_multi_inferior_tests
+
set compile_options "debug pthreads"
if {[build_executable $testfile.exp $testfile ${srcfile} ${compile_options}] == -1} {
untested "failed to compile"
@@ -985,7 +987,7 @@ proc_with_prefix test_mi_stack_select_frame { mode } {
# Now use the '-stack-select-frame' command with the --frame
# option, this verifies that even when the frame GDB would
- # swith to is the same as the frame specified with --frame, an
+ # switch to is the same as the frame specified with --frame, an
# event is still sent to the CLI.
set cli_re [make_cli_re $mode -1 -1 0]
diff --git a/gdb/testsuite/gdb.multi/attach-no-multi-process.exp b/gdb/testsuite/gdb.multi/attach-no-multi-process.exp
index 28aabaf..502f309 100644
--- a/gdb/testsuite/gdb.multi/attach-no-multi-process.exp
+++ b/gdb/testsuite/gdb.multi/attach-no-multi-process.exp
@@ -59,7 +59,10 @@ proc test {target_non_stop} {
"switch to inferior 2"
set res [gdbserver_start "--multi" ""]
set gdbserver_gdbport [lindex $res 1]
- gdb_target_cmd "extended-remote" $gdbserver_gdbport
+ if { [gdb_target_cmd_ext "extended-remote" $gdbserver_gdbport] == 2 } {
+ unsupported "non-stop RSP"
+ return
+ }
# Start a program, then attach to it.
set spawn_id_list [spawn_wait_for_attach [list $binfile]]
diff --git a/gdb/testsuite/gdb.multi/attach-while-running.exp b/gdb/testsuite/gdb.multi/attach-while-running.exp
index 5b63030..723ebb2 100644
--- a/gdb/testsuite/gdb.multi/attach-while-running.exp
+++ b/gdb/testsuite/gdb.multi/attach-while-running.exp
@@ -37,6 +37,7 @@
standard_testfile
require can_spawn_for_attach
+require allow_multi_inferior_tests
if { [build_executable "failed to prepare" ${testfile} ${srcfile}] } {
return
@@ -49,7 +50,7 @@ proc do_test {} {
}
gdb_test -no-prompt-anchor "run &"
- gdb_test "add-inferior" "Added inferior 2 on connection 1 .*"
+ gdb_test -no-prompt-anchor "add-inferior" "Added inferior 2 on connection 1 .*"
gdb_test "inferior 2" "Switching to inferior 2 .*"
set spawn_id [spawn_wait_for_attach $::binfile]
diff --git a/gdb/testsuite/gdb.multi/bp-thread-specific.exp b/gdb/testsuite/gdb.multi/bp-thread-specific.exp
index 32b7602..3fe4c20 100644
--- a/gdb/testsuite/gdb.multi/bp-thread-specific.exp
+++ b/gdb/testsuite/gdb.multi/bp-thread-specific.exp
@@ -19,6 +19,8 @@
# Also check that the correct thread-ids are used in the saved
# breakpoints file.
+require allow_multi_inferior_tests
+
# The plain remote target can't do multiple inferiors.
require !use_gdb_stub
diff --git a/gdb/testsuite/gdb.multi/dummy-frame-restore.exp b/gdb/testsuite/gdb.multi/dummy-frame-restore.exp
index 1a9d413..4119e3f 100644
--- a/gdb/testsuite/gdb.multi/dummy-frame-restore.exp
+++ b/gdb/testsuite/gdb.multi/dummy-frame-restore.exp
@@ -19,6 +19,8 @@ set executable ${testfile}
# The plain remote target can't do multiple inferiors.
require !use_gdb_stub
+require allow_multi_inferior_tests
+
if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug}]} {
return -1
}
diff --git a/gdb/testsuite/gdb.multi/multi-arch.exp b/gdb/testsuite/gdb.multi/multi-arch.exp
index d0ae511..1d41ba5 100644
--- a/gdb/testsuite/gdb.multi/multi-arch.exp
+++ b/gdb/testsuite/gdb.multi/multi-arch.exp
@@ -18,6 +18,8 @@
set testfile "multi-arch"
+require allow_multi_inferior_tests
+
# The plain remote target can't do multiple inferiors.
require !use_gdb_stub
diff --git a/gdb/testsuite/gdb.multi/multi-attach.exp b/gdb/testsuite/gdb.multi/multi-attach.exp
index 2d702ee..210c8ca 100644
--- a/gdb/testsuite/gdb.multi/multi-attach.exp
+++ b/gdb/testsuite/gdb.multi/multi-attach.exp
@@ -17,6 +17,8 @@
# Test attaching to multiple threaded programs.
+require allow_multi_inferior_tests
+
standard_testfile
require can_spawn_for_attach
diff --git a/gdb/testsuite/gdb.multi/multi-exit.exp b/gdb/testsuite/gdb.multi/multi-exit.exp
index 71236c1..8393067 100644
--- a/gdb/testsuite/gdb.multi/multi-exit.exp
+++ b/gdb/testsuite/gdb.multi/multi-exit.exp
@@ -24,6 +24,8 @@
standard_testfile
+require allow_multi_inferior_tests
+
require !use_gdb_stub
if {[build_executable "failed to prepare" $testfile $srcfile]} {
diff --git a/gdb/testsuite/gdb.multi/multi-kill.exp b/gdb/testsuite/gdb.multi/multi-kill.exp
index 48a2534..7d66ab0 100644
--- a/gdb/testsuite/gdb.multi/multi-kill.exp
+++ b/gdb/testsuite/gdb.multi/multi-kill.exp
@@ -24,6 +24,8 @@
standard_testfile
+require allow_multi_inferior_tests
+
require !use_gdb_stub
if {[build_executable "failed to prepare" $testfile $srcfile {debug}]} {
diff --git a/gdb/testsuite/gdb.multi/multi-re-run.exp b/gdb/testsuite/gdb.multi/multi-re-run.exp
index 002de57..4caadea 100644
--- a/gdb/testsuite/gdb.multi/multi-re-run.exp
+++ b/gdb/testsuite/gdb.multi/multi-re-run.exp
@@ -20,6 +20,8 @@
# misbehave, including failing to load libthread_db.so. See PR
# gdb/25410.
+require allow_multi_inferior_tests
+
# Build two executables, with different symbols.
set exec1 "multi-re-run-1"
diff --git a/gdb/testsuite/gdb.multi/multi-target.exp.tcl b/gdb/testsuite/gdb.multi/multi-target.exp.tcl
index 8c24602..dc88ca4 100644
--- a/gdb/testsuite/gdb.multi/multi-target.exp.tcl
+++ b/gdb/testsuite/gdb.multi/multi-target.exp.tcl
@@ -175,6 +175,10 @@ proc multi_target_prepare {} {
return 0
}
+ if {![allow_multi_inferior_tests]} {
+ return 0
+ }
+
# The plain remote target can't do multiple inferiors.
if {[target_info gdb_protocol] != ""} {
return 0
diff --git a/gdb/testsuite/gdb.multi/multi-term-settings.exp b/gdb/testsuite/gdb.multi/multi-term-settings.exp
index 2f8b3b8..38322be 100644
--- a/gdb/testsuite/gdb.multi/multi-term-settings.exp
+++ b/gdb/testsuite/gdb.multi/multi-term-settings.exp
@@ -25,6 +25,8 @@
standard_testfile
+require allow_multi_inferior_tests
+
require can_spawn_for_attach
if [build_executable "failed to prepare" $testfile $srcfile {debug}] {
diff --git a/gdb/testsuite/gdb.multi/start-inferior-specific.exp b/gdb/testsuite/gdb.multi/start-inferior-specific.exp
index 819c1c3..74f984c 100644
--- a/gdb/testsuite/gdb.multi/start-inferior-specific.exp
+++ b/gdb/testsuite/gdb.multi/start-inferior-specific.exp
@@ -25,6 +25,8 @@
standard_testfile .c -other.c
+require allow_multi_inferior_tests
+
require !use_gdb_stub
set srcfile_other ${srcfile2}
diff --git a/gdb/testsuite/gdb.multi/stop-all-on-exit.exp b/gdb/testsuite/gdb.multi/stop-all-on-exit.exp
index b4ff09c..47071f3 100644
--- a/gdb/testsuite/gdb.multi/stop-all-on-exit.exp
+++ b/gdb/testsuite/gdb.multi/stop-all-on-exit.exp
@@ -18,6 +18,8 @@
# Test that in all-stop mode with multiple inferiors, GDB stops all
# threads upon receiving an exit event from one of the inferiors.
+require allow_multi_inferior_tests
+
# This is a test specific for a native target, where we use the
# "-exec" argument to "add-inferior" and we explicitly don't do
# "maint set target-non-stop on".
diff --git a/gdb/testsuite/gdb.multi/tids-gid-reset.exp b/gdb/testsuite/gdb.multi/tids-gid-reset.exp
index 6cc27eb..1785ac2 100644
--- a/gdb/testsuite/gdb.multi/tids-gid-reset.exp
+++ b/gdb/testsuite/gdb.multi/tids-gid-reset.exp
@@ -54,6 +54,8 @@ with_test_prefix "single-inferior" {
# non-extended gdbserver is not supported.
require !use_gdb_stub
+require allow_multi_inferior_tests
+
# Test with multiple inferiors. This time, since we restart inferior
# 1 while inferior 2 still has threads, then the new thread 1.1 should
# end up with GID == 3, since we won't be able to reset the global
diff --git a/gdb/testsuite/gdb.multi/tids.exp b/gdb/testsuite/gdb.multi/tids.exp
index b84f908..436a38a 100644
--- a/gdb/testsuite/gdb.multi/tids.exp
+++ b/gdb/testsuite/gdb.multi/tids.exp
@@ -124,6 +124,9 @@ with_test_prefix "single inferior" {
gdb_test "print \$_inferior_thread_count" " = 1"
}
+# The rest of the tests require running multiple inferiors.
+require allow_multi_inferior_tests
+
# "info threads" while there are multiple inferiors should show
# qualified thread IDs.
with_test_prefix "two inferiors" {
@@ -290,7 +293,7 @@ with_test_prefix "two inferiors" {
# Try both the convenience variable and the literal number.
foreach thr {"\$thr" "20" "1.20" "\$inf.1" "30.1" } {
set expected [string_to_regexp $thr]
- gdb_test "info threads $thr" "No threads match '${expected}'."
+ gdb_test "info threads $thr" "No threads matched\\."
# "info threads" works like a filter. If there's any other
# valid thread in the list, there's no error.
info_threads "$thr 1.1" "1.1"
@@ -412,7 +415,7 @@ with_test_prefix "two inferiors" {
# Check that we do parse the inferior number and don't confuse it.
gdb_test "info threads 3.1" \
- "No threads match '3.1'\."
+ "No threads matched\\."
}
if { [allow_python_tests] } {
diff --git a/gdb/testsuite/gdb.multi/watchpoint-multi-exit.exp b/gdb/testsuite/gdb.multi/watchpoint-multi-exit.exp
index 70c3da9..3446296 100644
--- a/gdb/testsuite/gdb.multi/watchpoint-multi-exit.exp
+++ b/gdb/testsuite/gdb.multi/watchpoint-multi-exit.exp
@@ -17,6 +17,8 @@
# watchpoints don't end up with stale locations, preventing resumption
# of other inferiors.
+require allow_fork_tests
+
standard_testfile
if {[build_executable "failed to build" $testfile $srcfile {debug}]} {
diff --git a/gdb/testsuite/gdb.multi/watchpoint-multi.exp b/gdb/testsuite/gdb.multi/watchpoint-multi.exp
index f448689..b0c8731 100644
--- a/gdb/testsuite/gdb.multi/watchpoint-multi.exp
+++ b/gdb/testsuite/gdb.multi/watchpoint-multi.exp
@@ -16,6 +16,8 @@
standard_testfile
set executable ${testfile}
+require allow_multi_inferior_tests
+
# Multiple inferiors are needed, therefore both native and extended gdbserver
# modes are supported. Only non-extended gdbserver is not supported.
require !use_gdb_stub
diff --git a/gdb/testsuite/gdb.opt/break-on-_exit.exp b/gdb/testsuite/gdb.opt/break-on-_exit.exp
index 2b94be8..9295fea 100644
--- a/gdb/testsuite/gdb.opt/break-on-_exit.exp
+++ b/gdb/testsuite/gdb.opt/break-on-_exit.exp
@@ -25,7 +25,7 @@
# for libc, then the breakpoint is set on the exec-local _exit@plt instead,
# and that functionality will also not be used.
#
-# We may get the required setup in case of a libc with misssing separate
+# We may get the required setup in case of a libc with missing separate
# debuginfo, but we want the same effect if that debuginfo is installed.
#
# So, we use -readnever to read minimal symbols, but not non-miminal symbols.
diff --git a/gdb/testsuite/gdb.pascal/integers.exp b/gdb/testsuite/gdb.pascal/integers.exp
index 5c878c5..c9974a1 100644
--- a/gdb/testsuite/gdb.pascal/integers.exp
+++ b/gdb/testsuite/gdb.pascal/integers.exp
@@ -59,7 +59,7 @@ gdb_test "next" "l := k;" "next to 'l := k' line"
gdb_test "print j" " = 2"
# k should be equal to 3
gdb_test "print k" " = 3"
-# But l shoud still be zero
+# But l should still be zero
if { $pascal_compiler_is_gpc } {
setup_xfail *-*-*
}
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/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-cmd.exp b/gdb/testsuite/gdb.python/py-cmd.exp
index f76c176..5ac5712 100644
--- a/gdb/testsuite/gdb.python/py-cmd.exp
+++ b/gdb/testsuite/gdb.python/py-cmd.exp
@@ -328,4 +328,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..28afd59
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-color-leak.py
@@ -0,0 +1,37 @@
+# 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
+
+# Avoid generating
+# src/gdb/testsuite/gdb.python/__pycache__/gdb_leak_detector.cpython-<n>.pyc.
+sys.dont_write_bytecode = True
+
+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..2601cf3 100644
--- a/gdb/testsuite/gdb.python/py-color.exp
+++ b/gdb/testsuite/gdb.python/py-color.exp
@@ -13,17 +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/>.
-# 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
-# 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 +63,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 +110,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-disasm.exp.tcl b/gdb/testsuite/gdb.python/py-disasm.exp.tcl
index 938326d..c5099ba 100644
--- a/gdb/testsuite/gdb.python/py-disasm.exp.tcl
+++ b/gdb/testsuite/gdb.python/py-disasm.exp.tcl
@@ -152,7 +152,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..9761337 100644
--- a/gdb/testsuite/gdb.python/py-disasm.py
+++ b/gdb/testsuite/gdb.python/py-disasm.py
@@ -294,6 +294,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."""
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-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..bf61668 100644
--- a/gdb/testsuite/gdb.python/py-inferior-leak.py
+++ b/gdb/testsuite/gdb.python/py-inferior-leak.py
@@ -13,100 +13,39 @@
# 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 re
-import tracemalloc
-
-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
-
-
-# Register the new_inferior event handler.
-def new_inferior_handler(event):
- global inf
- inf = event.inferior
-
-
-gdb.events.new_inferior.connect(new_inferior_handler)
+import sys
-# A global filters list, we only care about memory allocations
-# originating from this script.
-filters = [tracemalloc.Filter(True, "*py-inferior-leak.py")]
+# Avoid generating
+# src/gdb/testsuite/gdb.python/__pycache__/gdb_leak_detector.cpython-<n>.pyc.
+sys.dont_write_bytecode = True
+import re
-# 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()
+import gdb_leak_detector
- # 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")
+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)
- # Total up all the deallocated things.
- total = 0
- for stat in stats:
- total += stat.size_diff
- return total
+ 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")
-# 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)
+ gdb.execute("remove-inferiors %s" % num)
-# 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)
+ def deallocate(self):
+ self.inferior = None
-# 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-missing-objfile.exp b/gdb/testsuite/gdb.python/py-missing-objfile.exp
index e4a1b3f..29bc555 100644
--- a/gdb/testsuite/gdb.python/py-missing-objfile.exp
+++ b/gdb/testsuite/gdb.python/py-missing-objfile.exp
@@ -79,6 +79,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"
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..8d11028 100644
--- a/gdb/testsuite/gdb.python/py-objfile.exp
+++ b/gdb/testsuite/gdb.python/py-objfile.exp
@@ -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.
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..214c570 100644
--- a/gdb/testsuite/gdb.python/py-parameter.exp
+++ b/gdb/testsuite/gdb.python/py-parameter.exp
@@ -346,6 +346,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
@@ -669,6 +754,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 +862,15 @@ 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_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-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..89647cf 100644
--- a/gdb/testsuite/gdb.python/py-read-memory-leak.py
+++ b/gdb/testsuite/gdb.python/py-read-memory-leak.py
@@ -13,81 +13,27 @@
# 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
+# Avoid generating
+# src/gdb/testsuite/gdb.python/__pycache__/gdb_leak_detector.cpython-<n>.pyc.
+sys.dont_write_bytecode = True
-# A global variable in which we store a reference to the memory buffer
-# returned from gdb.Inferior.read_memory().
-mem_buf = None
+import gdb_leak_detector
-# 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]
+ def allocate(self):
+ self.mem_buf = self.inf.read_memory(self.addr, 4096)
-# 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 deallocate(self):
+ self.mem_buf = None
- 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.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-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..0faccf2 100644
--- a/gdb/testsuite/gdb.python/py-unwind.py
+++ b/gdb/testsuite/gdb.python/py-unwind.py
@@ -267,4 +267,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-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.replay/connect.exp b/gdb/testsuite/gdb.replay/connect.exp
index 5790d38..26b7aa3 100644
--- a/gdb/testsuite/gdb.replay/connect.exp
+++ b/gdb/testsuite/gdb.replay/connect.exp
@@ -13,7 +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/>. */
#
-# Starts a communication with gdbsever setting the remotelog file.
+# Starts a communication with gdbserver setting the remotelog file.
# Modifies the remotelog with update_log proc, injects an error message
# instead of the expected replay to the vMustReplyEmpty packet in order
# to test GDB reacts to the error response properly. After the remotelog
diff --git a/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp b/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp
index 0ff56dd..00f58f8 100644
--- a/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp
@@ -397,7 +397,7 @@ gdb_test_no_output "set \$ymm15.v2_int128 = {0x0, 0xcafeface}" "set ymm15 for vp
if {[record_full_function "vzeroupper"] == true} {
# Since vzeroupper needs to save 8 or 16 registers, let's check what was
# actually recorded, instead of just undoing an instruction. Only
- # really check the values of egisters 0, 1, 2 and 15 because those are
+ # really check the values of registers 0, 1, 2 and 15 because those are
# the only ones we're setting.
gdb_test "maint print record-instruction" \
[multi_line "Register ymm0h changed: 74565" \
diff --git a/gdb/testsuite/gdb.reverse/solib-precsave.exp b/gdb/testsuite/gdb.reverse/solib-precsave.exp
index 277e33c..82b08cd 100644
--- a/gdb/testsuite/gdb.reverse/solib-precsave.exp
+++ b/gdb/testsuite/gdb.reverse/solib-precsave.exp
@@ -140,7 +140,7 @@ gdb_test_multiple "reverse-step" "reverse-step into solib function one" {
pass $gdb_test_name
}
}
-# Depending on wether the closing } has a line associated, we might have
+# Depending on whether the closing } has a line associated, we might have
# different acceptable results here
gdb_test_multiple "reverse-step" "reverse-step within solib function one" {
-re -wrap "return y;.*" {
diff --git a/gdb/testsuite/gdb.reverse/solib-reverse.exp b/gdb/testsuite/gdb.reverse/solib-reverse.exp
index 1e22e91..b2ef9b0 100644
--- a/gdb/testsuite/gdb.reverse/solib-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/solib-reverse.exp
@@ -116,7 +116,7 @@ gdb_test_multiple "reverse-step" "reverse-step into solib function one" {
pass $gdb_test_name
}
}
-# Depending on wether the closing } has a line associated, we might have
+# Depending on whether the closing } has a line associated, we might have
# different acceptable results here
gdb_test_multiple "reverse-step" "reverse-step within solib function one" {
-re -wrap "return y;.*" {
diff --git a/gdb/testsuite/gdb.reverse/time-reverse.exp b/gdb/testsuite/gdb.reverse/time-reverse.exp
index fe191a0..58dcdde 100644
--- a/gdb/testsuite/gdb.reverse/time-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/time-reverse.exp
@@ -20,6 +20,7 @@
#
require supports_reverse
+require supports_process_record
standard_testfile
@@ -38,23 +39,49 @@ proc test {mode} {
return
}
- runto marker1
-
- if [supports_process_record] {
- # Activate process record/replay
- gdb_test_no_output "record" "turn on process record"
+ if { ![runto marker1] } {
+ return
}
+ # Activate process record/replay
+ gdb_test_no_output "record" "turn on process record"
+ gdb_test_no_output "set record full stop-at-limit on"
+ gdb_test_no_output "set record full insn-number-max 2000"
+
+ set re_srcfile [string_to_regexp $::srcfile]
+
gdb_test "break marker2" \
- "Breakpoint $::decimal at $::hex: file .*$::srcfile, line $::decimal.*" \
+ "Breakpoint $::decimal at $::hex: file .*$re_srcfile, line $::decimal.*" \
"set breakpoint at marker2"
- gdb_continue_to_breakpoint "marker2" ".*$::srcfile:.*"
+ set re_question \
+ [string_list_to_regexp \
+ "Do you want to auto delete previous execution log entries when" \
+ " record/replay buffer becomes full" \
+ { (record full stop-at-limit)?([y] or n)}]
+ set re_program_stopped \
+ [multi_line \
+ [string_to_regexp "Process record: stopped by user."] \
+ "" \
+ [string_to_regexp "Program stopped."]]
+ set re_marker2 [string_to_regexp "marker2 ()"]
+ gdb_test_multiple "continue" "continue to breakpoint: marker2" {
+ -re "$re_question " {
+ send_gdb "n\n"
+ exp_continue
+ }
+ -re -wrap "Breakpoint $::decimal, $re_marker2 .*" {
+ pass $gdb_test_name
+ }
+ -re -wrap "\r\n$re_program_stopped\r\n.*" {
+ unsupported $gdb_test_name
+ }
+ }
# Show how many instructions we've recorded.
gdb_test "info record" "Active record target: .*"
- gdb_test "reverse-continue" ".*$::srcfile:$::decimal.*" "reverse to marker1"
+ gdb_test "reverse-continue" ".*$re_srcfile:$::decimal.*" "reverse to marker1"
# If the variable was recorded properly, the old contents (-1)
# will be remembered. If not, new contents (current time) will be
diff --git a/gdb/testsuite/gdb.rocm/code-object-load-while-breakpoint-hit.cpp b/gdb/testsuite/gdb.rocm/code-object-load-while-breakpoint-hit.cpp
new file mode 100644
index 0000000..d75bc76
--- /dev/null
+++ b/gdb/testsuite/gdb.rocm/code-object-load-while-breakpoint-hit.cpp
@@ -0,0 +1,86 @@
+/* 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/>. */
+
+#ifdef DEVICE
+
+#include <hip/hip_runtime.h>
+
+constexpr unsigned int NUM_BREAKPOINT_HITS = 5;
+
+static __device__ void
+break_here ()
+{
+}
+
+extern "C" __global__ void
+kernel ()
+{
+ for (int n = 0; n < NUM_BREAKPOINT_HITS; ++n)
+ break_here ();
+}
+
+#else
+
+#include <hip/hip_runtime.h>
+#include <unistd.h>
+
+constexpr unsigned int NUM_ITEMS_PER_BLOCK = 256;
+constexpr unsigned int NUM_BLOCKS = 128;
+constexpr unsigned int NUM_ITEMS = NUM_ITEMS_PER_BLOCK * NUM_BLOCKS;
+constexpr unsigned int NUM_LOAD_UNLOADS = 5;
+
+#define CHECK(cmd) \
+ { \
+ hipError_t error = cmd; \
+ if (error != hipSuccess) \
+ { \
+ fprintf (stderr, "error: '%s'(%d) at %s:%d\n", \
+ hipGetErrorString (error), error, __FILE__, __LINE__); \
+ exit (EXIT_FAILURE); \
+ } \
+ }
+
+int
+main (int argc, const char **argv)
+{
+ if (argc != 2)
+ {
+ fprintf (stderr, "Usage: %s <hip_module_path>\n", argv[0]);
+ return 1;
+ }
+
+ const auto module_path = argv[1];
+ hipModule_t module;
+ CHECK (hipModuleLoad (&module, module_path));
+
+ /* Launch the kernel. */
+ hipFunction_t function;
+ CHECK (hipModuleGetFunction (&function, module, "kernel"));
+ CHECK (hipModuleLaunchKernel (function, NUM_BLOCKS, 1, 1,
+ NUM_ITEMS_PER_BLOCK, 1, 1, 0, nullptr, nullptr,
+ nullptr));
+
+ /* Load and unload the module many times. */
+ for (int i = 0; i < NUM_LOAD_UNLOADS; ++i)
+ {
+ hipModule_t dummy_module;
+ CHECK (hipModuleLoad (&dummy_module, module_path));
+ CHECK (hipModuleUnload (dummy_module));
+ }
+}
+
+#endif
diff --git a/gdb/testsuite/gdb.rocm/code-object-load-while-breakpoint-hit.exp b/gdb/testsuite/gdb.rocm/code-object-load-while-breakpoint-hit.exp
new file mode 100644
index 0000000..3fe6a95
--- /dev/null
+++ b/gdb/testsuite/gdb.rocm/code-object-load-while-breakpoint-hit.exp
@@ -0,0 +1,68 @@
+# 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/>.
+
+# This test verifies what happens when a code object list update happens at the
+# same time as some wave stop events are reported. It was added following a
+# performance bug fix, where forward progress requirement disabled when
+# pulling events from amd-dbgapi in amd_dbgapi_target_breakpoint::check_status.
+#
+# The test launches a kernel that hits a breakpoint with an always false
+# condition a certain number of times. Meanwhile, the host loads and unloads
+# a code object in a loop, causing check_status to be called. The hope is that
+# check_status, when calling process_event_queue, will pull many WAVE_STOP
+# events from the kernel hitting the breakpoint.
+#
+# Without the appropriate fix (of disabling forward progress requirement in
+# check_status), GDB would hit the newly-added assert in process_event_queue,
+# which verifies that forward progress requirement is disabled. Even without
+# this assert, the test would likely time out (depending on the actual timeout
+# value).
+
+load_lib rocm.exp
+standard_testfile .cpp
+require allow_hipcc_tests
+
+# Build the host executable.
+if { [build_executable "failed to prepare" \
+ $testfile $srcfile {debug hip}] == -1 } {
+ return -1
+}
+
+set hipmodule_path [standard_output_file ${testfile}.co]
+
+# Build the kernel object file.
+if { [gdb_compile $srcdir/$subdir/$srcfile \
+ $hipmodule_path object \
+ { debug hip additional_flags=--genco additional_flags=-DDEVICE } ] != "" } {
+ return -1
+}
+
+proc do_test { } {
+ with_rocm_gpu_lock {
+ clean_restart $::binfile
+ gdb_test_no_output "set args $::hipmodule_path" "set args"
+
+ if { ![runto_main] } {
+ return
+ }
+
+ gdb_test "with breakpoint pending on -- break break_here if 0"
+ gdb_continue_to_end "continue to end" "continue" 1
+ }
+}
+
+do_test
diff --git a/gdb/testsuite/gdb.rocm/fork-exec-gpu-to-non-gpu.exp b/gdb/testsuite/gdb.rocm/fork-exec-gpu-to-non-gpu.exp
index 7588525..22d4b75 100644
--- a/gdb/testsuite/gdb.rocm/fork-exec-gpu-to-non-gpu.exp
+++ b/gdb/testsuite/gdb.rocm/fork-exec-gpu-to-non-gpu.exp
@@ -21,6 +21,7 @@
load_lib rocm.exp
require allow_hipcc_tests
+require allow_fork_tests
standard_testfile -execer.cpp -execee.cpp
diff --git a/gdb/testsuite/gdb.rocm/fork-exec-non-gpu-to-gpu.exp b/gdb/testsuite/gdb.rocm/fork-exec-non-gpu-to-gpu.exp
index a6bcf69..1386099 100644
--- a/gdb/testsuite/gdb.rocm/fork-exec-non-gpu-to-gpu.exp
+++ b/gdb/testsuite/gdb.rocm/fork-exec-non-gpu-to-gpu.exp
@@ -20,6 +20,7 @@
load_lib rocm.exp
require allow_hipcc_tests
+require allow_fork_tests
standard_testfile -execer.cpp -execee.cpp
diff --git a/gdb/testsuite/gdb.rocm/mi-attach.exp b/gdb/testsuite/gdb.rocm/mi-attach.exp
index 2ca610c..37ce92a 100644
--- a/gdb/testsuite/gdb.rocm/mi-attach.exp
+++ b/gdb/testsuite/gdb.rocm/mi-attach.exp
@@ -13,10 +13,11 @@
# 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 rocm.exp
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-require can_spawn_for_attach
+require can_spawn_for_attach allow_hipcc_tests
standard_testfile .cpp
diff --git a/gdb/testsuite/gdb.rocm/precise-memory-fork.exp b/gdb/testsuite/gdb.rocm/precise-memory-fork.exp
index d326c2e..23c1ebe 100644
--- a/gdb/testsuite/gdb.rocm/precise-memory-fork.exp
+++ b/gdb/testsuite/gdb.rocm/precise-memory-fork.exp
@@ -21,6 +21,7 @@
load_lib rocm.exp
require allow_hipcc_tests
+require allow_fork_tests
standard_testfile .c
diff --git a/gdb/testsuite/gdb.rocm/precise-memory.exp b/gdb/testsuite/gdb.rocm/precise-memory.exp
index fbcb451..6711d80 100644
--- a/gdb/testsuite/gdb.rocm/precise-memory.exp
+++ b/gdb/testsuite/gdb.rocm/precise-memory.exp
@@ -59,7 +59,7 @@ proc do_test { } {
return
}
- # Get to the begining of the GPU kernel without precise memory enabled.
+ # Get to the beginning of the GPU kernel without precise memory enabled.
with_test_prefix "goto gpu code" {
gdb_test_no_output "set amdgpu precise-memory off"
gdb_breakpoint "kernel" allow-pending
diff --git a/gdb/testsuite/gdb.server/build-id-seqno.exp b/gdb/testsuite/gdb.server/build-id-seqno.exp
index a508a44..8475ccc 100644
--- a/gdb/testsuite/gdb.server/build-id-seqno.exp
+++ b/gdb/testsuite/gdb.server/build-id-seqno.exp
@@ -90,13 +90,13 @@ proc load_binfile_check_debug_is_found { debuginfo_file testname } {
with_test_prefix "$testname" {
with_timeout_factor 5 {
# Probing for .build-id based debug files on remote
- # targets uses the vFile:stat packet by default, though
+ # targets uses the vFile:lstat packet by default, though
# there is a work around that avoids this which can be
# used if GDB is connected to an older gdbserver without
# 'stat' support.
#
# Check the work around works by disabling use of the
- # vFile:stat packet.
+ # vFile:lstat packet.
foreach_with_prefix stat_pkt {auto off} {
clean_restart
@@ -105,7 +105,7 @@ proc load_binfile_check_debug_is_found { debuginfo_file testname } {
gdb_test_no_output "set sysroot target:"
- gdb_test "set remote hostio-stat-packet $stat_pkt"
+ gdb_test "set remote hostio-lstat-packet $stat_pkt"
# Make sure we're disconnected, in case we're testing with an
# extended-remote board, therefore already connected.
diff --git a/gdb/testsuite/gdb.server/fileio-packets.exp b/gdb/testsuite/gdb.server/fileio-packets.exp
new file mode 100644
index 0000000..9435efd
--- /dev/null
+++ b/gdb/testsuite/gdb.server/fileio-packets.exp
@@ -0,0 +1,66 @@
+# 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/>.
+
+# Test some remote file I/O. The associated Python script uses the
+# Python API to create and send vFile:* packets to gdbserver to
+# perform actions like 'stat'. The same action is then performed
+# directly from Python (e.g. a 'stat' is performed), and the results,
+# from gdbserver, and from the local syscall, are compared.
+
+load_lib gdb-python.exp
+load_lib gdbserver-support.exp
+
+require allow_python_tests
+require allow_gdbserver_tests
+require {!is_remote host}
+require {!is_remote target}
+
+standard_testfile
+
+clean_restart
+
+# Make sure we're disconnected, in case we're testing with an
+# extended-remote board, therefore already connected.
+gdb_test "disconnect" ".*"
+
+set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
+gdb_test_no_output "source $pyfile" "source the script"
+
+# Start gdbserver, but always in extended-remote mode, and then
+# connect to it from GDB.
+set res [gdbserver_start "--multi --once" ""]
+set gdbserver_protocol "extended-remote"
+set gdbserver_gdbport [lindex $res 1]
+gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport
+
+gdb_test_no_output "set python print-stack full"
+
+set test_file_1 [standard_output_file "test_file_1"]
+remote_exec host "touch $test_file_1"
+
+set test_file_2 [standard_output_file "test_file_2"]
+remote_exec host "ln -s $test_file_1 $test_file_2"
+
+gdb_test "python check_lstat(\"$test_file_1\")" "PASS" \
+ "check remote lstat works on a normal file"
+
+gdb_test "python check_lstat(\"$test_file_2\")" "PASS" \
+ "check remote lstat works on a symbolic link"
+
+gdb_test "python check_stat(\"$test_file_1\")" "PASS" \
+ "check remote stat works on a normal file"
+
+gdb_test "python check_stat(\"$test_file_2\")" "PASS" \
+ "check remote stat works on a symbolic link"
diff --git a/gdb/testsuite/gdb.server/fileio-packets.py b/gdb/testsuite/gdb.server/fileio-packets.py
new file mode 100644
index 0000000..f132e91
--- /dev/null
+++ b/gdb/testsuite/gdb.server/fileio-packets.py
@@ -0,0 +1,208 @@
+# 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 os
+import stat
+
+
+# Hex encode INPUT_STRING in the same way that GDB does. Each
+# character in INPUT_STRING is expanded to its two digit hex
+# representation in the returned string.
+#
+# Only ASCII characters may appear in INPUT_STRING, this is more
+# restrictive than GDB, but is good enough for testing.
+def hex_encode(input_string):
+ byte_string = input_string.encode("ascii")
+ hex_string = byte_string.hex()
+ return hex_string
+
+
+# Binary remote data packets can contain some escaped bytes. Decode
+# the packet now.
+def unescape_remote_data(buf):
+ escaped = False
+ res = bytearray()
+ for b in buf:
+ if escaped:
+ res.append(b ^ 0x20)
+ escaped = False
+ elif b == ord("}"):
+ escaped = True
+ else:
+ res.append(b)
+ res = bytes(res)
+ return res
+
+
+# Decode the results of a remote stat like command from BUF. Returns
+# None if BUF is not a valid stat result (e.g. if it indicates an
+# error, or the buffer is too short). If BUF is valid then the fields
+# are decoded according to the GDB remote protocol and placed into a
+# dictionary, this dictionary is then returned.
+def decode_stat_reply(buf, byteorder="big"):
+
+ buf = unescape_remote_data(buf)
+
+ if (
+ buf[0] != ord("F")
+ or buf[1] != ord("4")
+ or buf[2] != ord("0")
+ or buf[3] != ord(";")
+ or len(buf) != 68
+ ):
+ l = len(buf)
+ print(f"decode_stat_reply failed: {buf}\t(length = {l})")
+ return None
+
+ # Discard the 'F40;' prefix. The rest is the 64 bytes of data to
+ # be decoded.
+ buf = buf[4:]
+
+ st_dev = int.from_bytes(buf[0:4], byteorder=byteorder)
+ st_ino = int.from_bytes(buf[4:8], byteorder=byteorder)
+ st_mode = int.from_bytes(buf[8:12], byteorder=byteorder)
+ st_nlink = int.from_bytes(buf[12:16], byteorder=byteorder)
+ st_uid = int.from_bytes(buf[16:20], byteorder=byteorder)
+ st_gid = int.from_bytes(buf[20:24], byteorder=byteorder)
+ st_rdev = int.from_bytes(buf[24:28], byteorder=byteorder)
+ st_size = int.from_bytes(buf[28:36], byteorder=byteorder)
+ st_blksize = int.from_bytes(buf[36:44], byteorder=byteorder)
+ st_blocks = int.from_bytes(buf[44:52], byteorder=byteorder)
+ st_atime = int.from_bytes(buf[52:56], byteorder=byteorder)
+ st_mtime = int.from_bytes(buf[56:60], byteorder=byteorder)
+ st_ctime = int.from_bytes(buf[60:64], byteorder=byteorder)
+
+ return {
+ "st_dev": st_dev,
+ "st_ino": st_ino,
+ "st_mode": st_mode,
+ "st_nlink": st_nlink,
+ "st_uid": st_uid,
+ "st_gid": st_gid,
+ "st_rdev": st_rdev,
+ "st_size": st_size,
+ "st_blksize": st_blksize,
+ "st_blocks": st_blocks,
+ "st_atime": st_atime,
+ "st_mtime": st_mtime,
+ "st_ctime": st_ctime,
+ }
+
+
+# Perform an lstat of remote file FILENAME, and create a dictionary of
+# the results, the keys are the fields of the stat structure.
+def remote_lstat(filename):
+ conn = gdb.selected_inferior().connection
+ if not isinstance(conn, gdb.RemoteTargetConnection):
+ raise gdb.GdbError("connection is the wrong type")
+
+ filename_hex = hex_encode(filename)
+ reply = conn.send_packet("vFile:lstat:%s" % filename_hex)
+
+ stat = decode_stat_reply(reply)
+ return stat
+
+
+# Perform a stat of remote file FILENAME, and create a dictionary of
+# the results, the keys are the fields of the stat structure.
+def remote_stat(filename):
+ conn = gdb.selected_inferior().connection
+ if not isinstance(conn, gdb.RemoteTargetConnection):
+ raise gdb.GdbError("connection is the wrong type")
+
+ filename_hex = hex_encode(filename)
+ reply = conn.send_packet("vFile:stat:%s" % filename_hex)
+
+ stat = decode_stat_reply(reply)
+ return stat
+
+
+# Convert a stat_result object to a dictionary that should match the
+# dictionary built from the remote protocol reply.
+def stat_result_to_dict(res):
+ # GDB doesn't support the S_IFLNK flag for the remote protocol, so
+ # clear that flag in the local results.
+ if stat.S_ISLNK(res.st_mode):
+ st_mode = stat.S_IMODE(res.st_mode)
+ else:
+ st_mode = res.st_mode
+
+ # GDB returns an integer for these fields, while Python returns a
+ # floating point value. Convert back to an integer to match GDB.
+ st_atime = int(res.st_atime)
+ st_mtime = int(res.st_mtime)
+ st_ctime = int(res.st_ctime)
+
+ return {
+ "st_dev": res.st_dev,
+ "st_ino": res.st_ino,
+ "st_mode": st_mode,
+ "st_nlink": res.st_nlink,
+ "st_uid": res.st_uid,
+ "st_gid": res.st_gid,
+ "st_rdev": res.st_rdev,
+ "st_size": res.st_size,
+ "st_blksize": res.st_blksize,
+ "st_blocks": res.st_blocks,
+ "st_atime": st_atime,
+ "st_mtime": st_mtime,
+ "st_ctime": st_ctime,
+ }
+
+
+# Perform an lstat of local file FILENAME, and create a dictionary of
+# the results, the keys are the fields of the stat structure.
+def local_lstat(filename):
+ res = os.lstat(filename)
+ return stat_result_to_dict(res)
+
+
+# Perform an lstat of local file FILENAME, and create a dictionary of
+# the results, the keys are the fields of the stat structure.
+def local_stat(filename):
+ res = os.stat(filename)
+ return stat_result_to_dict(res)
+
+
+# Perform a remote lstat using GDB, and a local lstat using os.lstat.
+# Compare the results to check they are the same.
+#
+# For this test to work correctly, gdbserver, and GDB (where this
+# Python script is running), must see the same filesystem.
+def check_lstat(filename):
+ s1 = remote_lstat(filename)
+ s2 = local_lstat(filename)
+
+ print(f"remote = {s1}")
+ print(f"local = {s2}")
+
+ assert s1 == s2
+ print("PASS")
+
+
+# Perform a remote stat using GDB, and a local stat using os.stat.
+# Compare the results to check they are the same.
+#
+# For this test to work correctly, gdbserver, and GDB (where this
+# Python script is running), must see the same filesystem.
+def check_stat(filename):
+ s1 = remote_stat(filename)
+ s2 = local_stat(filename)
+
+ print(f"remote = {s1}")
+ print(f"local = {s2}")
+
+ assert s1 == s2
+ print("PASS")
diff --git a/gdb/testsuite/gdb.server/no-thread-db.exp b/gdb/testsuite/gdb.server/no-thread-db.exp
index cc24708..9fd2090 100644
--- a/gdb/testsuite/gdb.server/no-thread-db.exp
+++ b/gdb/testsuite/gdb.server/no-thread-db.exp
@@ -57,6 +57,8 @@ gdb_breakpoint ${srcfile}:[gdb_get_line_number "after tls assignment"]
gdb_continue_to_breakpoint "after tls assignment"
# Printing a tls variable should fail gracefully without a libthread_db.
+# Alternately, the correct answer might be printed due GDB's internal
+# TLS support for some targets.
set re_exec "\[^\r\n\]*[file tail $binfile]"
gdb_test "print foo" \
- "Cannot find thread-local storage for Thread \[^,\]+, executable file $re_exec:\[\r\n\]+Remote target failed to process qGetTLSAddr request"
+ "= 1|(?:Cannot find thread-local storage for Thread \[^,\]+, executable file $re_exec:\[\r\n\]+Remote target failed to process qGetTLSAddr request)"
diff --git a/gdb/testsuite/gdb.server/pread-offset-size.S b/gdb/testsuite/gdb.server/pread-offset-size.S
new file mode 100644
index 0000000..6ca8cf0
--- /dev/null
+++ b/gdb/testsuite/gdb.server/pread-offset-size.S
@@ -0,0 +1,29 @@
+/* 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/>. */
+
+/* Here we are trying to create a large binary (> 2 GB),
+ 3742415472 bytes is about 3.5 gigabytes. */
+
+ .text
+ .globl _start
+_start:
+ .skip 3742415472
+ ret
+ .globl f
+ .type f, @function
+f:
+ ret
diff --git a/gdb/testsuite/gdb.server/pread-offset-size.exp b/gdb/testsuite/gdb.server/pread-offset-size.exp
new file mode 100644
index 0000000..54e67c5
--- /dev/null
+++ b/gdb/testsuite/gdb.server/pread-offset-size.exp
@@ -0,0 +1,49 @@
+# 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/>.
+#
+# Check that GDBserver's vFile::pread implementation is able to access
+# large files (> 2GB).
+
+load_lib gdbserver-support.exp
+
+require allow_gdbserver_tests
+
+standard_testfile .S
+
+if { [prepare_for_testing ${testfile}.exp $testfile \
+ $srcfile {debug additional_flags=-nostdlib} ] } {
+ return -1
+}
+
+clean_restart
+
+gdb_test_no_output "set remote exec-file $binfile" \
+ "set remote exec-file"
+
+# Make sure we're disconnected, in case we're testing with an
+# extended-remote board, therefore already connected.
+gdb_test "disconnect" ".*"
+
+set res [gdbserver_spawn ""]
+set gdbserver_protocol [lindex $res 0]
+set gdbserver_gdbport [lindex $res 1]
+
+gdb_test "target $gdbserver_protocol $gdbserver_gdbport" \
+ "Remote debugging using .*" \
+ "target $gdbserver_protocol"
+
+# If loading the large binary was successful, we should be able to
+# place a breakpoint on f.
+gdb_test "break f" "Breakpoint 1.*"
diff --git a/gdb/testsuite/gdb.stabs/weird.def b/gdb/testsuite/gdb.stabs/weird.def
index 179b126..f809963 100644
--- a/gdb/testsuite/gdb.stabs/weird.def
+++ b/gdb/testsuite/gdb.stabs/weird.def
@@ -294,7 +294,7 @@ attr69:
# Using double quotes requires an escaping, as the stabs string
# is a double quote delimited string.
.stabs "constString2:c=s\"Double quote String2\"", N_LSYM,0,0, 0
-# Escaping sinlge quote with is easy
+# Escaping single quote with is easy
.stabs "constString3:c=s'String3 with embedded quote \' in the middle'", N_LSYM,0,0, 0
# Esaping double quotes is less clear...
.stabs "constString4:c=s\"String4 with embedded quote \\" in the middle\"", N_LSYM,0,0, 0
diff --git a/gdb/testsuite/gdb.testsuite/gdb_test_multiple-lbl.exp b/gdb/testsuite/gdb.testsuite/gdb_test_multiple-lbl.exp
new file mode 100644
index 0000000..a05ce61
--- /dev/null
+++ b/gdb/testsuite/gdb.testsuite/gdb_test_multiple-lbl.exp
@@ -0,0 +1,84 @@
+# 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/>.
+
+# Test gdb_test_multiple -lbl, particularly with patterns that share a
+# common prefix.
+
+standard_testfile
+
+clean_restart
+
+gdb_test_no_output "source ${srcdir}/${subdir}/$testfile.gdb" \
+ "source gdb test script"
+
+set saw_prompt 0
+set saw_prefix 0
+set saw_command 0
+set saw_prefix_foo 0
+set saw_prefix_bar 0
+
+# #1 - We need anchors so that the "prefix foo" pattern below does not
+# match when the expect output buffer contains:
+#
+# "\r\nprefix xxx\r\n\prefix foo\r\n"
+#
+# #2 - We need an anchor on the prompt match as otherwise the prompt
+# regexp would match:
+#
+# "\r\nmeant-to-be-matched-by-lbl-2\r\nprefix xxx\r\n(gdb) "
+#
+# This test would fail if -lbl did not force the built-in prompt match
+# regexp to have an anchor as well, as without it, the built-in prompt
+# regexp would have the exact same issue as #2 above.
+
+gdb_test_multiple "command" "" -lbl {
+ -re "^command(?=\r\n)" {
+ verbose -log <COMMAND>
+ incr saw_command
+ exp_continue
+ }
+ -re "^\r\nprefix foo(?=\r\n)" {
+ verbose -log <PREFIX-FOO>
+ incr saw_prefix_foo
+ exp_continue
+ }
+ -re "^\r\nprefix bar(?=\r\n)" {
+ verbose -log <PREFIX-BAR>
+ incr saw_prefix_bar
+ exp_continue
+ }
+ -re "^\r\nprefix \[^\r\n\]*(?=\r\n)" {
+ verbose -log <PREFIX>
+ incr saw_prefix
+ exp_continue
+ }
+ -re "^\r\n$gdb_prompt $" {
+ verbose -log <PROMPT>
+ incr saw_prompt
+ pass $gdb_test_name
+ }
+}
+
+verbose -log "saw_command: $saw_command"
+verbose -log "saw_prefix_foo: $saw_prefix_foo"
+verbose -log "saw_prefix_bar: $saw_prefix_bar"
+verbose -log "saw_prefix: $saw_prefix"
+verbose -log "saw_prompt: $saw_prompt"
+
+gdb_assert {$saw_command == 1}
+gdb_assert {$saw_prefix_foo == 1}
+gdb_assert {$saw_prefix_bar == 1}
+gdb_assert {$saw_prefix == 3}
+gdb_assert {$saw_prompt == 1}
diff --git a/gdb/testsuite/gdb.testsuite/gdb_test_multiple-lbl.gdb b/gdb/testsuite/gdb.testsuite/gdb_test_multiple-lbl.gdb
new file mode 100755
index 0000000..8c94dfa
--- /dev/null
+++ b/gdb/testsuite/gdb.testsuite/gdb_test_multiple-lbl.gdb
@@ -0,0 +1,25 @@
+# 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/>.
+
+define command
+ echo prefix xxx\n
+ echo meant-to-be-matched-by-lbl-1\n
+ echo prefix foo\n
+ echo prefix bar\n
+ echo meant-to-be-matched-by-lbl-2\n
+ echo prefix xxx\n
+ echo prefix xxx\n
+ echo meant-to-be-matched-by-lbl-3\n
+end
diff --git a/gdb/testsuite/gdb.threads/access-mem-running-thread-exit.exp b/gdb/testsuite/gdb.threads/access-mem-running-thread-exit.exp
index b41e3b2..fec31c3 100644
--- a/gdb/testsuite/gdb.threads/access-mem-running-thread-exit.exp
+++ b/gdb/testsuite/gdb.threads/access-mem-running-thread-exit.exp
@@ -74,42 +74,45 @@ proc test { non_stop } {
delete_breakpoints
# Start the second inferior.
- with_test_prefix "second inferior" {
- # With stub targets that do reload on run, if we let the new
- # inferior share inferior 1's connection, runto would
- # fail because GDB is already connected to something, like
- # e.g. with --target_board=native-gdbserver:
- #
- # (gdb) kill
- # ...
- # (gdb) target remote localhost:2348
- # Already connected to a remote target. Disconnect? (y or n)
- #
- # Instead, start the inferior with no connection, and let
- # gdb_load/runto spawn a new remote connection/gdbserver.
- #
- # OTOH, with extended-remote, we must let the new inferior
- # reuse the current connection, so that runto below can
- # issue the "run" command, and have the inferior run on the
- # remote target. If we forced no connection, then "run" would
- # either fail if "set auto-connect-native-target" is on, like
- # the native-extended-gdbserver board enforces, or it would
- # run the inferior on the native target, which isn't what is
- # being tested.
- #
- # Since it's reload_on_run targets that need special care, we
- # default to reusing the connection on most targets.
- if [target_info exists gdb,do_reload_on_run] {
- gdb_test "add-inferior -no-connection" "New inferior 2.*"
- } else {
- gdb_test "add-inferior" "New inferior 2.*"
- }
- gdb_test "inferior 2" "Switching to inferior 2 .*"
-
- gdb_load $binfile
-
- if ![runto setup_done] {
- return -1
+ if {[allow_multi_inferior_tests]} {
+ with_test_prefix "second inferior" {
+ # With stub targets that do reload on run, if we let the
+ # new inferior share inferior 1's connection, runto would
+ # fail because GDB is already connected to something, like
+ # e.g. with --target_board=native-gdbserver:
+ #
+ # (gdb) kill
+ # ...
+ # (gdb) target remote localhost:2348
+ # Already connected to a remote target. Disconnect? (y or n)
+ #
+ # Instead, start the inferior with no connection, and let
+ # gdb_load/runto spawn a new remote connection/gdbserver.
+ #
+ # OTOH, with extended-remote, we must let the new inferior
+ # reuse the current connection, so that runto below can
+ # issue the "run" command, and have the inferior run on
+ # the remote target. If we forced no connection, then
+ # "run" would either fail if "set
+ # auto-connect-native-target" is on, like the
+ # native-extended-gdbserver board enforces, or it would
+ # run the inferior on the native target, which isn't what
+ # is being tested.
+ #
+ # Since it's reload_on_run targets that need special care,
+ # we default to reusing the connection on most targets.
+ if [target_info exists gdb,do_reload_on_run] {
+ gdb_test "add-inferior -no-connection" "New inferior 2.*"
+ } else {
+ gdb_test "add-inferior" "New inferior 2.*"
+ }
+ gdb_test "inferior 2" "Switching to inferior 2 .*"
+
+ gdb_load $binfile
+
+ if ![runto setup_done] {
+ return -1
+ }
}
}
@@ -158,13 +161,15 @@ proc test { non_stop } {
verbose -log "xxxxx: iteration $iter"
gdb_test -nopass "info threads"
- if {$inf == 1} {
- set inf 2
- } else {
- set inf 1
- }
+ if {[allow_multi_inferior_tests]} {
+ if {$inf == 1} {
+ set inf 2
+ } else {
+ set inf 1
+ }
- my_gdb_test "inferior $inf" ".*" "inferior $inf"
+ my_gdb_test "inferior $inf" ".*" "inferior $inf"
+ }
my_gdb_test "print global_var = 555" " = 555" \
"write to global_var"
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/gdb.threads/current-lwp-dead.exp b/gdb/testsuite/gdb.threads/current-lwp-dead.exp
index 7aa7ab9..c8364df 100644
--- a/gdb/testsuite/gdb.threads/current-lwp-dead.exp
+++ b/gdb/testsuite/gdb.threads/current-lwp-dead.exp
@@ -47,6 +47,6 @@ gdb_breakpoint $line
gdb_continue_to_breakpoint "fn_return" ".*at-fn_return.*"
# Confirm thread 2 is really gone.
-gdb_test "info threads 2" "No threads match '2'\\."
+gdb_test "info threads 2" "No threads matched\\."
gdb_continue_to_end "" continue 1
diff --git a/gdb/testsuite/gdb.threads/detach-step-over.exp b/gdb/testsuite/gdb.threads/detach-step-over.exp
index e48b83c..8a1cb29 100644
--- a/gdb/testsuite/gdb.threads/detach-step-over.exp
+++ b/gdb/testsuite/gdb.threads/detach-step-over.exp
@@ -50,6 +50,8 @@
require can_spawn_for_attach
+require allow_multi_inferior_tests
+
standard_testfile
set bp_lineno [gdb_get_line_number "Set breakpoint here"]
diff --git a/gdb/testsuite/gdb.threads/foll-fork-other-thread.exp b/gdb/testsuite/gdb.threads/foll-fork-other-thread.exp
index 5245988..8ab540c 100644
--- a/gdb/testsuite/gdb.threads/foll-fork-other-thread.exp
+++ b/gdb/testsuite/gdb.threads/foll-fork-other-thread.exp
@@ -17,6 +17,8 @@
# another thread, in different combinations of "set follow-fork
# parent/child", and other execution modes.
+require allow_fork_tests
+
standard_testfile
# Line where to stop the main thread.
diff --git a/gdb/testsuite/gdb.threads/fork-child-threads.exp b/gdb/testsuite/gdb.threads/fork-child-threads.exp
index abe9769..ba9dfc2 100644
--- a/gdb/testsuite/gdb.threads/fork-child-threads.exp
+++ b/gdb/testsuite/gdb.threads/fork-child-threads.exp
@@ -13,10 +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/>.
-# Only GNU/Linux is known to support `set follow-fork-mode child'.
-if { ! [istarget "*-*-linux*"] } {
- return 0
-}
+require allow_fork_tests
standard_testfile
diff --git a/gdb/testsuite/gdb.threads/fork-plus-threads.exp b/gdb/testsuite/gdb.threads/fork-plus-threads.exp
index 3a5e66a..4ce88d3 100644
--- a/gdb/testsuite/gdb.threads/fork-plus-threads.exp
+++ b/gdb/testsuite/gdb.threads/fork-plus-threads.exp
@@ -20,6 +20,8 @@
#
# See https://sourceware.org/bugzilla/show_bug.cgi?id=18600
+require allow_fork_tests
+
# In remote mode, we cannot continue debugging after all
# inferiors have terminated, and this test requires that.
if { [target_info exists gdb_protocol]
diff --git a/gdb/testsuite/gdb.threads/fork-thread-pending.exp b/gdb/testsuite/gdb.threads/fork-thread-pending.exp
index d0a1ca1..538e1ca 100644
--- a/gdb/testsuite/gdb.threads/fork-thread-pending.exp
+++ b/gdb/testsuite/gdb.threads/fork-thread-pending.exp
@@ -13,11 +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/>.
-# Only GNU/Linux is known to support `set follow-fork-mode child'.
-#
-if { ! [istarget "*-*-linux*"] } {
- return 0
-}
+require allow_fork_tests
standard_testfile
diff --git a/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp b/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp
index 1f76898..c668a65 100644
--- a/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp
+++ b/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp
@@ -16,6 +16,8 @@
# This test verifies that several threads forking while another thread
# is constantly stepping over a breakpoint is properly handled.
+require allow_fork_tests
+
standard_testfile
set linenum [gdb_get_line_number "set break here"]
diff --git a/gdb/testsuite/gdb.threads/inf-thr-count.exp b/gdb/testsuite/gdb.threads/inf-thr-count.exp
index d7a7687..61533ab 100644
--- a/gdb/testsuite/gdb.threads/inf-thr-count.exp
+++ b/gdb/testsuite/gdb.threads/inf-thr-count.exp
@@ -43,7 +43,7 @@ if {[build_executable "failed to prepare" $testfile $srcfile \
# Start GDB. Ensure we are in non-stop mode as we need to read from
# the inferior while it is running.
save_vars {GDBFLAGS} {
- append GDBFLAGS " -ex \"set non-stop on\""
+ append GDBFLAGS { -ex "set non-stop on"}
clean_restart $binfile
}
@@ -54,22 +54,20 @@ if ![runto_main] {
gdb_breakpoint breakpt
gdb_continue_to_breakpoint "first breakpt call"
+set re_var [string_to_regexp "$"]$decimal
+
# Check we can see a single thread to begin with.
-gdb_test "p \$_inferior_thread_count" \
- "^\\\$$::decimal = 1" \
- "only one thread in \$_inferior_thread_count"
+gdb_test {p $_inferior_thread_count} \
+ "^$re_var = 1" \
+ {only one thread in $_inferior_thread_count}
# We don't want thread events, it makes it harder to match GDB's
# output.
gdb_test_no_output "set print thread-events off"
# Continue the program in the background.
-set test "continue&"
-gdb_test_multiple "continue&" $test {
- -re "Continuing\\.\r\n$gdb_prompt " {
- pass $test
- }
-}
+gdb_test -no-prompt-anchor "continue&" \
+ [string_to_regexp "Continuing."]
# Read the 'stage' flag from the inferior. This is initially 0, but
# will be set to 1 once the extra thread has been created, and then 2
@@ -88,8 +86,17 @@ proc wait_for_stage { num } {
set failure_count 0
set cmd "print /d stage"
set stage_flag 0
+
+ set re_int -?$::decimal
+
+ set re_msg \
+ [multi_line \
+ "Cannot execute this command while the target is running" \
+ {Use the "interrupt" command to stop the target} \
+ [string_to_regexp "and then try again."]]
+
gdb_test_multiple "$cmd" "wait for 'stage' flag to be $num" {
- -re -wrap "^Cannot execute this command while the target is running\\.\r\nUse the \"interrupt\" command to stop the target\r\nand then try again\\." {
+ -re -wrap ^$re_msg {
fail "$gdb_test_name (can't read asynchronously)"
gdb_test_no_output "interrupt"
@@ -101,7 +108,7 @@ proc wait_for_stage { num } {
}
}
- -re -wrap "^\\$\[0-9\]* = (\[-\]*\[0-9\]*).*" {
+ -re -wrap "^$::re_var = ($re_int).*" {
set stage_flag $expect_out(1,string)
if {$stage_flag != $num} {
set stage_flag 0
@@ -131,8 +138,8 @@ if {![wait_for_stage 1]} {
if {[target_info exists gdb_protocol]
&& ([target_info gdb_protocol] == "remote"
|| [target_info gdb_protocol] == "extended-remote")} {
- set new_thread_re "\\\[New Thread \[^\r\n\]+\\\]\r\n"
- set exit_thread_re "\\\[Thread \[^\r\n\]+ exited\\\]\r\n"
+ set new_thread_re {\[New Thread [^\r\n]+\]\r\n}
+ set exit_thread_re {\[Thread [^\r\n]+ exited\]\r\n}
} else {
set new_thread_re ""
set exit_thread_re ""
@@ -141,9 +148,9 @@ if {[target_info exists gdb_protocol]
# This is the test we actually care about. Check that the
# $_inferior_thread_count convenience variable shows the correct
# thread count; the new thread should be visible.
-gdb_test "with print thread-events on -- p \$_inferior_thread_count" \
- "^${new_thread_re}\\\$$::decimal = 2" \
- "second thread visible in \$_inferior_thread_count"
+gdb_test {with print thread-events on -- p $_inferior_thread_count} \
+ "^${new_thread_re}$re_var = 2" \
+ {second thread visible in $_inferior_thread_count}
# Set a variable in the inferior, this will cause the second thread to
# exit.
@@ -157,19 +164,25 @@ if {![wait_for_stage 2]} {
}
# Check that the second thread has gone away.
-gdb_test "with print thread-events on -- p \$_inferior_thread_count" \
- "^${exit_thread_re}\\\$$::decimal = 1" \
- "back to one thread visible in \$_inferior_thread_count"
+gdb_test {with print thread-events on -- p $_inferior_thread_count} \
+ "^${exit_thread_re}$re_var = 1" \
+ {back to one thread visible in $_inferior_thread_count}
# Set a variable in the inferior, this will cause the second thread to
# exit.
-gdb_test_no_output "set variable spin = 0" \
+gdb_test_no_output -no-prompt-anchor "set variable spin = 0" \
"set 'spin' flag to allow main thread to exit"
# When the second thread exits, the main thread joins with it, and
# then proceeds to hit the breakpt function again.
+set re_breakpt [string_to_regexp "breakpt ()"]
+set re \
+ [multi_line \
+ "Thread 1 \[^\r\n\]+ hit Breakpoint $decimal, $re_breakpt\[^\r\n\]+" \
+ "\[^\r\n\]+" \
+ ""]
gdb_test_multiple "" "wait for main thread to stop" {
- -re "Thread 1 \[^\r\n\]+ hit Breakpoint $decimal, breakpt \\(\\)\[^\r\n\]+\r\n\[^\r\n\]+\r\n" {
+ -re $re {
pass $gdb_test_name
}
}
diff --git a/gdb/testsuite/gdb.threads/info-threads-options.c b/gdb/testsuite/gdb.threads/info-threads-options.c
new file mode 100644
index 0000000..2c4cd85
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/info-threads-options.c
@@ -0,0 +1,77 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2022-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/>. */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#define NUM 4
+
+static pthread_barrier_t threads_started_barrier;
+
+static void
+stop_here ()
+{
+}
+
+static void
+spin ()
+{
+ while (1)
+ usleep (1);
+}
+
+static void *
+work (void *arg)
+{
+ int id = *(int *) arg;
+
+ pthread_barrier_wait (&threads_started_barrier);
+
+ if (id % 2 == 0)
+ stop_here ();
+ else
+ spin ();
+
+ pthread_exit (NULL);
+}
+
+int
+main ()
+{
+ /* Ensure we stop if GDB crashes and DejaGNU fails to kill us. */
+ alarm (10);
+
+ pthread_t threads[NUM];
+ int ids[NUM];
+
+ pthread_barrier_init (&threads_started_barrier, NULL, NUM + 1);
+
+ for (int i = 0; i < NUM; i++)
+ {
+ ids[i] = i;
+ pthread_create (&threads[i], NULL, work, &ids[i]);
+ }
+
+ /* Wait until all threads are seen running. */
+ pthread_barrier_wait (&threads_started_barrier);
+
+ stop_here ();
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.threads/info-threads-options.exp b/gdb/testsuite/gdb.threads/info-threads-options.exp
new file mode 100644
index 0000000..38e4e67
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/info-threads-options.exp
@@ -0,0 +1,131 @@
+# Copyright (C) 2022-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 filter flags of the "info threads" command.
+
+standard_testfile
+
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
+ executable debug] != "" } {
+ return -1
+}
+
+save_vars { GDBFLAGS } {
+ append GDBFLAGS " -ex \"set non-stop on\""
+ clean_restart $binfile
+}
+
+if ![runto_main] {
+ return -1
+}
+
+gdb_breakpoint "stop_here"
+gdb_test_multiple "continue -a&" "" {
+ -re "Continuing.\r\n$gdb_prompt " {
+ pass $gdb_test_name
+ }
+}
+
+set expected_hits 3
+set fill "\[^\r\n\]+"
+set num_hits 0
+gdb_test_multiple "" "hit the breakpoint" -lbl {
+ -re "\r\nThread ${fill} hit Breakpoint ${decimal}," {
+ incr num_hits
+ if {$num_hits < $expected_hits} {
+ exp_continue
+ }
+ }
+}
+gdb_assert {$num_hits == $expected_hits} "expected threads hit the bp"
+
+# Count the number of running/stopped threads reported
+# by the "info threads" command. We also capture thread ids
+# for additional tests.
+set running_tid "invalid"
+set stopped_tid "invalid"
+
+set eol "(?=\r\n)"
+
+foreach_with_prefix flag {"" "-running" "-stopped" "-running -stopped"} {
+ set num_running 0
+ set num_stopped 0
+ gdb_test_multiple "info threads $flag" "info threads $flag" -lbl {
+ -re "Id${fill}Target Id${fill}Frame${fill}${eol}" {
+ exp_continue
+ }
+ -re "^\r\n. (${decimal})${fill}Thread ${fill}.running.${eol}" {
+ incr num_running
+ set running_tid $expect_out(1,string)
+ exp_continue
+ }
+ -re "^\r\n. (${decimal})${fill}Thread ${fill}stop_here ${fill}${eol}" {
+ incr num_stopped
+ set stopped_tid $expect_out(1,string)
+ exp_continue
+ }
+ -re "^\r\n$gdb_prompt $" {
+ pass $gdb_test_name
+ }
+ }
+
+ if {$flag eq "-running"} {
+ gdb_assert {$num_running == 2} "num running"
+ gdb_assert {$num_stopped == 0} "num stopped"
+ } elseif {$flag eq "-stopped"} {
+ gdb_assert {$num_running == 0} "num running"
+ gdb_assert {$num_stopped == 3} "num stopped"
+ } else {
+ gdb_assert {$num_running == 2} "num running"
+ gdb_assert {$num_stopped == 3} "num stopped"
+ }
+}
+
+verbose -log "running_tid=$running_tid, stopped_tid=$stopped_tid"
+
+# Test specifying thread ids.
+gdb_test "info threads -running $stopped_tid" \
+ "No threads matched\\." \
+ "info thread -running for a stopped thread"
+gdb_test "info threads -stopped $running_tid" \
+ "No threads matched\\." \
+ "info thread -stopped for a running thread"
+
+set ws "\[ \t\]+"
+foreach tid "\"$running_tid\" \"$running_tid $stopped_tid\"" {
+ gdb_test "info threads -running $tid" \
+ [multi_line \
+ "${ws}Id${ws}Target Id${ws}Frame${ws}" \
+ "${ws}${running_tid}${ws}Thread ${fill}.running."] \
+ "info thread -running with [llength $tid] thread ids"
+}
+
+foreach tid "\"$stopped_tid\" \"$stopped_tid $running_tid\"" {
+ gdb_test "info threads -stopped $tid" \
+ [multi_line \
+ "${ws}Id${ws}Target Id${ws}Frame${ws}" \
+ "${ws}${stopped_tid}${ws}Thread ${fill} stop_here ${fill}"] \
+ "info thread -stopped with [llength $tid] thread ids"
+}
+
+gdb_test_multiple "info threads -stopped -running $stopped_tid $running_tid" \
+ "filter flags and tids combined" {
+ -re -wrap ".*stop_here.*running.*" {
+ pass $gdb_test_name
+ }
+ -re -wrap ".*running.*stop_here.*" {
+ pass $gdb_test_name
+ }
+}
diff --git a/gdb/testsuite/gdb.threads/next-fork-exec-other-thread.exp b/gdb/testsuite/gdb.threads/next-fork-exec-other-thread.exp
index bd81438..3a97127 100644
--- a/gdb/testsuite/gdb.threads/next-fork-exec-other-thread.exp
+++ b/gdb/testsuite/gdb.threads/next-fork-exec-other-thread.exp
@@ -25,6 +25,8 @@
# 20.04.5 LTS with 32-bit kernel + 32-bit userland. It was NOT reproducible
# using a circa 2023 Raspberry Pi OS w/ 64-bit kernel and 32-bit userland.
+require allow_fork_tests
+
standard_testfile
# Line where to stop the main thread.
diff --git a/gdb/testsuite/gdb.threads/next-fork-other-thread.exp b/gdb/testsuite/gdb.threads/next-fork-other-thread.exp
index 183fda6..1cd6685 100644
--- a/gdb/testsuite/gdb.threads/next-fork-other-thread.exp
+++ b/gdb/testsuite/gdb.threads/next-fork-other-thread.exp
@@ -16,6 +16,8 @@
# Test doing a "next" on a thread during which forks or vforks happen in other
# threads.
+require allow_fork_tests
+
standard_testfile
# Line where to stop the main thread.
diff --git a/gdb/testsuite/gdb.threads/pending-fork-event-detach-ns.exp b/gdb/testsuite/gdb.threads/pending-fork-event-detach-ns.exp
index e6e311e..29a011e 100644
--- a/gdb/testsuite/gdb.threads/pending-fork-event-detach-ns.exp
+++ b/gdb/testsuite/gdb.threads/pending-fork-event-detach-ns.exp
@@ -29,6 +29,8 @@
# parent thread from waitpid'ing it, preventing the main thread from joining
# it, prevent it from writing the flag file, failing the test.
+require allow_fork_tests
+
standard_testfile
if { [is_remote target] } {
diff --git a/gdb/testsuite/gdb.threads/pending-fork-event-detach.exp b/gdb/testsuite/gdb.threads/pending-fork-event-detach.exp
index 8e77ab0..e627241 100644
--- a/gdb/testsuite/gdb.threads/pending-fork-event-detach.exp
+++ b/gdb/testsuite/gdb.threads/pending-fork-event-detach.exp
@@ -34,6 +34,8 @@
# event, and erroneously create a new inferior for it. Once fixed, the child
# process' thread is hidden by whoever holds the pending fork event.
+require allow_fork_tests
+
standard_testfile .c -touch-file.c
set touch_file_bin $binfile-touch-file
diff --git a/gdb/testsuite/gdb.threads/thread-bp-deleted.exp b/gdb/testsuite/gdb.threads/thread-bp-deleted.exp
index 2eadd38..8cabb70 100644
--- a/gdb/testsuite/gdb.threads/thread-bp-deleted.exp
+++ b/gdb/testsuite/gdb.threads/thread-bp-deleted.exp
@@ -147,7 +147,7 @@ if {$is_remote} {
exp_continue
}
- -re "No threads match '99'\\.\r\n$gdb_prompt $" {
+ -re "No threads matched\\.\r\n$gdb_prompt $" {
if {!$saw_thread_exited && !$saw_bp_deleted && $attempt_count > 0} {
sleep 1
incr attempt_count -1
diff --git a/gdb/testsuite/gdb.threads/thread-execl.c b/gdb/testsuite/gdb.threads/thread-execl.c
index 403aa31..2d312d4 100644
--- a/gdb/testsuite/gdb.threads/thread-execl.c
+++ b/gdb/testsuite/gdb.threads/thread-execl.c
@@ -25,8 +25,9 @@ static const char *image;
void *
thread_execler (void *arg)
{
- /* Exec ourselves again. */
- if (execl (image, image, NULL) == -1)
+ /* Exec ourselves again. Pass an extra argument so that the
+ post-exec image knows to not re-exec yet again. */
+ if (execl (image, image, "1", NULL) == -1)
{
perror ("execl");
abort ();
@@ -40,6 +41,11 @@ main (int argc, char **argv)
{
pthread_t thread;
+ /* An extra argument means we're in the post-exec image, so we're
+ done. Don't re-exec again. */
+ if (argc > 1)
+ exit (0);
+
image = argv[0];
pthread_create (&thread, NULL, thread_execler, NULL);
diff --git a/gdb/testsuite/gdb.threads/threadapply.exp b/gdb/testsuite/gdb.threads/threadapply.exp
index c53db79..9110617 100644
--- a/gdb/testsuite/gdb.threads/threadapply.exp
+++ b/gdb/testsuite/gdb.threads/threadapply.exp
@@ -224,6 +224,8 @@ proc kill_and_remove_inferior {thread_set} {
# Test both "all" and a thread list, because those are implemented as
# different commands in GDB.
-foreach_with_prefix thread_set {"all" "1.1"} {
- kill_and_remove_inferior $thread_set
+if {[allow_multi_inferior_tests]} {
+ foreach_with_prefix thread_set {"all" "1.1"} {
+ kill_and_remove_inferior $thread_set
+ }
}
diff --git a/gdb/testsuite/gdb.threads/tls.exp b/gdb/testsuite/gdb.threads/tls.exp
index 1bc5df2..73fada7 100644
--- a/gdb/testsuite/gdb.threads/tls.exp
+++ b/gdb/testsuite/gdb.threads/tls.exp
@@ -159,7 +159,7 @@ gdb_test_multiple "print a_thread_local" "" {
-re -wrap "Cannot find thread-local variables on this target" {
kfail "gdb/25807" $gdb_test_name
}
- -re -wrap "Cannot read .a_thread_local. without registers" {
+ -re -wrap "Cannot (?:read|find address of TLS symbol) .a_thread_local. without registers" {
pass $gdb_test_name
}
}
diff --git a/gdb/testsuite/gdb.threads/vfork-follow-child-exec.exp b/gdb/testsuite/gdb.threads/vfork-follow-child-exec.exp
index e23db0a..0b95a75 100644
--- a/gdb/testsuite/gdb.threads/vfork-follow-child-exec.exp
+++ b/gdb/testsuite/gdb.threads/vfork-follow-child-exec.exp
@@ -16,6 +16,8 @@
# Test following a vfork child that execs, when the vfork parent is a
# threaded program, and it's a non-main thread that vforks.
+require allow_fork_tests
+
standard_testfile
if {[build_executable "failed to prepare" $testfile $srcfile {debug pthreads}]} {
diff --git a/gdb/testsuite/gdb.threads/vfork-follow-child-exit.exp b/gdb/testsuite/gdb.threads/vfork-follow-child-exit.exp
index a6b7f49..ced52df 100644
--- a/gdb/testsuite/gdb.threads/vfork-follow-child-exit.exp
+++ b/gdb/testsuite/gdb.threads/vfork-follow-child-exit.exp
@@ -16,6 +16,8 @@
# Test following a vfork child that exits, when the vfork parent is a
# threaded program, and it's a non-main thread that vforks.
+require allow_fork_tests
+
standard_testfile
if {[build_executable "failed to prepare" $testfile $srcfile {debug pthreads}]} {
diff --git a/gdb/testsuite/gdb.threads/vfork-multi-inferior.exp b/gdb/testsuite/gdb.threads/vfork-multi-inferior.exp
index fd081b3..1f87427 100644
--- a/gdb/testsuite/gdb.threads/vfork-multi-inferior.exp
+++ b/gdb/testsuite/gdb.threads/vfork-multi-inferior.exp
@@ -25,6 +25,10 @@
# To catch the bug, this test verifies that we can hit a breakpoint after a
# vfork call, while a second inferior runs in the background.
+require allow_fork_tests
+
+require allow_multi_inferior_tests
+
require !use_gdb_stub
standard_testfile .c -sleep.c
diff --git a/gdb/testsuite/gdb.threads/vfork-multi-thread.exp b/gdb/testsuite/gdb.threads/vfork-multi-thread.exp
index 2b9294d..61811ae 100644
--- a/gdb/testsuite/gdb.threads/vfork-multi-thread.exp
+++ b/gdb/testsuite/gdb.threads/vfork-multi-thread.exp
@@ -30,6 +30,8 @@
# breakpoints are removed, so the main thread would miss the breakpoint and run
# until exit.
+require allow_fork_tests
+
standard_testfile
if { [build_executable "failed to prepare" ${testfile} ${srcfile} {debug pthreads}] } {
diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork.exp b/gdb/testsuite/gdb.threads/watchpoint-fork.exp
index 376ca2a..8e9b1c3 100644
--- a/gdb/testsuite/gdb.threads/watchpoint-fork.exp
+++ b/gdb/testsuite/gdb.threads/watchpoint-fork.exp
@@ -21,6 +21,8 @@
# must be done before starting the test so as to not disrupt the execution
# of the actual test.
+require allow_fork_tests
+
set allow_hw_watchpoint_tests_p [allow_hw_watchpoint_tests]
set testfile watchpoint-fork
diff --git a/gdb/testsuite/gdb.trace/tspeed.exp b/gdb/testsuite/gdb.trace/tspeed.exp
index 25862bf..be7f37e 100644
--- a/gdb/testsuite/gdb.trace/tspeed.exp
+++ b/gdb/testsuite/gdb.trace/tspeed.exp
@@ -17,7 +17,7 @@ load_lib "trace-support.exp"
require allow_shlib_tests
-# Do not run if gdbsever debug is enabled - the output file is many Gb.
+# Do not run if gdbserver debug is enabled - the output file is many Gb.
if [gdbserver_debug_enabled] {
return 0
}
diff --git a/gdb/testsuite/gdb.tui/corefile-run.exp b/gdb/testsuite/gdb.tui/corefile-run.exp
index 89a48b5..657fc83 100644
--- a/gdb/testsuite/gdb.tui/corefile-run.exp
+++ b/gdb/testsuite/gdb.tui/corefile-run.exp
@@ -18,6 +18,8 @@
#
# Ref.: https://bugzilla.redhat.com/show_bug.cgi?id=1765117
+require gcore_cmd_available
+
tuiterm_env
standard_testfile tui-layout.c
diff --git a/gdb/testsuite/gdb.tui/pr30056.exp b/gdb/testsuite/gdb.tui/pr30056.exp
index 1123593..3403033 100644
--- a/gdb/testsuite/gdb.tui/pr30056.exp
+++ b/gdb/testsuite/gdb.tui/pr30056.exp
@@ -76,12 +76,12 @@ save_vars { env(LC_ALL) } {
# open about this.
kfail cli/30498 $test
- # At this point we don't have a reponsive prompt. Send ^G to abort
+ # At this point we don't have a responsive prompt. Send ^G to abort
# the i-search.
send_gdb "\007"
}
- # We need a reponsive prompt here, to deal with the "monitor exit"
+ # We need a responsive prompt here, to deal with the "monitor exit"
# that native-extended-gdbserver will send. Check that we have a
# responsive prompt.
Term::command "echo \\n"
diff --git a/gdb/testsuite/gdb.tui/tui-focus.exp b/gdb/testsuite/gdb.tui/tui-focus.exp
index 4c9d2a0..26e5060 100644
--- a/gdb/testsuite/gdb.tui/tui-focus.exp
+++ b/gdb/testsuite/gdb.tui/tui-focus.exp
@@ -73,7 +73,7 @@ foreach spec {{src true} {cmd true} {status true} {regs false} \
}
}
-# Use the Python TUI API to exercise some of the ambigous window name
+# Use the Python TUI API to exercise some of the ambiguous window name
# handling parts of the 'focus' command.
Term::clean_restart 24 80 $binfile
if {[allow_python_tests]} {
diff --git a/gdb/testsuite/gdb.tui/tui-layout-asm.exp b/gdb/testsuite/gdb.tui/tui-layout-asm.exp
index ec78a0c..333276e 100644
--- a/gdb/testsuite/gdb.tui/tui-layout-asm.exp
+++ b/gdb/testsuite/gdb.tui/tui-layout-asm.exp
@@ -24,7 +24,9 @@ if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} {
return -1
}
-# PPC currently needs a minimum window width of 90 to work correctly.
+# The wider the window is, the less line truncation happens, so matching
+# pre-scroll to post-scroll lines is more accurate. But 100% accurate line
+# matching isn't a goal of the test-case.
set tui_asm_window_width 90
Term::clean_restart 24 ${tui_asm_window_width} $testfile
@@ -33,15 +35,41 @@ if {![Term::prepare_for_tui]} {
return
}
-# Helper proc, returns a count of the ' ' characters in STRING.
-proc count_whitespace { string } {
- return [expr {[llength [split $string { }]] - 1}]
-}
-
# This puts us into TUI mode, and should display the ASM window.
Term::command_no_prompt_prefix "layout asm"
Term::check_box_contents "check asm box contents" 0 0 ${tui_asm_window_width} 15 "<main>"
+set re_border [string_to_regexp "|"]
+
+proc drop_borders { line } {
+ # Drop left border.
+ set line [regsub -- ^$::re_border $line {}]
+ # Drop right border.
+ set line [regsub -- $::re_border$ $line {}]
+
+ return $line
+}
+
+proc lines_match { line1 line2 } {
+ set line1 [drop_borders $line1]
+ set line2 [drop_borders $line2]
+
+ foreach line [list $line1 $line2] re [list $line2 $line1] {
+ # Convert to regexp.
+ set re [string_to_regexp $re]
+
+ # Ignore whitespace mismatches.
+ regsub -all {\s+} $re {\s+} re
+
+ # Allow a substring match.
+ if { [regexp -- $re $line] } {
+ return 1
+ }
+ }
+
+ return 0
+}
+
# Scroll the ASM window down using the down arrow key. In an ideal
# world we'd like to use PageDown here, but currently our terminal
# library doesn't support such advanced things.
@@ -58,51 +86,55 @@ while (1) {
# below will just timeout. So for now we avoid testing the edge
# case.
if {[regexp -- "^\\| +\\|$" $line]} {
- # Second line is blank, we're at the end of the assembler.
- pass $testname
+ # Second line is blank, we're at the end of the assembly.
+ pass "$testname (end of assembly reached)"
break
}
# Send the down key to GDB.
send_gdb "\033\[B"
incr down_count
- set re_line [string_to_regexp $line]
- # Ignore whitespace mismatches.
- regsub -all {\s+} $re_line {\s+} re_line
+
+ # Get address from the line.
+ regexp \
+ [join \
+ [list \
+ ^ \
+ $re_border \
+ {\s+} \
+ ($hex) \
+ {\s+}] \
+ ""] \
+ $line \
+ match \
+ address
+
+ # Regexp to match line containing address.
+ set re_line \
+ [join \
+ [list \
+ ^ \
+ $re_border \
+ {\s+} \
+ $address \
+ {\s+} \
+ {[^\r\n]+} \
+ $re_border \
+ $] \
+ ""]
+
if {[Term::wait_for $re_line] \
- && [regexp $re_line [Term::get_line 1]]} {
+ && [lines_match $line [Term::get_line 1]]} {
# We scrolled successfully.
} else {
- if {[count_whitespace ${line}] != \
- [count_whitespace [Term::get_line 1]]} {
- # GDB's TUI assembler display will widen columns based on
- # the longest item that appears in a column on any line.
- # As we have just scrolled, and so revealed a new line, it
- # is possible that the width of some columns has changed.
- #
- # As a result it is possible that part of the line we were
- # expected to see in the output is now off the screen. And
- # this test will fail.
- #
- # This is unfortunate, but, right now, there's no easy way
- # to "lock" the format of the TUI assembler window. The
- # only option appears to be making the window width wider,
- # this can be done by adjusting TUI_ASM_WINDOW_WIDTH.
- verbose -log "WARNING: The following failure is probably due to the TUI window"
- verbose -log " width. See the comments in the test script for more"
- verbose -log " details."
- }
-
fail "$testname (scroll failed)"
Term::dump_screen
break
}
- if { $down_count > 250 } {
- # Maybe we should accept this as a pass in case a target
- # really does have loads of assembler to scroll through.
- fail "$testname (too much assembler)"
- Term::dump_screen
+ if { $down_count > 25 } {
+ # We've scrolled enough, we're done.
+ pass "$testname (scroll limit reached)"
break
}
}
diff --git a/gdb/testsuite/gdb.xml/bad-include.xml b/gdb/testsuite/gdb.xml/bad-include.xml
index f7a2b72..cd9cce3 100644
--- a/gdb/testsuite/gdb.xml/bad-include.xml
+++ b/gdb/testsuite/gdb.xml/bad-include.xml
@@ -1 +1 @@
-<xi:include href="nonexistant.xml"/>
+<xi:include href="nonexistent.xml"/>
diff --git a/gdb/testsuite/gdb.xml/tdesc-xinclude.exp b/gdb/testsuite/gdb.xml/tdesc-xinclude.exp
index 885d217..b934c80 100644
--- a/gdb/testsuite/gdb.xml/tdesc-xinclude.exp
+++ b/gdb/testsuite/gdb.xml/tdesc-xinclude.exp
@@ -43,7 +43,7 @@ set_arch "includes.xml" \
# This file contains a missing include. We should warn the user about
# it.
set_arch "bad-include.xml" \
- "warning:.*Could not load XML document \"nonexistant.xml\"$common_warn"
+ "warning:.*Could not load XML document \"nonexistent.xml\"$common_warn"
# Make sure we detect infinite loops, eventually.
set_arch "loop.xml" \
diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index 46b39a1..3a182c2 100644
--- a/gdb/testsuite/lib/dwarf.exp
+++ b/gdb/testsuite/lib/dwarf.exp
@@ -678,6 +678,11 @@ namespace eval Dwarf {
}
}
close $fd
+
+ variable _constants
+
+ # Add DW_FORM_strx_id as alias of DW_FORM_strx.
+ _process_one_constant DW_FORM_strx_id $_constants(DW_FORM_strx)
}
proc _quote {string} {
@@ -823,6 +828,12 @@ namespace eval Dwarf {
DW_FORM_indirect -
DW_FORM_exprloc -
+ # Generate a DW_FORM_str index, but assume generation of .debug_str and
+ # .debug_str_offsets is taken care of elsewhere.
+ DW_FORM_strx_id {
+ _op .uleb128 $value
+ }
+
DW_FORM_strx -
DW_FORM_strx1 -
DW_FORM_strx2 -
@@ -1061,7 +1072,10 @@ namespace eval Dwarf {
}
proc _section {name {flags ""} {type ""}} {
- if {$flags == "" && $type == ""} {
+ if {$name == ".debug_str"} {
+ # Hard-code this because it's always desirable.
+ _emit " .section $name, \"MS\", %progbits, 1"
+ } elseif {$flags == "" && $type == ""} {
_emit " .section $name"
} elseif {$type == ""} {
_emit " .section $name, \"$flags\""
@@ -3068,6 +3082,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]
@@ -3367,6 +3399,58 @@ namespace eval Dwarf {
debug_names_end:
}
+ # Add the strings in ARGS to the .debug_str section, and create a
+ # .debug_str_offsets section pointing to those strings.
+ # Current options are:
+ # dwo 0|1 - boolean indicating if the sections have the dwo suffix.
+ # default = 0 (no .dwo suffix)
+ # base_offset label
+ # - generate label, to be used in DW_AT_str_offsets_base.
+ # default = "" (don't generate a label).
+ proc debug_str_offsets { options args } {
+ parse_options {
+ { dwo 0 }
+ { base_offset "" }
+ }
+
+ if { $dwo } {
+ _section .debug_str.dwo
+ } else {
+ _section .debug_str
+ }
+
+ set num 0
+ foreach arg $args {
+ set str_label [_compute_label "str_${num}"]
+ define_label $str_label
+ _op .asciz \"$arg\" ".debug_str_offsets string $num"
+ incr num
+ }
+
+ declare_labels debug_str_offsets_start debug_str_offsets_end
+ set initial_length "$debug_str_offsets_end - $debug_str_offsets_start"
+
+ if { $dwo } {
+ _section .debug_str_offsets.dwo
+ } else {
+ _section .debug_str_offsets
+ }
+ _op .4byte $initial_length "Initial_length"
+ debug_str_offsets_start:
+ _op .2byte 0x5 "version"
+ _op .2byte 0x0 "padding"
+ if { $base_offset != "" } {
+ $base_offset:
+ }
+ set num 0
+ foreach arg $args {
+ set str_label [_compute_label "str_${num}"]
+ _op .4byte $str_label "string $num"
+ incr num
+ }
+ debug_str_offsets_end:
+ }
+
# The top-level interface to the DWARF assembler.
# OPTIONS is a list with an even number of elements containing
# option-name and option-value pairs.
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
+}
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index c37cc89..777d64d 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -269,6 +269,13 @@ if ![info exists INTERNAL_GDBFLAGS] {
}
set INTERNAL_GDBFLAGS [append_gdb_data_directory_option $INTERNAL_GDBFLAGS]
+
+ # Handle the case that "interactive-mode auto" reports off.
+ append INTERNAL_GDBFLAGS { -iex "set interactive-mode on"}
+
+ if { [ishost "*-*-mingw*"] } {
+ append INTERNAL_GDBFLAGS { -iex "maint set console-translation-mode binary"}
+ }
}
# The variable gdb_prompt is a regexp which matches the gdb prompt.
@@ -1026,7 +1033,10 @@ proc command_to_message { command } {
# should not be anchored at the end of the buffer. This means that the
# pattern can match even if there is stuff output after the prompt. Does not
# have any effect if -prompt is specified.
-# -lbl specifies that line-by-line matching will be used.
+# -lbl specifies that line-by-line matching will be used. This means
+# that lines from GDB not matched by any pattern will be consumed from
+# the output buffer. This helps avoid buffer overflows and timeouts
+# when testing verbose commands.
# EXPECT_ARGUMENTS will be fed to expect in addition to the standard
# patterns. Pattern elements will be evaluated in the caller's
# context; action elements will be executed in the caller's context.
@@ -1124,6 +1134,7 @@ proc gdb_test_multiple { command message args } {
global any_spawn_id
set line_by_line 0
+ set lbl_anchor_re ""
set prompt_regexp ""
set prompt_anchor 1
for {set i 0} {$i < [llength $args]} {incr i} {
@@ -1133,6 +1144,7 @@ proc gdb_test_multiple { command message args } {
set prompt_regexp [lindex $args $i]
} elseif { $arg == "-lbl" } {
set line_by_line 1
+ set lbl_anchor_re "^"
} elseif { $arg == "-no-prompt-anchor" } {
set prompt_anchor 0
} else {
@@ -1391,7 +1403,7 @@ proc gdb_test_multiple { command message args } {
fail "$errmsg"
set result -1
}
- -re "\r\n$prompt_regexp" {
+ -re "${lbl_anchor_re}\r\n$prompt_regexp" {
if {![string match "" $message]} {
fail "$message"
}
@@ -2301,7 +2313,8 @@ proc default_gdb_exit {} {
}
}
- if { [is_remote host] && [board_info host exists fileid] } {
+ if { ([is_remote host] && [board_info host exists fileid])
+ || [istarget *-*-mingw*] } {
send_gdb "quit\n"
gdb_expect 10 {
-re "y or n" {
@@ -2314,7 +2327,9 @@ proc default_gdb_exit {} {
}
if ![is_remote host] {
- remote_close host
+ if {[catch { remote_close host } message]} {
+ warning "closing gdb failed with: $message"
+ }
}
unset gdb_spawn_id
unset ::gdb_tty_name
@@ -2577,6 +2592,17 @@ proc default_gdb_start { } {
# Output with -q, and bracketed paste mode enabled, see above.
verbose "GDB initialized."
}
+ -re "^\033\\\[6n$gdb_prompt $" {
+ # With MSYS2 and TERM={xterm,ansi}, I get:
+ #
+ # builtin_spawn gdb -q ...
+ # ^[[6n(gdb)
+ #
+ # We set TERM to dumb by default to avoid this, but some
+ # test-cases set TERM to xterm or ansi, in which case we get this
+ # output.
+ verbose "GDB initialized."
+ }
-re "$gdb_prompt $" {
perror "GDB never initialized."
unset gdb_spawn_id
@@ -3758,7 +3784,8 @@ proc supports_reverse {} {
|| [istarget "aarch64*-*-linux*"]
|| [istarget "loongarch*-*-linux*"]
|| [istarget "powerpc*-*-linux*"]
- || [istarget "s390*-*-linux*"] } {
+ || [istarget "s390*-*-linux*"]
+ || [istarget "riscv*-*-*"] } {
return 1
}
@@ -5086,6 +5113,40 @@ proc skip_inline_var_tests {} {
return 0
}
+# Return whether we allow running fork-related testcases. Targets
+# that don't even have any concept of fork will just fail to compile
+# the testcases and skip the tests that way if this returns true for
+# them. Unix targets that do have a fork system call, but don't
+# support intercepting forks will want to return false here, otherwise
+# the testcases that exercise fork may hit a number of long cascading
+# time out sequences.
+
+proc allow_fork_tests {} {
+ if {[istarget "*-*-cygwin*"] || [istarget "*-*-mingw*"]} {
+ return 0
+ }
+
+ return 1
+}
+
+# Return whether we allow running testcases that want to debug
+# multiple inferiors with the same target. Not all targets support
+# this. Note that some tests add a second inferior but never start
+# it. Those tests should not be skipped due to this proc returning
+# false.
+
+proc allow_multi_inferior_tests {} {
+ if {[istarget "*-*-cygwin*"] || [istarget "*-*-mingw*"]} {
+ return 0
+ }
+
+ if {[use_gdb_stub]} {
+ return 0
+ }
+
+ return 1
+}
+
# Return a 1 if we should run tests that require hardware breakpoints
proc allow_hw_breakpoint_tests {} {
@@ -6919,7 +6980,7 @@ proc kill_wait_spawned_process { proc_spawn_id } {
proc spawn_id_get_pid { spawn_id } {
set testpid [exp_pid -i $spawn_id]
- if { [istarget "*-*-cygwin*"] } {
+ if { [istarget "*-*-cygwin*"] || [istarget "*-*-mingw*"] } {
# testpid is the Cygwin PID, GDB uses the Windows PID, which
# might be different due to the way fork/exec works.
set testpid [ exec ps -e | gawk "{ if (\$1 == $testpid) print \$4; }" ]
@@ -7006,6 +7067,24 @@ proc gdb_load_cmd { args } {
return -1
}
+# Return non-zero if 'gcore' command is available.
+gdb_caching_proc gcore_cmd_available { } {
+ gdb_exit
+ gdb_start
+
+ # Does this gdb support gcore?
+ gdb_test_multiple "help gcore" "" {
+ -re -wrap "Undefined command: .*" {
+ return 0
+ }
+ -re -wrap "Save a core file .*" {
+ return 1
+ }
+ }
+
+ return 0
+}
+
# Invoke "gcore". CORE is the name of the core file to write. TEST
# is the name of the test case. This will return 1 if the core file
# was created, 0 otherwise. If this fails to make a core file because
@@ -7470,6 +7549,22 @@ proc default_gdb_init { test_file_name } {
setenv LC_CTYPE C
setenv LANG C
+ # With MSYS2 and TERM={xterm,ansi}, I get:
+ #
+ # builtin_spawn gdb -q ...
+ # ^[[6n(gdb)
+ #
+ # While we're addressing this in default_gdb_start, this is not specific
+ # to gdb, other tools produce the same CSI sequence, and consequently we
+ # run into trouble in other places (like get_compiler_info).
+ #
+ # Set TERM to dumb to prevent the '^[[6n' from occurring.
+ #
+ # We could do this only for ishost *-*-mingw*, but that introduces
+ # inconsistency between platforms, with test-cases passing on one platform
+ # but failing on the other. So, we do this for all platforms.
+ setenv TERM dumb
+
# Don't let a .inputrc file or an existing setting of INPUTRC mess
# up the test results. Certain tests (style tests and TUI tests)
# want to set the terminal to a non-"dumb" value, and for those we
@@ -9285,7 +9380,12 @@ proc core_find {binfile {deletefiles {}} {arg ""}} {
file mkdir $coredir
catch "system \"(cd ${coredir}; ulimit -c unlimited; ${binfile} ${arg}; true) >/dev/null 2>&1\""
# remote_exec host "${binfile}"
- foreach i "${coredir}/core ${coredir}/core.coremaker.c ${binfile}.core" {
+ set binfile_basename [file tail $binfile]
+ foreach i [list \
+ ${coredir}/core \
+ ${coredir}/core.coremaker.c \
+ ${coredir}/${binfile_basename}.core \
+ ${coredir}/${binfile_basename}.exe.core] {
if [remote_file build exists $i] {
remote_exec build "mv $i $destcore"
set found 1
diff --git a/gdb/testsuite/lib/gdbserver-support.exp b/gdb/testsuite/lib/gdbserver-support.exp
index c285072..2389206 100644
--- a/gdb/testsuite/lib/gdbserver-support.exp
+++ b/gdb/testsuite/lib/gdbserver-support.exp
@@ -69,7 +69,7 @@ proc gdb_target_cmd_ext { targetname serialport {additional_text ""} } {
}
-re "Non-stop mode requested, but remote does not support non-stop.*$gdb_prompt $" {
verbose "remote does not support non-stop"
- return 1
+ return 2
}
-re "Remote MIPS debugging.*$additional_text.*$gdb_prompt" {
verbose "Set target to $targetname"
diff --git a/gdb/testsuite/make-check-all.sh b/gdb/testsuite/make-check-all.sh
index c2fbadb..ab72574 100755
--- a/gdb/testsuite/make-check-all.sh
+++ b/gdb/testsuite/make-check-all.sh
@@ -192,7 +192,7 @@ do_tests ()
# Run make check.
make $maketarget \
- RUNTESTFLAGS="${rtf[*]} ${tests[*]}" \
+ RUNTESTFLAGS="${rtf[*]}" TESTS="${tests[*]}" \
2>&1 \
| summary
@@ -216,7 +216,7 @@ do_tests ()
cp gdb.sum gdb.log "$dir"
# Record the 'make check' command to enable easy re-running.
- echo "make $maketarget RUNTESTFLAGS=\"${rtf[*]} ${tests[*]}\"" \
+ echo "make $maketarget RUNTESTFLAGS=\"${rtf[*]}\" TESTS=\"${tests[*]}\"" \
> "$dir/make-check.sh"
fi
}