aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/MAINTAINERS15
-rw-r--r--gdb/Makefile.in100
-rw-r--r--gdb/NEWS147
-rw-r--r--gdb/README35
-rw-r--r--gdb/aarch64-fbsd-nat.c4
-rw-r--r--gdb/aarch64-fbsd-tdep.c7
-rw-r--r--gdb/aarch64-linux-nat.c83
-rw-r--r--gdb/aarch64-linux-tdep.c217
-rw-r--r--gdb/aarch64-nat.h4
-rw-r--r--gdb/aarch64-newlib-tdep.c4
-rw-r--r--gdb/aarch64-tdep.c164
-rw-r--r--gdb/aarch64-tdep.h25
-rw-r--r--gdb/ada-exp.h50
-rw-r--r--gdb/ada-exp.y19
-rw-r--r--gdb/ada-lang.c498
-rw-r--r--gdb/ada-lang.h15
-rw-r--r--gdb/ada-lex.l23
-rw-r--r--gdb/ada-tasks.c4
-rw-r--r--gdb/ada-typeprint.c5
-rw-r--r--gdb/ada-valprint.c5
-rw-r--r--gdb/addrmap.c77
-rw-r--r--gdb/addrmap.h4
-rw-r--r--gdb/agent.c4
-rw-r--r--gdb/aix-thread.c4
-rw-r--r--gdb/alpha-bsd-nat.c4
-rw-r--r--gdb/alpha-linux-nat.c4
-rw-r--r--gdb/alpha-linux-tdep.c9
-rw-r--r--gdb/alpha-netbsd-tdep.c9
-rw-r--r--gdb/alpha-obsd-tdep.c9
-rw-r--r--gdb/alpha-tdep.c94
-rw-r--r--gdb/amd-dbgapi-target.c364
-rw-r--r--gdb/amd-dbgapi-target.h5
-rw-r--r--gdb/amd64-darwin-tdep.c6
-rw-r--r--gdb/amd64-dicos-tdep.c4
-rw-r--r--gdb/amd64-fbsd-nat.c4
-rw-r--r--gdb/amd64-fbsd-tdep.c7
-rw-r--r--gdb/amd64-gnu-tdep.c7
-rw-r--r--gdb/amd64-linux-nat.c21
-rw-r--r--gdb/amd64-linux-tdep.c239
-rw-r--r--gdb/amd64-netbsd-nat.c4
-rw-r--r--gdb/amd64-netbsd-tdep.c7
-rw-r--r--gdb/amd64-obsd-nat.c4
-rw-r--r--gdb/amd64-obsd-tdep.c7
-rw-r--r--gdb/amd64-sol2-tdep.c7
-rwxr-xr-x[-rw-r--r--]gdb/amd64-tdep.c379
-rw-r--r--gdb/amd64-tdep.h9
-rw-r--r--gdb/amd64-windows-nat.c4
-rw-r--r--gdb/amd64-windows-tdep.c4
-rw-r--r--gdb/amdgpu-tdep.c5
-rw-r--r--gdb/annotate.c4
-rw-r--r--gdb/arc-linux-nat.c4
-rw-r--r--gdb/arc-linux-tdep.c12
-rw-r--r--gdb/arc-newlib-tdep.c4
-rw-r--r--gdb/arc-tdep.c4
-rw-r--r--gdb/arch-utils.c16
-rw-r--r--gdb/arch-utils.h5
-rw-r--r--gdb/arch/aarch64-gcs-linux.h44
-rw-r--r--gdb/arch/aarch64.c8
-rw-r--r--gdb/arch/aarch64.h10
-rw-r--r--gdb/arch/amd64-linux-tdesc.c31
-rw-r--r--gdb/arch/amd64-linux-tdesc.h7
-rw-r--r--gdb/arch/amd64.c25
-rw-r--r--gdb/arch/amd64.h10
-rw-r--r--gdb/arch/arc.c1
-rw-r--r--gdb/arch/i386-linux-tdesc.c29
-rw-r--r--gdb/arch/i386-linux-tdesc.h5
-rw-r--r--gdb/arch/i386.c19
-rw-r--r--gdb/arch/i386.h7
-rw-r--r--gdb/arch/loongarch.c1
-rw-r--r--gdb/arch/riscv.c1
-rw-r--r--gdb/arch/x86-linux-tdesc-features.c60
-rw-r--r--gdb/arch/x86-linux-tdesc-features.h27
-rw-r--r--gdb/arm-fbsd-nat.c4
-rw-r--r--gdb/arm-fbsd-tdep.c9
-rw-r--r--gdb/arm-linux-nat.c14
-rw-r--r--gdb/arm-linux-tdep.c19
-rw-r--r--gdb/arm-netbsd-nat.c4
-rw-r--r--gdb/arm-netbsd-tdep.c9
-rw-r--r--gdb/arm-none-tdep.c4
-rw-r--r--gdb/arm-obsd-tdep.c9
-rw-r--r--gdb/arm-pikeos-tdep.c6
-rw-r--r--gdb/arm-tdep.c17
-rw-r--r--gdb/arm-wince-tdep.c6
-rw-r--r--gdb/auto-load.c87
-rw-r--r--gdb/auxv.c4
-rw-r--r--gdb/avr-tdep.c4
-rw-r--r--gdb/ax-gdb.c9
-rw-r--r--gdb/bfin-linux-tdep.c4
-rw-r--r--gdb/bfin-tdep.c4
-rw-r--r--gdb/block.c67
-rw-r--r--gdb/block.h27
-rw-r--r--gdb/bpf-tdep.c4
-rw-r--r--gdb/break-catch-exec.c8
-rw-r--r--gdb/break-catch-fork.c6
-rw-r--r--gdb/break-catch-load.c9
-rw-r--r--gdb/break-catch-sig.c6
-rw-r--r--gdb/break-catch-syscall.c10
-rw-r--r--gdb/break-catch-throw.c11
-rw-r--r--gdb/break-cond-parse.c22
-rw-r--r--gdb/breakpoint.c79
-rw-r--r--gdb/breakpoint.h4
-rw-r--r--gdb/bsd-kvm.c4
-rw-r--r--gdb/bsd-uthread.c13
-rw-r--r--gdb/btrace.c9
-rw-r--r--gdb/build-id.c8
-rw-r--r--gdb/c-exp.y472
-rw-r--r--gdb/c-lang.c37
-rw-r--r--gdb/c-support.h10
-rw-r--r--gdb/c-typeprint.c13
-rw-r--r--gdb/charset.c5
-rw-r--r--gdb/cli/cli-cmds.c70
-rw-r--r--gdb/cli/cli-decode.c9
-rw-r--r--gdb/cli/cli-dump.c5
-rw-r--r--gdb/cli/cli-interp.c4
-rw-r--r--gdb/cli/cli-logging.c4
-rw-r--r--gdb/cli/cli-option.c4
-rw-r--r--gdb/cli/cli-script.c11
-rw-r--r--gdb/cli/cli-setshow.c3
-rw-r--r--gdb/cli/cli-style.c112
-rw-r--r--gdb/cli/cli-style.h14
-rw-r--r--gdb/cli/cli-utils.c27
-rw-r--r--gdb/coff-pe-read.c7
-rw-r--r--gdb/coffread.c35
-rw-r--r--gdb/compile/compile-c-support.c8
-rw-r--r--gdb/compile/compile-c-symbols.c6
-rw-r--r--gdb/compile/compile-cplus-symbols.c4
-rw-r--r--gdb/compile/compile-cplus-types.c4
-rw-r--r--gdb/compile/compile.c5
-rw-r--r--gdb/complaints.c4
-rw-r--r--gdb/completer.c12
-rw-r--r--gdb/config.in15
-rwxr-xr-xgdb/configure427
-rw-r--r--gdb/configure.ac141
-rw-r--r--gdb/configure.tgt86
-rw-r--r--gdb/contrib/ari/create-web-ari-in-src.sh2
-rwxr-xr-xgdb/contrib/ari/gdb_ari.sh4
-rw-r--r--gdb/contrib/ari/update-web-ari.sh6
-rw-r--r--gdb/contrib/codespell-dictionary.txt1
-rw-r--r--gdb/contrib/codespell-ignore-words.txt1
-rw-r--r--gdb/contrib/setup.cfg1
-rw-r--r--gdb/copying.c4
-rwxr-xr-xgdb/copyright.py11
-rw-r--r--gdb/corefile.c4
-rw-r--r--gdb/corelow.c75
-rw-r--r--gdb/cp-abi.c4
-rw-r--r--gdb/cp-name-parser.y45
-rw-r--r--gdb/cp-namespace.c4
-rw-r--r--gdb/cp-support.c67
-rw-r--r--gdb/cp-support.h4
-rw-r--r--gdb/cp-valprint.c4
-rw-r--r--gdb/cris-linux-tdep.c9
-rw-r--r--gdb/cris-tdep.c6
-rw-r--r--gdb/csky-linux-tdep.c8
-rw-r--r--gdb/csky-tdep.c4
-rw-r--r--gdb/ctfread.c46
-rw-r--r--gdb/d-exp.y34
-rw-r--r--gdb/darwin-nat-info.c4
-rw-r--r--gdb/darwin-nat.c7
-rw-r--r--gdb/dbxread.c4
-rw-r--r--gdb/dcache.c4
-rw-r--r--gdb/debuginfod-support.c5
-rw-r--r--gdb/defs.h8
-rw-r--r--gdb/dicos-tdep.c2
-rw-r--r--gdb/dictionary.c30
-rw-r--r--gdb/disasm-selftests.c4
-rw-r--r--gdb/disasm.c5
-rw-r--r--gdb/displaced-stepping.c4
-rw-r--r--gdb/doc/gdb.texinfo633
-rw-r--r--gdb/doc/guile.texi19
-rw-r--r--gdb/doc/python.texi148
-rw-r--r--gdb/dtrace-probe.c4
-rw-r--r--gdb/dummy-frame.c4
-rw-r--r--gdb/dwarf2/abbrev.c9
-rw-r--r--gdb/dwarf2/abbrev.h8
-rw-r--r--gdb/dwarf2/ada-imported.c2
-rw-r--r--gdb/dwarf2/attribute.c16
-rw-r--r--gdb/dwarf2/attribute.h19
-rw-r--r--gdb/dwarf2/call-site.h2
-rw-r--r--gdb/dwarf2/cooked-index-entry.c14
-rw-r--r--gdb/dwarf2/cooked-index-shard.c18
-rw-r--r--gdb/dwarf2/cooked-index-shard.h7
-rw-r--r--gdb/dwarf2/cooked-index-worker.c2
-rw-r--r--gdb/dwarf2/cooked-index-worker.h45
-rw-r--r--gdb/dwarf2/cooked-index.c7
-rw-r--r--gdb/dwarf2/cooked-index.h10
-rw-r--r--gdb/dwarf2/cooked-indexer.c79
-rw-r--r--gdb/dwarf2/cooked-indexer.h4
-rw-r--r--gdb/dwarf2/cu.h7
-rw-r--r--gdb/dwarf2/dwz.c60
-rw-r--r--gdb/dwarf2/frame-tailcall.c4
-rw-r--r--gdb/dwarf2/frame.c4
-rw-r--r--gdb/dwarf2/frame.h61
-rw-r--r--gdb/dwarf2/index-cache.c4
-rw-r--r--gdb/dwarf2/index-common.c10
-rw-r--r--gdb/dwarf2/index-write.c246
-rw-r--r--gdb/dwarf2/line-program.c720
-rw-r--r--gdb/dwarf2/line-program.h47
-rw-r--r--gdb/dwarf2/loc.c49
-rw-r--r--gdb/dwarf2/loc.h111
-rw-r--r--gdb/dwarf2/public.h25
-rw-r--r--gdb/dwarf2/read-debug-names.c178
-rw-r--r--gdb/dwarf2/read-gdb-index.c1349
-rw-r--r--gdb/dwarf2/read-gdb-index.h14
-rw-r--r--gdb/dwarf2/read.c2264
-rw-r--r--gdb/dwarf2/read.h194
-rw-r--r--gdb/dwarf2/section.h12
-rw-r--r--gdb/dwarf2/stringify.c6
-rw-r--r--gdb/dwarf2/tag.h12
-rw-r--r--gdb/elfread.c14
-rw-r--r--gdb/eval.c36
-rw-r--r--gdb/event-top.c7
-rw-r--r--gdb/exceptions.c3
-rw-r--r--gdb/exec.c55
-rw-r--r--gdb/expop.h10
-rw-r--r--gdb/expprint.c1
-rw-r--r--gdb/extension.c83
-rw-r--r--gdb/extract-store-integer.c4
-rw-r--r--gdb/f-exp.y10
-rw-r--r--gdb/f-lang.c4
-rw-r--r--gdb/f-typeprint.c11
-rw-r--r--gdb/f-valprint.c6
-rw-r--r--gdb/fbsd-nat.c8
-rw-r--r--gdb/fbsd-tdep.c83
-rw-r--r--gdb/features/Makefile5
-rw-r--r--gdb/features/aarch64-gcs-linux.c21
-rw-r--r--gdb/features/aarch64-gcs-linux.xml18
-rw-r--r--gdb/features/aarch64-gcs.c14
-rw-r--r--gdb/features/aarch64-gcs.xml11
-rw-r--r--gdb/features/alpha-core.xml136
-rw-r--r--gdb/features/alpha.c111
-rw-r--r--gdb/features/alpha.xml11
-rw-r--r--gdb/features/i386/32bit-ssp.c14
-rw-r--r--gdb/features/i386/32bit-ssp.xml11
-rw-r--r--gdb/features/i386/64bit-ssp.c14
-rw-r--r--gdb/features/i386/64bit-ssp.xml11
-rw-r--r--gdb/filesystem.c4
-rw-r--r--gdb/findcmd.c11
-rw-r--r--gdb/findvar.c16
-rw-r--r--gdb/fork-child.c4
-rw-r--r--gdb/frame-unwind.c16
-rw-r--r--gdb/frame.c38
-rw-r--r--gdb/frame.h3
-rw-r--r--gdb/frv-linux-tdep.c4
-rw-r--r--gdb/frv-tdep.c7
-rw-r--r--gdb/frv-tdep.h3
-rw-r--r--gdb/ft32-tdep.c4
-rw-r--r--gdb/gcore-1.in6
-rw-r--r--gdb/gcore.c18
-rw-r--r--gdb/gdb-demangle.c4
-rw-r--r--gdb/gdb-gdb.gdb.in3
-rw-r--r--gdb/gdb-gdb.py.in8
-rw-r--r--gdb/gdb-stabs.h4
-rw-r--r--gdb/gdb_bfd.c4
-rw-r--r--gdb/gdb_buildall.sh2
-rw-r--r--gdb/gdb_wchar.h4
-rw-r--r--gdb/gdbarch-gen.c154
-rw-r--r--gdb/gdbarch-gen.h90
-rw-r--r--gdb/gdbarch-selftests.c4
-rw-r--r--gdb/gdbarch.h7
-rw-r--r--gdb/gdbarch_components.py109
-rw-r--r--gdb/gdbtypes.c289
-rw-r--r--gdb/gdbtypes.h85
-rw-r--r--gdb/gmp-utils.c5
-rw-r--r--gdb/gnu-nat.c7
-rw-r--r--gdb/gnu-v2-abi.c17
-rw-r--r--gdb/gnu-v3-abi.c6
-rw-r--r--gdb/go-exp.y11
-rw-r--r--gdb/go-lang.c3
-rw-r--r--gdb/go32-nat.c5
-rw-r--r--gdb/guile/guile-internal.h9
-rw-r--r--gdb/guile/guile.c4
-rw-r--r--gdb/guile/scm-cmd.c84
-rw-r--r--gdb/guile/scm-color.c11
-rw-r--r--gdb/guile/scm-param.c41
-rw-r--r--gdb/guile/scm-symbol.c26
-rw-r--r--gdb/guile/scm-type.c2
-rw-r--r--gdb/h8300-tdep.c4
-rw-r--r--gdb/hppa-bsd-tdep.c13
-rw-r--r--gdb/hppa-linux-nat.c4
-rw-r--r--gdb/hppa-linux-tdep.c16
-rw-r--r--gdb/hppa-netbsd-nat.c4
-rw-r--r--gdb/hppa-netbsd-tdep.c4
-rw-r--r--gdb/hppa-obsd-nat.c4
-rw-r--r--gdb/hppa-obsd-tdep.c4
-rw-r--r--gdb/hppa-tdep.c12
-rw-r--r--gdb/i386-bsd-nat.c4
-rw-r--r--gdb/i386-darwin-nat.c4
-rw-r--r--gdb/i386-darwin-tdep.c6
-rw-r--r--gdb/i386-dicos-tdep.c4
-rw-r--r--gdb/i386-fbsd-nat.c4
-rw-r--r--gdb/i386-fbsd-tdep.c12
-rw-r--r--gdb/i386-fbsd-tdep.h5
-rw-r--r--gdb/i386-gnu-tdep.c7
-rw-r--r--gdb/i386-go32-tdep.c4
-rw-r--r--gdb/i386-linux-nat.c4
-rw-r--r--gdb/i386-linux-tdep.c13
-rw-r--r--gdb/i386-linux-tdep.h1
-rw-r--r--gdb/i386-netbsd-nat.c4
-rw-r--r--gdb/i386-netbsd-tdep.c7
-rw-r--r--gdb/i386-obsd-nat.c4
-rw-r--r--gdb/i386-obsd-tdep.c7
-rw-r--r--gdb/i386-sol2-nat.c4
-rw-r--r--gdb/i386-sol2-tdep.c7
-rw-r--r--gdb/i386-tdep.c316
-rw-r--r--gdb/i386-tdep.h96
-rw-r--r--gdb/i386-windows-nat.c4
-rw-r--r--gdb/i386-windows-tdep.c4
-rw-r--r--gdb/ia64-libunwind-tdep.c4
-rw-r--r--gdb/ia64-linux-nat.c4
-rw-r--r--gdb/ia64-linux-tdep.c13
-rw-r--r--gdb/ia64-tdep.c20
-rw-r--r--gdb/ia64-vms-tdep.c4
-rw-r--r--gdb/inf-child.c6
-rw-r--r--gdb/inf-child.h4
-rw-r--r--gdb/infcall.c30
-rw-r--r--gdb/infcmd.c35
-rw-r--r--gdb/inferior.c1
-rw-r--r--gdb/inferior.h11
-rw-r--r--gdb/inflow.c27
-rw-r--r--gdb/infrun.c52
-rw-r--r--gdb/inline-frame.c4
-rw-r--r--gdb/interps.c4
-rw-r--r--gdb/interps.h8
-rw-r--r--gdb/iq2000-tdep.c4
-rw-r--r--gdb/jit.c6
-rw-r--r--gdb/language.c7
-rw-r--r--gdb/linespec.c137
-rw-r--r--gdb/linux-fork.c7
-rw-r--r--gdb/linux-nat.c38
-rw-r--r--gdb/linux-nat.h15
-rw-r--r--gdb/linux-tdep.c309
-rw-r--r--gdb/linux-tdep.h22
-rw-r--r--gdb/linux-thread-db.c5
-rw-r--r--gdb/lm32-tdep.c4
-rw-r--r--gdb/location.c17
-rw-r--r--gdb/loongarch-linux-nat.c15
-rw-r--r--gdb/loongarch-linux-tdep.c12
-rw-r--r--gdb/loongarch-tdep.c382
-rw-r--r--gdb/m2-exp.y6
-rw-r--r--gdb/m32c-tdep.c4
-rw-r--r--gdb/m32r-linux-nat.c4
-rw-r--r--gdb/m32r-linux-tdep.c8
-rw-r--r--gdb/m32r-tdep.c4
-rw-r--r--gdb/m68hc11-tdep.c4
-rw-r--r--gdb/m68k-bsd-nat.c4
-rw-r--r--gdb/m68k-bsd-tdep.c7
-rw-r--r--gdb/m68k-linux-nat.c4
-rw-r--r--gdb/m68k-linux-tdep.c8
-rw-r--r--gdb/m68k-tdep.c4
-rw-r--r--gdb/machoread.c16
-rw-r--r--gdb/macrocmd.c41
-rw-r--r--gdb/macroscope.c45
-rw-r--r--gdb/macroscope.h20
-rw-r--r--gdb/main.c53
-rw-r--r--gdb/main.h3
-rw-r--r--gdb/maint-test-options.c4
-rw-r--r--gdb/maint-test-settings.c4
-rw-r--r--gdb/maint.c45
-rw-r--r--gdb/maint.h8
-rwxr-xr-xgdb/make-init-c25
-rw-r--r--gdb/mdebugread.c81
-rw-r--r--gdb/mdebugread.h33
-rw-r--r--gdb/memattr.c4
-rw-r--r--gdb/mep-tdep.c4
-rw-r--r--gdb/mi/mi-cmd-break.c3
-rw-r--r--gdb/mi/mi-cmd-env.c4
-rw-r--r--gdb/mi/mi-cmd-file.c5
-rw-r--r--gdb/mi/mi-cmd-stack.c4
-rw-r--r--gdb/mi/mi-cmd-var.c3
-rw-r--r--gdb/mi/mi-cmds.c4
-rw-r--r--gdb/mi/mi-interp.c12
-rw-r--r--gdb/mi/mi-main.c5
-rw-r--r--gdb/mi/mi-parse.c11
-rw-r--r--gdb/microblaze-linux-tdep.c8
-rw-r--r--gdb/microblaze-tdep.c98
-rw-r--r--gdb/microblaze-tdep.h2
-rw-r--r--gdb/mingw-hdep.c103
-rw-r--r--gdb/minsyms.c10
-rw-r--r--gdb/minsyms.h2
-rw-r--r--gdb/mips-fbsd-nat.c4
-rw-r--r--gdb/mips-fbsd-tdep.c67
-rw-r--r--gdb/mips-linux-nat.c4
-rw-r--r--gdb/mips-linux-tdep.c80
-rw-r--r--gdb/mips-netbsd-nat.c4
-rw-r--r--gdb/mips-netbsd-tdep.c64
-rw-r--r--gdb/mips-sde-tdep.c4
-rw-r--r--gdb/mips-tdep.c6
-rw-r--r--gdb/mips64-obsd-nat.c4
-rw-r--r--gdb/mips64-obsd-tdep.c7
-rw-r--r--gdb/mipsread.c16
-rw-r--r--gdb/mn10300-linux-tdep.c8
-rw-r--r--gdb/mn10300-tdep.c4
-rw-r--r--gdb/moxie-tdep.c6
-rw-r--r--gdb/msp430-tdep.c4
-rw-r--r--gdb/nat/aarch64-hw-point.c6
-rw-r--r--gdb/nat/linux-namespaces.c167
-rw-r--r--gdb/nat/linux-namespaces.h11
-rw-r--r--gdb/nat/linux-osdata.c15
-rw-r--r--gdb/nat/linux-procfs.c30
-rw-r--r--gdb/nat/linux-procfs.h14
-rw-r--r--gdb/nat/linux-ptrace.c4
-rw-r--r--gdb/nat/x86-gcc-cpuid.h153
-rw-r--r--gdb/nat/x86-linux-tdesc.c20
-rw-r--r--gdb/nat/x86-linux-tdesc.h7
-rw-r--r--gdb/nat/x86-linux.c59
-rw-r--r--gdb/nat/x86-linux.h4
-rw-r--r--gdb/nds32-tdep.c4
-rw-r--r--gdb/netbsd-nat.c2
-rw-r--r--gdb/objc-lang.c17
-rw-r--r--gdb/objfiles.c64
-rw-r--r--gdb/objfiles.h104
-rw-r--r--gdb/observable.c4
-rw-r--r--gdb/or1k-linux-nat.c4
-rw-r--r--gdb/or1k-linux-tdep.c10
-rw-r--r--gdb/or1k-tdep.c5
-rw-r--r--gdb/osabi.c4
-rw-r--r--gdb/osdata.c4
-rw-r--r--gdb/p-exp.y23
-rw-r--r--gdb/p-lang.c1
-rw-r--r--gdb/p-typeprint.c5
-rw-r--r--gdb/p-valprint.c4
-rw-r--r--gdb/pager.h16
-rw-r--r--gdb/parse.c5
-rw-r--r--gdb/ppc-fbsd-nat.c4
-rw-r--r--gdb/ppc-fbsd-tdep.c10
-rw-r--r--gdb/ppc-linux-nat.c4
-rw-r--r--gdb/ppc-linux-tdep.c78
-rw-r--r--gdb/ppc-netbsd-nat.c4
-rw-r--r--gdb/ppc-netbsd-tdep.c7
-rw-r--r--gdb/ppc-obsd-nat.c4
-rw-r--r--gdb/ppc-obsd-tdep.c7
-rw-r--r--gdb/ppc-sysv-tdep.c7
-rw-r--r--gdb/printcmd.c45
-rw-r--r--gdb/probe.c7
-rw-r--r--gdb/proc-api.c4
-rw-r--r--gdb/proc-events.c4
-rw-r--r--gdb/proc-service.c4
-rw-r--r--gdb/procfs.c23
-rw-r--r--gdb/producer.c8
-rw-r--r--gdb/progspace.c16
-rw-r--r--gdb/progspace.h51
-rw-r--r--gdb/psymtab.c45
-rw-r--r--gdb/psymtab.h18
-rw-r--r--gdb/python/lib/gdb/__init__.py153
-rw-r--r--gdb/python/lib/gdb/dap/breakpoint.py6
-rw-r--r--gdb/python/lib/gdb/dap/completions.py7
-rw-r--r--gdb/python/lib/gdb/dap/evaluate.py6
-rw-r--r--gdb/python/lib/gdb/dap/events.py6
-rw-r--r--gdb/python/lib/gdb/dap/next.py15
-rw-r--r--gdb/python/lib/gdb/dap/server.py90
-rw-r--r--gdb/python/lib/gdb/dap/sources.py6
-rw-r--r--gdb/python/lib/gdb/dap/threads.py23
-rw-r--r--gdb/python/lib/gdb/dap/varref.py10
-rw-r--r--gdb/python/lib/gdb/printing.py14
-rw-r--r--gdb/python/py-block.c3
-rw-r--r--gdb/python/py-breakpoint.c4
-rw-r--r--gdb/python/py-cmd.c108
-rw-r--r--gdb/python/py-color.c9
-rw-r--r--gdb/python/py-connection.c4
-rw-r--r--gdb/python/py-dap.c4
-rw-r--r--gdb/python/py-disasm.c85
-rw-r--r--gdb/python/py-finishbreakpoint.c6
-rw-r--r--gdb/python/py-framefilter.c2
-rw-r--r--gdb/python/py-gdb-readline.c4
-rw-r--r--gdb/python/py-infevents.c2
-rw-r--r--gdb/python/py-infthread.c33
-rw-r--r--gdb/python/py-mi.c6
-rw-r--r--gdb/python/py-micmd.c8
-rw-r--r--gdb/python/py-objfile.c12
-rw-r--r--gdb/python/py-param.c18
-rw-r--r--gdb/python/py-record.c3
-rw-r--r--gdb/python/py-symbol.c44
-rw-r--r--gdb/python/py-type.c17
-rw-r--r--gdb/python/py-unwind.c6
-rw-r--r--gdb/python/py-value.c82
-rw-r--r--gdb/python/python-internal.h23
-rw-r--r--gdb/python/python.c78
-rw-r--r--gdb/quick-symbol.h66
-rw-r--r--gdb/ravenscar-thread.c6
-rw-r--r--gdb/record-btrace.c33
-rw-r--r--gdb/record-full.c75
-rw-r--r--gdb/record.c13
-rw-r--r--gdb/regcache-dump.c4
-rw-r--r--gdb/regcache.c11
-rw-r--r--gdb/reggroups.c4
-rw-r--r--gdb/remote-notif.c4
-rw-r--r--gdb/remote-sim.c5
-rw-r--r--gdb/remote.c133
-rw-r--r--gdb/reverse.c4
-rw-r--r--gdb/riscv-fbsd-nat.c4
-rw-r--r--gdb/riscv-fbsd-tdep.c13
-rw-r--r--gdb/riscv-linux-nat.c4
-rw-r--r--gdb/riscv-linux-tdep.c14
-rw-r--r--gdb/riscv-none-tdep.c4
-rw-r--r--gdb/riscv-tdep.c84
-rw-r--r--gdb/rl78-tdep.c4
-rw-r--r--gdb/rs6000-aix-nat.c4
-rw-r--r--gdb/rs6000-aix-tdep.c15
-rw-r--r--gdb/rs6000-lynx178-tdep.c4
-rw-r--r--gdb/rs6000-tdep.c6
-rw-r--r--gdb/run-on-main-thread.c5
-rw-r--r--gdb/rust-exp.h36
-rw-r--r--gdb/rust-lang.c52
-rw-r--r--gdb/rust-parse.c10
-rw-r--r--gdb/rx-tdep.c4
-rw-r--r--gdb/s12z-tdep.c6
-rw-r--r--gdb/s390-linux-nat.c4
-rw-r--r--gdb/s390-linux-tdep.c11
-rw-r--r--gdb/s390-tdep.c10
-rw-r--r--gdb/ser-go32.c4
-rw-r--r--gdb/ser-mingw.c4
-rw-r--r--gdb/ser-pipe.c4
-rw-r--r--gdb/ser-tcp.c4
-rw-r--r--gdb/ser-uds.c4
-rw-r--r--gdb/ser-unix.c164
-rw-r--r--gdb/serial.c7
-rw-r--r--gdb/sh-linux-tdep.c8
-rw-r--r--gdb/sh-netbsd-nat.c4
-rw-r--r--gdb/sh-netbsd-tdep.c7
-rw-r--r--gdb/sh-tdep.c4
-rw-r--r--gdb/skip.c4
-rw-r--r--gdb/sol-thread.c18
-rw-r--r--gdb/solib-aix.c100
-rw-r--r--gdb/solib-aix.h7
-rw-r--r--gdb/solib-darwin.c94
-rw-r--r--gdb/solib-darwin.h6
-rw-r--r--gdb/solib-dsbt.c90
-rw-r--r--gdb/solib-dsbt.h6
-rw-r--r--gdb/solib-frv.c90
-rw-r--r--gdb/solib-frv.h28
-rw-r--r--gdb/solib-rocm.c190
-rw-r--r--gdb/solib-svr4-linux.c98
-rw-r--r--gdb/solib-svr4-linux.h51
-rw-r--r--gdb/solib-svr4.c807
-rw-r--r--gdb/solib-svr4.h150
-rw-r--r--gdb/solib-target.c64
-rw-r--r--gdb/solib-target.h18
-rw-r--r--gdb/solib.c417
-rw-r--r--gdb/solib.h283
-rw-r--r--gdb/solist.h225
-rw-r--r--gdb/source-cache.c4
-rw-r--r--gdb/source.c32
-rw-r--r--gdb/sparc-linux-nat.c4
-rw-r--r--gdb/sparc-linux-tdep.c8
-rw-r--r--gdb/sparc-nat.c4
-rw-r--r--gdb/sparc-netbsd-nat.c4
-rw-r--r--gdb/sparc-netbsd-tdep.c7
-rw-r--r--gdb/sparc-obsd-tdep.c4
-rw-r--r--gdb/sparc-sol2-tdep.c9
-rw-r--r--gdb/sparc-tdep.c6
-rw-r--r--gdb/sparc64-fbsd-nat.c4
-rw-r--r--gdb/sparc64-fbsd-tdep.c7
-rw-r--r--gdb/sparc64-linux-nat.c4
-rw-r--r--gdb/sparc64-linux-tdep.c8
-rw-r--r--gdb/sparc64-nat.c4
-rw-r--r--gdb/sparc64-netbsd-nat.c4
-rw-r--r--gdb/sparc64-netbsd-tdep.c7
-rw-r--r--gdb/sparc64-obsd-nat.c4
-rw-r--r--gdb/sparc64-obsd-tdep.c7
-rw-r--r--gdb/sparc64-sol2-tdep.c9
-rw-r--r--gdb/sparc64-tdep.c4
-rw-r--r--gdb/stabsread.c102
-rw-r--r--gdb/stack.c52
-rw-r--r--gdb/stap-probe.c27
-rw-r--r--gdb/std-regs.c4
-rw-r--r--gdb/svr4-tls-tdep.c6
-rw-r--r--gdb/symfile-debug.c94
-rw-r--r--gdb/symfile-mem.c4
-rw-r--r--gdb/symfile.c116
-rw-r--r--gdb/symfile.h9
-rw-r--r--gdb/symmisc.c12
-rw-r--r--gdb/symtab.c373
-rw-r--r--gdb/symtab.h47
-rwxr-xr-xgdb/syscalls/riscv-canonicalize-syscall-gen.py2
-rw-r--r--gdb/target-connection.c5
-rw-r--r--gdb/target-dcache.c4
-rw-r--r--gdb/target-descriptions.c4
-rw-r--r--gdb/target.c18
-rw-r--r--gdb/target.h8
-rw-r--r--gdb/terminal.h15
-rw-r--r--gdb/testsuite/Makefile.in12
-rw-r--r--gdb/testsuite/gdb.ada/array_long_idx.exp36
-rw-r--r--gdb/testsuite/gdb.ada/array_long_idx/main.adb31
-rw-r--r--gdb/testsuite/gdb.ada/array_long_idx/pck.adb21
-rw-r--r--gdb/testsuite/gdb.ada/array_long_idx/pck.ads19
-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/exec_changed.exp2
-rw-r--r--gdb/testsuite/gdb.ada/file-then-restart.exp2
-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/import.exp28
-rw-r--r--gdb/testsuite/gdb.ada/mi_catch_assert.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_catch_ex.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_dyn_arr.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_ex_cond.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_exc_info.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_interface.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_prot.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_ref_changeable.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_string_access.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_task_arg.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_task_info.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_var_access.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_var_array.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_var_union.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_variant.exp2
-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/operator_call.exp6
-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/return-small-char-array.exp40
-rw-r--r--gdb/testsuite/gdb.ada/return-small-char-array/proc.adb22
-rw-r--r--gdb/testsuite/gdb.ada/return-small-char-array/value.adb21
-rw-r--r--gdb/testsuite/gdb.ada/return-small-char-array/value.ads20
-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.ada/var_arr_typedef/pack.adb2
-rw-r--r--gdb/testsuite/gdb.ada/var_arr_typedef/pack.ads4
-rw-r--r--gdb/testsuite/gdb.ada/var_arr_typedef/var_arr_typedef.adb2
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-frameptr-vecreg-unwind.c62
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-frameptr-vecreg-unwind.exp33
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-gcs-core.c123
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-gcs-core.exp116
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.c140
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.exp86
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-gcs-return.c105
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-gcs-return.exp132
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-gcs-tdesc-without-linux.xml65
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.c26
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.exp48
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-gcs.c180
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-gcs.exp99
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-mte-core.exp6
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp2
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl6
-rw-r--r--gdb/testsuite/gdb.arch/alpha-step.exp3
-rw-r--r--gdb/testsuite/gdb.arch/altivec-abi.exp3
-rw-r--r--gdb/testsuite/gdb.arch/amd64-byte.exp2
-rw-r--r--gdb/testsuite/gdb.arch/amd64-disp-step-avx.exp1
-rw-r--r--gdb/testsuite/gdb.arch/amd64-disp-step-self-call-alarm.c18
-rw-r--r--gdb/testsuite/gdb.arch/amd64-disp-step-self-call.S23
-rw-r--r--gdb/testsuite/gdb.arch/amd64-dword.exp2
-rw-r--r--gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis-no-cfi.S117
-rw-r--r--gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis-offset.S112
-rw-r--r--gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.S143
-rw-r--r--gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.c56
-rw-r--r--gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.exp208
-rw-r--r--gdb/testsuite/gdb.arch/amd64-frameptr-vecreg-unwind.c63
-rw-r--r--gdb/testsuite/gdb.arch/amd64-frameptr-vecreg-unwind.exp40
-rw-r--r--gdb/testsuite/gdb.arch/amd64-init-x87-values.exp6
-rw-r--r--gdb/testsuite/gdb.arch/amd64-invalid-stack-middle.exp4
-rw-r--r--gdb/testsuite/gdb.arch/amd64-invalid-stack-top.exp4
-rw-r--r--gdb/testsuite/gdb.arch/amd64-prologue-skip.exp5
-rw-r--r--gdb/testsuite/gdb.arch/amd64-prologue-xmm.exp2
-rw-r--r--gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp2
-rw-r--r--gdb/testsuite/gdb.arch/amd64-shadow-stack-cmds.exp143
-rw-r--r--gdb/testsuite/gdb.arch/amd64-shadow-stack-corefile.c46
-rw-r--r--gdb/testsuite/gdb.arch/amd64-shadow-stack-corefile.exp119
-rw-r--r--gdb/testsuite/gdb.arch/amd64-shadow-stack-disp-step.exp84
-rw-r--r--gdb/testsuite/gdb.arch/amd64-shadow-stack.c40
-rw-r--r--gdb/testsuite/gdb.arch/amd64-shadow-stack.exp71
-rw-r--r--gdb/testsuite/gdb.arch/amd64-watchpoint-downgrade.exp2
-rw-r--r--gdb/testsuite/gdb.arch/amd64-word.exp2
-rw-r--r--gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp2
-rw-r--r--gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp2
-rw-r--r--gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp2
-rw-r--r--gdb/testsuite/gdb.arch/e500-prologue.exp3
-rw-r--r--gdb/testsuite/gdb.arch/e500-regs.exp3
-rw-r--r--gdb/testsuite/gdb.arch/gdb1291.exp3
-rw-r--r--gdb/testsuite/gdb.arch/gdb1431.exp3
-rw-r--r--gdb/testsuite/gdb.arch/gdb1558.exp3
-rw-r--r--gdb/testsuite/gdb.arch/i386-avx.exp4
-rw-r--r--gdb/testsuite/gdb.arch/i386-bp_permanent.exp2
-rw-r--r--gdb/testsuite/gdb.arch/i386-byte.exp2
-rw-r--r--gdb/testsuite/gdb.arch/i386-disp-step-self-call-alarm.c18
-rw-r--r--gdb/testsuite/gdb.arch/i386-disp-step-self-call.S23
-rw-r--r--gdb/testsuite/gdb.arch/i386-dr3-watch.exp2
-rw-r--r--gdb/testsuite/gdb.arch/i386-gnu-cfi.exp2
-rw-r--r--gdb/testsuite/gdb.arch/i386-permbkpt.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.arch/i386-prologue.exp2
-rw-r--r--gdb/testsuite/gdb.arch/i386-signal.exp2
-rw-r--r--gdb/testsuite/gdb.arch/i386-size-overlap.exp2
-rw-r--r--gdb/testsuite/gdb.arch/i386-size.exp2
-rw-r--r--gdb/testsuite/gdb.arch/i386-sse.exp2
-rw-r--r--gdb/testsuite/gdb.arch/i386-unwind.exp2
-rw-r--r--gdb/testsuite/gdb.arch/i386-word.exp2
-rw-r--r--gdb/testsuite/gdb.arch/ia64-breakpoint-shadow.exp3
-rw-r--r--gdb/testsuite/gdb.arch/mips-fpregset-core.exp6
-rw-r--r--gdb/testsuite/gdb.arch/mips-octeon-bbit.exp3
-rw-r--r--gdb/testsuite/gdb.arch/pa-nullify.exp3
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp3
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-altivec.exp3
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-altivec2.exp3
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-altivec3.exp3
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-d128-regs.exp2
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp2
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-htm-regs.exp5
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-power10.exp3
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-power7.exp3
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-power8.exp3
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-power9.exp3
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-ppr-dscr.exp4
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-prologue-frame.exp2
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-prologue.exp2
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-tar.exp4
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-vector-regs.exp4
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp2
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-vsx.exp3
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-vsx2.exp3
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-vsx3.exp3
-rw-r--r--gdb/testsuite/gdb.arch/ppc-dfp.exp2
-rw-r--r--gdb/testsuite/gdb.arch/ppc-fp.exp2
-rw-r--r--gdb/testsuite/gdb.arch/ppc-longdouble.exp2
-rw-r--r--gdb/testsuite/gdb.arch/pr25124.exp2
-rw-r--r--gdb/testsuite/gdb.arch/sparc-sysstep.exp2
-rw-r--r--gdb/testsuite/gdb.arch/thumb-prologue.exp2
-rw-r--r--gdb/testsuite/gdb.arch/thumb2-it.exp2
-rw-r--r--gdb/testsuite/gdb.arch/vsx-regs.exp3
-rw-r--r--gdb/testsuite/gdb.base/a2-run.exp7
-rw-r--r--gdb/testsuite/gdb.base/access-mem-running.exp3
-rw-r--r--gdb/testsuite/gdb.base/annota1.exp3
-rw-r--r--gdb/testsuite/gdb.base/annotate-symlink.exp2
-rw-r--r--gdb/testsuite/gdb.base/args.exp195
-rw-r--r--gdb/testsuite/gdb.base/arrayidx.exp3
-rw-r--r--gdb/testsuite/gdb.base/assign.exp3
-rw-r--r--gdb/testsuite/gdb.base/attach-deleted-exec.exp44
-rw-r--r--gdb/testsuite/gdb.base/attach-fail-twice.exp3
-rw-r--r--gdb/testsuite/gdb.base/attach-non-pgrp-leader.exp6
-rw-r--r--gdb/testsuite/gdb.base/attach-wait-input.exp3
-rw-r--r--gdb/testsuite/gdb.base/attach.c4
-rw-r--r--gdb/testsuite/gdb.base/attach.exp9
-rw-r--r--gdb/testsuite/gdb.base/auxv.exp3
-rw-r--r--gdb/testsuite/gdb.base/backtrace-through-cu-nodebug.exp72
-rw-r--r--gdb/testsuite/gdb.base/backtrace.exp6
-rw-r--r--gdb/testsuite/gdb.base/basic-edit-cmd.exp3
-rw-r--r--gdb/testsuite/gdb.base/bfp-test.exp3
-rw-r--r--gdb/testsuite/gdb.base/bg-exec-sigint-bp-cond.exp3
-rw-r--r--gdb/testsuite/gdb.base/bg-execution-repeat.exp3
-rw-r--r--gdb/testsuite/gdb.base/bigcore.exp3
-rw-r--r--gdb/testsuite/gdb.base/bitfields2.exp3
-rw-r--r--gdb/testsuite/gdb.base/bp-cmds-continue-ctrl-c.exp6
-rw-r--r--gdb/testsuite/gdb.base/bp-cond-failure.exp9
-rw-r--r--gdb/testsuite/gdb.base/bp-disabled-by-cond.exp3
-rw-r--r--gdb/testsuite/gdb.base/bp-permanent.c2
-rw-r--r--gdb/testsuite/gdb.base/bp-permanent.exp7
-rw-r--r--gdb/testsuite/gdb.base/break-dbg.cc31
-rw-r--r--gdb/testsuite/gdb.base/break-dbg.exp80
-rw-r--r--gdb/testsuite/gdb.base/break-fun-addr.exp3
-rw-r--r--gdb/testsuite/gdb.base/break-idempotent.exp2
-rw-r--r--gdb/testsuite/gdb.base/break-interp.exp4
-rw-r--r--gdb/testsuite/gdb.base/bt-on-fatal-signal.exp3
-rw-r--r--gdb/testsuite/gdb.base/bt-selected-frame.exp3
-rw-r--r--gdb/testsuite/gdb.base/call-rt-st.exp3
-rw-r--r--gdb/testsuite/gdb.base/call-sc.exp2
-rw-r--r--gdb/testsuite/gdb.base/call-signal-resume.exp3
-rw-r--r--gdb/testsuite/gdb.base/callexit.exp3
-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/catch-syscall.exp12
-rw-r--r--gdb/testsuite/gdb.base/checkpoint.exp6
-rw-r--r--gdb/testsuite/gdb.base/chng-syms.exp3
-rw-r--r--gdb/testsuite/gdb.base/clear_non_user_bp.exp3
-rw-r--r--gdb/testsuite/gdb.base/cli-suppress-notification.exp2
-rw-r--r--gdb/testsuite/gdb.base/code-expr.exp3
-rw-r--r--gdb/testsuite/gdb.base/color-prompt.exp29
-rw-r--r--gdb/testsuite/gdb.base/command-line-input.exp60
-rw-r--r--gdb/testsuite/gdb.base/cond-expr.exp3
-rw-r--r--gdb/testsuite/gdb.base/condbreak-bad.exp2
-rw-r--r--gdb/testsuite/gdb.base/condbreak-multi-context.exp15
-rw-r--r--gdb/testsuite/gdb.base/constvars.exp3
-rw-r--r--gdb/testsuite/gdb.base/continue-after-aborted-step-over.exp3
-rw-r--r--gdb/testsuite/gdb.base/coredump-filter-build-id.exp2
-rw-r--r--gdb/testsuite/gdb.base/corefile-exec-context.exp9
-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.exp230
-rw-r--r--gdb/testsuite/gdb.base/corefile.exp13
-rw-r--r--gdb/testsuite/gdb.base/corefile2.exp7
-rw-r--r--gdb/testsuite/gdb.base/corefile3.exp4
-rw-r--r--gdb/testsuite/gdb.base/cvexpr.exp2
-rw-r--r--gdb/testsuite/gdb.base/default-args.exp3
-rw-r--r--gdb/testsuite/gdb.base/default.exp264
-rw-r--r--gdb/testsuite/gdb.base/detach-sysroot-target.exp2
-rw-r--r--gdb/testsuite/gdb.base/detach-while-running.exp3
-rw-r--r--gdb/testsuite/gdb.base/detach.exp3
-rw-r--r--gdb/testsuite/gdb.base/dfp-test.exp3
-rw-r--r--gdb/testsuite/gdb.base/display.exp3
-rw-r--r--gdb/testsuite/gdb.base/dlmopen-ns-ids.exp193
-rw-r--r--gdb/testsuite/gdb.base/dlmopen.exp50
-rw-r--r--gdb/testsuite/gdb.base/dprintf-bp-same-addr.exp3
-rw-r--r--gdb/testsuite/gdb.base/dprintf-detach.exp6
-rw-r--r--gdb/testsuite/gdb.base/dprintf-execution-x-script.exp3
-rw-r--r--gdb/testsuite/gdb.base/dprintf-pending.exp3
-rw-r--r--gdb/testsuite/gdb.base/dprintf.exp3
-rw-r--r--gdb/testsuite/gdb.base/dso2dso.exp3
-rw-r--r--gdb/testsuite/gdb.base/dtrace-probe.exp7
-rw-r--r--gdb/testsuite/gdb.base/dump.c2
-rw-r--r--gdb/testsuite/gdb.base/dump.exp12
-rw-r--r--gdb/testsuite/gdb.base/duplicate-bp.exp3
-rw-r--r--gdb/testsuite/gdb.base/eh_return.exp3
-rw-r--r--gdb/testsuite/gdb.base/errno.exp6
-rw-r--r--gdb/testsuite/gdb.base/eval-skip.exp3
-rw-r--r--gdb/testsuite/gdb.base/exe-lock.exp3
-rw-r--r--gdb/testsuite/gdb.base/exec-invalid-sysroot.exp3
-rw-r--r--gdb/testsuite/gdb.base/execl-update-breakpoints.exp9
-rw-r--r--gdb/testsuite/gdb.base/exprs.exp8
-rw-r--r--gdb/testsuite/gdb.base/fileio.c4
-rw-r--r--gdb/testsuite/gdb.base/fileio.exp5
-rw-r--r--gdb/testsuite/gdb.base/filename-completion.exp27
-rw-r--r--gdb/testsuite/gdb.base/find.exp3
-rw-r--r--gdb/testsuite/gdb.base/fixsection.exp3
-rw-r--r--gdb/testsuite/gdb.base/float128.exp3
-rw-r--r--gdb/testsuite/gdb.base/floatn.exp3
-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)96
-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.exp4
-rw-r--r--gdb/testsuite/gdb.base/fork-print-inferior-events.exp5
-rw-r--r--gdb/testsuite/gdb.base/fork-running-state.exp2
-rw-r--r--gdb/testsuite/gdb.base/frame-args.exp3
-rw-r--r--gdb/testsuite/gdb.base/frame-info-consistent.exp3
-rw-r--r--gdb/testsuite/gdb.base/frame-view.exp3
-rw-r--r--gdb/testsuite/gdb.base/fullname.exp11
-rw-r--r--gdb/testsuite/gdb.base/gcore-buffer-overflow.exp3
-rw-r--r--gdb/testsuite/gdb.base/gcore-memory-usage.exp25
-rw-r--r--gdb/testsuite/gdb.base/gcore-relro-pie.exp6
-rw-r--r--gdb/testsuite/gdb.base/gcore-relro.exp6
-rw-r--r--gdb/testsuite/gdb.base/gcore-tls-pie.exp6
-rw-r--r--gdb/testsuite/gdb.base/gcore.exp4
-rw-r--r--gdb/testsuite/gdb.base/gdb-index-err.exp6
-rw-r--r--gdb/testsuite/gdb.base/gdb1250.exp3
-rw-r--r--gdb/testsuite/gdb.base/gdb1555.exp3
-rw-r--r--gdb/testsuite/gdb.base/gdbindex-stabs.exp3
-rw-r--r--gdb/testsuite/gdb.base/global-var-nested-by-dso.exp3
-rw-r--r--gdb/testsuite/gdb.base/gnu-ifunc.exp11
-rw-r--r--gdb/testsuite/gdb.base/gnu_vector.exp3
-rw-r--r--gdb/testsuite/gdb.base/hashline1.exp3
-rw-r--r--gdb/testsuite/gdb.base/hashline2.exp3
-rw-r--r--gdb/testsuite/gdb.base/hashline3.exp3
-rw-r--r--gdb/testsuite/gdb.base/hbreak-in-shr-unsupported.exp3
-rw-r--r--gdb/testsuite/gdb.base/hook-stop.exp3
-rw-r--r--gdb/testsuite/gdb.base/huge.exp3
-rw-r--r--gdb/testsuite/gdb.base/infcall-exec.exp3
-rw-r--r--gdb/testsuite/gdb.base/infcall-failure-2.exp37
-rw-r--r--gdb/testsuite/gdb.base/infcall-failure.exp19
-rw-r--r--gdb/testsuite/gdb.base/infcall-nested-structs.exp.tcl5
-rw-r--r--gdb/testsuite/gdb.base/infcall-timeout.exp3
-rw-r--r--gdb/testsuite/gdb.base/inferior-args.exp35
-rw-r--r--gdb/testsuite/gdb.base/inferior-died.exp8
-rw-r--r--gdb/testsuite/gdb.base/info-proc.exp3
-rw-r--r--gdb/testsuite/gdb.base/info-program.exp3
-rw-r--r--gdb/testsuite/gdb.base/info-shared.exp3
-rw-r--r--gdb/testsuite/gdb.base/info-types.exp.tcl2
-rw-r--r--gdb/testsuite/gdb.base/info_sources_2.exp38
-rw-r--r--gdb/testsuite/gdb.base/inline-frame-cycle-unwind.py4
-rw-r--r--gdb/testsuite/gdb.base/internal-string-values.exp3
-rw-r--r--gdb/testsuite/gdb.base/interrupt-daemon-attach.exp6
-rw-r--r--gdb/testsuite/gdb.base/interrupt-daemon.exp5
-rw-r--r--gdb/testsuite/gdb.base/jit-bfd-name.exp3
-rw-r--r--gdb/testsuite/gdb.base/jit-elf-fork.exp4
-rw-r--r--gdb/testsuite/gdb.base/jit-elf-so.exp3
-rw-r--r--gdb/testsuite/gdb.base/jit-elf.exp6
-rw-r--r--gdb/testsuite/gdb.base/jit-reader-exec.exp3
-rw-r--r--gdb/testsuite/gdb.base/jit-reader-simple.exp9
-rw-r--r--gdb/testsuite/gdb.base/jit-reader.exp3
-rw-r--r--gdb/testsuite/gdb.base/kill-detach-inferiors-cmd.exp1
-rw-r--r--gdb/testsuite/gdb.base/kill-during-detach.exp3
-rw-r--r--gdb/testsuite/gdb.base/killed-outside.exp3
-rw-r--r--gdb/testsuite/gdb.base/langs.exp3
-rw-r--r--gdb/testsuite/gdb.base/large-frame.exp4
-rw-r--r--gdb/testsuite/gdb.base/lineinc.exp3
-rw-r--r--gdb/testsuite/gdb.base/list-missing-source.exp3
-rw-r--r--gdb/testsuite/gdb.base/list.exp9
-rw-r--r--gdb/testsuite/gdb.base/logical.exp3
-rw-r--r--gdb/testsuite/gdb.base/long_long.exp3
-rw-r--r--gdb/testsuite/gdb.base/longjmp.exp3
-rw-r--r--gdb/testsuite/gdb.base/macro-source-path.exp5
-rw-r--r--gdb/testsuite/gdb.base/macscp.exp3
-rw-r--r--gdb/testsuite/gdb.base/maint-info-inline-frames-and-blocks.exp3
-rw-r--r--gdb/testsuite/gdb.base/maint.exp39
-rw-r--r--gdb/testsuite/gdb.base/many-headers.exp1
-rw-r--r--gdb/testsuite/gdb.base/max-depth.exp.tcl4
-rw-r--r--gdb/testsuite/gdb.base/miscexprs.exp3
-rw-r--r--gdb/testsuite/gdb.base/msym-bp-shl.exp3
-rw-r--r--gdb/testsuite/gdb.base/multi-forks.exp15
-rw-r--r--gdb/testsuite/gdb.base/nodebug.exp3
-rw-r--r--gdb/testsuite/gdb.base/nofield.exp3
-rw-r--r--gdb/testsuite/gdb.base/nostdlib.exp3
-rw-r--r--gdb/testsuite/gdb.base/options.exp22
-rw-r--r--gdb/testsuite/gdb.base/paginate-after-ctrl-c-running.exp3
-rw-r--r--gdb/testsuite/gdb.base/paginate-bg-execution.exp3
-rw-r--r--gdb/testsuite/gdb.base/paginate-inferior-exit.exp3
-rw-r--r--gdb/testsuite/gdb.base/patch.exp6
-rw-r--r--gdb/testsuite/gdb.base/pc-not-saved.exp3
-rw-r--r--gdb/testsuite/gdb.base/pie-fork.exp5
-rw-r--r--gdb/testsuite/gdb.base/pointers.exp3
-rw-r--r--gdb/testsuite/gdb.base/pr11022.exp3
-rw-r--r--gdb/testsuite/gdb.base/print-symbol-loading.exp8
-rw-r--r--gdb/testsuite/gdb.base/prologue.exp3
-rw-r--r--gdb/testsuite/gdb.base/ptr-typedef.exp3
-rw-r--r--gdb/testsuite/gdb.base/quit-live.exp3
-rw-r--r--gdb/testsuite/gdb.base/random-signal.exp6
-rw-r--r--gdb/testsuite/gdb.base/readline-ask.exp5
-rw-r--r--gdb/testsuite/gdb.base/readline-commands-eof.exp3
-rw-r--r--gdb/testsuite/gdb.base/readline.exp2
-rw-r--r--gdb/testsuite/gdb.base/readnever.exp2
-rw-r--r--gdb/testsuite/gdb.base/relativedebug.exp3
-rw-r--r--gdb/testsuite/gdb.base/remote.exp3
-rw-r--r--gdb/testsuite/gdb.base/reread.exp3
-rw-r--r--gdb/testsuite/gdb.base/reset-catchpoint-cond.exp3
-rw-r--r--gdb/testsuite/gdb.base/restore.exp3
-rw-r--r--gdb/testsuite/gdb.base/return2.exp3
-rw-r--r--gdb/testsuite/gdb.base/rtld-step.exp3
-rw-r--r--gdb/testsuite/gdb.base/run-attach-while-running.exp3
-rw-r--r--gdb/testsuite/gdb.base/run-control-while-bg-execution.exp8
-rw-r--r--gdb/testsuite/gdb.base/run-fail-twice.exp3
-rw-r--r--gdb/testsuite/gdb.base/savedregs.exp3
-rw-r--r--gdb/testsuite/gdb.base/sep.exp6
-rw-r--r--gdb/testsuite/gdb.base/sepsymtab.exp3
-rw-r--r--gdb/testsuite/gdb.base/set-cwd.exp6
-rw-r--r--gdb/testsuite/gdb.base/set-inferior-tty.exp3
-rw-r--r--gdb/testsuite/gdb.base/setshow.exp6
-rw-r--r--gdb/testsuite/gdb.base/settings.exp3
-rw-r--r--gdb/testsuite/gdb.base/share-env-with-gdbserver.exp12
-rw-r--r--gdb/testsuite/gdb.base/shlib-call.exp6
-rw-r--r--gdb/testsuite/gdb.base/shlib-unload.exp12
-rw-r--r--gdb/testsuite/gdb.base/shreloc.exp3
-rw-r--r--gdb/testsuite/gdb.base/sigall.exp9
-rw-r--r--gdb/testsuite/gdb.base/sigaltstack.exp3
-rw-r--r--gdb/testsuite/gdb.base/sigchld.exp3
-rw-r--r--gdb/testsuite/gdb.base/siginfo-obj.exp3
-rw-r--r--gdb/testsuite/gdb.base/siginfo-thread.exp6
-rw-r--r--gdb/testsuite/gdb.base/signals-state-child.exp3
-rw-r--r--gdb/testsuite/gdb.base/signals.exp3
-rw-r--r--gdb/testsuite/gdb.base/signull.exp3
-rw-r--r--gdb/testsuite/gdb.base/sigrepeat.exp3
-rw-r--r--gdb/testsuite/gdb.base/sigstep.exp3
-rw-r--r--gdb/testsuite/gdb.base/skip.exp3
-rw-r--r--gdb/testsuite/gdb.base/so-impl-ld.exp3
-rw-r--r--gdb/testsuite/gdb.base/solib-abort.exp3
-rw-r--r--gdb/testsuite/gdb.base/solib-disc.exp3
-rw-r--r--gdb/testsuite/gdb.base/solib-search.exp2
-rw-r--r--gdb/testsuite/gdb.base/solib-symbol.exp3
-rw-r--r--gdb/testsuite/gdb.base/solib-weak.exp3
-rw-r--r--gdb/testsuite/gdb.base/source-dir.exp55
-rw-r--r--gdb/testsuite/gdb.base/source-search.c127
-rw-r--r--gdb/testsuite/gdb.base/source-search.exp106
-rw-r--r--gdb/testsuite/gdb.base/stack-checking.exp3
-rw-r--r--gdb/testsuite/gdb.base/startup-with-shell.exp161
-rw-r--r--gdb/testsuite/gdb.base/step-over-exit.exp7
-rw-r--r--gdb/testsuite/gdb.base/step-over-no-symbols.exp3
-rw-r--r--gdb/testsuite/gdb.base/step-sw-breakpoint-adjust-pc.exp3
-rw-r--r--gdb/testsuite/gdb.base/step-test.exp3
-rw-r--r--gdb/testsuite/gdb.base/structs.exp2
-rw-r--r--gdb/testsuite/gdb.base/structs2.exp2
-rw-r--r--gdb/testsuite/gdb.base/style.exp312
-rw-r--r--gdb/testsuite/gdb.base/sym-file.exp6
-rw-r--r--gdb/testsuite/gdb.base/symtab-search-order.exp3
-rw-r--r--gdb/testsuite/gdb.base/testenv.exp8
-rw-r--r--gdb/testsuite/gdb.base/tls-common.exp.tcl2
-rw-r--r--gdb/testsuite/gdb.base/tls-dlobj-lib.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-dlobj.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-dlobj.exp8
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj.exp8
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj1.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj2.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj3.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-nothreads.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-nothreads.exp11
-rw-r--r--gdb/testsuite/gdb.base/twice.exp3
-rw-r--r--gdb/testsuite/gdb.base/type-opaque.exp3
-rw-r--r--gdb/testsuite/gdb.base/unload.exp3
-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/varargs.exp3
-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/watch_thread_num.exp3
-rw-r--r--gdb/testsuite/gdb.base/watchpoint-hw-attach.exp24
-rw-r--r--gdb/testsuite/gdb.base/watchpoint-running.exp3
-rw-r--r--gdb/testsuite/gdb.base/watchpoint-solib.exp3
-rw-r--r--gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.exp3
-rw-r--r--gdb/testsuite/gdb.base/watchpoint-unaligned.c37
-rw-r--r--gdb/testsuite/gdb.base/watchpoint-unaligned.exp111
-rw-r--r--gdb/testsuite/gdb.base/watchpoints.exp3
-rw-r--r--gdb/testsuite/gdb.base/wchar.exp4
-rw-r--r--gdb/testsuite/gdb.base/with-mf.exp3
-rw-r--r--gdb/testsuite/gdb.base/with.exp9
-rw-r--r--gdb/testsuite/gdb.btrace/multi-inferior.exp2
-rw-r--r--gdb/testsuite/gdb.compile/compile-tls.exp2
-rw-r--r--gdb/testsuite/gdb.compile/compile.exp7
-rw-r--r--gdb/testsuite/gdb.cp/call-c.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/gdb2384.exp2
-rw-r--r--gdb/testsuite/gdb.cp/infcall-nodebug.exp.tcl4
-rw-r--r--gdb/testsuite/gdb.cp/method-ref-return.cc42
-rw-r--r--gdb/testsuite/gdb.cp/method-ref-return.exp70
-rw-r--r--gdb/testsuite/gdb.cp/pr10728.exp2
-rw-r--r--gdb/testsuite/gdb.cp/print-global-stub.exp7
-rw-r--r--gdb/testsuite/gdb.cp/psmang.exp2
-rw-r--r--gdb/testsuite/gdb.cp/ref-params.exp2
-rw-r--r--gdb/testsuite/gdb.cp/rvalue-ref-params.exp2
-rw-r--r--gdb/testsuite/gdb.cp/static-print-quit.exp23
-rw-r--r--gdb/testsuite/gdb.cp/templates.exp49
-rw-r--r--gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp4
-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/scopes.c2
-rw-r--r--gdb/testsuite/gdb.dap/scopes.exp44
-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.exp19
-rw-r--r--gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp6
-rw-r--r--gdb/testsuite/gdb.debuginfod/solib-with-soname.exp4
-rw-r--r--gdb/testsuite/gdb.disasm/am33.exp2
-rw-r--r--gdb/testsuite/gdb.disasm/hppa.exp2
-rw-r--r--gdb/testsuite/gdb.disasm/mn10300.exp2
-rw-r--r--gdb/testsuite/gdb.disasm/sh3.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/backward-spec-inter-cu.exp6
-rw-r--r--gdb/testsuite/gdb.dwarf2/debug-names-missing-cu.exp4
-rw-r--r--gdb/testsuite/gdb.dwarf2/debug-names-non-ascending-cu.exp81
-rw-r--r--gdb/testsuite/gdb.dwarf2/debug-names-tu.exp.tcl4
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw-form-ref-addr-with-type-units.exp109
-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-aranges.exp3
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-bad-elf.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-entry-points.c17
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-entry-points.exp7
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-is-stmt-2.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-is-stmt.exp8
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-linkage-name-trust.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-modula2-self-type.S6
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-multiple-debug-info.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-opt-structptr.exp4
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-prologue-end.exp2
-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/dw2-var-zero-addr.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-zero-range.exp3
-rw-r--r--gdb/testsuite/gdb.dwarf2/dynamic-bit-offset.exp95
-rw-r--r--gdb/testsuite/gdb.dwarf2/entry-value-typedef.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/fission-base.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/fission-dw-form-strx.exp88
-rw-r--r--gdb/testsuite/gdb.dwarf2/fission-loclists-pie.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/fission-loclists.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/fission-mix.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/fission-multi-cu.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/fission-reread.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp6
-rw-r--r--gdb/testsuite/gdb.dwarf2/frame-inlined-in-outer-frame.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/gdb-add-index-symlink.exp3
-rw-r--r--gdb/testsuite/gdb.dwarf2/gdb-add-index.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/gdb-index-tilde.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/gdb-index-types-dwarf5.exp6
-rw-r--r--gdb/testsuite/gdb.dwarf2/gdb-index.exp10
-rw-r--r--gdb/testsuite/gdb.dwarf2/imported-unit-runto-main.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/locexpr-data-member-location.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw4.exp4
-rw-r--r--gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw5.exp4
-rw-r--r--gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld234-dw5.exp4
-rw-r--r--gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw4.exp4
-rw-r--r--gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw5.exp4
-rw-r--r--gdb/testsuite/gdb.dwarf2/macro-source-path.exp.tcl4
-rw-r--r--gdb/testsuite/gdb.dwarf2/pr11465.S6
-rw-r--r--gdb/testsuite/gdb.dwarf2/varval.exp2
-rw-r--r--gdb/testsuite/gdb.fortran/array-slices.exp2
-rw-r--r--gdb/testsuite/gdb.fortran/call-no-debug.exp2
-rw-r--r--gdb/testsuite/gdb.fortran/huge.exp2
-rw-r--r--gdb/testsuite/gdb.fortran/mixed-lang-stack.exp4
-rw-r--r--gdb/testsuite/gdb.gdb/index-file.exp10
-rw-r--r--gdb/testsuite/gdb.gdb/python-helper.exp22
-rw-r--r--gdb/testsuite/gdb.gdb/selftest.exp2
-rw-r--r--gdb/testsuite/gdb.gdb/unittest.exp2
-rw-r--r--gdb/testsuite/gdb.guile/scm-cmd.exp59
-rw-r--r--gdb/testsuite/gdb.guile/scm-color.exp11
-rw-r--r--gdb/testsuite/gdb.guile/scm-frame.exp2
-rw-r--r--gdb/testsuite/gdb.guile/scm-parameter.exp275
-rw-r--r--gdb/testsuite/gdb.guile/scm-pretty-print.exp5
-rw-r--r--gdb/testsuite/gdb.guile/scm-symbol.exp2
-rw-r--r--gdb/testsuite/gdb.guile/scm-type.exp3
-rw-r--r--gdb/testsuite/gdb.guile/scm-value.exp5
-rw-r--r--gdb/testsuite/gdb.linespec/explicit.exp2
-rw-r--r--gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.exp2
-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/dw2-ref-missing-frame.exp4
-rw-r--r--gdb/testsuite/gdb.mi/gdb2549.exp2
-rw-r--r--gdb/testsuite/gdb.mi/gdb669.exp2
-rw-r--r--gdb/testsuite/gdb.mi/gdb701.exp2
-rw-r--r--gdb/testsuite/gdb.mi/gdb792.exp2
-rw-r--r--gdb/testsuite/gdb.mi/interrupt-thread-group.exp4
-rw-r--r--gdb/testsuite/gdb.mi/mi-add-inferior.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-async-run.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-async.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-break-qualified.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-break.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp6
-rw-r--r--gdb/testsuite/gdb.mi/mi-breakpoint-multiple-locations.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-breakpoint-script.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-catch-cpp-exceptions.exp4
-rw-r--r--gdb/testsuite/gdb.mi/mi-catch-load.exp4
-rw-r--r--gdb/testsuite/gdb.mi/mi-cli.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-cmd-param-changed.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-cmd-user-context.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-complete.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-condbreak-call-thr-state.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-condbreak-fail.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-condbreak-throw.exp4
-rw-r--r--gdb/testsuite/gdb.mi/mi-console.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-corefile.exp1
-rw-r--r--gdb/testsuite/gdb.mi/mi-detach.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-disassemble.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-dlmopen.exp16
-rw-r--r--gdb/testsuite/gdb.mi/mi-dprintf-modified.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-dprintf-pending.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-dprintf.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-eval.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-exec-run.exp5
-rw-r--r--gdb/testsuite/gdb.mi/mi-exit-code.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-fill-memory.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-fortran-modules.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-frame-regs.exp4
-rw-r--r--gdb/testsuite/gdb.mi/mi-fullname-deleted.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-info-os.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-info-sources.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-inheritance-syntax-error.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-linespec-err-cp.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-logging.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-memory-changed.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-multi-commands.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-nonstop-exit.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-nonstop.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-ns-stale-regcache.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-nsintrall.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-nsmoribund.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-nsthrexec.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-pending.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-pthreads.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-py-modify-bp.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-read-memory.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-record-changed.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-reg-undefined.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-regs.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-return.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-reverse.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-simplerun.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-solib.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-stack.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-start.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-stepi.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-stepn.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-sym-info.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-syn-frame.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-thread-bp-deleted.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-thread-specific-bp.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-threads-interrupt.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-until.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-block.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-child-f.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-child.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-cmd.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-cp.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-create-rtti.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-display.exp6
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-invalidate.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-list-children-invalid-grandchild.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-rtti.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-vla-c99.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-vla-fortran.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-watch-nonstop.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-watch.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi2-amd64-entry-value.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi2-cli-display.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi2-var-child.exp2
-rw-r--r--gdb/testsuite/gdb.mi/new-ui-mi-sync.exp2
-rw-r--r--gdb/testsuite/gdb.mi/pr11022.exp2
-rw-r--r--gdb/testsuite/gdb.mi/print-simple-values.exp2
-rw-r--r--gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp2
-rw-r--r--gdb/testsuite/gdb.mi/user-selected-context-sync.exp6
-rw-r--r--gdb/testsuite/gdb.multi/attach-no-multi-process.exp7
-rw-r--r--gdb/testsuite/gdb.multi/attach-while-running.exp5
-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/gdb-settings.exp2
-rw-r--r--gdb/testsuite/gdb.multi/inferior-specific-bp.exp8
-rw-r--r--gdb/testsuite/gdb.multi/interrupt-bg-exec.c47
-rw-r--r--gdb/testsuite/gdb.multi/interrupt-bg-exec.exp143
-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.exp4
-rw-r--r--gdb/testsuite/gdb.multi/multi-kill.exp4
-rw-r--r--gdb/testsuite/gdb.multi/multi-re-run.exp16
-rw-r--r--gdb/testsuite/gdb.multi/multi-target.exp.tcl18
-rw-r--r--gdb/testsuite/gdb.multi/multi-term-settings.exp4
-rw-r--r--gdb/testsuite/gdb.multi/pending-bp-del-inferior.exp2
-rw-r--r--gdb/testsuite/gdb.multi/pending-bp.exp8
-rw-r--r--gdb/testsuite/gdb.multi/remote-with-running-inferior.c38
-rw-r--r--gdb/testsuite/gdb.multi/remote-with-running-inferior.exp171
-rw-r--r--gdb/testsuite/gdb.multi/remove-inferiors.exp2
-rw-r--r--gdb/testsuite/gdb.multi/run-only-second-inf.exp2
-rw-r--r--gdb/testsuite/gdb.multi/sched-multi-add-inferior.exp109
-rw-r--r--gdb/testsuite/gdb.multi/start-inferior-specific.exp7
-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.exp4
-rw-r--r--gdb/testsuite/gdb.multi/watchpoint-multi.exp2
-rw-r--r--gdb/testsuite/gdb.objc/basicclass.exp2
-rw-r--r--gdb/testsuite/gdb.objc/nondebug.exp2
-rw-r--r--gdb/testsuite/gdb.objc/objcdecode.exp2
-rw-r--r--gdb/testsuite/gdb.objc/print.exp2
-rw-r--r--gdb/testsuite/gdb.opencl/callfuncs.exp7
-rw-r--r--gdb/testsuite/gdb.opt/break-on-_exit.exp2
-rw-r--r--gdb/testsuite/gdb.opt/inline-break.exp8
-rw-r--r--gdb/testsuite/gdb.opt/inline-cmds.exp2
-rw-r--r--gdb/testsuite/gdb.opt/inline-entry.exp4
-rw-r--r--gdb/testsuite/gdb.opt/inline-small-func.exp2
-rw-r--r--gdb/testsuite/gdb.opt/solib-intra-step.exp2
-rw-r--r--gdb/testsuite/gdb.pascal/floats.exp6
-rw-r--r--gdb/testsuite/gdb.pascal/gdb11492.exp4
-rw-r--r--gdb/testsuite/gdb.pascal/hello.exp2
-rw-r--r--gdb/testsuite/gdb.pascal/integers.exp6
-rw-r--r--gdb/testsuite/gdb.pascal/print.exp2
-rw-r--r--gdb/testsuite/gdb.pascal/types.exp2
-rw-r--r--gdb/testsuite/gdb.perf/backtrace.exp2
-rw-r--r--gdb/testsuite/gdb.perf/single-step.exp2
-rw-r--r--gdb/testsuite/gdb.perf/skip-command.exp2
-rw-r--r--gdb/testsuite/gdb.perf/skip-prologue.exp2
-rw-r--r--gdb/testsuite/gdb.perf/solib.exp2
-rw-r--r--gdb/testsuite/gdb.perf/template-breakpoints.exp2
-rw-r--r--gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-cmd.exp93
-rw-r--r--gdb/testsuite/gdb.python/py-color-pagination.exp137
-rw-r--r--gdb/testsuite/gdb.python/py-color-pagination.py46
-rw-r--r--gdb/testsuite/gdb.python/py-color.exp13
-rw-r--r--gdb/testsuite/gdb.python/py-disasm.exp.tcl10
-rw-r--r--gdb/testsuite/gdb.python/py-exec-file.exp8
-rw-r--r--gdb/testsuite/gdb.python/py-format-address.exp8
-rw-r--r--gdb/testsuite/gdb.python/py-format-string.exp7
-rw-r--r--gdb/testsuite/gdb.python/py-framefilter-mi.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-mi-objfile.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-mi.exp4
-rw-r--r--gdb/testsuite/gdb.python/py-missing-objfile.exp2
-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.exp195
-rw-r--r--gdb/testsuite/gdb.python/py-prettyprint.exp5
-rw-r--r--gdb/testsuite/gdb.python/py-source-styling-2.exp24
-rw-r--r--gdb/testsuite/gdb.python/py-source-styling.exp6
-rw-r--r--gdb/testsuite/gdb.python/py-startup-opt.exp1
-rw-r--r--gdb/testsuite/gdb.python/py-styled-execute.exp1
-rw-r--r--gdb/testsuite/gdb.python/py-symbol.exp11
-rw-r--r--gdb/testsuite/gdb.python/py-thrhandle.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-type.exp3
-rw-r--r--gdb/testsuite/gdb.python/py-value.c9
-rw-r--r--gdb/testsuite/gdb.python/py-value.exp53
-rw-r--r--gdb/testsuite/gdb.python/py-varobj.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-warning.exp63
-rw-r--r--gdb/testsuite/gdb.python/python.exp16
-rw-r--r--gdb/testsuite/gdb.replay/connect.exp8
-rw-r--r--gdb/testsuite/gdb.reverse/i386-avx-reverse.c359
-rw-r--r--gdb/testsuite/gdb.reverse/i386-avx-reverse.exp571
-rw-r--r--gdb/testsuite/gdb.reverse/sigall-precsave.exp2
-rw-r--r--gdb/testsuite/gdb.reverse/sigall-reverse.exp2
-rw-r--r--gdb/testsuite/gdb.reverse/solib-precsave.exp4
-rw-r--r--gdb/testsuite/gdb.reverse/solib-reverse.exp4
-rw-r--r--gdb/testsuite/gdb.reverse/step-precsave.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.exp69
-rw-r--r--gdb/testsuite/gdb.rocm/displaced-stepping.exp3
-rw-r--r--gdb/testsuite/gdb.rocm/fork-exec-gpu-to-non-gpu.exp4
-rw-r--r--gdb/testsuite/gdb.rocm/fork-exec-non-gpu-to-gpu.exp4
-rw-r--r--gdb/testsuite/gdb.rocm/mi-attach.cpp4
-rw-r--r--gdb/testsuite/gdb.rocm/mi-attach.exp3
-rw-r--r--gdb/testsuite/gdb.rocm/multi-inferior-gpu.exp3
-rw-r--r--gdb/testsuite/gdb.rocm/precise-memory-exec.exp3
-rw-r--r--gdb/testsuite/gdb.rocm/precise-memory-fork.exp1
-rw-r--r--gdb/testsuite/gdb.rocm/precise-memory-multi-inferiors.exp6
-rw-r--r--gdb/testsuite/gdb.rocm/precise-memory-warning-sigsegv.exp3
-rw-r--r--gdb/testsuite/gdb.rocm/precise-memory.exp5
-rw-r--r--gdb/testsuite/gdb.rocm/simple.exp3
-rw-r--r--gdb/testsuite/gdb.rust/modules.exp2
-rw-r--r--gdb/testsuite/gdb.rust/traits.exp2
-rw-r--r--gdb/testsuite/gdb.server/bkpt-other-inferior.exp2
-rw-r--r--gdb/testsuite/gdb.server/build-id-seqno.exp6
-rw-r--r--gdb/testsuite/gdb.server/connect-stopped-target.exp2
-rw-r--r--gdb/testsuite/gdb.server/connect-with-no-symbol-file.exp2
-rw-r--r--gdb/testsuite/gdb.server/connect-without-multi-process.exp2
-rw-r--r--gdb/testsuite/gdb.server/exit-multiple-threads.exp5
-rw-r--r--gdb/testsuite/gdb.server/ext-attach.exp2
-rw-r--r--gdb/testsuite/gdb.server/ext-run.exp2
-rw-r--r--gdb/testsuite/gdb.server/extended-remote-restart.exp4
-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/inferior-args.c27
-rw-r--r--gdb/testsuite/gdb.server/inferior-args.exp156
-rw-r--r--gdb/testsuite/gdb.server/monitor-exit-quit.exp4
-rw-r--r--gdb/testsuite/gdb.server/non-existing-program.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.server/reconnect-ctrl-c.exp2
-rw-r--r--gdb/testsuite/gdb.server/server-exec-info.exp2
-rw-r--r--gdb/testsuite/gdb.server/server-kill.exp2
-rw-r--r--gdb/testsuite/gdb.server/server-pipe.exp2
-rw-r--r--gdb/testsuite/gdb.server/server-run.exp2
-rw-r--r--gdb/testsuite/gdb.server/stop-reply-no-thread-multi.exp4
-rw-r--r--gdb/testsuite/gdb.server/stop-reply-no-thread.exp4
-rw-r--r--gdb/testsuite/gdb.stabs/weird.def2
-rw-r--r--gdb/testsuite/gdb.testsuite/board-sanity.exp6
-rw-r--r--gdb/testsuite/gdb.testsuite/gdb-caching-proc-consistency.exp9
-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.testsuite/mount-point-map.exp49
-rw-r--r--gdb/testsuite/gdb.testsuite/with-override.exp4
-rw-r--r--gdb/testsuite/gdb.threads/access-mem-running-thread-exit.exp91
-rw-r--r--gdb/testsuite/gdb.threads/async.exp2
-rw-r--r--gdb/testsuite/gdb.threads/attach-non-stop.exp2
-rw-r--r--gdb/testsuite/gdb.threads/attach-stopped.exp2
-rw-r--r--gdb/testsuite/gdb.threads/bp_in_thread.exp2
-rw-r--r--gdb/testsuite/gdb.threads/break-while-running.exp2
-rw-r--r--gdb/testsuite/gdb.threads/check-libthread-db.exp6
-rw-r--r--gdb/testsuite/gdb.threads/corethreads.exp1
-rw-r--r--gdb/testsuite/gdb.threads/current-lwp-dead.exp2
-rw-r--r--gdb/testsuite/gdb.threads/detach-step-over.exp4
-rw-r--r--gdb/testsuite/gdb.threads/execl.exp2
-rw-r--r--gdb/testsuite/gdb.threads/foll-fork-other-thread.exp4
-rw-r--r--gdb/testsuite/gdb.threads/fork-child-threads.exp7
-rw-r--r--gdb/testsuite/gdb.threads/fork-plus-threads.exp2
-rw-r--r--gdb/testsuite/gdb.threads/fork-thread-pending.exp10
-rw-r--r--gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp6
-rw-r--r--gdb/testsuite/gdb.threads/hand-call-in-threads.exp2
-rw-r--r--gdb/testsuite/gdb.threads/inf-thr-count.exp59
-rw-r--r--gdb/testsuite/gdb.threads/infcall-from-bp-cond-other-thread-event.exp2
-rw-r--r--gdb/testsuite/gdb.threads/infcall-from-bp-cond-simple.exp2
-rw-r--r--gdb/testsuite/gdb.threads/infcall-from-bp-cond-single.exp2
-rw-r--r--gdb/testsuite/gdb.threads/infcall-from-bp-cond-timeout.exp2
-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/interrupt-while-step-over.exp2
-rw-r--r--gdb/testsuite/gdb.threads/interrupted-hand-call.exp2
-rw-r--r--gdb/testsuite/gdb.threads/killed.exp2
-rw-r--r--gdb/testsuite/gdb.threads/leader-exit-attach.exp2
-rw-r--r--gdb/testsuite/gdb.threads/linux-dp.exp2
-rw-r--r--gdb/testsuite/gdb.threads/local-watch-wrong-thread.exp2
-rw-r--r--gdb/testsuite/gdb.threads/main-thread-exit-during-detach.exp2
-rw-r--r--gdb/testsuite/gdb.threads/manythreads.exp2
-rw-r--r--gdb/testsuite/gdb.threads/multi-create.exp2
-rw-r--r--gdb/testsuite/gdb.threads/multiple-successive-infcall.exp2
-rw-r--r--gdb/testsuite/gdb.threads/next-bp-other-thread.exp2
-rw-r--r--gdb/testsuite/gdb.threads/next-fork-exec-other-thread.exp4
-rw-r--r--gdb/testsuite/gdb.threads/next-fork-other-thread.exp4
-rw-r--r--gdb/testsuite/gdb.threads/pending-fork-event-detach-ns.exp4
-rw-r--r--gdb/testsuite/gdb.threads/pending-fork-event-detach.exp5
-rw-r--r--gdb/testsuite/gdb.threads/pending-step.exp2
-rw-r--r--gdb/testsuite/gdb.threads/print-threads.exp2
-rw-r--r--gdb/testsuite/gdb.threads/process-dies-while-detaching.exp12
-rw-r--r--gdb/testsuite/gdb.threads/process-dies-while-handling-bp.exp2
-rw-r--r--gdb/testsuite/gdb.threads/pthread_cond_wait.exp2
-rw-r--r--gdb/testsuite/gdb.threads/pthreads.exp2
-rw-r--r--gdb/testsuite/gdb.threads/queue-signal.exp2
-rw-r--r--gdb/testsuite/gdb.threads/schedlock-new-thread.exp2
-rw-r--r--gdb/testsuite/gdb.threads/schedlock-thread-exit.exp2
-rw-r--r--gdb/testsuite/gdb.threads/signal-command-handle-nopass.exp2
-rw-r--r--gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.exp2
-rw-r--r--gdb/testsuite/gdb.threads/signal-delivered-right-thread.exp2
-rw-r--r--gdb/testsuite/gdb.threads/signal-sigtrap.exp2
-rw-r--r--gdb/testsuite/gdb.threads/sigthread.exp2
-rw-r--r--gdb/testsuite/gdb.threads/staticthreads.exp4
-rw-r--r--gdb/testsuite/gdb.threads/step-N-all-progress.exp2
-rw-r--r--gdb/testsuite/gdb.threads/step-over-exec.exp3
-rw-r--r--gdb/testsuite/gdb.threads/step-over-thread-exit-while-stop-all-threads.exp2
-rw-r--r--gdb/testsuite/gdb.threads/step-over-thread-exit.exp2
-rw-r--r--gdb/testsuite/gdb.threads/stepi-over-clone.exp2
-rw-r--r--gdb/testsuite/gdb.threads/switch-threads.exp2
-rw-r--r--gdb/testsuite/gdb.threads/thread-bp-deleted.exp4
-rw-r--r--gdb/testsuite/gdb.threads/thread-execl.c10
-rw-r--r--gdb/testsuite/gdb.threads/thread-execl.exp2
-rw-r--r--gdb/testsuite/gdb.threads/thread-find.exp2
-rw-r--r--gdb/testsuite/gdb.threads/thread-specific-bp.exp2
-rw-r--r--gdb/testsuite/gdb.threads/thread-specific.exp2
-rw-r--r--gdb/testsuite/gdb.threads/thread-unwindonsignal.exp2
-rw-r--r--gdb/testsuite/gdb.threads/thread_check.exp2
-rw-r--r--gdb/testsuite/gdb.threads/threadapply.exp12
-rw-r--r--gdb/testsuite/gdb.threads/threadcrash.exp9
-rw-r--r--gdb/testsuite/gdb.threads/threxit-hop-specific.exp2
-rw-r--r--gdb/testsuite/gdb.threads/tls-core.exp4
-rw-r--r--gdb/testsuite/gdb.threads/tls-nodebug-pie.exp2
-rw-r--r--gdb/testsuite/gdb.threads/tls-nodebug.exp2
-rw-r--r--gdb/testsuite/gdb.threads/tls-shared.exp2
-rw-r--r--gdb/testsuite/gdb.threads/tls-so_extern.exp2
-rw-r--r--gdb/testsuite/gdb.threads/tls.exp2
-rw-r--r--gdb/testsuite/gdb.threads/vfork-follow-child-exec.exp4
-rw-r--r--gdb/testsuite/gdb.threads/vfork-follow-child-exit.exp4
-rw-r--r--gdb/testsuite/gdb.threads/vfork-multi-inferior.exp4
-rw-r--r--gdb/testsuite/gdb.threads/vfork-multi-thread.exp4
-rw-r--r--gdb/testsuite/gdb.threads/watchpoint-fork.exp2
-rw-r--r--gdb/testsuite/gdb.threads/watchthreads.exp2
-rw-r--r--gdb/testsuite/gdb.threads/watchthreads2.exp2
-rw-r--r--gdb/testsuite/gdb.threads/wp-replication.exp2
-rw-r--r--gdb/testsuite/gdb.trace/ax.exp2
-rw-r--r--gdb/testsuite/gdb.trace/basic-libipa.exp2
-rw-r--r--gdb/testsuite/gdb.trace/entry-values.exp4
-rw-r--r--gdb/testsuite/gdb.trace/ftrace-lock.exp4
-rw-r--r--gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp2
-rw-r--r--gdb/testsuite/gdb.trace/mi-trace-unavailable.exp2
-rw-r--r--gdb/testsuite/gdb.trace/mi-traceframe-changed.exp10
-rw-r--r--gdb/testsuite/gdb.trace/mi-tracepoint-changed.exp7
-rw-r--r--gdb/testsuite/gdb.trace/mi-tsv-changed.exp7
-rw-r--r--gdb/testsuite/gdb.trace/packetlen.exp2
-rw-r--r--gdb/testsuite/gdb.trace/passc-dyn.exp2
-rw-r--r--gdb/testsuite/gdb.trace/report.exp2
-rw-r--r--gdb/testsuite/gdb.trace/tfile.exp4
-rw-r--r--gdb/testsuite/gdb.trace/tfind.exp2
-rw-r--r--gdb/testsuite/gdb.trace/trace-mt.exp22
-rw-r--r--gdb/testsuite/gdb.trace/tspeed.exp2
-rw-r--r--gdb/testsuite/gdb.trace/tsv.exp4
-rw-r--r--gdb/testsuite/gdb.trace/while-dyn.exp2
-rw-r--r--gdb/testsuite/gdb.tui/basic.exp6
-rw-r--r--gdb/testsuite/gdb.tui/color-prompt.exp10
-rw-r--r--gdb/testsuite/gdb.tui/color-prompt.exp.tcl80
-rw-r--r--gdb/testsuite/gdb.tui/compact-source.exp8
-rw-r--r--gdb/testsuite/gdb.tui/corefile-run.exp2
-rw-r--r--gdb/testsuite/gdb.tui/empty.exp2
-rw-r--r--gdb/testsuite/gdb.tui/esc-match.exp48
-rw-r--r--gdb/testsuite/gdb.tui/esc-match.py26
-rwxr-xr-x[-rw-r--r--]gdb/testsuite/gdb.tui/gdb.tcl (renamed from gdb/testsuite/gdb.testsuite/lmap.exp)14
-rw-r--r--gdb/testsuite/gdb.tui/main-2.exp6
-rw-r--r--gdb/testsuite/gdb.tui/main.exp5
-rw-r--r--gdb/testsuite/gdb.tui/new-layout.exp20
-rw-r--r--gdb/testsuite/gdb.tui/pr30056.exp9
-rw-r--r--gdb/testsuite/gdb.tui/source-search.c127
-rw-r--r--gdb/testsuite/gdb.tui/source-search.exp72
-rw-r--r--gdb/testsuite/gdb.tui/tui-disasm-long-lines.exp2
-rw-r--r--gdb/testsuite/gdb.tui/tui-disasm-styling.exp5
-rw-r--r--gdb/testsuite/gdb.tui/tui-focus.exp6
-rw-r--r--gdb/testsuite/gdb.tui/tui-layout-asm-short-prog.exp10
-rw-r--r--gdb/testsuite/gdb.tui/tui-layout-asm.exp106
-rw-r--r--gdb/testsuite/gdb.tui/tui-layout.exp6
-rw-r--r--gdb/testsuite/gdb.tui/tui-missing-src.exp6
-rw-r--r--gdb/testsuite/gdb.tui/tui-mode-switch.exp57
-rw-r--r--gdb/testsuite/gdb.tui/tuiterm-2.exp70
-rw-r--r--gdb/testsuite/gdb.tui/tuiterm.exp62
-rw-r--r--gdb/testsuite/gdb.tui/wrap-line.exp6
-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/ada.exp3
-rw-r--r--gdb/testsuite/lib/dwarf.exp68
-rw-r--r--gdb/testsuite/lib/future.exp13
-rw-r--r--gdb/testsuite/lib/gdb-utils.exp4
-rw-r--r--gdb/testsuite/lib/gdb.exp740
-rw-r--r--gdb/testsuite/lib/gdb_watchdog.h75
-rw-r--r--gdb/testsuite/lib/gdbserver-support.exp2
-rw-r--r--gdb/testsuite/lib/mi-support.exp3
-rw-r--r--gdb/testsuite/lib/selftest-support.exp216
-rw-r--r--gdb/testsuite/lib/tuiterm.exp2366
-rwxr-xr-xgdb/testsuite/make-check-all.sh4
-rw-r--r--gdb/thread.c131
-rw-r--r--gdb/tic6x-linux-tdep.c6
-rw-r--r--gdb/tic6x-tdep.c6
-rw-r--r--gdb/tid-parse.c7
-rw-r--r--gdb/tilegx-linux-nat.c4
-rw-r--r--gdb/tilegx-linux-tdep.c11
-rw-r--r--gdb/tilegx-tdep.c4
-rw-r--r--gdb/top.c17
-rw-r--r--gdb/tracectf.c7
-rw-r--r--gdb/tracefile-tfile.c18
-rw-r--r--gdb/tracefile.c4
-rw-r--r--gdb/tracepoint.c32
-rw-r--r--gdb/tui/tui-disasm.c38
-rw-r--r--gdb/tui/tui-file.c6
-rw-r--r--gdb/tui/tui-file.h11
-rw-r--r--gdb/tui/tui-hooks.c4
-rw-r--r--gdb/tui/tui-interp.c4
-rw-r--r--gdb/tui/tui-io.c12
-rw-r--r--gdb/tui/tui-layout.c11
-rw-r--r--gdb/tui/tui-regs.c4
-rw-r--r--gdb/tui/tui-status.c12
-rw-r--r--gdb/tui/tui-win.c7
-rw-r--r--gdb/tui/tui-winsource.c7
-rw-r--r--gdb/tui/tui.c17
-rw-r--r--gdb/type-stack.c6
-rw-r--r--gdb/type-stack.h143
-rw-r--r--gdb/typeprint.c11
-rw-r--r--gdb/ui-file.c64
-rw-r--r--gdb/ui-file.h46
-rw-r--r--gdb/ui-style.c75
-rw-r--r--gdb/ui-style.h62
-rw-r--r--gdb/ui.c4
-rw-r--r--gdb/unittests/array-view-selftests.c4
-rw-r--r--gdb/unittests/child-path-selftests.c4
-rw-r--r--gdb/unittests/cli-utils-selftests.c4
-rw-r--r--gdb/unittests/command-def-selftests.c8
-rw-r--r--gdb/unittests/common-utils-selftests.c4
-rw-r--r--gdb/unittests/copy_bitwise-selftests.c4
-rw-r--r--gdb/unittests/enum-flags-selftests.c5
-rw-r--r--gdb/unittests/environ-selftests.c4
-rw-r--r--gdb/unittests/filtered_iterator-selftests.c56
-rw-r--r--gdb/unittests/format_pieces-selftests.c4
-rw-r--r--gdb/unittests/frame_info_ptr-selftests.c4
-rw-r--r--gdb/unittests/function-view-selftests.c4
-rw-r--r--gdb/unittests/gdb_tilde_expand-selftests.c4
-rw-r--r--gdb/unittests/gmp-utils-selftests.c5
-rw-r--r--gdb/unittests/intrusive_list-selftests.c5
-rw-r--r--gdb/unittests/lookup_name_info-selftests.c4
-rw-r--r--gdb/unittests/main-thread-selftests.c4
-rw-r--r--gdb/unittests/memory-map-selftests.c4
-rw-r--r--gdb/unittests/memrange-selftests.c4
-rw-r--r--gdb/unittests/mkdir-recursive-selftests.c4
-rw-r--r--gdb/unittests/observable-selftests.c4
-rw-r--r--gdb/unittests/offset-type-selftests.c4
-rw-r--r--gdb/unittests/packed-selftests.c4
-rw-r--r--gdb/unittests/parallel-for-selftests.c141
-rw-r--r--gdb/unittests/parse-connection-spec-selftests.c4
-rw-r--r--gdb/unittests/path-join-selftests.c4
-rw-r--r--gdb/unittests/remote-arg-selftests.c5
-rw-r--r--gdb/unittests/rsp-low-selftests.c4
-rw-r--r--gdb/unittests/scoped_fd-selftests.c4
-rw-r--r--gdb/unittests/scoped_ignore_signal-selftests.c4
-rw-r--r--gdb/unittests/scoped_mmap-selftests.c8
-rw-r--r--gdb/unittests/scoped_restore-selftests.c4
-rw-r--r--gdb/unittests/search-memory-selftests.c4
-rw-r--r--gdb/unittests/style-selftests.c36
-rw-r--r--gdb/unittests/tracepoint-selftests.c4
-rw-r--r--gdb/unittests/tui-selftests.c4
-rw-r--r--gdb/unittests/ui-file-selftests.c4
-rw-r--r--gdb/unittests/unique_xmalloc_ptr_char.c4
-rw-r--r--gdb/unittests/unpack-selftests.c4
-rw-r--r--gdb/unittests/utils-selftests.c59
-rw-r--r--gdb/unittests/vec-utils-selftests.c4
-rw-r--r--gdb/unittests/xml-utils-selftests.c4
-rw-r--r--gdb/user-regs.c4
-rw-r--r--gdb/utils.c156
-rw-r--r--gdb/utils.h5
-rw-r--r--gdb/v850-tdep.c4
-rw-r--r--gdb/valops.c20
-rw-r--r--gdb/valprint.c5
-rw-r--r--gdb/value.c32
-rw-r--r--gdb/value.h18
-rw-r--r--gdb/varobj.c4
-rw-r--r--gdb/vax-bsd-nat.c4
-rw-r--r--gdb/vax-netbsd-tdep.c7
-rw-r--r--gdb/vax-tdep.c4
-rw-r--r--gdb/version.in2
-rw-r--r--gdb/windows-nat.c22
-rw-r--r--gdb/windows-tdep.c117
-rw-r--r--gdb/windows-tdep.h1
-rw-r--r--gdb/x86-bsd-nat.c4
-rw-r--r--gdb/x86-gnu-nat.c4
-rw-r--r--gdb/x86-linux-nat.c52
-rw-r--r--gdb/x86-linux-nat.h11
-rw-r--r--gdb/x86-tdep.c21
-rw-r--r--gdb/x86-tdep.h9
-rw-r--r--gdb/xcoffread.c7
-rw-r--r--gdb/xml-support.c10
-rw-r--r--gdb/xml-syscall.c2
-rw-r--r--gdb/xml-tdesc.c2
-rw-r--r--gdb/xstormy16-tdep.c12
-rw-r--r--gdb/xtensa-linux-nat.c4
-rw-r--r--gdb/xtensa-linux-tdep.c8
-rw-r--r--gdb/xtensa-tdep.c7
-rw-r--r--gdb/z80-tdep.c29
1590 files changed, 30210 insertions, 13615 deletions
diff --git a/gdb/MAINTAINERS b/gdb/MAINTAINERS
index 5e1aada..375068a 100644
--- a/gdb/MAINTAINERS
+++ b/gdb/MAINTAINERS
@@ -234,7 +234,7 @@ Pedro Alves pedro@palves.net
John Baldwin jhb@freebsd.org
Kevin Buettner kevinb@redhat.com
Andrew Burgess aburgess@redhat.com
-Luis Machado luis.machado@arm.com
+Luis Machado luis.machado.foss@gmail.com
Simon Marchi simon.marchi@polymtl.ca
Tom Tromey tom@tromey.com
Tom de Vries tdevries@suse.de
@@ -320,7 +320,7 @@ the native maintainer when resolving ABI issues.
aarch64 --target=aarch64-elf
Alan Hayward alan.hayward@arm.com
- Luis Machado luis.machado@arm.com
+ Luis Machado luis.machado.foss@gmail.com
alpha --target=alpha-elf
@@ -332,7 +332,7 @@ the native maintainer when resolving ABI issues.
arm --target=arm-elf
Alan Hayward alan.hayward@arm.com
- Luis Machado luis.machado@arm.com
+ Luis Machado luis.machado.foss@gmail.com
avr --target=avr
@@ -492,7 +492,7 @@ sim/ See sim/MAINTAINERS
readline/ Master version: ftp://ftp.cwru.edu/pub/bash/
ALL
- Host maintainers (host dependant parts)
+ Host maintainers (host dependent parts)
(but get your changes into the master version)
tcl/ tk/ itcl/ ALL
@@ -554,6 +554,7 @@ Paul Brook paul@codesourcery.com
Julian Brown julian@codesourcery.com
Iain Buclaw ibuclaw@gdcproject.org
Kevin Buettner kevinb@redhat.com
+Gopi Kumar Bulusu gopi@sankhya.com
Richard Bunt richard.bunt@linaro.org
Andrew Burgess aburgess@redhat.com
David Carlton carlton@bactrian.org
@@ -602,15 +603,18 @@ Klaus Gerlicher klaus.gerlicher@intel.com
Mircea Gherzan mircea.gherzan@intel.com
Paul Gilliam pgilliam@us.ibm.com
Tristan Gingold tgingold@free.fr
+Timur Golubovich timurgol007@gmail.com
Anton Gorenkov xgsa@yandex.ru
Raoul Gough RaoulGough@yahoo.co.uk
Anthony Green green@redhat.com
Matthew Green mrg@eterna.com.au
Matthew Gretton-Dann matthew.gretton-dann@arm.com
+Aaron Griffith aargri@gmail.com
Maxim Grigoriev maxim2405@gmail.com
Jerome Guitton guitton@act-europe.fr
Alexandra Hájková ahajkova@redhat.com
Ben Harris bjh21@netbsd.org
+Jannik Hartung peacemakerctf@gmail.com
Alan Hayward alan.hayward@arm.com
Bernhard Heckel heckel_bernhard@web.de
Richard Henderson rth@redhat.com
@@ -682,6 +686,7 @@ Fawzi Mohamed fawzi.mohamed@nokia.com
Jason Molenda jmolenda@apple.com
Chris Moller cmoller@redhat.com
Patrick Monnerat patrick@monnerat.net
+Pietro Monteiro pietro@sociotechnical.xyz
Phil Muldoon pmuldoon@redhat.com
Pierre Muller muller@sourceware.org
Gaius Mulley gaiusmod2@gmail.com
@@ -773,7 +778,7 @@ David Ung davidu@mips.com
Shahab Vahedi shahab.vahedi@amd.com
D Venkatasubramanian dvenkat@noida.hcltech.com
Corinna Vinschen vinschen@redhat.com
-Jan Vrany jan.vrany@fit.cvut.cz
+Jan Vrany jan.vrany@labware.com
Sami Wagiaalla swagiaal@redhat.com
Keith Walker keith.walker@arm.com
Ricard Wanderlof ricardw@axis.com
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 77e03e4..689f37f 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -265,7 +265,7 @@ INCSUPPORT = \
-I..
#
-# CLI sub directory definitons
+# CLI sub directory definitions
#
SUBDIR_CLI_SRCS = \
cli/cli-cmds.c \
@@ -282,7 +282,7 @@ SUBDIR_CLI_SRCS = \
SUBDIR_CLI_OBS = $(patsubst %.c,%.o,$(SUBDIR_CLI_SRCS))
#
-# MI sub directory definitons
+# MI sub directory definitions
#
SUBDIR_MI_SRCS = \
mi/mi-cmd-break.c \
@@ -350,7 +350,7 @@ SUBDIR_GCC_COMPILE_SRCS = \
SUBDIR_GCC_COMPILE_OBS = $(patsubst %.c,%.o,$(filter %.c,$(SUBDIR_GCC_COMPILE_SRCS)))
#
-# Guile sub directory definitons for guile support.
+# Guile sub directory definitions for guile support.
#
SUBDIR_GUILE_SRCS = \
guile/guile.c \
@@ -387,7 +387,7 @@ SUBDIR_GUILE_LDFLAGS =
SUBDIR_GUILE_CFLAGS =
#
-# python sub directory definitons
+# python sub directory definitions
#
SUBDIR_PYTHON_SRCS = \
python/py-arch.c \
@@ -492,7 +492,6 @@ SELFTESTS_SRCS = \
unittests/ui-file-selftests.c \
unittests/unique_xmalloc_ptr_char.c \
unittests/unpack-selftests.c \
- unittests/utils-selftests.c \
unittests/vec-utils-selftests.c \
unittests/xml-utils-selftests.c
@@ -892,6 +891,7 @@ ALL_TARGET_OBS = \
solib-dsbt.o \
solib-frv.o \
solib-svr4.o \
+ solib-svr4-linux.o \
sparc-linux-tdep.o \
sparc-netbsd-tdep.o \
sparc-obsd-tdep.o \
@@ -907,13 +907,22 @@ ALL_TARGET_OBS = \
vax-tdep.o \
windows-tdep.o \
x86-tdep.o \
- xcoffread.o \
xstormy16-tdep.o \
xtensa-config.o \
xtensa-linux-tdep.o \
xtensa-tdep.o \
z80-tdep.o
+# Object files for reading specific types of debug information.
+coff_SRCS = coffread.c coff-pe-read.c
+dbx_SRCS = dbxread.c
+elf_SRCS = elfread.c stap-probe.c dtrace-probe.c
+macho_SRCS = machoread.c
+mips_SRCS = mipsread.c
+xcoff_SRCS = xcoffread.c
+FORMAT_SRCS = @FORMAT_SRCS@
+FORMAT_OBS = $(patsubst %.c,%.o,$(FORMAT_SRCS))
+
# The following native-target dependent variables are defined on
# configure.nat.
NAT_FILE = @NAT_FILE@
@@ -1070,8 +1079,6 @@ COMMON_SFILES = \
c-varobj.c \
charset.c \
cli-out.c \
- coff-pe-read.c \
- coffread.c \
complaints.c \
completer.c \
copying.c \
@@ -1085,7 +1092,6 @@ COMMON_SFILES = \
d-lang.c \
d-namespace.c \
d-valprint.c \
- dbxread.c \
dcache.c \
debug.c \
debuginfod-support.c \
@@ -1093,36 +1099,6 @@ COMMON_SFILES = \
disasm.c \
displaced-stepping.c \
dummy-frame.c \
- dwarf2/abbrev.c \
- dwarf2/abbrev-table-cache.c \
- dwarf2/ada-imported.c \
- dwarf2/aranges.c \
- dwarf2/attribute.c \
- dwarf2/cooked-index.c \
- dwarf2/cooked-index-entry.c \
- dwarf2/cooked-index-shard.c \
- dwarf2/cooked-index-worker.c \
- dwarf2/cooked-indexer.c \
- dwarf2/cu.c \
- dwarf2/die.c \
- dwarf2/dwz.c \
- dwarf2/expr.c \
- dwarf2/frame-tailcall.c \
- dwarf2/frame.c \
- dwarf2/index-cache.c \
- dwarf2/index-common.c \
- dwarf2/index-write.c \
- dwarf2/leb.c \
- dwarf2/line-header.c \
- dwarf2/loc.c \
- dwarf2/macro.c \
- dwarf2/parent-map.c \
- dwarf2/read.c \
- dwarf2/read-debug-names.c \
- dwarf2/read-gdb-index.c \
- dwarf2/section.c \
- dwarf2/stringify.c \
- dwarf2/unit-head.c \
extract-store-integer.c \
eval.c \
event-top.c \
@@ -1173,7 +1149,6 @@ COMMON_SFILES = \
maint.c \
maint-test-options.c \
maint-test-settings.c \
- mdebugread.c \
mem-break.c \
memattr.c \
memory-map.c \
@@ -1181,7 +1156,6 @@ COMMON_SFILES = \
memtag.c \
minidebug.c \
minsyms.c \
- mipsread.c \
namespace.c \
objc-lang.c \
objfiles.c \
@@ -1274,7 +1248,6 @@ SFILES = \
d-exp.y \
dtrace-probe.c \
elf-none-tdep.c \
- elfread.c \
f-exp.y \
gcore-elf.c \
gdb.c \
@@ -1371,6 +1344,7 @@ HFILES_NO_SRCDIR = \
dwarf2/expr.h \
dwarf2/index-cache.h \
dwarf2/index-common.h \
+ dwarf2/line-program.h \
dwarf2/loc.h \
dwarf2/read.h \
dwarf2/read-debug-names.h \
@@ -1510,9 +1484,10 @@ HFILES_NO_SRCDIR = \
solib.h \
solib-aix.h \
solib-darwin.h \
+ solib-frv.h \
solib-svr4.h \
+ solib-svr4-linux.h \
solib-target.h \
- solist.h \
source.h \
source-cache.h \
sparc-nat.h \
@@ -1900,7 +1875,6 @@ ALLDEPFILES = \
x86-gnu-nat.c \
x86-nat.c \
x86-tdep.c \
- xcoffread.c \
xstormy16-tdep.c \
xtensa-config.c \
xtensa-linux-nat.c \
@@ -1914,6 +1888,41 @@ TAGFILES_NO_SRCDIR = $(SFILES) $(HFILES_NO_SRCDIR) $(ALLDEPFILES) \
$(CONFIG_SRCS)
TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR)
+# Files that are used to support certain debuginfo formats
+DWARF2_SRCS = \
+ dwarf2/abbrev.c \
+ dwarf2/abbrev-table-cache.c \
+ dwarf2/ada-imported.c \
+ dwarf2/aranges.c \
+ dwarf2/attribute.c \
+ dwarf2/cooked-index.c \
+ dwarf2/cooked-index-entry.c \
+ dwarf2/cooked-index-shard.c \
+ dwarf2/cooked-index-worker.c \
+ dwarf2/cooked-indexer.c \
+ dwarf2/cu.c \
+ dwarf2/die.c \
+ dwarf2/dwz.c \
+ dwarf2/expr.c \
+ dwarf2/frame-tailcall.c \
+ dwarf2/frame.c \
+ dwarf2/index-cache.c \
+ dwarf2/index-common.c \
+ dwarf2/index-write.c \
+ dwarf2/leb.c \
+ dwarf2/line-header.c \
+ dwarf2/line-program.c \
+ dwarf2/loc.c \
+ dwarf2/macro.c \
+ dwarf2/parent-map.c \
+ dwarf2/read.c \
+ dwarf2/read-debug-names.c \
+ dwarf2/read-gdb-index.c \
+ dwarf2/section.c \
+ dwarf2/stringify.c \
+ dwarf2/unit-head.c
+DWARF2_OBS = $(patsubst %.c,%.o, $(DWARF2_SRCS))
+
COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
mi/mi-common.o \
version.o \
@@ -1921,7 +1930,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
$(patsubst %.c,%.o,$(COMMON_SFILES)) \
$(SUBDIR_CLI_OBS) \
$(SUBDIR_MI_OBS) \
- $(SUBDIR_TARGET_OBS)
+ $(SUBDIR_TARGET_OBS) \
+ $(FORMAT_OBS)
SUBDIRS = doc @subdirs@ data-directory
CLEANDIRS = $(SUBDIRS)
diff --git a/gdb/NEWS b/gdb/NEWS
index 077d28a..01bd152 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -1,7 +1,39 @@
What has changed in GDB?
(Organized release by release)
-*** Changes since GDB 16
+*** Changes since GDB 17
+
+* Support for .gdb_index sections with version less than 7 has been
+ removed.
+
+* GDB now accepts --no-escape-args as an alternative to --args on the
+ command line. GDB will not escape special shell characters within
+ arguments after --no-escape-args.
+
+* gdbserver now accepts --no-escape-args as a command line flag. When
+ this flag is used gdbserver will not escape special shell characters
+ within the inferior arguments.
+
+* New targets
+
+GNU/Linux/MicroBlaze (gdbserver) microblazeel-*linux*
+
+* Changed remote packets
+
+single-inf-arg in qSupported
+ The new single-inf-arg feature within the qSupported packet allows
+ GDB to inform the stub that it would like to send the inferior
+ arguments as a single string within the vRun packet. The stub can
+ reply with the single-inf-arg feature to indicate that it is able to
+ accept arguments as a single string.
+
+*** Changes in GDB 17
+
+* Debugging Linux programs that use x86-64 or x86-64 with 32-bit pointer
+ size (X32) Shadow Stacks are now supported.
+
+* Support for the shadow stack pointer register on x86-64 or x86-64 with
+ 32-bit pointer size (X32) GNU/Linux.
* Debugger Adapter Protocol changes
@@ -35,18 +67,21 @@
a -h or --help option, which prints each options and a brief
description.
-* On systems that support linkage namespaces, the output of the command
+* On systems that support linker namespaces, the output of the command
"info sharedlibraries" may add one more column, NS, which identifies the
namespace into which the library was loaded, if more than one namespace
is active.
-* New built-in convenience variables $_active_linker_namespaces and
- $_current_linker_namespace. These show the number of active linkage
+* New built-in convenience variables $linker_namespace_count and
+ $_linker_namespace. These show the number of active linker
namespaces, and the namespace to which the current location belongs to.
- In systems that don't support linkage namespaces, these always return 1
- and [[0]] respectively.
+ In systems that don't support linker namespaces, or if the inferior hasn't
+ started yet, these always return the integer 0.
- * Add record full support for rv64gc architectures
+* Add record full support for rv64gc architectures
+
+* Debugging Linux programs that use AArch64 Guarded Control Stacks is now
+ supported.
* New commands
@@ -59,12 +94,31 @@ maintenance check symtabs
maintenance canonicalize
Show the canonical form of a C++ name.
+maintenance set console-translation-mode <binary|text>
+maintenance show console-translation-mode
+ Controls the translation mode of GDB stdout/stderr. MS-Windows only. In
+ binary mode, no translation is done. In text mode, a Line Feed is
+ translated into a Carriage Return-Line Feed combination.
+
set riscv numeric-register-names on|off
show riscv numeric-register-names
Controls whether GDB refers to risc-v registers by their numeric names
(e.g 'x1') or their abi names (e.g. 'ra').
Defaults to 'off', matching the old behaviour (abi names).
+set style emoji on|off|auto
+show style emoji
+ Controls whether GDB can display emoji. The default is "auto",
+ which means emoji will be displayed in some situations when
+ the host charset is UTF-8.
+
+set style warning-prefix STRING
+set style error-prefix STRING
+ These commands control the prefix that is printed before warnings
+ and errors, respectively. This functionality is intended for use
+ with emoji display, and so the prefixes are only displayed if emoji
+ styling is enabled.
+
info linker-namespaces
info linker-namespaces [[N]]
Print information about the given linker namespace (identified as N),
@@ -77,6 +131,18 @@ info sharedlibrary
command are now for the full memory range allocated to the shared
library.
+info threads [-gid] [-stopped] [-running] [ID]...
+ If no threads match the given ID(s) or filter options, GDB now prints
+
+ No threads matched.
+
+ without printing the provided arguments. The newly added '-stopped'
+ option makes GDB list the stopped threads only. Similarly,
+ '-running' makes GDB list the running threads only. If both options
+ are given together, both stopped and running threads are listed.
+ These new flags can be useful to get a reduced list when there is a
+ large number of threads.
+
* GDB-internal Thread Local Storage (TLS) support
** Linux targets for the x86_64, aarch64, ppc64, s390x, and riscv
@@ -99,6 +165,8 @@ info sharedlibrary
* Python API
+ ** GDB no longer supports Python versions less than 3.4.
+
** New class gdb.Color for dealing with colors.
** New constant gdb.PARAM_COLOR represents color type of a
@@ -115,6 +183,27 @@ info sharedlibrary
when output is going to standard output, and False when output is
going to a string.
+ ** Setting the documentation string (__doc__) of a gdb.Parameter
+ sub-class to the empty string, means GDB will only display the
+ set_doc or show_doc strings in the set/show help output.
+
+ ** New gdb.ParameterPrefix class. This can be used to create 'set'
+ and 'show' gdb.Command prefixes, suitable for use with new
+ gdb.Parameters.
+
+ ** Prefix commands (gdb.Command sub-classes) that don't have an
+ invoke method will now behave like builtin prefix commands when
+ invoked without a sub-command name. This means printing the help
+ text for all sub-commands, unless the prefix command is a 'show'
+ command, in which case the value of all sub-commands is printed.
+
+ ** New gdb.warning() function that takes a string and prints it as a
+ warning, with GDB's standard 'warning' prefix.
+
+ ** New attribute gdb.Value.is_unavailable, this checks for
+ unavailability like gdb.Value.is_optimized_out checks for
+ optimized out values.
+
* Guile API
** New type <gdb:color> for dealing with colors.
@@ -122,6 +211,17 @@ info sharedlibrary
** New constant PARAM_COLOR represents color type of a value
of a <gdb:parameter> object. Parameter's value is <gdb::color> instance.
+ ** Eliding the #:doc string from make-parameter now means that GDB
+ will use a default documentation string. Setting #:doc to the
+ empty string for make-parameter means GDB will only display the
+ #:set_doc or #:show_doc strings in the set/show help output.
+
+ ** Prefix commands (using make-command) that don't have a #:invoke
+ property will now behave like builtin prefix commands when
+ invoked without a sub-command name. This means printing the help
+ text for all sub-commands, unless the prefix command is a 'show'
+ command, in which case the value of all sub-commands is printed.
+
* New remote packets
binary-upload in qSupported reply
@@ -130,6 +230,11 @@ binary-upload in qSupported reply
stub doesn't report this feature supported, then GDB will not use
the 'x' packet.
+vFile:lstat
+ Return information about files on the remote system. Like
+ vFile:stat but if the filename is a symbolic link, return
+ information about the link itself, the file the link refers to.
+
* Changed remote packets
qXfer:threads:read
@@ -138,6 +243,11 @@ qXfer:threads:read
should print as the target ID of the thread, for example in the
"info threads" command or when switching to the thread.
+vFile:stat
+ Previously, gdbserver incorrectly implemented this packet using
+ lstat rather than stat. This has now been corrected. The
+ documentation has also been clarified.
+
* MI changes
** The =library-unloaded event now includes the 'ranges' field, which
@@ -153,10 +263,31 @@ qXfer:threads:read
* Support for stabs debugging format and the a.out/dbx object format is
deprecated, and will be removed in GDB 18.
+* Configure changes
+
+--enable-binary-file-formats=[FORMAT,...]
+--enable-binary-file-formats=all
+ A user can now decide to only compile support for certain file formats.
+ The available formats at this point are: dbx, coff, xcoff, elf, mach-o
+ and mips. Some targets require specific file formats to be available,
+ and in such cases, the configure script will warn the user and add
+ support anyway. By default, all formats will be compiled in, to
+ continue the behavior from before adding the switch.
+
* A new configure option was added, allowing support for the compile
subsystem to be disabled at configure time, in the form of
--disable-gdb-compile.
+* A new configure option was added, allowing support for DWARF debug
+ information to be disabled at configure time. The flag is
+ --disable-gdb-dwarf-support.
+
+* A new configure option was added, allowing support for mdebug/ecoff
+ debug information to be disabled at configure time. The flag to do
+ that is --disable-gdb-mdebug-support.
+
+* The Alpha target now supports target descriptions.
+
*** Changes in GDB 16
* Support for Nios II targets has been removed as this architecture
@@ -7532,7 +7663,7 @@ for DW_OP_piece is still missing).
A number of long standing bugs that caused GDB to die while starting a
Java application have been fixed. GDB's Java support is now
-considered "useable".
+considered "usable".
* GNU/Linux support for fork, vfork, and exec.
diff --git a/gdb/README b/gdb/README
index 5a00305..5dc2e7e 100644
--- a/gdb/README
+++ b/gdb/README
@@ -417,6 +417,30 @@ more obscure GDB `configure' options are not listed here.
There is no convenient way to generate a list of all available
targets.
+`--enable-binary-file-formats=FORMAT,FORMAT,...'
+`--enable-binary-file-formats=all'
+ Configure GDB to only be be able to read selected file formats.
+ The special value "all" causes all file formats to be compiled
+ in, and is the the default behavior of the option. This option
+ is meant for advanced users who are sure of what they expect,
+ if you are unsure which options you will need on your debugging
+ sessions, we recommend that you not use this feature. The
+ accepted options are:
+ * coff: Main format on Windows systems, this is required to
+ compile with windows target support;
+ * dbx (also known as a.out): Legacy file format, this is
+ recommended if you know you will be dealing with this
+ file format;
+ * elf: Main format on Linux systems, this is heavily
+ recommended when compiling with linux support;
+ * macho: Main format on MacOS systems, this is heavily
+ recommended when compiling for those targets;
+ * mips (also known as ecoff): Main file format for targets
+ running on MIPS CPUs, this is heavily recommended when
+ supporting those targets;
+ * xcoff: Main format on AIX systems, this is required to
+ compile for AIX targets and rs6000 CPUs.
+
`--with-gdb-datadir=PATH'
Set the GDB-specific data directory. GDB will look here for
certain supporting files or scripts. This defaults to the `gdb'
@@ -443,7 +467,14 @@ more obscure GDB `configure' options are not listed here.
supported).
`--disable-gdb-compile'
- Build GDB without support for the 'compile' command.
+ Build GDB without support for the 'compile' command. DWARF support
+ is required for this feature.
+
+`--disable-gdb-dwarf-support'
+ Build GDB without support for reading DWARF debug information.
+
+`--disable-gdb-mdebug-support'
+ Build GDB without support for reading mdebug debug information.
`--with-curses'
Use the curses library instead of the termcap library, for
@@ -533,7 +564,7 @@ more obscure GDB `configure' options are not listed here.
GDB scripting much more powerful than the restricted CLI
scripting language. If your host does not have Python installed,
you can find it on `http://www.python.org/download/'. The oldest
- version of Python supported by GDB is 3.2. The optional argument
+ version of Python supported by GDB is 3.4. The optional argument
PYTHON is used to find the Python headers and libraries. It can
be either the name of a Python executable, or the name of the
directory in which Python is installed.
diff --git a/gdb/aarch64-fbsd-nat.c b/gdb/aarch64-fbsd-nat.c
index 1746ad1..ecf0bb2 100644
--- a/gdb/aarch64-fbsd-nat.c
+++ b/gdb/aarch64-fbsd-nat.c
@@ -348,9 +348,7 @@ aarch64_notify_debug_reg_change (ptid_t ptid,
}
#endif
-void _initialize_aarch64_fbsd_nat ();
-void
-_initialize_aarch64_fbsd_nat ()
+INIT_GDB_FILE (aarch64_fbsd_nat)
{
#ifdef HAVE_DBREG
aarch64_initialize_hw_point ();
diff --git a/gdb/aarch64-fbsd-tdep.c b/gdb/aarch64-fbsd-tdep.c
index 07fa38a..db9b82f 100644
--- a/gdb/aarch64-fbsd-tdep.c
+++ b/gdb/aarch64-fbsd-tdep.c
@@ -239,8 +239,7 @@ aarch64_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Generic FreeBSD support. */
fbsd_init_abi (info, gdbarch);
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
tramp_frame_prepend_unwinder (gdbarch, &aarch64_fbsd_sigframe);
@@ -261,9 +260,7 @@ aarch64_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
}
}
-void _initialize_aarch64_fbsd_tdep ();
-void
-_initialize_aarch64_fbsd_tdep ()
+INIT_GDB_FILE (aarch64_fbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_FREEBSD,
aarch64_fbsd_init_abi);
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index d7869f4..89ecedd 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -51,6 +51,7 @@
#include "gdb_proc_service.h"
#include "arch-utils.h"
+#include "arch/aarch64-gcs-linux.h"
#include "arch/aarch64-mte-linux.h"
#include "nat/aarch64-mte-linux-ptrace.h"
@@ -542,6 +543,67 @@ store_tlsregs_to_thread (struct regcache *regcache)
perror_with_name (_("unable to store TLS register"));
}
+/* Fill GDB's register array with the GCS register values from
+ the current thread. */
+
+static void
+fetch_gcsregs_from_thread (regcache *regcache)
+{
+ aarch64_gdbarch_tdep *tdep
+ = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
+
+ gdb_assert (tdep->gcs_reg_base != -1);
+ gdb_assert (tdep->gcs_linux_reg_base != -1);
+
+ user_gcs user_gcs;
+ iovec iovec;
+
+ iovec.iov_base = &user_gcs;
+ iovec.iov_len = sizeof (user_gcs);
+
+ int tid = get_ptrace_pid (regcache->ptid ());
+ if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_GCS, &iovec) != 0)
+ perror_with_name (_("Unable to fetch GCS registers"));
+
+ regcache->raw_supply (tdep->gcs_reg_base, &user_gcs.gcspr_el0);
+ regcache->raw_supply (tdep->gcs_linux_reg_base, &user_gcs.features_enabled);
+ regcache->raw_supply (tdep->gcs_linux_reg_base + 1,
+ &user_gcs.features_locked);
+}
+
+/* Store to the current thread the valid GCS register set in the GDB's
+ register array. */
+
+static void
+store_gcsregs_to_thread (regcache *regcache)
+{
+ aarch64_gdbarch_tdep *tdep
+ = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
+
+ gdb_assert (tdep->gcs_reg_base != -1);
+ gdb_assert (tdep->gcs_linux_reg_base != -1);
+
+ if (REG_VALID != regcache->get_register_status (tdep->gcs_reg_base)
+ || REG_VALID != regcache->get_register_status (tdep->gcs_linux_reg_base)
+ || REG_VALID
+ != regcache->get_register_status (tdep->gcs_linux_reg_base + 1))
+ return;
+
+ user_gcs user_gcs;
+ regcache->raw_collect (tdep->gcs_reg_base, &user_gcs.gcspr_el0);
+ regcache->raw_collect (tdep->gcs_linux_reg_base, &user_gcs.features_enabled);
+ regcache->raw_collect (tdep->gcs_linux_reg_base + 1,
+ &user_gcs.features_locked);
+
+ iovec iovec;
+ iovec.iov_base = &user_gcs;
+ iovec.iov_len = sizeof (user_gcs);
+
+ int tid = get_ptrace_pid (regcache->ptid ());
+ if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_GCS, &iovec) != 0)
+ perror_with_name (_("Unable to store GCS registers"));
+}
+
/* The AArch64 version of the "fetch_registers" target_ops method. Fetch
REGNO from the target and place the result into REGCACHE. */
@@ -577,6 +639,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
if (tdep->has_sme2 ())
fetch_zt_from_thread (regcache);
+
+ if (tdep->has_gcs_linux ())
+ fetch_gcsregs_from_thread (regcache);
}
/* General purpose register? */
else if (regno < AARCH64_V0_REGNUM)
@@ -609,6 +674,11 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
&& regno >= tdep->tls_regnum_base
&& regno < tdep->tls_regnum_base + tdep->tls_register_count)
fetch_tlsregs_from_thread (regcache);
+ /* GCS register? */
+ else if (tdep->has_gcs_linux ()
+ && (regno == tdep->gcs_reg_base || regno == tdep->gcs_linux_reg_base
+ || regno == tdep->gcs_linux_reg_base + 1))
+ fetch_gcsregs_from_thread (regcache);
}
/* A version of the "fetch_registers" target_ops method used when running
@@ -680,6 +750,9 @@ aarch64_store_registers (struct regcache *regcache, int regno)
if (tdep->has_sme2 ())
store_zt_to_thread (regcache);
+
+ if (tdep->has_gcs_linux ())
+ store_gcsregs_to_thread (regcache);
}
/* General purpose register? */
else if (regno < AARCH64_V0_REGNUM)
@@ -706,6 +779,11 @@ aarch64_store_registers (struct regcache *regcache, int regno)
&& regno >= tdep->tls_regnum_base
&& regno < tdep->tls_regnum_base + tdep->tls_register_count)
store_tlsregs_to_thread (regcache);
+ /* GCS register? */
+ else if (tdep->has_gcs_linux ()
+ && (regno == tdep->gcs_reg_base || regno == tdep->gcs_linux_reg_base
+ || regno == tdep->gcs_linux_reg_base + 1))
+ store_gcsregs_to_thread (regcache);
/* PAuth registers are read-only. */
}
@@ -881,6 +959,7 @@ aarch64_linux_nat_target::read_description ()
active or not. */
features.vq = aarch64_sve_get_vq (tid);
features.pauth = hwcap & AARCH64_HWCAP_PACA;
+ features.gcs = features.gcs_linux = hwcap & HWCAP_GCS;
features.mte = hwcap2 & HWCAP2_MTE;
features.tls = aarch64_tls_register_count (tid);
/* SME feature check. */
@@ -1068,9 +1147,7 @@ aarch64_linux_nat_target::is_address_tagged (gdbarch *gdbarch, CORE_ADDR address
return gdbarch_tagged_address_p (gdbarch, address);
}
-void _initialize_aarch64_linux_nat ();
-void
-_initialize_aarch64_linux_nat ()
+INIT_GDB_FILE (aarch64_linux_nat)
{
aarch64_initialize_hw_point ();
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index b6cdcf0..048be4f 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -23,6 +23,7 @@
#include "extract-store-integer.h"
#include "gdbarch.h"
#include "glibc-tdep.h"
+#include "solib-svr4-linux.h"
#include "linux-tdep.h"
#include "svr4-tls-tdep.h"
#include "aarch64-tdep.h"
@@ -32,6 +33,7 @@
#include "symtab.h"
#include "tramp-frame.h"
#include "trad-frame.h"
+#include "dwarf2/frame.h"
#include "target.h"
#include "target/target.h"
#include "expop.h"
@@ -45,11 +47,11 @@
#include "parser-defs.h"
#include "user-regs.h"
#include "xml-syscall.h"
-#include <ctype.h>
#include "record-full.h"
#include "linux-record.h"
+#include "arch/aarch64-gcs-linux.h"
#include "arch/aarch64-mte.h"
#include "arch/aarch64-mte-linux.h"
#include "arch/aarch64-scalable-linux.h"
@@ -164,6 +166,7 @@
#define AARCH64_ZA_MAGIC 0x54366345
#define AARCH64_TPIDR2_MAGIC 0x54504902
#define AARCH64_ZT_MAGIC 0x5a544e01
+#define AARCH64_GCS_MAGIC 0x47435300
/* Defines for the extra_context that follows an AARCH64_EXTRA_MAGIC. */
#define AARCH64_EXTRA_DATAP_OFFSET 8
@@ -205,6 +208,11 @@
the signal context state. */
#define AARCH64_SME2_CONTEXT_REGS_OFFSET 16
+/* GCSPR register value offset in the GCS signal frame context. */
+#define AARCH64_GCS_CONTEXT_GCSPR_OFFSET 8
+/* features_enabled value offset in the GCS signal frame context. */
+#define AARCH64_GCS_CONTEXT_FEATURES_ENABLED_OFFSET 16
+
/* Holds information about the signal frame. */
struct aarch64_linux_sigframe
{
@@ -245,6 +253,13 @@ struct aarch64_linux_sigframe
bool za_payload = false;
/* True if we have a ZT entry in the signal context, false otherwise. */
bool zt_available = false;
+
+ /* True if we have a GCS entry in the signal context, false otherwise. */
+ bool gcs_availabe = false;
+ /* The Guarded Control Stack Pointer Register. */
+ uint64_t gcspr;
+ /* Flags indicating which GCS features are enabled for the thread. */
+ uint64_t gcs_features_enabled;
};
/* Read an aarch64_ctx, returning the magic value, and setting *SIZE to the
@@ -528,6 +543,39 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame,
section += size;
break;
}
+ case AARCH64_GCS_MAGIC:
+ {
+ gdb_byte buf[8];
+
+ /* Extract the GCSPR. */
+ if (target_read_memory (section + AARCH64_GCS_CONTEXT_GCSPR_OFFSET,
+ buf, 8) != 0)
+ {
+ warning (_("Failed to read the GCS pointer from the GCS signal"
+ " frame context."));
+ section += size;
+ break;
+ }
+
+ signal_frame.gcspr = extract_unsigned_integer (buf, byte_order);
+
+ /* Extract the features_enabled field. */
+ if (target_read_memory (section
+ + AARCH64_GCS_CONTEXT_FEATURES_ENABLED_OFFSET,
+ buf, sizeof (buf)) != 0)
+ {
+ warning (_("Failed to read the enabled features from the GCS"
+ " signal frame context."));
+ section += size;
+ break;
+ }
+
+ signal_frame.gcs_features_enabled
+ = extract_unsigned_integer (buf, byte_order);
+ signal_frame.gcs_availabe = true;
+ section += size;
+ break;
+ }
case AARCH64_EXTRA_MAGIC:
{
/* Extra is always the last valid section in reserved and points to
@@ -702,6 +750,19 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self,
+ AARCH64_TPIDR2_CONTEXT_TPIDR2_OFFSET);
}
+ /* Restore the GCS registers, if the target supports it and if there is
+ an entry for them. */
+ if (signal_frame.gcs_availabe && tdep->has_gcs_linux ())
+ {
+ /* Restore GCSPR. */
+ trad_frame_set_reg_value (this_cache, tdep->gcs_reg_base,
+ signal_frame.gcspr);
+ /* Restore gcs_features_enabled. */
+ trad_frame_set_reg_value (this_cache, tdep->gcs_linux_reg_base,
+ signal_frame.gcs_features_enabled);
+ /* gcs_features_locked isn't present in the GCS signal context. */
+ }
+
trad_frame_set_id (this_cache, frame_id_build (signal_frame.sp, func));
}
@@ -1604,6 +1665,27 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
cb (".reg-aarch-tls", sizeof_tls_regset, sizeof_tls_regset,
&aarch64_linux_tls_regset, "TLS register", cb_data);
}
+
+ /* Handle GCS registers. */
+ if (tdep->has_gcs_linux ())
+ {
+ /* Create this on the fly in order to handle the variable regnums. */
+ const regcache_map_entry gcs_regmap[] =
+ {
+ { 1, tdep->gcs_linux_reg_base, 8 }, /* features_enabled */
+ { 1, tdep->gcs_linux_reg_base + 1, 8 }, /* features_locked */
+ { 1, tdep->gcs_reg_base, 8 }, /* GCSPR */
+ { 0 }
+ };
+
+ const regset aarch64_linux_gcs_regset =
+ {
+ gcs_regmap, regcache_supply_regset, regcache_collect_regset
+ };
+
+ cb (".reg-aarch-gcs", sizeof (user_gcs), sizeof (user_gcs),
+ &aarch64_linux_gcs_regset, "GCS registers", cb_data);
+ }
}
/* Implement the "core_read_description" gdbarch method. */
@@ -1628,6 +1710,7 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
length. */
features.vq = aarch64_linux_core_read_vq_from_sections (gdbarch, abfd);
features.pauth = hwcap & AARCH64_HWCAP_PACA;
+ features.gcs = features.gcs_linux = hwcap & HWCAP_GCS;
features.mte = hwcap2 & HWCAP2_MTE;
/* Handle the TLS section. */
@@ -1665,9 +1748,9 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
static int
aarch64_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
{
- return (*s == '#' || isdigit (*s) /* Literal number. */
+ return (*s == '#' || c_isdigit (*s) /* Literal number. */
|| *s == '[' /* Register indirection. */
- || isalpha (*s)); /* Register value. */
+ || c_isalpha (*s)); /* Register value. */
}
/* This routine is used to parse a special token in AArch64's assembly.
@@ -1698,7 +1781,7 @@ aarch64_stap_parse_special_token (struct gdbarch *gdbarch,
start = tmp;
/* Register name. */
- while (isalnum (*tmp))
+ while (c_isalnum (*tmp))
++tmp;
if (*tmp != ',')
@@ -1726,7 +1809,7 @@ aarch64_stap_parse_special_token (struct gdbarch *gdbarch,
else if (*tmp == '+')
++tmp;
- if (!isdigit (*tmp))
+ if (!c_isdigit (*tmp))
return {};
displacement = strtol (tmp, &endp, 10);
@@ -2452,6 +2535,80 @@ aarch64_linux_tagged_address_p (struct gdbarch *gdbarch, CORE_ADDR address)
return true;
}
+/* Implement the "get_shadow_stack_pointer" gdbarch method. */
+
+static std::optional<CORE_ADDR>
+aarch64_linux_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache,
+ bool &shadow_stack_enabled)
+{
+ aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
+ shadow_stack_enabled = false;
+
+ if (!tdep->has_gcs_linux ())
+ return {};
+
+ uint64_t features_enabled;
+ register_status status = regcache->cooked_read (tdep->gcs_linux_reg_base,
+ &features_enabled);
+ if (status != REG_VALID)
+ error (_("Can't read $gcs_features_enabled."));
+
+ CORE_ADDR gcspr;
+ status = regcache->cooked_read (tdep->gcs_reg_base, &gcspr);
+ if (status != REG_VALID)
+ error (_("Can't read $gcspr."));
+
+ shadow_stack_enabled = features_enabled & PR_SHADOW_STACK_ENABLE;
+ return gcspr;
+}
+
+/* Implement Guarded Control Stack Pointer Register unwinding. For each
+ previous GCS pointer check if its address is still in the GCS memory
+ range. If it's outside the range set the returned value to unavailable,
+ otherwise return a value containing the new GCS pointer. */
+
+static value *
+aarch64_linux_dwarf2_prev_gcspr (const frame_info_ptr &this_frame,
+ void **this_cache, int regnum)
+{
+ value *v = frame_unwind_got_register (this_frame, regnum, regnum);
+ gdb_assert (v != nullptr);
+
+ gdbarch *gdbarch = get_frame_arch (this_frame);
+
+ if (v->entirely_available () && !v->optimized_out ())
+ {
+ int size = register_size (gdbarch, regnum);
+ bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ CORE_ADDR gcspr = extract_unsigned_integer (v->contents_all ().data (),
+ size, byte_order);
+
+ /* Starting with v6.13, the Linux kernel supports Guarded Control
+ Stack. Using /proc/PID/smaps we can only check if the current
+ GCSPR points to GCS memory. Only if this is the case a valid
+ previous GCS pointer can be calculated. */
+ std::pair<CORE_ADDR, CORE_ADDR> range;
+ if (linux_address_in_shadow_stack_mem_range (gcspr, &range))
+ {
+ /* The GCS grows downwards. To compute the previous GCS pointer,
+ we need to increment the GCSPR. */
+ CORE_ADDR new_gcspr = gcspr + 8;
+
+ /* If NEW_GCSPR still points within the current GCS memory range
+ we consider it to be valid. */
+ if (new_gcspr < range.second)
+ return frame_unwind_got_address (this_frame, regnum, new_gcspr);
+ }
+ }
+
+ /* Return a value which is marked as unavailable in case we could not
+ calculate a valid previous GCS pointer. */
+ value *retval
+ = value::allocate_register (get_next_frame_sentinel_okay (this_frame),
+ regnum, register_type (gdbarch, regnum));
+ retval->mark_bytes_unavailable (0, retval->type ()->length ());
+ return retval;
+}
/* AArch64 Linux implementation of the report_signal_info gdbarch
hook. Displays information about possible memory tag violations. */
@@ -2463,17 +2620,18 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch,
{
aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
- if (!tdep->has_mte () || siggnal != GDB_SIGNAL_SEGV)
+ if (!(tdep->has_mte () || tdep->has_gcs ()) || siggnal != GDB_SIGNAL_SEGV)
return;
CORE_ADDR fault_addr = 0;
- long si_code = 0;
+ long si_code = 0, si_errno = 0;
try
{
/* Sigcode tells us if the segfault is actually a memory tag
violation. */
si_code = parse_and_eval_long ("$_siginfo.si_code");
+ si_errno = parse_and_eval_long ("$_siginfo.si_errno");
fault_addr
= parse_and_eval_long ("$_siginfo._sifields._sigfault.si_addr");
@@ -2484,13 +2642,18 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch,
return;
}
- /* If this is not a memory tag violation, just return. */
- if (si_code != SEGV_MTEAERR && si_code != SEGV_MTESERR)
+ const char *meaning;
+
+ if (si_code == SEGV_MTEAERR || si_code == SEGV_MTESERR)
+ meaning = _("Memory tag violation");
+ else if (si_code == SEGV_CPERR && si_errno == 0)
+ meaning = _("Guarded Control Stack error");
+ else
return;
uiout->text ("\n");
- uiout->field_string ("sigcode-meaning", _("Memory tag violation"));
+ uiout->field_string ("sigcode-meaning", meaning);
/* For synchronous faults, show additional information. */
if (si_code == SEGV_MTESERR)
@@ -2516,7 +2679,7 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch,
uiout->field_string ("logical-tag", hex_string (ltag));
}
}
- else
+ else if (si_code != SEGV_CPERR)
{
uiout->text ("\n");
uiout->text (_("Fault address unavailable"));
@@ -2599,8 +2762,8 @@ aarch64_linux_fill_memtag_section (struct gdbarch *gdbarch, asection *osec)
static_cast<int> (memtag_type::allocation)))
{
warning (_("Failed to read MTE tags from memory range [%s,%s)."),
- phex_nz (start_address, sizeof (start_address)),
- phex_nz (end_address, sizeof (end_address)));
+ phex_nz (start_address),
+ phex_nz (end_address));
return false;
}
@@ -2765,12 +2928,17 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
NULL };
aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
+ if (tdep->has_gcs () && !tdep->has_gcs_linux ())
+ {
+ warning (_("Incomplete GCS support in the target: missing Linux part."
+ " GCS feature disabled."));
+ tdep->gcs_reg_base = -1;
+ }
+
tdep->lowest_pc = 0x8000;
linux_init_abi (info, gdbarch, 1);
-
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- linux_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_lp64_svr4_solib_ops);
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
@@ -2815,9 +2983,6 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Register a hook for checking if an address is tagged or not. */
set_gdbarch_tagged_address_p (gdbarch, aarch64_linux_tagged_address_p);
- set_gdbarch_report_signal_info (gdbarch,
- aarch64_linux_report_signal_info);
-
/* Core file helpers. */
/* Core file helper to create a memory tag section for a particular
@@ -2834,6 +2999,9 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
aarch64_linux_decode_memtag_section);
}
+ if (tdep->has_mte () || tdep->has_gcs ())
+ set_gdbarch_report_signal_info (gdbarch, aarch64_linux_report_signal_info);
+
/* Initialize the aarch64_linux_record_tdep. */
/* These values are the size of the type that will be used in a system
call. They are obtained from Linux Kernel source. */
@@ -3015,6 +3183,13 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
sections. */
set_gdbarch_use_target_description_from_corefile_notes (gdbarch,
aarch64_use_target_description_from_corefile_notes);
+
+ if (tdep->has_gcs_linux ())
+ {
+ set_gdbarch_get_shadow_stack_pointer (gdbarch,
+ aarch64_linux_get_shadow_stack_pointer);
+ tdep->fn_prev_gcspr = aarch64_linux_dwarf2_prev_gcspr;
+ }
}
#if GDB_SELF_TEST
@@ -3041,9 +3216,7 @@ aarch64_linux_ltag_tests (void)
} /* namespace selftests */
#endif /* GDB_SELF_TEST */
-void _initialize_aarch64_linux_tdep ();
-void
-_initialize_aarch64_linux_tdep ()
+INIT_GDB_FILE (aarch64_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_LINUX,
aarch64_linux_init_abi);
diff --git a/gdb/aarch64-nat.h b/gdb/aarch64-nat.h
index 3120bca..ec7c564 100644
--- a/gdb/aarch64-nat.h
+++ b/gdb/aarch64-nat.h
@@ -92,10 +92,6 @@ struct aarch64_nat_target : public BaseTarget
int remove_hw_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt) override
{ return aarch64_remove_hw_breakpoint (gdbarch, bp_tgt); }
-
- bool watchpoint_addr_within_range (CORE_ADDR addr, CORE_ADDR start,
- int length) override
- { return start <= addr && start + length - 1 >= addr; }
};
#endif /* GDB_AARCH64_NAT_H */
diff --git a/gdb/aarch64-newlib-tdep.c b/gdb/aarch64-newlib-tdep.c
index c0ecd3f..5045d5f9 100644
--- a/gdb/aarch64-newlib-tdep.c
+++ b/gdb/aarch64-newlib-tdep.c
@@ -35,9 +35,7 @@ aarch64_newlib_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->jb_pc = 11;
}
-void _initialize_aarch64_newlib_tdep ();
-void
-_initialize_aarch64_newlib_tdep ()
+INIT_GDB_FILE (aarch64_newlib_tdep)
{
gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_NEWLIB,
aarch64_newlib_init_abi);
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index bf5b5d3..500ac77d 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -159,6 +159,18 @@ static const char *const aarch64_mte_register_names[] =
"tag_ctl"
};
+static const char *const aarch64_gcs_register_names[] = {
+ /* Guarded Control Stack Pointer Register. */
+ "gcspr"
+};
+
+static const char *const aarch64_gcs_linux_register_names[] = {
+ /* Field in struct user_gcs. */
+ "gcs_features_enabled",
+ /* Field in struct user_gcs. */
+ "gcs_features_locked",
+};
+
static int aarch64_stack_frame_destroyed_p (struct gdbarch *, CORE_ADDR);
/* AArch64 prologue cache structure. */
@@ -1396,6 +1408,12 @@ aarch64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
return;
}
}
+ if (tdep->has_gcs () && tdep->fn_prev_gcspr != nullptr
+ && regnum == tdep->gcs_reg_base)
+ {
+ reg->how = DWARF2_FRAME_REG_FN;
+ reg->loc.fn = tdep->fn_prev_gcspr;
+ }
}
/* Implement the execute_dwarf_cfa_vendor_op method. */
@@ -1875,6 +1893,55 @@ pass_in_v_vfp_candidate (struct gdbarch *gdbarch, struct regcache *regcache,
}
}
+/* Push LR_VALUE to the Guarded Control Stack. */
+
+static void
+aarch64_push_gcs_entry (regcache *regs, CORE_ADDR lr_value)
+{
+ gdbarch *arch = regs->arch ();
+ aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (arch);
+ CORE_ADDR gcs_addr;
+
+ register_status status = regs->cooked_read (tdep->gcs_reg_base, &gcs_addr);
+ if (status != REG_VALID)
+ error (_("Can't read $gcspr."));
+
+ gcs_addr -= 8;
+ gdb_byte buf[8];
+ store_integer (buf, gdbarch_byte_order (arch), lr_value);
+ if (target_write_memory (gcs_addr, buf, sizeof (buf)) != 0)
+ error (_("Can't write to Guarded Control Stack."));
+
+ /* Update GCSPR. */
+ regcache_cooked_write_unsigned (regs, tdep->gcs_reg_base, gcs_addr);
+}
+
+/* Remove the newest entry from the Guarded Control Stack. */
+
+static void
+aarch64_pop_gcs_entry (regcache *regs)
+{
+ gdbarch *arch = regs->arch ();
+ aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (arch);
+ CORE_ADDR gcs_addr;
+
+ register_status status = regs->cooked_read (tdep->gcs_reg_base, &gcs_addr);
+ if (status != REG_VALID)
+ error (_("Can't read $gcspr."));
+
+ /* Update GCSPR. */
+ regcache_cooked_write_unsigned (regs, tdep->gcs_reg_base, gcs_addr + 8);
+}
+
+/* Implement the "shadow_stack_push" gdbarch method. */
+
+static void
+aarch64_shadow_stack_push (gdbarch *gdbarch, CORE_ADDR new_addr,
+ regcache *regcache)
+{
+ aarch64_push_gcs_entry (regcache, new_addr);
+}
+
/* Implement the "push_dummy_call" gdbarch method. */
static CORE_ADDR
@@ -3557,6 +3624,9 @@ struct aarch64_displaced_step_copy_insn_closure
/* PC adjustment offset after displaced stepping. If 0, then we don't
write the PC back, assuming the PC is already the right address. */
int32_t pc_adjust = 0;
+
+ /* True if it's a branch instruction that saves the link register. */
+ bool linked_branch = false;
};
/* Data when visiting instructions for displaced stepping. */
@@ -3608,6 +3678,12 @@ aarch64_displaced_step_b (const int is_bl, const int32_t offset,
/* Update LR. */
regcache_cooked_write_unsigned (dsd->regs, AARCH64_LR_REGNUM,
data->insn_addr + 4);
+ dsd->dsc->linked_branch = true;
+ bool gcs_is_enabled;
+ gdbarch_get_shadow_stack_pointer (dsd->regs->arch (), dsd->regs,
+ gcs_is_enabled);
+ if (gcs_is_enabled)
+ aarch64_push_gcs_entry (dsd->regs, data->insn_addr + 4);
}
}
@@ -3766,6 +3842,12 @@ aarch64_displaced_step_others (const uint32_t insn,
aarch64_emit_insn (dsd->insn_buf, insn & 0xffdfffff);
regcache_cooked_write_unsigned (dsd->regs, AARCH64_LR_REGNUM,
data->insn_addr + 4);
+ dsd->dsc->linked_branch = true;
+ bool gcs_is_enabled;
+ gdbarch_get_shadow_stack_pointer (dsd->regs->arch (), dsd->regs,
+ gcs_is_enabled);
+ if (gcs_is_enabled)
+ aarch64_push_gcs_entry (dsd->regs, data->insn_addr + 4);
}
else
aarch64_emit_insn (dsd->insn_buf, insn);
@@ -3862,20 +3944,24 @@ aarch64_displaced_step_fixup (struct gdbarch *gdbarch,
CORE_ADDR from, CORE_ADDR to,
struct regcache *regs, bool completed_p)
{
+ aarch64_displaced_step_copy_insn_closure *dsc
+ = (aarch64_displaced_step_copy_insn_closure *) dsc_;
CORE_ADDR pc = regcache_read_pc (regs);
- /* If the displaced instruction didn't complete successfully then all we
- need to do is restore the program counter. */
+ /* If the displaced instruction didn't complete successfully then we need
+ to restore the program counter, and perhaps the Guarded Control Stack. */
if (!completed_p)
{
+ bool gcs_is_enabled;
+ gdbarch_get_shadow_stack_pointer (gdbarch, regs, gcs_is_enabled);
+ if (dsc->linked_branch && gcs_is_enabled)
+ aarch64_pop_gcs_entry (regs);
+
pc = from + (pc - to);
regcache_write_pc (regs, pc);
return;
}
- aarch64_displaced_step_copy_insn_closure *dsc
- = (aarch64_displaced_step_copy_insn_closure *) dsc_;
-
displaced_debug_printf ("PC after stepping: %s (was %s).",
paddress (gdbarch, pc), paddress (gdbarch, to));
@@ -4046,6 +4132,14 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc)
features.sme2 = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.sme2")
!= nullptr);
+ /* Check for the GCS feature. */
+ features.gcs = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.gcs")
+ != nullptr);
+
+ /* Check for the GCS Linux feature. */
+ features.gcs_linux = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.gcs.linux")
+ != nullptr);
+
return features;
}
@@ -4236,7 +4330,7 @@ aarch64_memtag_to_string (struct gdbarch *gdbarch, struct value *tag_value)
CORE_ADDR tag = value_as_address (tag_value);
- return string_printf ("0x%s", phex_nz (tag, sizeof (tag)));
+ return string_printf ("0x%s", phex_nz (tag));
}
/* See aarch64-tdep.h. */
@@ -4590,6 +4684,48 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
int first_w_regnum = num_pseudo_regs;
num_pseudo_regs += 31;
+ const tdesc_feature *feature_gcs
+ = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.gcs");
+ int first_gcs_regnum = -1;
+ /* Add the GCS registers. */
+ if (feature_gcs != nullptr)
+ {
+ first_gcs_regnum = num_regs;
+ /* Validate the descriptor provides the mandatory GCS registers and
+ allocate their numbers. */
+ for (i = 0; i < ARRAY_SIZE (aarch64_gcs_register_names); i++)
+ valid_p &= tdesc_numbered_register (feature_gcs, tdesc_data.get (),
+ first_gcs_regnum + i,
+ aarch64_gcs_register_names[i]);
+
+ num_regs += i;
+ }
+
+ if (!valid_p)
+ return nullptr;
+
+ const tdesc_feature *feature_gcs_linux
+ = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.gcs.linux");
+ int first_gcs_linux_regnum = -1;
+ /* Add the GCS Linux registers. */
+ if (feature_gcs_linux != nullptr && feature_gcs == nullptr)
+ {
+ /* This feature depends on the GCS feature. */
+ return nullptr;
+ }
+ else if (feature_gcs_linux != nullptr)
+ {
+ first_gcs_linux_regnum = num_regs;
+ /* Validate the descriptor provides the mandatory GCS Linux registers
+ and allocate their numbers. */
+ for (i = 0; i < ARRAY_SIZE (aarch64_gcs_linux_register_names); i++)
+ valid_p &= tdesc_numbered_register (feature_gcs_linux, tdesc_data.get (),
+ first_gcs_linux_regnum + i,
+ aarch64_gcs_linux_register_names[i]);
+
+ num_regs += i;
+ }
+
if (!valid_p)
return nullptr;
@@ -4611,6 +4747,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->mte_reg_base = first_mte_regnum;
tdep->tls_regnum_base = first_tls_regnum;
tdep->tls_register_count = tls_register_count;
+ tdep->gcs_reg_base = first_gcs_regnum;
+ tdep->gcs_linux_reg_base = first_gcs_linux_regnum;
/* Set the SME register set details. The pseudo-registers will be adjusted
later. */
@@ -4638,7 +4776,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_sw_breakpoint_from_kind (gdbarch,
aarch64_breakpoint::bp_from_kind);
set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
- set_gdbarch_software_single_step (gdbarch, aarch64_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, aarch64_software_single_step);
/* Information about registers, etc. */
set_gdbarch_sp_regnum (gdbarch, AARCH64_SP_REGNUM);
@@ -4733,6 +4871,9 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_get_pc_address_flags (gdbarch, aarch64_get_pc_address_flags);
+ if (tdep->has_gcs ())
+ set_gdbarch_shadow_stack_push (gdbarch, aarch64_shadow_stack_push);
+
tdesc_use_registers (gdbarch, tdesc, std::move (tdesc_data));
/* Fetch the updated number of registers after we're done adding all
@@ -4905,6 +5046,11 @@ aarch64_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
pulongest (tdep->sme_tile_pseudo_base));
gdb_printf (file, _("aarch64_dump_tdep: sme_svq = %s\n"),
pulongest (tdep->sme_svq));
+
+ gdb_printf (file, _("aarch64_dump_tdep: gcs_reg_base = %d\n"),
+ tdep->gcs_reg_base);
+ gdb_printf (file, _("aarch64_dump_tdep: gcs_linux_reg_base = %d\n"),
+ tdep->gcs_linux_reg_base);
}
#if GDB_SELF_TEST
@@ -4914,9 +5060,7 @@ static void aarch64_process_record_test (void);
}
#endif
-void _initialize_aarch64_tdep ();
-void
-_initialize_aarch64_tdep ()
+INIT_GDB_FILE (aarch64_tdep)
{
gdbarch_register (bfd_arch_aarch64, aarch64_gdbarch_init,
aarch64_dump_tdep);
diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
index 3b8dcc2..99e7d26 100644
--- a/gdb/aarch64-tdep.h
+++ b/gdb/aarch64-tdep.h
@@ -23,6 +23,7 @@
#define GDB_AARCH64_TDEP_H
#include "arch/aarch64.h"
+#include "dwarf2/frame.h"
#include "displaced-stepping.h"
#include "infrun.h"
#include "gdbarch.h"
@@ -182,6 +183,30 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base
{
return sme2_zt0_regnum > 0;
}
+
+ /* First GCS register. This is -1 if no GCS registers are available. */
+ int gcs_reg_base = -1;
+
+ /* First GCS Linux-specific register. This is -1 if no GCS Linux feature is
+ available. */
+ int gcs_linux_reg_base = -1;
+
+ /* Function to unwind the GCSPR from the given frame. */
+ fn_prev_register fn_prev_gcspr = nullptr;
+
+ /* Returns true if the target supports GCS. */
+ bool
+ has_gcs () const
+ {
+ return gcs_reg_base != -1;
+ }
+
+ /* Returns true if the target supports the Linux GCS feature. */
+ bool
+ has_gcs_linux () const
+ {
+ return gcs_linux_reg_base != -1;
+ }
};
const target_desc *aarch64_read_description (const aarch64_features &features);
diff --git a/gdb/ada-exp.h b/gdb/ada-exp.h
index 8c9bfe8..7354d65 100644
--- a/gdb/ada-exp.h
+++ b/gdb/ada-exp.h
@@ -34,28 +34,10 @@ extern struct value *ada_abs (struct type *expect_type,
struct expression *exp,
enum noside noside, enum exp_opcode op,
struct value *arg1);
-extern struct value *ada_unop_in_range (struct type *expect_type,
- struct expression *exp,
- enum noside noside, enum exp_opcode op,
- struct value *arg1, struct type *type);
extern struct value *ada_mult_binop (struct type *expect_type,
struct expression *exp,
enum noside noside, enum exp_opcode op,
struct value *arg1, struct value *arg2);
-extern struct value *ada_equal_binop (struct type *expect_type,
- struct expression *exp,
- enum noside noside, enum exp_opcode op,
- struct value *arg1, struct value *arg2);
-extern struct value *ada_ternop_slice (struct expression *exp,
- enum noside noside,
- struct value *array,
- struct value *low_bound_val,
- struct value *high_bound_val);
-extern struct value *ada_binop_in_bounds (struct expression *exp,
- enum noside noside,
- struct value *arg1,
- struct value *arg2,
- int n);
extern struct value *ada_binop_minmax (struct type *expect_type,
struct expression *exp,
enum noside noside, enum exp_opcode op,
@@ -224,12 +206,7 @@ public:
value *evaluate (struct type *expect_type,
struct expression *exp,
- enum noside noside) override
- {
- value *val = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
- return ada_unop_in_range (expect_type, exp, noside, UNOP_IN_RANGE,
- val, std::get<1> (m_storage));
- }
+ enum noside noside) override;
enum exp_opcode opcode () const override
{ return UNOP_IN_RANGE; }
@@ -271,14 +248,7 @@ public:
value *evaluate (struct type *expect_type,
struct expression *exp,
- enum noside noside) override
- {
- value *arg1 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
- value *arg2 = std::get<2> (m_storage)->evaluate (arg1->type (),
- exp, noside);
- return ada_equal_binop (expect_type, exp, noside, std::get<0> (m_storage),
- arg1, arg2);
- }
+ enum noside noside) override;
void do_generate_ax (struct expression *exp,
struct agent_expr *ax,
@@ -307,13 +277,7 @@ public:
value *evaluate (struct type *expect_type,
struct expression *exp,
- enum noside noside) override
- {
- value *array = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
- value *low = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
- value *high = std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
- return ada_ternop_slice (exp, noside, array, low, high);
- }
+ enum noside noside) override;
enum exp_opcode opcode () const override
{ return TERNOP_SLICE; }
@@ -335,13 +299,7 @@ public:
value *evaluate (struct type *expect_type,
struct expression *exp,
- enum noside noside) override
- {
- value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
- value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
- return ada_binop_in_bounds (exp, noside, arg1, arg2,
- std::get<2> (m_storage));
- }
+ enum noside noside) override;
enum exp_opcode opcode () const override
{ return BINOP_IN_BOUNDS; }
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 1546ae9..ed5694e 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -35,7 +35,6 @@
%{
-#include <ctype.h>
#include "gdbsupport/unordered_map.h"
#include "expression.h"
#include "value.h"
@@ -1338,7 +1337,7 @@ write_object_renaming (struct parser_state *par_state,
SEARCH_VFT);
if (sym_info.symbol == NULL)
error (_("Could not find renamed variable: %s"), ada_decode (name).c_str ());
- else if (sym_info.symbol->aclass () == LOC_TYPEDEF)
+ else if (sym_info.symbol->loc_class () == LOC_TYPEDEF)
/* We have a renaming of an old-style renaming symbol. Don't
trust the block information. */
sym_info.block = orig_left_context;
@@ -1380,7 +1379,7 @@ write_object_renaming (struct parser_state *par_state,
[[fallthrough]];
case 'S':
renaming_expr += 1;
- if (isdigit (*renaming_expr))
+ if (c_isdigit (*renaming_expr))
{
char *next;
long val = strtol (renaming_expr, &next, 10);
@@ -1408,7 +1407,7 @@ write_object_renaming (struct parser_state *par_state,
SEARCH_VFT);
if (index_sym_info.symbol == NULL)
error (_("Could not find %s"), index_name);
- else if (index_sym_info.symbol->aclass () == LOC_TYPEDEF)
+ else if (index_sym_info.symbol->loc_class () == LOC_TYPEDEF)
/* Index is an old-style renaming symbol. */
index_sym_info.block = orig_left_context;
write_var_from_sym (par_state, index_sym_info);
@@ -1478,14 +1477,14 @@ block_lookup (const struct block *context, const char *raw_name)
= ada_lookup_symbol_list (name, context, SEARCH_FUNCTION_DOMAIN);
if (context == NULL
- && (syms.empty () || syms[0].symbol->aclass () != LOC_BLOCK))
+ && (syms.empty () || syms[0].symbol->loc_class () != LOC_BLOCK))
symtab = lookup_symtab (current_program_space, name);
else
symtab = NULL;
if (symtab != NULL)
result = symtab->compunit ()->blockvector ()->static_block ();
- else if (syms.empty () || syms[0].symbol->aclass () != LOC_BLOCK)
+ else if (syms.empty () || syms[0].symbol->loc_class () != LOC_BLOCK)
{
if (context == NULL)
error (_("No file or function \"%s\"."), raw_name);
@@ -1511,7 +1510,7 @@ select_possible_type_sym (const std::vector<struct block_symbol> &syms)
preferred_index = -1; preferred_type = NULL;
for (i = 0; i < syms.size (); i += 1)
- switch (syms[i].symbol->aclass ())
+ switch (syms[i].symbol->loc_class ())
{
case LOC_TYPEDEF:
if (ada_prefer_type (syms[i].symbol->type (), preferred_type))
@@ -1555,7 +1554,7 @@ find_primitive_type (struct parser_state *par_state, const char *name)
strcpy (expanded_name, "standard__");
strcat (expanded_name, name);
sym = ada_lookup_symbol (expanded_name, NULL, SEARCH_TYPE_DOMAIN).symbol;
- if (sym != NULL && sym->aclass () == LOC_TYPEDEF)
+ if (sym != NULL && sym->loc_class () == LOC_TYPEDEF)
type = sym->type ();
}
@@ -1888,7 +1887,7 @@ ada_parse_state::find_completion_bounds ()
const char *end = pstate->lexptr;
/* First the end of the prefix. Here we stop at the token start or
at '.' or space. */
- for (; end > m_original_expr && end[-1] != '.' && !isspace (end[-1]); --end)
+ for (; end > m_original_expr && end[-1] != '.' && !c_isspace (end[-1]); --end)
{
/* Nothing. */
}
@@ -1966,7 +1965,7 @@ write_name_assoc (struct parser_state *par_state, struct stoken name)
par_state->expression_context_block,
SEARCH_VFT);
- if (syms.size () != 1 || syms[0].symbol->aclass () == LOC_TYPEDEF)
+ if (syms.size () != 1 || syms[0].symbol->loc_class () == LOC_TYPEDEF)
pstate->push_new<ada_string_operation> (copy_name (name));
else
write_var_from_sym (par_state, syms[0]);
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 3f5e707..af7bc1e 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -18,7 +18,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include <ctype.h>
#include "event-top.h"
#include "exceptions.h"
#include "extract-store-integer.h"
@@ -183,7 +182,7 @@ static struct value *ada_search_struct_field (const char *, struct value *, int,
struct type *);
static int find_struct_field (const char *, struct type *, int,
- struct type **, int *, int *, int *, int *);
+ struct type **, int *, int *, int *, LONGEST *);
static int ada_resolve_function (std::vector<struct block_symbol> &,
struct value **, int, const char *,
@@ -875,7 +874,7 @@ is_compiler_suffix (const char *str)
{
gdb_assert (*str == '[');
++str;
- while (*str != '\0' && isalpha (*str))
+ while (*str != '\0' && c_isalpha (*str))
++str;
/* We accept a missing "]" in order to support completion. */
return *str == '\0' || (str[0] == ']' && str[1] == '\0');
@@ -1167,7 +1166,7 @@ ada_encode (const char *decoded, bool fold)
static int
is_lower_alphanum (const char c)
{
- return (isdigit (c) || (isalpha (c) && islower (c)));
+ return (c_isdigit (c) || (c_isalpha (c) && c_islower (c)));
}
/* ENCODED is the linkage name of a symbol and LEN contains its length.
@@ -1185,11 +1184,11 @@ is_lower_alphanum (const char c)
static void
ada_remove_trailing_digits (const char *encoded, int *len)
{
- if (*len > 1 && isdigit (encoded[*len - 1]))
+ if (*len > 1 && c_isdigit (encoded[*len - 1]))
{
int i = *len - 2;
- while (i > 0 && isdigit (encoded[i]))
+ while (i > 0 && c_isdigit (encoded[i]))
i--;
if (i >= 0 && encoded[i] == '.')
*len = i;
@@ -1220,7 +1219,7 @@ ada_remove_po_subprogram_suffix (const char *encoded, int *len)
if (*len > 1
&& encoded[*len - 1] == 'N'
- && (isdigit (encoded[*len - 2]) || islower (encoded[*len - 2])))
+ && (c_isdigit (encoded[*len - 2]) || c_islower (encoded[*len - 2])))
*len = *len - 1;
}
@@ -1232,7 +1231,7 @@ static int
remove_compiler_suffix (const char *encoded, int *len)
{
int offset = *len - 1;
- while (offset > 0 && isalpha (encoded[offset]))
+ while (offset > 0 && c_isalpha (encoded[offset]))
--offset;
if (offset > 0 && encoded[offset] == '.')
{
@@ -1252,7 +1251,7 @@ convert_hex (const char *str, int n, uint32_t *out)
for (int i = 0; i < n; ++i)
{
- if (!isxdigit (str[i]))
+ if (!c_isxdigit (str[i]))
return false;
result <<= 4;
result |= fromhex (str[i]);
@@ -1311,7 +1310,7 @@ convert_from_hex_encoded (std::string &out, const char *str, int n)
/* See ada-lang.h. */
std::string
-ada_decode (const char *encoded, bool wrap, bool operators, bool wide)
+ada_decode (const char *encoded, bool wrap, bool translate)
{
int i;
int len0;
@@ -1384,11 +1383,11 @@ ada_decode (const char *encoded, bool wrap, bool operators, bool wide)
/* Remove trailing __{digit}+ or trailing ${digit}+. */
- if (len0 > 1 && isdigit (encoded[len0 - 1]))
+ if (len0 > 1 && c_isdigit (encoded[len0 - 1]))
{
i = len0 - 2;
- while ((i >= 0 && isdigit (encoded[i]))
- || (i >= 1 && encoded[i] == '_' && isdigit (encoded[i - 1])))
+ while ((i >= 0 && c_isdigit (encoded[i]))
+ || (i >= 1 && encoded[i] == '_' && c_isdigit (encoded[i - 1])))
i -= 1;
if (i > 1 && encoded[i] == '_' && encoded[i - 1] == '_')
len0 = i - 1;
@@ -1399,14 +1398,14 @@ ada_decode (const char *encoded, bool wrap, bool operators, bool wide)
/* The first few characters that are not alphabetic are not part
of any encoding we use, so we can copy them over verbatim. */
- for (i = 0; i < len0 && !isalpha (encoded[i]); i += 1)
+ for (i = 0; i < len0 && !c_isalpha (encoded[i]); i += 1)
decoded.push_back (encoded[i]);
at_start_name = 1;
while (i < len0)
{
/* Is this a symbol function? */
- if (operators && at_start_name && encoded[i] == 'O')
+ if (at_start_name && encoded[i] == 'O')
{
int k;
@@ -1415,9 +1414,12 @@ ada_decode (const char *encoded, bool wrap, bool operators, bool wide)
int op_len = strlen (ada_opname_table[k].encoded);
if ((strncmp (ada_opname_table[k].encoded + 1, encoded + i + 1,
op_len - 1) == 0)
- && !isalnum (encoded[i + op_len]))
+ && !c_isalnum (encoded[i + op_len]))
{
- decoded.append (ada_opname_table[k].decoded);
+ if (translate)
+ decoded.append (ada_opname_table[k].decoded);
+ else
+ decoded.append (ada_opname_table[k].encoded);
at_start_name = 0;
i += op_len;
break;
@@ -1440,11 +1442,11 @@ ada_decode (const char *encoded, bool wrap, bool operators, bool wide)
if (len0 - i > 5 && encoded [i] == '_' && encoded [i+1] == '_'
&& encoded [i+2] == 'B' && encoded [i+3] == '_'
- && isdigit (encoded [i+4]))
+ && c_isdigit (encoded [i+4]))
{
int k = i + 5;
- while (k < len0 && isdigit (encoded[k]))
+ while (k < len0 && c_isdigit (encoded[k]))
k++; /* Skip any extra digit. */
/* Double-check that the "__B_{DIGITS}+" sequence we found
@@ -1467,11 +1469,11 @@ ada_decode (const char *encoded, bool wrap, bool operators, bool wide)
internally generated. */
if (len0 - i > 3 && encoded [i] == '_' && encoded[i+1] == 'E'
- && isdigit (encoded[i+2]))
+ && c_isdigit (encoded[i+2]))
{
int k = i + 3;
- while (k < len0 && isdigit (encoded[k]))
+ while (k < len0 && c_isdigit (encoded[k]))
k++;
if (k < len0
@@ -1505,33 +1507,65 @@ ada_decode (const char *encoded, bool wrap, bool operators, bool wide)
i++;
}
- if (wide && i < len0 + 3 && encoded[i] == 'U' && isxdigit (encoded[i + 1]))
+ /* Handle wide characters while respecting the arguments to the
+ function: we may want to copy them verbatim, but in this case
+ we do not want to register that we've copied an upper-case
+ character. */
+ if (i < len0 + 3 && encoded[i] == 'U' && c_isxdigit (encoded[i + 1]))
{
- if (convert_from_hex_encoded (decoded, &encoded[i + 1], 2))
+ if (translate)
{
- i += 3;
+ if (convert_from_hex_encoded (decoded, &encoded[i + 1], 2))
+ {
+ i += 3;
+ continue;
+ }
+ }
+ else
+ {
+ decoded.push_back (encoded[i]);
+ ++i;
continue;
}
}
- else if (wide && i < len0 + 5 && encoded[i] == 'W' && isxdigit (encoded[i + 1]))
+ else if (i < len0 + 5 && encoded[i] == 'W'
+ && c_isxdigit (encoded[i + 1]))
{
- if (convert_from_hex_encoded (decoded, &encoded[i + 1], 4))
+ if (translate)
+ {
+ if (convert_from_hex_encoded (decoded, &encoded[i + 1], 4))
+ {
+ i += 5;
+ continue;
+ }
+ }
+ else
{
- i += 5;
+ decoded.push_back (encoded[i]);
+ ++i;
continue;
}
}
- else if (wide && i < len0 + 10 && encoded[i] == 'W' && encoded[i + 1] == 'W'
- && isxdigit (encoded[i + 2]))
+ else if (i < len0 + 10 && encoded[i] == 'W' && encoded[i + 1] == 'W'
+ && c_isxdigit (encoded[i + 2]))
{
- if (convert_from_hex_encoded (decoded, &encoded[i + 2], 8))
+ if (translate)
{
- i += 10;
+ if (convert_from_hex_encoded (decoded, &encoded[i + 2], 8))
+ {
+ i += 10;
+ continue;
+ }
+ }
+ else
+ {
+ decoded.push_back (encoded[i]);
+ ++i;
continue;
}
}
- if (encoded[i] == 'X' && i != 0 && isalnum (encoded[i - 1]))
+ if (encoded[i] == 'X' && i != 0 && c_isalnum (encoded[i - 1]))
{
/* This is a X[bn]* sequence not separated from the previous
part of the name with a non-alpha-numeric character (in other
@@ -1553,6 +1587,12 @@ ada_decode (const char *encoded, bool wrap, bool operators, bool wide)
at_start_name = 1;
i += 2;
}
+ else if (isupper (encoded[i]) || encoded[i] == ' ')
+ {
+ /* Decoded names should never contain any uppercase
+ character. */
+ goto Suppress;
+ }
else
{
/* It's a character part of the decoded name, so just copy it
@@ -1562,16 +1602,6 @@ ada_decode (const char *encoded, bool wrap, bool operators, bool wide)
}
}
- /* Decoded names should never contain any uppercase character.
- Double-check this, and abort the decoding if we find one. */
-
- if (operators)
- {
- for (i = 0; i < decoded.length(); ++i)
- if (isupper (decoded[i]) || decoded[i] == ' ')
- goto Suppress;
- }
-
/* If the compiler added a suffix, append it now. */
if (suffix >= 0)
decoded = decoded + "[" + &encoded[suffix] + "]";
@@ -1597,6 +1627,13 @@ ada_decode_tests ()
/* This isn't valid, but used to cause a crash. PR gdb/30639. The
result does not really matter very much. */
SELF_CHECK (ada_decode ("44") == "44");
+
+ /* Check that the settings used by the DWARF reader have the desired
+ effect. */
+ SELF_CHECK (ada_decode ("symada__cS", false, false) == "");
+ SELF_CHECK (ada_decode ("pkg__Oxor", false, false) == "pkg.Oxor");
+ SELF_CHECK (ada_decode ("pack__func_W017b", false, false)
+ == "pack.func_W017b");
}
#endif
@@ -1677,8 +1714,6 @@ ada_decode_symbol (const struct general_symbol_info *arg)
void
ada_fixup_array_indexes_type (struct type *index_desc_type)
{
- int i;
-
if (index_desc_type == NULL)
return;
gdb_assert (index_desc_type->num_fields () > 0);
@@ -1696,13 +1731,13 @@ ada_fixup_array_indexes_type (struct type *index_desc_type)
return;
/* Fixup each field of INDEX_DESC_TYPE. */
- for (i = 0; i < index_desc_type->num_fields (); i++)
+ for (auto &field : index_desc_type->fields ())
{
- const char *name = index_desc_type->field (i).name ();
+ const char *name = field.name ();
struct type *raw_type = ada_check_typedef (ada_find_any_type (name));
if (raw_type)
- index_desc_type->field (i).set_type (raw_type);
+ field.set_type (raw_type);
}
}
@@ -2140,8 +2175,8 @@ ada_type_of_array (struct value *arr, int bounds)
arity -= 1;
struct type *range_type
= create_static_range_type (alloc, low->type (),
- longest_to_int (value_as_long (low)),
- longest_to_int (value_as_long (high)));
+ value_as_long (low),
+ value_as_long (high));
elt_type = create_array_type (alloc, elt_type, range_type);
INIT_GNAT_SPECIFIC (elt_type);
@@ -3084,7 +3119,7 @@ ada_value_ptr_subscript (struct value *arr, int arity, struct value **ind)
this array is LOW, as per Ada rules. */
static struct value *
ada_value_slice_from_ptr (struct value *array_ptr, struct type *type,
- int low, int high)
+ LONGEST low, LONGEST high)
{
struct type *type0 = ada_check_typedef (type);
struct type *base_index_type = type0->index_type ()->target_type ();
@@ -3095,7 +3130,7 @@ ada_value_slice_from_ptr (struct value *array_ptr, struct type *type,
(alloc, type0->target_type (), index_type,
type0->dyn_prop (DYN_PROP_BYTE_STRIDE),
type0->field (0).bitsize ());
- int base_low = ada_discrete_type_low_bound (type0->index_type ());
+ LONGEST base_low = ada_discrete_type_low_bound (type0->index_type ());
std::optional<LONGEST> base_low_pos, low_pos;
CORE_ADDR base;
@@ -3119,7 +3154,7 @@ ada_value_slice_from_ptr (struct value *array_ptr, struct type *type,
static struct value *
-ada_value_slice (struct value *array, int low, int high)
+ada_value_slice (struct value *array, LONGEST low, LONGEST high)
{
struct type *type = ada_check_typedef (array->type ());
struct type *base_index_type = type->index_type ()->target_type ();
@@ -3392,7 +3427,7 @@ ada_array_length (struct value *arr, int n)
less than LOW, then LOW-1 is used. */
static struct value *
-empty_array (struct type *arr_type, int low, int high)
+empty_array (struct type *arr_type, LONGEST low, LONGEST high)
{
struct type *arr_type0 = ada_check_typedef (arr_type);
type_allocator alloc (arr_type0->index_type ()->target_type ());
@@ -3639,7 +3674,7 @@ See set/show multiple-symbol."));
if (syms[i].symbol == NULL)
continue;
- if (syms[i].symbol->aclass () == LOC_BLOCK)
+ if (syms[i].symbol->loc_class () == LOC_BLOCK)
{
struct symtab_and_line sal =
find_function_start_sal (syms[i].symbol, 1);
@@ -3661,7 +3696,7 @@ See set/show multiple-symbol."));
else
{
int is_enumeral =
- (syms[i].symbol->aclass () == LOC_CONST
+ (syms[i].symbol->loc_class () == LOC_CONST
&& syms[i].symbol->type () != NULL
&& syms[i].symbol->type ()->code () == TYPE_CODE_ENUM);
struct symtab *symtab = NULL;
@@ -3824,7 +3859,7 @@ ada_resolve_variable (struct symbol *sym, const struct block *block,
candidates.end (),
[] (block_symbol &bsym)
{
- switch (bsym.symbol->aclass ())
+ switch (bsym.symbol->loc_class ())
{
case LOC_REGISTER:
case LOC_ARG:
@@ -3847,7 +3882,7 @@ ada_resolve_variable (struct symbol *sym, const struct block *block,
candidates.end (),
[] (block_symbol &bsym)
{
- return bsym.symbol->aclass () == LOC_TYPEDEF;
+ return bsym.symbol->loc_class () == LOC_TYPEDEF;
}),
candidates.end ());
}
@@ -4002,7 +4037,7 @@ ada_args_match (struct symbol *func, struct value **actuals, int n_actuals)
int i;
struct type *func_type = func->type ();
- if (func->aclass () == LOC_CONST
+ if (func->loc_class () == LOC_CONST
&& func_type->code () == TYPE_CODE_ENUM)
return (n_actuals == 0);
else if (func_type == NULL || func_type->code () != TYPE_CODE_FUNC)
@@ -4312,7 +4347,7 @@ ada_parse_renaming (struct symbol *sym,
if (sym == NULL)
return ADA_NOT_RENAMING;
- switch (sym->aclass ())
+ switch (sym->loc_class ())
{
default:
return ADA_NOT_RENAMING;
@@ -4778,7 +4813,7 @@ is_nonfunction (const std::vector<struct block_symbol> &syms)
for (const block_symbol &sym : syms)
if (sym.symbol->type ()->code () != TYPE_CODE_FUNC
&& (sym.symbol->type ()->code () != TYPE_CODE_ENUM
- || sym.symbol->aclass () != LOC_CONST))
+ || sym.symbol->loc_class () != LOC_CONST))
return 1;
return 0;
@@ -4813,10 +4848,10 @@ lesseq_defined_than (struct symbol *sym0, struct symbol *sym1)
if (sym0 == sym1)
return 1;
if (sym0->domain () != sym1->domain ()
- || sym0->aclass () != sym1->aclass ())
+ || sym0->loc_class () != sym1->loc_class ())
return 0;
- switch (sym0->aclass ())
+ switch (sym0->loc_class ())
{
case LOC_UNDEF:
return 1;
@@ -4903,9 +4938,8 @@ ada_lookup_simple_minsym (const char *name, struct objfile *objfile)
symbol_name_matcher_ftype *match_name
= ada_get_symbol_name_matcher (lookup_name);
- gdbarch_iterate_over_objfiles_in_search_order
- (objfile != NULL ? objfile->arch () : current_inferior ()->arch (),
- [&result, lookup_name, match_name] (struct objfile *obj)
+ current_program_space->iterate_over_objfiles_in_search_order
+ ([&result, lookup_name, match_name] (struct objfile *obj)
{
for (minimal_symbol *msymbol : obj->msymbols ())
{
@@ -5071,7 +5105,7 @@ remove_extra_symbols (std::vector<struct block_symbol> &syms)
should be identical. */
else if (syms[i].symbol->linkage_name () != NULL
- && syms[i].symbol->aclass () == LOC_STATIC
+ && syms[i].symbol->loc_class () == LOC_STATIC
&& is_nondebugging_type (syms[i].symbol->type ()))
{
for (j = 0; !remove_p && j < syms.size (); j += 1)
@@ -5080,8 +5114,8 @@ remove_extra_symbols (std::vector<struct block_symbol> &syms)
&& syms[j].symbol->linkage_name () != NULL
&& strcmp (syms[i].symbol->linkage_name (),
syms[j].symbol->linkage_name ()) == 0
- && (syms[i].symbol->aclass ()
- == syms[j].symbol->aclass ())
+ && (syms[i].symbol->loc_class ()
+ == syms[j].symbol->loc_class ())
&& syms[i].symbol->value_address ()
== syms[j].symbol->value_address ())
remove_p = true;
@@ -5090,12 +5124,12 @@ remove_extra_symbols (std::vector<struct block_symbol> &syms)
/* Two functions with the same block are identical. */
- else if (syms[i].symbol->aclass () == LOC_BLOCK)
+ else if (syms[i].symbol->loc_class () == LOC_BLOCK)
{
for (j = 0; !remove_p && j < syms.size (); j += 1)
{
if (i != j
- && syms[j].symbol->aclass () == LOC_BLOCK
+ && syms[j].symbol->loc_class () == LOC_BLOCK
&& (syms[i].symbol->value_block ()
== syms[j].symbol->value_block ()))
remove_p = true;
@@ -5172,7 +5206,7 @@ is_package_name (const char *name)
static int
old_renaming_is_invisible (const struct symbol *sym, const char *function_name)
{
- if (sym->aclass () != LOC_TYPEDEF)
+ if (sym->loc_class () != LOC_TYPEDEF)
return 0;
std::string scope = xget_renaming_scope (sym->type ());
@@ -5251,7 +5285,7 @@ remove_irrelevant_renamings (std::vector<struct block_symbol> *syms,
const char *name;
const char *suffix;
- if (sym == NULL || sym->aclass () == LOC_TYPEDEF)
+ if (sym == NULL || sym->loc_class () == LOC_TYPEDEF)
continue;
name = sym->linkage_name ();
suffix = strstr (name, "___XR");
@@ -5376,7 +5410,7 @@ match_data::operator() (struct block_symbol *bsym)
}
else
{
- if (sym->aclass () == LOC_UNRESOLVED)
+ if (sym->loc_class () == LOC_UNRESOLVED)
return true;
else if (sym->is_argument ())
arg_sym = sym;
@@ -5475,22 +5509,19 @@ map_matching_symbols (struct objfile *objfile,
match_data &data)
{
data.objfile = objfile;
- objfile->expand_symtabs_matching (nullptr, &lookup_name,
- nullptr, nullptr,
- global
- ? SEARCH_GLOBAL_BLOCK
- : SEARCH_STATIC_BLOCK,
- domain);
const int block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK;
- for (compunit_symtab *symtab : objfile->compunits ())
+ auto callback = [&] (compunit_symtab *symtab)
{
const struct block *block
= symtab->blockvector ()->block (block_kind);
- if (!iterate_over_symbols_terminated (block, lookup_name,
- domain, data))
- break;
- }
+ return iterate_over_symbols_terminated (block, lookup_name,
+ domain, data);
+ };
+
+ objfile->search (nullptr, &lookup_name, nullptr, callback,
+ global ? SEARCH_GLOBAL_BLOCK : SEARCH_STATIC_BLOCK,
+ domain);
}
/* Add to RESULT all non-local symbols whose name and domain match
@@ -5732,10 +5763,10 @@ is_name_suffix (const char *str)
/* Skip optional leading __[0-9]+. */
- if (len > 3 && str[0] == '_' && str[1] == '_' && isdigit (str[2]))
+ if (len > 3 && str[0] == '_' && str[1] == '_' && c_isdigit (str[2]))
{
str += 3;
- while (isdigit (str[0]))
+ while (c_isdigit (str[0]))
str += 1;
}
@@ -5744,7 +5775,7 @@ is_name_suffix (const char *str)
if (str[0] == '.' || str[0] == '$')
{
matching = str + 1;
- while (isdigit (matching[0]))
+ while (c_isdigit (matching[0]))
matching += 1;
if (matching[0] == '\0')
return 1;
@@ -5755,7 +5786,7 @@ is_name_suffix (const char *str)
if (len > 3 && str[0] == '_' && str[1] == '_' && str[2] == '_')
{
matching = str + 3;
- while (isdigit (matching[0]))
+ while (c_isdigit (matching[0]))
matching += 1;
if (matching[0] == '\0')
return 1;
@@ -5784,10 +5815,10 @@ is_name_suffix (const char *str)
#endif
/* _E[0-9]+[bs]$ */
- if (len > 3 && str[0] == '_' && str [1] == 'E' && isdigit (str[2]))
+ if (len > 3 && str[0] == '_' && str [1] == 'E' && c_isdigit (str[2]))
{
matching = str + 3;
- while (isdigit (matching[0]))
+ while (c_isdigit (matching[0]))
matching += 1;
if ((matching[0] == 'b' || matching[0] == 's')
&& matching [1] == '\0')
@@ -5837,17 +5868,17 @@ is_name_suffix (const char *str)
return 1;
return 0;
}
- if (!isdigit (str[2]))
+ if (!c_isdigit (str[2]))
return 0;
for (k = 3; str[k] != '\0'; k += 1)
- if (!isdigit (str[k]) && str[k] != '_')
+ if (!c_isdigit (str[k]) && str[k] != '_')
return 0;
return 1;
}
- if (str[0] == '$' && isdigit (str[1]))
+ if (str[0] == '$' && c_isdigit (str[1]))
{
for (k = 2; str[k] != '\0'; k += 1)
- if (!isdigit (str[k]) && str[k] != '_')
+ if (!c_isdigit (str[k]) && str[k] != '_')
return 0;
return 1;
}
@@ -5870,7 +5901,7 @@ is_valid_name_for_wild_match (const char *name0)
return 0;
for (i=0; decoded_name[i] != '\0'; i++)
- if (isalpha (decoded_name[i]) && !islower (decoded_name[i]))
+ if (c_isalpha (decoded_name[i]) && !c_islower (decoded_name[i]))
return 0;
return 1;
@@ -5981,7 +6012,7 @@ ada_add_block_symbols (std::vector<struct block_symbol> &result,
{
if (sym->matches (domain))
{
- if (sym->aclass () != LOC_UNRESOLVED)
+ if (sym->loc_class () != LOC_UNRESOLVED)
{
if (sym->is_argument ())
arg_sym = sym;
@@ -6030,7 +6061,7 @@ ada_add_block_symbols (std::vector<struct block_symbol> &result,
if (cmp == 0
&& is_name_suffix (sym->linkage_name () + name_len + 5))
{
- if (sym->aclass () != LOC_UNRESOLVED)
+ if (sym->loc_class () != LOC_UNRESOLVED)
{
if (sym->is_argument ())
arg_sym = sym;
@@ -6094,7 +6125,7 @@ ada_lookup_name_info::matches
angle bracket notation. */
const char *tmp;
- for (tmp = sym_name; *tmp != '\0' && !isupper (*tmp); tmp++);
+ for (tmp = sym_name; *tmp != '\0' && !c_isupper (*tmp); tmp++);
if (*tmp != '\0')
match = false;
}
@@ -6209,7 +6240,7 @@ ada_is_ignored_field (struct type *type, int field_num)
{
/* Wrapper field. */
}
- else if (isupper (name[0]))
+ else if (c_isupper (name[0]))
return 1;
}
@@ -6433,7 +6464,7 @@ ada_get_tsd_type (struct inferior *inf)
if (data->tsd_type == 0)
data->tsd_type
- = lookup_transparent_type ("<ada__tags__type_specific_data>",
+ = lookup_transparent_type ("ada.tags.type_specific_data",
SEARCH_TYPE_DOMAIN);
return data->tsd_type;
}
@@ -6720,14 +6751,14 @@ ada_scan_number (const char str[], int k, LONGEST * R, int *new_k)
{
ULONGEST RU;
- if (!isdigit (str[k]))
+ if (!c_isdigit (str[k]))
return 0;
/* Do it the hard way so as not to make any assumption about
the relationship of unsigned long (%lu scan format code) and
LONGEST. */
RU = 0;
- while (isdigit (str[k]))
+ while (c_isdigit (str[k]))
{
RU = RU * 10 + (str[k] - '0');
k += 1;
@@ -6901,7 +6932,7 @@ static int
find_struct_field (const char *name, struct type *type, int offset,
struct type **field_type_p,
int *byte_offset_p, int *bit_offset_p, int *bit_size_p,
- int *index_p)
+ LONGEST *index_p)
{
int i;
int parent_offset = -1;
@@ -7015,12 +7046,10 @@ find_struct_field (const char *name, struct type *type, int offset,
/* Number of user-visible fields in record type TYPE. */
-static int
+static LONGEST
num_visible_fields (struct type *type)
{
- int n;
-
- n = 0;
+ LONGEST n = 0;
find_struct_field (NULL, type, 0, NULL, NULL, NULL, NULL, &n);
return n;
}
@@ -7080,17 +7109,16 @@ ada_search_struct_field (const char *name, struct value *arg, int offset,
else if (ada_is_variant_part (type, i))
{
/* PNH: Do we ever get here? See find_struct_field. */
- int j;
struct type *field_type = ada_check_typedef (type->field (i).type ());
int var_offset = offset + type->field (i).loc_bitpos () / 8;
- for (j = 0; j < field_type->num_fields (); j += 1)
+ for (const auto &field : field_type->fields ())
{
- struct value *v = ada_search_struct_field /* Force line
- break. */
- (name, arg,
- var_offset + field_type->field (j).loc_bitpos () / 8,
- field_type->field (j).type ());
+ struct value *v
+ = (ada_search_struct_field
+ (name, arg,
+ var_offset + field.loc_bitpos () / 8,
+ field.type ()));
if (v != NULL)
return v;
@@ -7384,10 +7412,10 @@ field_alignment (struct type *type, int f)
len = strlen (name);
- if (!isdigit (name[len - 1]))
+ if (!c_isdigit (name[len - 1]))
return 1;
- if (isdigit (name[len - 2]))
+ if (c_isdigit (name[len - 2]))
align_offset = len - 2;
else
align_offset = len - 1;
@@ -8182,12 +8210,11 @@ ada_is_redundant_index_type_desc (struct type *array_type,
struct type *desc_type)
{
struct type *this_layer = check_typedef (array_type);
- int i;
- for (i = 0; i < desc_type->num_fields (); i++)
+ for (const auto &field : desc_type->fields ())
{
if (!ada_is_redundant_range_encoding (this_layer->index_type (),
- desc_type->field (i).type ()))
+ field.type ()))
return 0;
this_layer = check_typedef (this_layer->target_type ());
}
@@ -8784,9 +8811,9 @@ ada_atr_enum_val (struct expression *exp, enum noside noside, struct type *type,
error (_("'Enum_Val requires integral argument"));
LONGEST value = value_as_long (arg);
- for (int i = 0; i < type->num_fields (); ++i)
+ for (const auto &field : type->fields ())
{
- if (type->field (i).loc_enumval () == value)
+ if (field.loc_enumval () == value)
return value_from_longest (original_type, value);
}
@@ -8969,7 +8996,7 @@ ada_unqualify_enum_name (const char *name)
{
while ((tmp = strstr (name, "__")) != NULL)
{
- if (isdigit (tmp[2]))
+ if (c_isdigit (tmp[2]))
break;
else
name = tmp + 2;
@@ -9012,7 +9039,7 @@ ada_enum_name (const char *name)
else
return name;
- if (isascii (v) && isprint (v))
+ if (c_isascii (v) && c_isprint (v))
storage = string_printf ("'%c'", v);
else if (name[1] == 'U')
storage = string_printf ("'[\"%02x\"]'", v);
@@ -9540,12 +9567,12 @@ void
ada_name_association::assign (aggregate_assigner &assigner,
operation_up &op)
{
- int index;
+ LONGEST index;
if (ada_is_direct_array_type (assigner.lhs->type ()))
{
value *tem = m_val->evaluate (nullptr, assigner.exp, EVAL_NORMAL);
- index = longest_to_int (value_as_long (tem));
+ index = value_as_long (tem);
}
else
{
@@ -10046,14 +10073,19 @@ ada_unop_neg (struct type *expect_type,
return value_neg (arg1);
}
-/* A helper function for UNOP_IN_RANGE. */
+namespace expr
+{
+
+/* Implement UNOP_IN_RANGE. */
value *
-ada_unop_in_range (struct type *expect_type,
- struct expression *exp,
- enum noside noside, enum exp_opcode op,
- struct value *arg1, struct type *type)
+ada_unop_range_operation::evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside)
{
+ value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+ struct type *type = std::get<1> (m_storage);
+
struct value *arg2, *arg3;
switch (type->code ())
{
@@ -10080,6 +10112,8 @@ ada_unop_in_range (struct type *expect_type,
}
}
+} /* namespace expr */
+
/* A helper function for OP_ATR_TAG. */
value *
@@ -10167,14 +10201,21 @@ ada_mult_binop (struct type *expect_type,
}
}
-/* A helper function for BINOP_EQUAL and BINOP_NOTEQUAL. */
+namespace expr
+{
+
+/* Implement BINOP_EQUAL and BINOP_NOTEQUAL. */
value *
-ada_equal_binop (struct type *expect_type,
- struct expression *exp,
- enum noside noside, enum exp_opcode op,
- struct value *arg1, struct value *arg2)
+ada_binop_equal_operation::evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside)
{
+ enum exp_opcode op = std::get<0> (m_storage);
+ value *arg1 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+ value *arg2 = std::get<2> (m_storage)->evaluate (arg1->type (),
+ exp, noside);
+
int tem;
if (noside == EVAL_AVOID_SIDE_EFFECTS)
tem = 0;
@@ -10189,14 +10230,19 @@ ada_equal_binop (struct type *expect_type,
return value_from_longest (type, tem);
}
-/* A helper function for TERNOP_SLICE. */
+/* Implement TERNOP_SLICE. */
value *
-ada_ternop_slice (struct expression *exp,
- enum noside noside,
- struct value *array, struct value *low_bound_val,
- struct value *high_bound_val)
+ada_ternop_slice_operation::evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside)
{
+ value *array = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+ value *low_bound_val
+ = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+ value *high_bound_val
+ = std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
+
LONGEST low_bound;
LONGEST high_bound;
@@ -10257,8 +10303,7 @@ ada_ternop_slice (struct expression *exp,
to_fixed_array_type (type0->target_type (), NULL, 1);
return ada_value_slice_from_ptr (array, arr_type0,
- longest_to_int (low_bound),
- longest_to_int (high_bound));
+ low_bound, high_bound);
}
}
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
@@ -10266,16 +10311,20 @@ ada_ternop_slice (struct expression *exp,
else if (high_bound < low_bound)
return empty_array (array->type (), low_bound, high_bound);
else
- return ada_value_slice (array, longest_to_int (low_bound),
- longest_to_int (high_bound));
+ return ada_value_slice (array, low_bound, high_bound);
}
-/* A helper function for BINOP_IN_BOUNDS. */
+/* Implement BINOP_IN_BOUNDS. */
value *
-ada_binop_in_bounds (struct expression *exp, enum noside noside,
- struct value *arg1, struct value *arg2, int n)
+ada_binop_in_bounds_operation::evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside)
{
+ value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+ value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+ int n = std::get<2> (m_storage);
+
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
struct type *type = language_bool_type (exp->language_defn,
@@ -10300,6 +10349,8 @@ ada_binop_in_bounds (struct expression *exp, enum noside noside,
|| value_equal (arg2, arg1)));
}
+} /* namespace expr */
+
/* A helper function for some attribute operations. */
static value *
@@ -10502,7 +10553,6 @@ static LONGEST
convert_char_literal (struct type *type, LONGEST val)
{
char name[12];
- int f;
if (type == NULL)
return val;
@@ -10519,17 +10569,17 @@ convert_char_literal (struct type *type, LONGEST val)
else
xsnprintf (name, sizeof (name), "QWW%08lx", (unsigned long) val);
size_t len = strlen (name);
- for (f = 0; f < type->num_fields (); f += 1)
+ for (const auto &field : type->fields ())
{
/* Check the suffix because an enum constant in a package will
have a name like "pkg__QUxx". This is safe enough because we
already have the correct type, and because mangling means
there can't be clashes. */
- const char *ename = type->field (f).name ();
+ const char *ename = field.name ();
size_t elen = strlen (ename);
if (elen >= len && strcmp (name, ename + elen - len) == 0)
- return type->field (f).loc_enumval ();
+ return field.loc_enumval ();
}
return val;
}
@@ -11712,9 +11762,9 @@ ada_has_this_exception_support (const struct exception_support_info *einfo)
/* Make sure that the symbol we found corresponds to a function. */
- if (sym->aclass () != LOC_BLOCK)
+ if (sym->loc_class () != LOC_BLOCK)
error (_("Symbol \"%s\" is not a function (class = %d)"),
- sym->linkage_name (), sym->aclass ());
+ sym->linkage_name (), sym->loc_class ());
sym = standard_lookup (einfo->catch_handlers_sym, NULL,
SEARCH_FUNCTION_DOMAIN);
@@ -11734,9 +11784,9 @@ ada_has_this_exception_support (const struct exception_support_info *einfo)
/* Make sure that the symbol we found corresponds to a function. */
- if (sym->aclass () != LOC_BLOCK)
+ if (sym->loc_class () != LOC_BLOCK)
error (_("Symbol \"%s\" is not a function (class = %d)"),
- sym->linkage_name (), sym->aclass ());
+ sym->linkage_name (), sym->loc_class ());
return 1;
}
@@ -12536,7 +12586,7 @@ catch_ada_exception_command_split (const char *args,
args = skip_spaces (args);
if (startswith (args, "if")
- && (isspace (args[2]) || args[2] == '\0'))
+ && (c_isspace (args[2]) || args[2] == '\0'))
{
args += 2;
args = skip_spaces (args);
@@ -12691,7 +12741,7 @@ ada_exception_sal (enum ada_exception_catchpoint_kind ex)
throw_error (NOT_FOUND_ERROR, _("Catchpoint symbol not found: %s"),
sym_name);
- if (sym->aclass () != LOC_BLOCK)
+ if (sym->loc_class () != LOC_BLOCK)
error (_("Unable to insert catchpoint. %s is not a function."), sym_name);
return find_function_start_sal (sym, 1);
@@ -12813,7 +12863,7 @@ catch_ada_assert_command_split (const char *args, std::string &cond_string)
/* Check whether a condition was provided. */
if (startswith (args, "if")
- && (isspace (args[2]) || args[2] == '\0'))
+ && (c_isspace (args[2]) || args[2] == '\0'))
{
args += 2;
args = skip_spaces (args);
@@ -12857,10 +12907,10 @@ ada_is_exception_sym (struct symbol *sym)
{
const char *type_name = sym->type ()->name ();
- return (sym->aclass () != LOC_TYPEDEF
- && sym->aclass () != LOC_BLOCK
- && sym->aclass () != LOC_CONST
- && sym->aclass () != LOC_UNRESOLVED
+ return (sym->loc_class () != LOC_TYPEDEF
+ && sym->loc_class () != LOC_BLOCK
+ && sym->loc_class () != LOC_CONST
+ && sym->loc_class () != LOC_UNRESOLVED
&& type_name != NULL && strcmp (type_name, "exception") == 0);
}
@@ -12993,7 +13043,7 @@ ada_add_exceptions_from_frame (compiled_regex *preg,
{
for (struct symbol *sym : block_iterator_range (block))
{
- switch (sym->aclass ())
+ switch (sym->loc_class ())
{
case LOC_TYPEDEF:
case LOC_BLOCK:
@@ -13044,31 +13094,11 @@ ada_add_global_exceptions (compiled_regex *preg,
return preg == nullptr || preg->exec (name, 0, NULL, 0) == 0;
};
-
- /* In Ada, the symbol "search name" is a linkage name, whereas the
- regular expression used to do the matching refers to the natural
- name. So match against the decoded name. */
- expand_symtabs_matching (NULL,
- lookup_name_info::match_any (),
- [&] (const char *search_name)
- {
- std::string decoded = ada_decode (search_name);
- return name_matches_regex (decoded.c_str ());
- },
- NULL,
- SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
- SEARCH_VAR_DOMAIN,
- [&] (enum language lang)
- {
- /* Try to skip non-Ada CUs. */
- return lang == language_ada;
- });
-
/* Iterate over all objfiles irrespective of scope or linker namespaces
so we get all exceptions anywhere in the progspace. */
for (objfile *objfile : current_program_space->objfiles ())
{
- for (compunit_symtab *s : objfile->compunits ())
+ auto callback = [&] (compunit_symtab *s)
{
const struct blockvector *bv = s->blockvector ();
int i;
@@ -13087,7 +13117,30 @@ ada_add_global_exceptions (compiled_regex *preg,
exceptions->push_back (info);
}
}
- }
+
+ return true;
+ };
+
+ /* In Ada, the symbol "search name" is a linkage name, whereas
+ the regular expression used to do the matching refers to the
+ natural name. So match against the decoded name. */
+ auto any = lookup_name_info::match_any ();
+ objfile->search
+ (nullptr,
+ &any,
+ [&] (const char *search_name)
+ {
+ std::string decoded = ada_decode (search_name);
+ return name_matches_regex (decoded.c_str ());
+ },
+ callback,
+ SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
+ SEARCH_VAR_DOMAIN,
+ [&] (enum language lang)
+ {
+ /* Try to skip non-Ada CUs. */
+ return lang == language_ada;
+ });
}
}
@@ -13217,7 +13270,7 @@ do_full_match (const char *symbol_search_name,
&& symbol_search_name[1] == '_')
{
symbol_search_name += 2;
- while (isdigit (*symbol_search_name))
+ while (c_isdigit (*symbol_search_name))
++symbol_search_name;
if (symbol_search_name[0] == '_'
&& symbol_search_name[1] == '_')
@@ -13294,7 +13347,7 @@ ada_lookup_name_info::ada_lookup_name_info (const lookup_name_info &lookup_name)
else
m_standard_p = false;
- m_decoded_name = ada_decode (m_encoded_name.c_str (), true, false, false);
+ m_decoded_name = ada_decode (m_encoded_name.c_str (), true, false);
/* If the name contains a ".", then the user is entering a fully
qualified entity name, and the match must not be done in wild
@@ -13595,20 +13648,12 @@ public:
const char *text, const char *word,
enum type_code code) const override
{
- const struct block *b, *surrounding_static_block = 0;
+ const struct block *surrounding_static_block = 0;
gdb_assert (code == TYPE_CODE_UNDEF);
lookup_name_info lookup_name (text, name_match_type, true);
- /* First, look at the partial symtab symbols. */
- expand_symtabs_matching (NULL,
- lookup_name,
- NULL,
- NULL,
- SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
- SEARCH_ALL_DOMAINS);
-
/* At this point scan through the misc symbol vectors and add each
symbol you find to the list. Eventually we want to ignore
anything that isn't a text symbol (everything else will be
@@ -13650,7 +13695,9 @@ public:
/* Search upwards from currently selected frame (so that we can
complete on local vars. */
- for (b = get_selected_block (0); b != NULL; b = b->superblock ())
+ for (const block *b = get_selected_block (0);
+ b != nullptr;
+ b = b->superblock ())
{
if (b->is_static_block ())
surrounding_static_block = b; /* For elmin of dups */
@@ -13672,43 +13719,36 @@ public:
for (objfile *objfile : current_program_space->objfiles ())
{
- for (compunit_symtab *s : objfile->compunits ())
+ auto callback = [&] (compunit_symtab *s)
{
QUIT;
- b = s->blockvector ()->global_block ();
- for (struct symbol *sym : block_iterator_range (b))
+ for (const block *b = s->blockvector ()->static_block ();
+ b != nullptr;
+ b = b->superblock ())
{
- if (completion_skip_symbol (mode, sym))
- continue;
+ /* Don't do this block twice. */
+ if (b == surrounding_static_block)
+ break;
- completion_list_add_name (tracker,
- sym->language (),
- sym->linkage_name (),
- lookup_name, text, word);
+ for (struct symbol *sym : block_iterator_range (b))
+ {
+ if (completion_skip_symbol (mode, sym))
+ continue;
+
+ completion_list_add_name (tracker,
+ sym->language (),
+ sym->linkage_name (),
+ lookup_name, text, word);
+ }
}
- }
- }
- for (objfile *objfile : current_program_space->objfiles ())
- {
- for (compunit_symtab *s : objfile->compunits ())
- {
- QUIT;
- b = s->blockvector ()->static_block ();
- /* Don't do this block twice. */
- if (b == surrounding_static_block)
- continue;
- for (struct symbol *sym : block_iterator_range (b))
- {
- if (completion_skip_symbol (mode, sym))
- continue;
+ return true;
+ };
- completion_list_add_name (tracker,
- sym->language (),
- sym->linkage_name (),
- lookup_name, text, word);
- }
- }
+ objfile->search
+ (nullptr, &lookup_name, nullptr, callback,
+ SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
+ SEARCH_ALL_DOMAINS);
}
}
@@ -13928,9 +13968,7 @@ static const char * const gnat_source_charsets[] =
nullptr
};
-void _initialize_ada_language ();
-void
-_initialize_ada_language ()
+INIT_GDB_FILE (ada_language)
{
add_setshow_prefix_cmd
("ada", no_class,
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index c125fbc..5e08c3b 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -218,16 +218,13 @@ extern const char *ada_decode_symbol (const struct general_symbol_info *);
simply wrapped in <...>. If WRAP is false, then the empty string
will be returned.
- When OPERATORS is false, operator names will not be decoded. By
- default, they are decoded, e.g., 'Oadd' will be transformed to
- '"+"'.
-
- When WIDE is false, wide characters will be left as-is. By
- default, they converted from their hex encoding to the host
- charset. */
+ TRANSLATE has two effects. When true (the default), operator names
+ and wide characters will be decoded. E.g., 'Oadd' will be
+ transformed to '"+"', and wide characters converted from their hex
+ encoding to the host charset. When false, these will be left
+ alone. */
extern std::string ada_decode (const char *name, bool wrap = true,
- bool operators = true,
- bool wide = true);
+ bool translate = true);
extern std::vector<struct block_symbol> ada_lookup_symbol_list
(const char *, const struct block *, domain_search_flags);
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index 0cfa0c8..eec80cf 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -335,7 +335,6 @@ false { return FALSEKEYWORD; }
. { error (_("Invalid character '%s' in expression."), yytext); }
%%
-#include <ctype.h>
/* Initialize the lexer for processing new expression. */
static void
@@ -355,7 +354,7 @@ canonicalizeNumeral (char *s1, const char *s2)
{
if (*s2 != '_')
{
- *s1 = tolower(*s2);
+ *s1 = c_tolower(*s2);
s1 += 1;
}
}
@@ -411,7 +410,7 @@ processInt (struct parser_state *par_state, const char *base0,
exp = strtol(exp0, (char **) NULL, 10);
gdb_mpz result;
- while (isxdigit (*num0))
+ while (c_isxdigit (*num0))
{
int dig = fromhex (*num0);
if (dig >= base)
@@ -527,7 +526,7 @@ processId (const char *name0, int len)
struct stoken result;
result.ptr = name;
- while (len > 0 && isspace (name0[len-1]))
+ while (len > 0 && c_isspace (name0[len-1]))
len -= 1;
if (name0[0] == '<' || strstr (name0, "___") != NULL)
@@ -549,12 +548,12 @@ processId (const char *name0, int len)
}
else if (in_quotes)
name[i++] = name0[i0++];
- else if (isalnum (name0[i0]))
+ else if (c_isalnum (name0[i0]))
{
- name[i] = tolower (name0[i0]);
+ name[i] = c_tolower (name0[i0]);
i += 1; i0 += 1;
}
- else if (isspace (name0[i0]))
+ else if (c_isspace (name0[i0]))
i0 += 1;
else if (name0[i0] == '\'')
{
@@ -634,10 +633,10 @@ find_dot_all (const char *str)
do
i += 1;
- while (isspace (str[i]));
+ while (c_isspace (str[i]));
if (strncasecmp (str + i, "all", 3) == 0
- && !isalnum (str[i + 3]) && str[i + 3] != '_')
+ && !c_isalnum (str[i + 3]) && str[i + 3] != '_')
return i0;
}
return -1;
@@ -653,7 +652,7 @@ subseqMatch (const char *subseq, const char *str)
return 1;
else if (str[0] == '\0')
return 0;
- else if (tolower (subseq[0]) == tolower (str[0]))
+ else if (c_tolower (subseq[0]) == c_tolower (str[0]))
return subseqMatch (subseq+1, str+1) || subseqMatch (subseq, str+1);
else
return subseqMatch (subseq, str+1);
@@ -690,7 +689,7 @@ processAttribute (const char *str)
{
gdb_assert (*str == '\'');
++str;
- while (isspace (*str))
+ while (c_isspace (*str))
++str;
int len = strlen (str);
@@ -749,7 +748,7 @@ static void
rewind_to_char (int ch)
{
pstate->lexptr -= yyleng;
- while (toupper (*pstate->lexptr) != toupper (ch))
+ while (c_toupper (*pstate->lexptr) != c_toupper (ch))
pstate->lexptr -= 1;
yyrestart (NULL);
}
diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c
index 2595123..f9551d4 100644
--- a/gdb/ada-tasks.c
+++ b/gdb/ada-tasks.c
@@ -1650,9 +1650,7 @@ task_apply_command (const char *tidlist, int from_tty)
from_tty, flags);
}
-void _initialize_tasks ();
-void
-_initialize_tasks ()
+INIT_GDB_FILE (tasks)
{
/* Attach various observers. */
gdb::observers::normal_stop.attach (ada_tasks_normal_stop_observer,
diff --git a/gdb/ada-typeprint.c b/gdb/ada-typeprint.c
index 404d8fe..5829a9b 100644
--- a/gdb/ada-typeprint.c
+++ b/gdb/ada-typeprint.c
@@ -23,7 +23,6 @@
#include "cli/cli-style.h"
#include "typeprint.h"
#include "ada-lang.h"
-#include <ctype.h>
static int print_selected_record_field_types (struct type *, struct type *,
int, int,
@@ -70,7 +69,7 @@ decoded_type_name (struct type *type)
if (s == name_buffer)
return name_buffer;
- if (!islower (s[1]))
+ if (!c_islower (s[1]))
return NULL;
for (s = q = name_buffer; *s != '\0'; q += 1)
@@ -702,7 +701,7 @@ print_variant_part (const variant_part &part,
name = "?";
else
{
- name = type->field (part.discriminant_index).name ();;
+ name = type->field (part.discriminant_index).name ();
discr_type = type->field (part.discriminant_index).type ();
}
diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
index 7c6826e..c198fa5 100644
--- a/gdb/ada-valprint.c
+++ b/gdb/ada-valprint.c
@@ -17,7 +17,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include <ctype.h>
#include "event-top.h"
#include "extract-store-integer.h"
#include "gdbtypes.h"
@@ -265,10 +264,10 @@ ada_emit_char (int c, struct type *type, struct ui_file *stream,
/* If this character fits in the normal ASCII range, and is
a printable character, then print the character as if it was
an ASCII character, even if this is a wide character.
- The UCHAR_MAX check is necessary because the isascii function
+ The UCHAR_MAX check is necessary because the c_isascii function
requires that its argument have a value of an unsigned char,
or EOF (EOF is obviously not printable). */
- if (c <= UCHAR_MAX && isascii (c) && isprint (c))
+ if (c <= UCHAR_MAX && c_isascii (c) && c_isprint (c))
{
if (c == quoter && c == '"')
gdb_printf (stream, "\"\"");
diff --git a/gdb/addrmap.c b/gdb/addrmap.c
index c625973..2b333a1 100644
--- a/gdb/addrmap.c
+++ b/gdb/addrmap.c
@@ -201,10 +201,11 @@ xfree_wrapper (splay_tree_key key)
xfree ((void *) key);
}
-void
+bool
addrmap_mutable::set_empty (CORE_ADDR start, CORE_ADDR end_inclusive,
void *obj)
{
+ bool full_range = true;
splay_tree_node n, next;
void *prior_value;
@@ -234,7 +235,12 @@ addrmap_mutable::set_empty (CORE_ADDR start, CORE_ADDR end_inclusive,
n && addrmap_node_key (n) <= end_inclusive;
n = splay_tree_successor (addrmap_node_key (n)))
{
- if (! addrmap_node_value (n))
+ if (addrmap_node_value (n))
+ {
+ /* Already mapped. */
+ full_range = false;
+ }
+ else
addrmap_node_set_value (n, obj);
}
@@ -254,6 +260,8 @@ addrmap_mutable::set_empty (CORE_ADDR start, CORE_ADDR end_inclusive,
else
prior_value = addrmap_node_value (n);
}
+
+ return full_range;
}
@@ -398,20 +406,20 @@ namespace selftests {
/* Convert P to CORE_ADDR. */
static CORE_ADDR
-core_addr (void *p)
+core_addr (const void *p)
{
- return (CORE_ADDR)(uintptr_t)p;
+ return (CORE_ADDR) (uintptr_t) p;
}
/* Check that &ARRAY[LOW]..&ARRAY[HIGH] has VAL in MAP. */
-#define CHECK_ADDRMAP_FIND(MAP, ARRAY, LOW, HIGH, VAL) \
- do \
- { \
- for (unsigned i = LOW; i <= HIGH; ++i) \
- SELF_CHECK (MAP->find (core_addr (&ARRAY[i])) == VAL); \
- } \
- while (0)
+static void
+check_addrmap_find (const addrmap &map, const char *array, unsigned int low,
+ unsigned int high, const void *val)
+{
+ for (unsigned int i = low; i <= high; ++i)
+ SELF_CHECK (map.find (core_addr (&array[i])) == val);
+}
/* Entry point for addrmap unit tests. */
@@ -427,25 +435,26 @@ test_addrmap ()
/* Create mutable addrmap. */
auto_obstack temp_obstack;
- auto map = std::make_unique<struct addrmap_mutable> ();
- SELF_CHECK (map != nullptr);
+ addrmap_mutable map;
/* Check initial state. */
- CHECK_ADDRMAP_FIND (map, array, 0, 19, nullptr);
+ check_addrmap_find (map, array, 0, 19, nullptr);
/* Insert address range into mutable addrmap. */
- map->set_empty (core_addr (&array[10]), core_addr (&array[12]), val1);
- CHECK_ADDRMAP_FIND (map, array, 0, 9, nullptr);
- CHECK_ADDRMAP_FIND (map, array, 10, 12, val1);
- CHECK_ADDRMAP_FIND (map, array, 13, 19, nullptr);
+ bool full_range_p
+ = map.set_empty (core_addr (&array[10]), core_addr (&array[12]), val1);
+ SELF_CHECK (full_range_p);
+ check_addrmap_find (map, array, 0, 9, nullptr);
+ check_addrmap_find (map, array, 10, 12, val1);
+ check_addrmap_find (map, array, 13, 19, nullptr);
/* Create corresponding fixed addrmap. */
addrmap_fixed *map2
- = new (&temp_obstack) addrmap_fixed (&temp_obstack, map.get ());
+ = new (&temp_obstack) addrmap_fixed (&temp_obstack, &map);
SELF_CHECK (map2 != nullptr);
- CHECK_ADDRMAP_FIND (map2, array, 0, 9, nullptr);
- CHECK_ADDRMAP_FIND (map2, array, 10, 12, val1);
- CHECK_ADDRMAP_FIND (map2, array, 13, 19, nullptr);
+ check_addrmap_find (*map2, array, 0, 9, nullptr);
+ check_addrmap_find (*map2, array, 10, 12, val1);
+ check_addrmap_find (*map2, array, 13, 19, nullptr);
/* Iterate over both addrmaps. */
auto callback = [&] (CORE_ADDR start_addr, void *obj)
@@ -460,29 +469,29 @@ test_addrmap ()
SELF_CHECK (false);
return 0;
};
- SELF_CHECK (map->foreach (callback) == 0);
+ SELF_CHECK (map.foreach (callback) == 0);
SELF_CHECK (map2->foreach (callback) == 0);
/* Relocate fixed addrmap. */
map2->relocate (1);
- CHECK_ADDRMAP_FIND (map2, array, 0, 10, nullptr);
- CHECK_ADDRMAP_FIND (map2, array, 11, 13, val1);
- CHECK_ADDRMAP_FIND (map2, array, 14, 19, nullptr);
+ check_addrmap_find (*map2, array, 0, 10, nullptr);
+ check_addrmap_find (*map2, array, 11, 13, val1);
+ check_addrmap_find (*map2, array, 14, 19, nullptr);
/* Insert partially overlapping address range into mutable addrmap. */
- map->set_empty (core_addr (&array[11]), core_addr (&array[13]), val2);
- CHECK_ADDRMAP_FIND (map, array, 0, 9, nullptr);
- CHECK_ADDRMAP_FIND (map, array, 10, 12, val1);
- CHECK_ADDRMAP_FIND (map, array, 13, 13, val2);
- CHECK_ADDRMAP_FIND (map, array, 14, 19, nullptr);
+ full_range_p
+ = map.set_empty (core_addr (&array[11]), core_addr (&array[13]), val2);
+ SELF_CHECK (!full_range_p);
+ check_addrmap_find (map, array, 0, 9, nullptr);
+ check_addrmap_find (map, array, 10, 12, val1);
+ check_addrmap_find (map, array, 13, 13, val2);
+ check_addrmap_find (map, array, 14, 19, nullptr);
}
} /* namespace selftests */
#endif /* GDB_SELF_TEST */
-void _initialize_addrmap ();
-void
-_initialize_addrmap ()
+INIT_GDB_FILE (addrmap)
{
#if GDB_SELF_TEST
selftests::register_test ("addrmap", selftests::test_addrmap);
diff --git a/gdb/addrmap.h b/gdb/addrmap.h
index 179e1f8..398bdd8 100644
--- a/gdb/addrmap.h
+++ b/gdb/addrmap.h
@@ -152,7 +152,7 @@ public:
/* In the mutable address map MAP, associate the addresses from START
to END_INCLUSIVE that are currently associated with NULL with OBJ
instead. Addresses mapped to an object other than NULL are left
- unchanged.
+ unchanged. Return true if the full range is mapped to OBJ.
As the name suggests, END_INCLUSIVE is also mapped to OBJ. This
convention is unusual, but it allows callers to accurately specify
@@ -186,7 +186,7 @@ public:
semantics than to provide an interface which allows it to be
implemented efficiently, but doesn't reveal too much of the
representation. */
- void set_empty (CORE_ADDR start, CORE_ADDR end_inclusive,
+ bool set_empty (CORE_ADDR start, CORE_ADDR end_inclusive,
void *obj);
/* Clear this addrmap. */
diff --git a/gdb/agent.c b/gdb/agent.c
index 2009980..dd3a557 100644
--- a/gdb/agent.c
+++ b/gdb/agent.c
@@ -73,9 +73,7 @@ agent_new_objfile (struct objfile *objfile)
agent_look_up_symbols (objfile);
}
-void _initialize_agent ();
-void
-_initialize_agent ()
+INIT_GDB_FILE (agent)
{
gdb::observers::new_objfile.attach (agent_new_objfile,
"agent");
diff --git a/gdb/aix-thread.c b/gdb/aix-thread.c
index 2fd6121..1e3015d 100644
--- a/gdb/aix-thread.c
+++ b/gdb/aix-thread.c
@@ -2062,9 +2062,7 @@ aix_thread_target::get_ada_task_ptid (long lwp, ULONGEST thread)
/* Module startup initialization function, automagically called by
init.c. */
-void _initialize_aix_thread ();
-void
-_initialize_aix_thread ()
+INIT_GDB_FILE (aix_thread)
{
/* Notice when object files get loaded and unloaded. */
gdb::observers::new_objfile.attach (new_objfile, "aix-thread");
diff --git a/gdb/alpha-bsd-nat.c b/gdb/alpha-bsd-nat.c
index 85fb525..5f7d3ef 100644
--- a/gdb/alpha-bsd-nat.c
+++ b/gdb/alpha-bsd-nat.c
@@ -156,9 +156,7 @@ alphabsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
}
-void _initialize_alphabsd_nat ();
-void
-_initialize_alphabsd_nat ()
+INIT_GDB_FILE (alphabsd_nat)
{
add_inf_child_target (&the_alpha_bsd_nat_target);
diff --git a/gdb/alpha-linux-nat.c b/gdb/alpha-linux-nat.c
index 6d9de81..1297a45 100644
--- a/gdb/alpha-linux-nat.c
+++ b/gdb/alpha-linux-nat.c
@@ -100,9 +100,7 @@ alpha_linux_nat_target::register_u_offset (struct gdbarch *gdbarch,
return FPR_BASE + regno - gdbarch_fp0_regnum (gdbarch);
}
-void _initialize_alpha_linux_nat ();
-void
-_initialize_alpha_linux_nat ()
+INIT_GDB_FILE (alpha_linux_nat)
{
linux_target = &the_alpha_linux_nat_target;
add_inf_child_target (&the_alpha_linux_nat_target);
diff --git a/gdb/alpha-linux-tdep.c b/gdb/alpha-linux-tdep.c
index 2f6affa..8b4b4f1 100644
--- a/gdb/alpha-linux-tdep.c
+++ b/gdb/alpha-linux-tdep.c
@@ -17,6 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "frame.h"
+#include "solib-svr4-linux.h"
#include "osabi.h"
#include "solib-svr4.h"
#include "symtab.h"
@@ -369,9 +370,7 @@ alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->jb_elt_size = 8;
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
-
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_lp64_svr4_solib_ops);
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
@@ -386,9 +385,7 @@ alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
alpha_linux_gdb_signal_to_target);
}
-void _initialize_alpha_linux_tdep ();
-void
-_initialize_alpha_linux_tdep ()
+INIT_GDB_FILE (alpha_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_LINUX,
alpha_linux_init_abi);
diff --git a/gdb/alpha-netbsd-tdep.c b/gdb/alpha-netbsd-tdep.c
index a240039..56143ee 100644
--- a/gdb/alpha-netbsd-tdep.c
+++ b/gdb/alpha-netbsd-tdep.c
@@ -261,11 +261,10 @@ alphanbsd_init_abi (struct gdbarch_info info,
/* NetBSD/alpha does not provide single step support via ptrace(2); we
must use software single-stepping. */
- set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, alpha_software_single_step);
/* NetBSD/alpha has SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
tdep->dynamic_sigtramp_offset = alphanbsd_sigtramp_offset;
tdep->pc_in_sigtramp = alphanbsd_pc_in_sigtramp;
@@ -279,9 +278,7 @@ alphanbsd_init_abi (struct gdbarch_info info,
}
-void _initialize_alphanbsd_tdep ();
-void
-_initialize_alphanbsd_tdep ()
+INIT_GDB_FILE (alphanbsd_tdep)
{
/* Even though NetBSD/alpha used ELF since day one, it used the
traditional a.out-style core dump format before NetBSD 1.6, but
diff --git a/gdb/alpha-obsd-tdep.c b/gdb/alpha-obsd-tdep.c
index b5ddbbc..a84dfa8 100644
--- a/gdb/alpha-obsd-tdep.c
+++ b/gdb/alpha-obsd-tdep.c
@@ -106,11 +106,10 @@ alphaobsd_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
/* OpenBSD/alpha 3.0 and earlier does not provide single step
support via ptrace(2); use software single-stepping for now. */
- set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, alpha_software_single_step);
/* OpenBSD/alpha has SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
tdep->dynamic_sigtramp_offset = alphaobsd_sigtramp_offset;
@@ -125,9 +124,7 @@ alphaobsd_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
}
-void _initialize_alphaobsd_tdep ();
-void
-_initialize_alphaobsd_tdep ()
+INIT_GDB_FILE (alphaobsd_tdep)
{
gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_OPENBSD,
alphaobsd_init_abi);
diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c
index f0272b0..59e0162 100644
--- a/gdb/alpha-tdep.c
+++ b/gdb/alpha-tdep.c
@@ -43,6 +43,9 @@
#include "alpha-tdep.h"
#include <algorithm>
+#include "target-descriptions.h"
+#include "features/alpha.c"
+
/* Instruction decoding. The notations for registers, immediates and
opcodes are the same as the one used in Compaq's Alpha architecture
handbook. */
@@ -75,60 +78,38 @@ static const int subq_opcode = 0x10;
static const int subq_function = 0x29;
-/* Return the name of the REGNO register.
+/* Alpha registers using their software names.
An empty name corresponds to a register number that used to
be used for a virtual register. That virtual register has
been removed, but the index is still reserved to maintain
compatibility with existing remote alpha targets. */
-static const char *
-alpha_register_name (struct gdbarch *gdbarch, int regno)
+static const char * const alpha_register_names[] =
{
- static const char * const register_names[] =
- {
- "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
- "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
- "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
- "t10", "t11", "ra", "t12", "at", "gp", "sp", "zero",
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "fpcr",
- "pc", "", "unique"
- };
-
- static_assert (ALPHA_NUM_REGS == ARRAY_SIZE (register_names));
- return register_names[regno];
-}
+ "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
+ "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
+ "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
+ "t10", "t11", "ra", "t12", "at", "gp", "sp", "zero",
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "fpcr",
+ "pc", "", "unique"
+};
+static_assert (ALPHA_NUM_REGS == ARRAY_SIZE (alpha_register_names));
static int
alpha_cannot_fetch_register (struct gdbarch *gdbarch, int regno)
{
- return (strlen (alpha_register_name (gdbarch, regno)) == 0);
+ return (strlen (alpha_register_names[regno]) == 0);
}
static int
alpha_cannot_store_register (struct gdbarch *gdbarch, int regno)
{
return (regno == ALPHA_ZERO_REGNUM
- || strlen (alpha_register_name (gdbarch, regno)) == 0);
-}
-
-static struct type *
-alpha_register_type (struct gdbarch *gdbarch, int regno)
-{
- if (regno == ALPHA_SP_REGNUM || regno == ALPHA_GP_REGNUM)
- return builtin_type (gdbarch)->builtin_data_ptr;
- if (regno == ALPHA_PC_REGNUM)
- return builtin_type (gdbarch)->builtin_func_ptr;
-
- /* Don't need to worry about little vs big endian until
- some jerk tries to port to alpha-unicosmk. */
- if (regno >= ALPHA_FP0_REGNUM && regno < ALPHA_FP0_REGNUM + 31)
- return builtin_type (gdbarch)->builtin_double;
-
- return builtin_type (gdbarch)->builtin_int64;
+ || strlen (alpha_register_names[regno]) == 0);
}
/* Is REGNUM a member of REGGROUP? */
@@ -1715,11 +1696,39 @@ alpha_software_single_step (struct regcache *regcache)
static struct gdbarch *
alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
+ tdesc_arch_data_up tdesc_data;
+ const struct target_desc *tdesc = info.target_desc;
+
/* Find a candidate among extant architectures. */
arches = gdbarch_list_lookup_by_info (arches, &info);
if (arches != NULL)
return arches->gdbarch;
+ if (tdesc == nullptr)
+ tdesc = tdesc_alpha;
+
+ /* Validate target description. */
+ if (tdesc_has_registers (tdesc))
+ {
+ const struct tdesc_feature *feature;
+ bool valid_p;
+
+ feature = tdesc_find_feature (tdesc, "org.gnu.gdb.alpha.core");
+ if (feature == nullptr)
+ return nullptr;
+
+ tdesc_data = tdesc_data_alloc ();
+ valid_p = true;
+ for (int i = 0; i < ALPHA_NUM_REGS; ++i)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), i,
+ alpha_register_names[i]);
+
+ if (!valid_p)
+ return nullptr;
+ }
+
+ gdb_assert (tdesc_data != nullptr);
+
gdbarch *gdbarch
= gdbarch_alloc (&info, gdbarch_tdep_up (new alpha_gdbarch_tdep));
alpha_gdbarch_tdep *tdep = gdbarch_tdep<alpha_gdbarch_tdep> (gdbarch);
@@ -1756,8 +1765,7 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_pc_regnum (gdbarch, ALPHA_PC_REGNUM);
set_gdbarch_fp0_regnum (gdbarch, ALPHA_FP0_REGNUM);
- set_gdbarch_register_name (gdbarch, alpha_register_name);
- set_gdbarch_register_type (gdbarch, alpha_register_type);
+ tdesc_use_registers (gdbarch, tdesc, std::move (tdesc_data));
set_gdbarch_cannot_fetch_register (gdbarch, alpha_cannot_fetch_register);
set_gdbarch_cannot_store_register (gdbarch, alpha_cannot_store_register);
@@ -1789,7 +1797,7 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_cannot_step_breakpoint (gdbarch, 1);
/* Handles single stepping of atomic sequences. */
- set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, alpha_software_single_step);
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);
@@ -1815,13 +1823,13 @@ alpha_dwarf2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
}
-void _initialize_alpha_tdep ();
-void
-_initialize_alpha_tdep ()
+INIT_GDB_FILE (alpha_tdep)
{
gdbarch_register (bfd_arch_alpha, alpha_gdbarch_init, NULL);
+ initialize_tdesc_alpha ();
+
/* Let the user set the fence post for heuristic_proc_start. */
/* We really would like to have both "0" and "unlimited" work, but
diff --git a/gdb/amd-dbgapi-target.c b/gdb/amd-dbgapi-target.c
index 8e067b6..666e404 100644
--- a/gdb/amd-dbgapi-target.c
+++ b/gdb/amd-dbgapi-target.c
@@ -104,12 +104,26 @@ amd_dbgapi_lib_debug_module ()
static gdb::observers::token amd_dbgapi_target_inferior_created_observer_token;
+/* See amd-dbgapi-target.h. */
+
const gdb::observers::token &
get_amd_dbgapi_target_inferior_created_observer_token ()
{
return amd_dbgapi_target_inferior_created_observer_token;
}
+/* inferior_execd observer token. */
+
+static gdb::observers::token amd_dbgapi_target_inferior_execd_observer_token;
+
+/* See amd-dbgapi-target.h. */
+
+const gdb::observers::token &
+get_amd_dbgapi_target_inferior_execd_observer_token ()
+{
+ return amd_dbgapi_target_inferior_execd_observer_token;
+}
+
/* A type holding coordinates, etc. info for a given wave. */
struct wave_coordinates
@@ -234,7 +248,7 @@ struct amd_dbgapi_inferior_info
};
static amd_dbgapi_event_id_t process_event_queue
- (amd_dbgapi_process_id_t process_id,
+ (amd_dbgapi_inferior_info &info,
amd_dbgapi_event_kind_t until_event_kind = AMD_DBGAPI_EVENT_KIND_NONE);
static const target_info amd_dbgapi_target_info = {
@@ -331,15 +345,15 @@ static const registry<inferior>::key<amd_dbgapi_inferior_info>
/* Fetch the amd_dbgapi_inferior_info data for the given inferior. */
-static struct amd_dbgapi_inferior_info *
-get_amd_dbgapi_inferior_info (struct inferior *inferior)
+static amd_dbgapi_inferior_info &
+get_amd_dbgapi_inferior_info (inferior *inferior)
{
amd_dbgapi_inferior_info *info = amd_dbgapi_inferior_data.get (inferior);
if (info == nullptr)
info = amd_dbgapi_inferior_data.emplace (inferior, inferior);
- return info;
+ return *info;
}
/* The async event handler registered with the event loop, indicating that we
@@ -416,11 +430,11 @@ wave_coordinates::fetch ()
static wave_info &
get_thread_wave_info (thread_info *tp)
{
- amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (tp->inf);
+ amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (tp->inf);
amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (tp->ptid);
- auto it = info->wave_info_map.find (wave_id.handle);
- gdb_assert (it != info->wave_info_map.end ());
+ auto it = info.wave_info_map.find (wave_id.handle);
+ gdb_assert (it != info.wave_info_map.end ());
return it->second;
}
@@ -443,6 +457,32 @@ async_event_handler_mark ()
mark_async_event_handler (amd_dbgapi_async_event_handler);
}
+/* Set forward progress requirement to REQUIRE for inferior INFO. */
+
+static void
+require_forward_progress (amd_dbgapi_inferior_info &info, bool require)
+{
+ /* If we try to disable forward progress requirement but the target expects
+ resumed threads to be committed to the target, we could wait for events
+ that will never arrive. */
+ if (!require)
+ gdb_assert (!info.inf->process_target ()->commit_resumed_state);
+
+ gdb_assert (info.process_id != AMD_DBGAPI_PROCESS_NONE);
+
+ /* Don't do unnecessary calls to amd-dbgapi to avoid polluting the logs. */
+ if (info.forward_progress_required == require)
+ return;
+
+ const auto progress
+ = require ? AMD_DBGAPI_PROGRESS_NORMAL : AMD_DBGAPI_PROGRESS_NO_FORWARD;
+ const auto status
+ = amd_dbgapi_process_set_progress (info.process_id, progress);
+ gdb_assert (status == AMD_DBGAPI_STATUS_SUCCESS);
+
+ info.forward_progress_required = require;
+}
+
/* Set forward progress requirement to REQUIRE for all processes of PROC_TARGET
matching PTID. */
@@ -455,23 +495,10 @@ require_forward_progress (ptid_t ptid, process_stratum_target *proc_target,
if (ptid != minus_one_ptid && inf->pid != ptid.pid ())
continue;
- amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
+ amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (inf);
- if (info->process_id == AMD_DBGAPI_PROCESS_NONE)
- continue;
-
- /* Don't do unnecessary calls to amd-dbgapi to avoid polluting the logs. */
- if (info->forward_progress_required == require)
- continue;
-
- amd_dbgapi_status_t status
- = amd_dbgapi_process_set_progress
- (info->process_id, (require
- ? AMD_DBGAPI_PROGRESS_NORMAL
- : AMD_DBGAPI_PROGRESS_NO_FORWARD));
- gdb_assert (status == AMD_DBGAPI_STATUS_SUCCESS);
-
- info->forward_progress_required = require;
+ if (info.process_id != AMD_DBGAPI_PROCESS_NONE)
+ require_forward_progress (info, require);
/* If ptid targets a single inferior and we have found it, no need to
continue. */
@@ -485,7 +512,7 @@ require_forward_progress (ptid_t ptid, process_stratum_target *proc_target,
amd_dbgapi_process_id_t
get_amd_dbgapi_process_id (inferior *inf)
{
- return get_amd_dbgapi_inferior_info (inf)->process_id;
+ return get_amd_dbgapi_inferior_info (inf).process_id;
}
/* A breakpoint dbgapi wants us to insert, to handle shared library
@@ -520,7 +547,7 @@ void
amd_dbgapi_target_breakpoint::check_status (struct bpstat *bs)
{
struct inferior *inf = current_inferior ();
- amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
+ amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (inf);
amd_dbgapi_status_t status;
bs->stop = 0;
@@ -528,13 +555,13 @@ amd_dbgapi_target_breakpoint::check_status (struct bpstat *bs)
/* Find the address the breakpoint is set at. */
auto match_breakpoint
- = [bs] (const decltype (info->breakpoint_map)::value_type &value)
+ = [bs] (const decltype (info.breakpoint_map)::value_type &value)
{ return value.second == bs->breakpoint_at; };
auto it
- = std::find_if (info->breakpoint_map.begin (), info->breakpoint_map.end (),
+ = std::find_if (info.breakpoint_map.begin (), info.breakpoint_map.end (),
match_breakpoint);
- if (it == info->breakpoint_map.end ())
+ if (it == info.breakpoint_map.end ())
error (_("Could not find breakpoint_id for breakpoint at %s"),
paddress (inf->arch (), bs->bp_location_at->address));
@@ -555,11 +582,12 @@ amd_dbgapi_target_breakpoint::check_status (struct bpstat *bs)
if (action == AMD_DBGAPI_BREAKPOINT_ACTION_RESUME)
return;
+ require_forward_progress (info, false);
+
/* If the action is AMD_DBGAPI_BREAKPOINT_ACTION_HALT, we need to wait until
a breakpoint resume event for this breakpoint_id is seen. */
amd_dbgapi_event_id_t resume_event_id
- = process_event_queue (info->process_id,
- AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME);
+ = process_event_queue (info, AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME);
/* We should always get a breakpoint_resume event after processing all
events generated by reporting the breakpoint hit. */
@@ -619,12 +647,12 @@ amd_dbgapi_target::pid_to_str (ptid_t ptid)
process_stratum_target *proc_target = current_inferior ()->process_target ();
inferior *inf = find_inferior_pid (proc_target, ptid.pid ());
gdb_assert (inf != nullptr);
- amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
+ const amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (inf);
auto wave_id = get_amd_dbgapi_wave_id (ptid);
- auto it = info->wave_info_map.find (wave_id.handle);
- if (it != info->wave_info_map.end ())
+ auto it = info.wave_info_map.find (wave_id.handle);
+ if (it != info.wave_info_map.end ())
return it->second.coords.to_string ();
/* A wave we don't know about. Shouldn't usually happen, but
@@ -880,7 +908,7 @@ amd_dbgapi_target::stop (ptid_t ptid)
if (m_report_thread_events)
{
- get_amd_dbgapi_inferior_info (thread->inf)->wave_events.emplace_back
+ get_amd_dbgapi_inferior_info (thread->inf).wave_events.emplace_back
(thread->ptid, target_waitstatus ().set_thread_exited (0));
if (target_is_async_p ())
@@ -948,18 +976,19 @@ private:
static void
dbgapi_notifier_handler (int err, gdb_client_data client_data)
{
- amd_dbgapi_inferior_info *info = (amd_dbgapi_inferior_info *) client_data;
+ amd_dbgapi_inferior_info &info
+ = *static_cast<amd_dbgapi_inferior_info *> (client_data);
int ret;
/* Drain the notifier pipe. */
do
{
char buf;
- ret = read (info->notifier, &buf, 1);
+ ret = read (info.notifier, &buf, 1);
}
while (ret >= 0 || (ret == -1 && errno == EINTR));
- if (info->inf->target_is_pushed (&the_amd_dbgapi_target))
+ if (info.inf->target_is_pushed (&the_amd_dbgapi_target))
{
/* The amd-dbgapi target is pushed: signal our async handler, the event
will be consumed through our wait method. */
@@ -976,7 +1005,7 @@ dbgapi_notifier_handler (int err, gdb_client_data client_data)
amd_dbgapi_event_id_t event_id;
amd_dbgapi_event_kind_t event_kind;
amd_dbgapi_status_t status
- = amd_dbgapi_process_next_pending_event (info->process_id, &event_id,
+ = amd_dbgapi_process_next_pending_event (info.process_id, &event_id,
&event_kind);
if (status != AMD_DBGAPI_STATUS_SUCCESS)
error (_("next_pending_event failed (%s)"), get_status_string (status));
@@ -1000,17 +1029,17 @@ dbgapi_notifier_handler (int err, gdb_client_data client_data)
switch (runtime_state)
{
case AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS:
- gdb_assert (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
- info->runtime_state = runtime_state;
+ gdb_assert (info.runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
+ info.runtime_state = runtime_state;
amd_dbgapi_debug_printf ("pushing amd-dbgapi target");
- info->inf->push_target (&the_amd_dbgapi_target);
+ info.inf->push_target (&the_amd_dbgapi_target);
/* The underlying target will already be async if we are running, but not if
we are attaching. */
- if (info->inf->process_target ()->is_async_p ())
+ if (info.inf->process_target ()->is_async_p ())
{
scoped_restore_current_thread restore_thread;
- switch_to_inferior_no_thread (info->inf);
+ switch_to_inferior_no_thread (info.inf);
/* Make sure our async event handler is created. */
target_async (true);
@@ -1018,14 +1047,14 @@ dbgapi_notifier_handler (int err, gdb_client_data client_data)
break;
case AMD_DBGAPI_RUNTIME_STATE_UNLOADED:
- gdb_assert (info->runtime_state
+ gdb_assert (info.runtime_state
== AMD_DBGAPI_RUNTIME_STATE_LOADED_ERROR_RESTRICTION);
- info->runtime_state = runtime_state;
+ info.runtime_state = runtime_state;
break;
case AMD_DBGAPI_RUNTIME_STATE_LOADED_ERROR_RESTRICTION:
- gdb_assert (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
- info->runtime_state = runtime_state;
+ gdb_assert (info.runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
+ info.runtime_state = runtime_state;
warning (_("amd-dbgapi: unable to enable GPU debugging "
"due to a restriction error"));
break;
@@ -1054,10 +1083,10 @@ amd_dbgapi_target::async (bool enable)
for (inferior *inf : all_non_exited_inferiors (proc_target))
{
- amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
+ amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (inf);
- if (info->notifier != -1)
- add_file_handler (info->notifier, dbgapi_notifier_handler, info,
+ if (info.notifier != -1)
+ add_file_handler (info.notifier, dbgapi_notifier_handler, &info,
string_printf ("amd-dbgapi notifier for pid %d",
inf->pid));
}
@@ -1077,10 +1106,11 @@ amd_dbgapi_target::async (bool enable)
for (inferior *inf : all_inferiors ())
{
- amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
+ const amd_dbgapi_inferior_info &info
+ = get_amd_dbgapi_inferior_info (inf);
- if (info->notifier != -1)
- delete_file_handler (info->notifier);
+ if (info.notifier != -1)
+ delete_file_handler (info.notifier);
}
delete_async_event_handler (&amd_dbgapi_async_event_handler);
@@ -1104,11 +1134,11 @@ amd_dbgapi_thread_deleted (thread_info *tp)
if (tp->inf->target_at (arch_stratum) == &the_amd_dbgapi_target
&& ptid_is_gpu (tp->ptid))
{
- amd_dbgapi_inferior_info *info = amd_dbgapi_inferior_data.get (tp->inf);
+ amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (tp->inf);
auto wave_id = get_amd_dbgapi_wave_id (tp->ptid);
- auto it = info->wave_info_map.find (wave_id.handle);
- gdb_assert (it != info->wave_info_map.end ());
- info->wave_info_map.erase (it);
+ auto it = info.wave_info_map.find (wave_id.handle);
+ gdb_assert (it != info.wave_info_map.end ());
+ info.wave_info_map.erase (it);
}
}
@@ -1119,11 +1149,11 @@ static thread_info *
add_gpu_thread (inferior *inf, ptid_t wave_ptid)
{
process_stratum_target *proc_target = inf->process_target ();
- amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
+ amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (inf);
auto wave_id = get_amd_dbgapi_wave_id (wave_ptid);
- if (!info->wave_info_map.try_emplace (wave_id.handle,
+ if (!info.wave_info_map.try_emplace (wave_id.handle,
wave_info (wave_id)).second)
internal_error ("wave ID %ld already in map", wave_id.handle);
@@ -1138,32 +1168,14 @@ add_gpu_thread (inferior *inf, ptid_t wave_ptid)
/* Process an event that was just pulled out of the amd-dbgapi library. */
static void
-process_one_event (amd_dbgapi_event_id_t event_id,
+process_one_event (amd_dbgapi_inferior_info &info,
+ amd_dbgapi_event_id_t event_id,
amd_dbgapi_event_kind_t event_kind)
{
/* Automatically mark this event processed when going out of scope. */
scoped_amd_dbgapi_event_processed mark_event_processed (event_id);
- amd_dbgapi_process_id_t process_id;
- amd_dbgapi_status_t status
- = amd_dbgapi_event_get_info (event_id, AMD_DBGAPI_EVENT_INFO_PROCESS,
- sizeof (process_id), &process_id);
- if (status != AMD_DBGAPI_STATUS_SUCCESS)
- error (_("event_get_info for event_%ld failed (%s)"), event_id.handle,
- get_status_string (status));
-
- amd_dbgapi_os_process_id_t pid;
- status = amd_dbgapi_process_get_info (process_id,
- AMD_DBGAPI_PROCESS_INFO_OS_ID,
- sizeof (pid), &pid);
- if (status != AMD_DBGAPI_STATUS_SUCCESS)
- error (_("process_get_info for process_%ld failed (%s)"),
- process_id.handle, get_status_string (status));
-
- auto *proc_target = current_inferior ()->process_target ();
- inferior *inf = find_inferior_pid (proc_target, pid);
- gdb_assert (inf != nullptr);
- amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
+ gdb_assert (info.inf != nullptr);
switch (event_kind)
{
@@ -1171,14 +1183,14 @@ process_one_event (amd_dbgapi_event_id_t event_id,
case AMD_DBGAPI_EVENT_KIND_WAVE_STOP:
{
amd_dbgapi_wave_id_t wave_id;
- status
+ amd_dbgapi_status_t status
= amd_dbgapi_event_get_info (event_id, AMD_DBGAPI_EVENT_INFO_WAVE,
sizeof (wave_id), &wave_id);
if (status != AMD_DBGAPI_STATUS_SUCCESS)
error (_("event_get_info for event_%ld failed (%s)"),
event_id.handle, get_status_string (status));
- ptid_t event_ptid = make_gpu_ptid (pid, wave_id);
+ ptid_t event_ptid = make_gpu_ptid (info.inf->pid, wave_id);
target_waitstatus ws;
amd_dbgapi_wave_stop_reasons_t stop_reason;
@@ -1219,9 +1231,10 @@ process_one_event (amd_dbgapi_event_id_t event_id,
else
ws.set_stopped (GDB_SIGNAL_0);
- thread_info *thread = proc_target->find_thread (event_ptid);
+ thread_info *thread
+ = info.inf->process_target ()->find_thread (event_ptid);
if (thread == nullptr)
- thread = add_gpu_thread (inf, event_ptid);
+ thread = add_gpu_thread (info.inf, event_ptid);
/* If the wave is stopped because of a software breakpoint, the
program counter needs to be adjusted so that it points to the
@@ -1243,7 +1256,7 @@ process_one_event (amd_dbgapi_event_id_t event_id,
error (_("wave_get_info for wave_%ld failed (%s)"),
wave_id.handle, get_status_string (status));
- info->wave_events.emplace_back (event_ptid, ws);
+ info.wave_events.emplace_back (event_ptid, ws);
break;
}
@@ -1261,7 +1274,7 @@ process_one_event (amd_dbgapi_event_id_t event_id,
When amd_dbgapi_target_breakpoint::check_status is called, the current
inferior is the inferior that hit the breakpoint, which should still be
the case now. */
- gdb_assert (inf == current_inferior ());
+ gdb_assert (info.inf == current_inferior ());
handle_solib_event ();
break;
@@ -1275,22 +1288,22 @@ process_one_event (amd_dbgapi_event_id_t event_id,
{
amd_dbgapi_runtime_state_t runtime_state;
- status = amd_dbgapi_event_get_info (event_id,
- AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE,
- sizeof (runtime_state),
- &runtime_state);
+ amd_dbgapi_status_t status
+ = amd_dbgapi_event_get_info (event_id,
+ AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE,
+ sizeof (runtime_state), &runtime_state);
if (status != AMD_DBGAPI_STATUS_SUCCESS)
error (_("event_get_info for event_%ld failed (%s)"),
event_id.handle, get_status_string (status));
gdb_assert (runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
gdb_assert
- (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS);
+ (info.runtime_state == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS);
- info->runtime_state = runtime_state;
+ info.runtime_state = runtime_state;
- gdb_assert (inf->target_is_pushed (&the_amd_dbgapi_target));
- inf->unpush_target (&the_amd_dbgapi_target);
+ gdb_assert (info.inf->target_is_pushed (&the_amd_dbgapi_target));
+ info.inf->unpush_target (&the_amd_dbgapi_target);
}
break;
@@ -1331,20 +1344,18 @@ event_kind_str (amd_dbgapi_event_kind_t kind)
gdb_assert_not_reached ("unhandled amd_dbgapi_event_kind_t value");
}
-/* Drain the dbgapi event queue of a given process_id, or of all processes if
- process_id is AMD_DBGAPI_PROCESS_NONE. Stop processing the events if an
- event of a given kind is requested and `process_id` is not
- AMD_DBGAPI_PROCESS_NONE. Wave stop events that are not returned are queued
- into their inferior's amd_dbgapi_inferior_info pending wave events. */
+/* Drain the dbgapi event queue of a given inferior. Stop processing the
+ events if an event of a given kind is requested (not AMD_DBGAPI_EVENT_NONE).
+ Wave stop events that are not returned are queued into their inferior's
+ amd_dbgapi_inferior_info pending wave events. */
static amd_dbgapi_event_id_t
-process_event_queue (amd_dbgapi_process_id_t process_id,
+process_event_queue (amd_dbgapi_inferior_info &info,
amd_dbgapi_event_kind_t until_event_kind)
{
- /* An event of a given type can only be requested from a single
- process_id. */
- gdb_assert (until_event_kind == AMD_DBGAPI_EVENT_KIND_NONE
- || process_id != AMD_DBGAPI_PROCESS_NONE);
+ /* Pulling events with forward progress required may result in bad
+ performance, make sure it is not required. */
+ gdb_assert (!info.forward_progress_required);
while (true)
{
@@ -1352,7 +1363,7 @@ process_event_queue (amd_dbgapi_process_id_t process_id,
amd_dbgapi_event_kind_t event_kind;
amd_dbgapi_status_t status
- = amd_dbgapi_process_next_pending_event (process_id, &event_id,
+ = amd_dbgapi_process_next_pending_event (info.process_id, &event_id,
&event_kind);
if (status != AMD_DBGAPI_STATUS_SUCCESS)
@@ -1368,7 +1379,7 @@ process_event_queue (amd_dbgapi_process_id_t process_id,
if (event_id == AMD_DBGAPI_EVENT_NONE || event_kind == until_event_kind)
return event_id;
- process_one_event (event_id, event_kind);
+ process_one_event (info, event_id, event_kind);
}
}
@@ -1390,13 +1401,13 @@ static std::pair<ptid_t, target_waitstatus>
consume_one_event (int pid)
{
auto *target = current_inferior ()->process_target ();
- struct amd_dbgapi_inferior_info *info = nullptr;
+ amd_dbgapi_inferior_info *info = nullptr;
if (pid == -1)
{
for (inferior *inf : all_inferiors (target))
{
- info = get_amd_dbgapi_inferior_info (inf);
+ info = &get_amd_dbgapi_inferior_info (inf);
if (!info->wave_events.empty ())
break;
}
@@ -1408,7 +1419,7 @@ consume_one_event (int pid)
inferior *inf = find_inferior_pid (target, pid);
gdb_assert (inf != nullptr);
- info = get_amd_dbgapi_inferior_info (inf);
+ info = &get_amd_dbgapi_inferior_info (inf);
}
if (info->wave_events.empty ())
@@ -1472,8 +1483,9 @@ amd_dbgapi_target::wait (ptid_t ptid, struct target_waitstatus *ws,
{
/* Drain the events for the current inferior from the amd_dbgapi and
preserve the ordering. */
- auto info = get_amd_dbgapi_inferior_info (current_inferior ());
- process_event_queue (info->process_id, AMD_DBGAPI_EVENT_KIND_NONE);
+ amd_dbgapi_inferior_info &info
+ = get_amd_dbgapi_inferior_info (current_inferior ());
+ process_event_queue (info);
std::tie (event_ptid, gpu_waitstatus) = consume_one_event (ptid.pid ());
if (event_ptid == minus_one_ptid)
@@ -1495,7 +1507,7 @@ amd_dbgapi_target::wait (ptid_t ptid, struct target_waitstatus *ws,
for (inferior *inf : all_inferiors ())
if (inf->target_at (arch_stratum) == &the_amd_dbgapi_target
- && get_amd_dbgapi_inferior_info (inf)->runtime_state
+ && get_amd_dbgapi_inferior_info (inf).runtime_state
== AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS)
{
ws->set_ignore ();
@@ -1596,20 +1608,20 @@ attach_amd_dbgapi (inferior *inf)
if (inf->vfork_parent != nullptr)
return;
- auto *info = get_amd_dbgapi_inferior_info (inf);
+ amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (inf);
/* Are we already attached? */
- if (info->process_id != AMD_DBGAPI_PROCESS_NONE)
+ if (info.process_id != AMD_DBGAPI_PROCESS_NONE)
{
amd_dbgapi_debug_printf
- ("already attached: process_id = %" PRIu64, info->process_id.handle);
+ ("already attached: process_id = %" PRIu64, info.process_id.handle);
return;
}
amd_dbgapi_status_t status
= amd_dbgapi_process_attach
(reinterpret_cast<amd_dbgapi_client_process_id_t> (inf),
- &info->process_id);
+ &info.process_id);
if (status == AMD_DBGAPI_STATUS_ERROR_RESTRICTION)
{
warning (_("amd-dbgapi: unable to enable GPU debugging due to a "
@@ -1624,29 +1636,29 @@ attach_amd_dbgapi (inferior *inf)
return;
}
- if (amd_dbgapi_process_get_info (info->process_id,
+ if (amd_dbgapi_process_get_info (info.process_id,
AMD_DBGAPI_PROCESS_INFO_NOTIFIER,
- sizeof (info->notifier), &info->notifier)
+ sizeof (info.notifier), &info.notifier)
!= AMD_DBGAPI_STATUS_SUCCESS)
{
- amd_dbgapi_process_detach (info->process_id);
- info->process_id = AMD_DBGAPI_PROCESS_NONE;
+ amd_dbgapi_process_detach (info.process_id);
+ info.process_id = AMD_DBGAPI_PROCESS_NONE;
warning (_("amd-dbgapi: could not retrieve process %d's notifier, GPU "
"debugging will not be available."), inf->pid);
return;
}
amd_dbgapi_debug_printf ("process_id = %" PRIu64 ", notifier fd = %d",
- info->process_id.handle, info->notifier);
+ info.process_id.handle, info.notifier);
- set_process_memory_precision (*info);
+ set_process_memory_precision (info);
/* If GDB is attaching to a process that has the runtime loaded, there will
already be a "runtime loaded" event available. Consume it and push the
target. */
- dbgapi_notifier_handler (0, info);
+ dbgapi_notifier_handler (0, &info);
- add_file_handler (info->notifier, dbgapi_notifier_handler, info,
+ add_file_handler (info.notifier, dbgapi_notifier_handler, &info,
"amd-dbgapi notifier");
}
@@ -1663,30 +1675,30 @@ detach_amd_dbgapi (inferior *inf)
{
AMD_DBGAPI_SCOPED_DEBUG_START_END ("inf num = %d", inf->num);
- auto *info = get_amd_dbgapi_inferior_info (inf);
+ amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (inf);
- if (info->process_id == AMD_DBGAPI_PROCESS_NONE)
+ if (info.process_id == AMD_DBGAPI_PROCESS_NONE)
return;
- info->runtime_state = AMD_DBGAPI_RUNTIME_STATE_UNLOADED;
+ info.runtime_state = AMD_DBGAPI_RUNTIME_STATE_UNLOADED;
- amd_dbgapi_status_t status = amd_dbgapi_process_detach (info->process_id);
+ amd_dbgapi_status_t status = amd_dbgapi_process_detach (info.process_id);
if (status != AMD_DBGAPI_STATUS_SUCCESS)
warning (_("amd-dbgapi: could not detach from process %d (%s)"),
inf->pid, get_status_string (status));
- gdb_assert (info->notifier != -1);
- delete_file_handler (info->notifier);
+ gdb_assert (info.notifier != -1);
+ delete_file_handler (info.notifier);
/* This is a noop if the target is not pushed. */
inf->unpush_target (&the_amd_dbgapi_target);
/* Delete the breakpoints that are still active. */
- for (auto &&value : info->breakpoint_map)
+ for (auto &&value : info.breakpoint_map)
delete_breakpoint (value.second);
/* Reset the amd_dbgapi_inferior_info, except for precise_memory_mode. */
- *info = amd_dbgapi_inferior_info (inf, info->precise_memory.requested);
+ info = amd_dbgapi_inferior_info (inf, info.precise_memory.requested);
maybe_reset_amd_dbgapi ();
}
@@ -1860,13 +1872,14 @@ amd_dbgapi_target::update_thread_list ()
if (changed == AMD_DBGAPI_CHANGED_NO)
continue;
+ gdb::unique_xmalloc_ptr<amd_dbgapi_wave_id_t> wave_list_holder
+ (wave_list);
+
/* Create a set and free the wave list. */
std::set<ptid_t::tid_type> threads;
for (size_t i = 0; i < count; ++i)
threads.emplace (wave_list[i].handle);
- xfree (wave_list);
-
/* Prune the wave_ids that already have a thread_info. Any thread_info
which does not have a corresponding wave_id represents a wave which
is gone at this point and should be deleted. */
@@ -1961,10 +1974,10 @@ amd_dbgapi_target::displaced_step_prepare (thread_info *thread,
}
/* Save the displaced stepping id in the per-inferior info. */
- amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (thread->inf);
+ amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (thread->inf);
bool inserted
- = info->stepping_id_map.emplace (thread, stepping_id.handle).second;
+ = info.stepping_id_map.emplace (thread, stepping_id.handle).second;
gdb_assert (inserted);
/* Get the new (displaced) PC. */
@@ -1996,8 +2009,8 @@ amd_dbgapi_target::displaced_step_finish (thread_info *thread,
gdb_assert (thread->displaced_step_state.in_progress ());
/* Find the displaced stepping id for this thread. */
- amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (thread->inf);
- auto entry = info->stepping_id_map.extract (thread);
+ amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (thread->inf);
+ auto entry = info.stepping_id_map.extract (thread);
gdb_assert (entry.has_value ());
amd_dbgapi_displaced_stepping_id_t stepping_id {entry->second};
@@ -2054,14 +2067,16 @@ static void
amd_dbgapi_target_inferior_cloned (inferior *original_inferior,
inferior *new_inferior)
{
- auto *orig_info = get_amd_dbgapi_inferior_info (original_inferior);
- auto *new_info = get_amd_dbgapi_inferior_info (new_inferior);
+ const amd_dbgapi_inferior_info &orig_info
+ = get_amd_dbgapi_inferior_info (original_inferior);
+ amd_dbgapi_inferior_info &new_info
+ = get_amd_dbgapi_inferior_info (new_inferior);
/* At this point, the process is not started. Therefore it is sufficient to
copy the precise memory request, it will be applied when the process
starts. */
- gdb_assert (new_info->process_id == AMD_DBGAPI_PROCESS_NONE);
- new_info->precise_memory.requested = orig_info->precise_memory.requested;
+ gdb_assert (new_info.process_id == AMD_DBGAPI_PROCESS_NONE);
+ new_info.precise_memory.requested = orig_info.precise_memory.requested;
}
/* inferior_execd observer. */
@@ -2077,8 +2092,8 @@ amd_dbgapi_inferior_execd (inferior *exec_inf, inferior *follow_inf)
/* If using "follow-exec-mode new", carry over the precise-memory setting
to the new inferior (otherwise, FOLLOW_INF and ORIG_INF point to the same
inferior, so this is a no-op). */
- get_amd_dbgapi_inferior_info (follow_inf)->precise_memory.requested
- = get_amd_dbgapi_inferior_info (exec_inf)->precise_memory.requested;
+ get_amd_dbgapi_inferior_info (follow_inf).precise_memory.requested
+ = get_amd_dbgapi_inferior_info (exec_inf).precise_memory.requested;
attach_amd_dbgapi (follow_inf);
}
@@ -2092,12 +2107,12 @@ amd_dbgapi_inferior_forked (inferior *parent_inf, inferior *child_inf,
if (child_inf != nullptr)
{
/* Copy precise-memory requested value from parent to child. */
- amd_dbgapi_inferior_info *parent_info
+ const amd_dbgapi_inferior_info &parent_info
= get_amd_dbgapi_inferior_info (parent_inf);
- amd_dbgapi_inferior_info *child_info
+ amd_dbgapi_inferior_info &child_info
= get_amd_dbgapi_inferior_info (child_inf);
- child_info->precise_memory.requested
- = parent_info->precise_memory.requested;
+ child_info.precise_memory.requested
+ = parent_info.precise_memory.requested;
if (fork_kind != TARGET_WAITKIND_VFORKED)
{
@@ -2171,10 +2186,10 @@ amd_dbgapi_insert_breakpoint_callback
amd_dbgapi_breakpoint_id_t breakpoint_id)
{
inferior *inf = reinterpret_cast<inferior *> (client_process_id);
- struct amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
+ amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (inf);
- auto it = info->breakpoint_map.find (breakpoint_id.handle);
- if (it != info->breakpoint_map.end ())
+ auto it = info.breakpoint_map.find (breakpoint_id.handle);
+ if (it != info.breakpoint_map.end ())
return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID;
/* We need to find the address in the given inferior's program space. */
@@ -2191,7 +2206,7 @@ amd_dbgapi_insert_breakpoint_callback
breakpoint *bp = install_breakpoint (true, std::move (bp_up), 1);
- info->breakpoint_map.emplace (breakpoint_id.handle, bp);
+ info.breakpoint_map.emplace (breakpoint_id.handle, bp);
return AMD_DBGAPI_STATUS_SUCCESS;
}
@@ -2203,14 +2218,14 @@ amd_dbgapi_remove_breakpoint_callback
amd_dbgapi_breakpoint_id_t breakpoint_id)
{
inferior *inf = reinterpret_cast<inferior *> (client_process_id);
- struct amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
+ amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (inf);
- auto it = info->breakpoint_map.find (breakpoint_id.handle);
- if (it == info->breakpoint_map.end ())
+ auto it = info.breakpoint_map.find (breakpoint_id.handle);
+ if (it == info.breakpoint_map.end ())
return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID;
delete_breakpoint (it->second);
- info->breakpoint_map.erase (it);
+ info.breakpoint_map.erase (it);
return AMD_DBGAPI_STATUS_SUCCESS;
}
@@ -2264,10 +2279,10 @@ amd_dbgapi_xfer_global_memory_callback
static void
amd_dbgapi_target_signal_received (gdb_signal sig)
{
- amd_dbgapi_inferior_info *info
+ const amd_dbgapi_inferior_info &info
= get_amd_dbgapi_inferior_info (current_inferior ());
- if (info->process_id == AMD_DBGAPI_PROCESS_NONE)
+ if (info.process_id == AMD_DBGAPI_PROCESS_NONE)
return;
if (!ptid_is_gpu (inferior_thread ()->ptid))
@@ -2276,7 +2291,7 @@ amd_dbgapi_target_signal_received (gdb_signal sig)
if (sig != GDB_SIGNAL_SEGV && sig != GDB_SIGNAL_BUS)
return;
- if (!info->precise_memory.enabled)
+ if (!info.precise_memory.enabled)
gdb_printf (_("\
Warning: precise memory violation signal reporting is not enabled, reported\n\
location may not be accurate. See \"show amdgpu precise-memory\".\n"));
@@ -2357,14 +2372,14 @@ static void
show_precise_memory_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- amd_dbgapi_inferior_info *info
+ const amd_dbgapi_inferior_info &info
= get_amd_dbgapi_inferior_info (current_inferior ());
gdb_printf (file,
_("AMDGPU precise memory access reporting is %s "
"(currently %s).\n"),
- info->precise_memory.requested ? "on" : "off",
- info->precise_memory.enabled ? "enabled" : "disabled");
+ info.precise_memory.requested ? "on" : "off",
+ info.precise_memory.enabled ? "enabled" : "disabled");
}
/* Callback for "set amdgpu precise-memory". */
@@ -2372,13 +2387,13 @@ show_precise_memory_mode (struct ui_file *file, int from_tty,
static void
set_precise_memory_mode (bool value)
{
- amd_dbgapi_inferior_info *info
+ amd_dbgapi_inferior_info &info
= get_amd_dbgapi_inferior_info (current_inferior ());
- info->precise_memory.requested = value;
+ info.precise_memory.requested = value;
- if (info->process_id != AMD_DBGAPI_PROCESS_NONE)
- set_process_memory_precision (*info);
+ if (info.process_id != AMD_DBGAPI_PROCESS_NONE)
+ set_process_memory_precision (info);
}
/* Return whether precise-memory is requested for the current inferior. */
@@ -2386,10 +2401,10 @@ set_precise_memory_mode (bool value)
static bool
get_precise_memory_mode ()
{
- amd_dbgapi_inferior_info *info
+ const amd_dbgapi_inferior_info &info
= get_amd_dbgapi_inferior_info (current_inferior ());
- return info->precise_memory.requested;
+ return info.precise_memory.requested;
}
/* List of set/show amdgpu commands. */
@@ -2462,9 +2477,9 @@ maybe_reset_amd_dbgapi ()
{
for (inferior *inf : all_non_exited_inferiors ())
{
- amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
+ const amd_dbgapi_inferior_info &info = get_amd_dbgapi_inferior_info (inf);
- if (info->process_id != AMD_DBGAPI_PROCESS_NONE)
+ if (info.process_id != AMD_DBGAPI_PROCESS_NONE)
return;
}
@@ -2479,10 +2494,7 @@ maybe_reset_amd_dbgapi ()
get_status_string (status));
}
-extern initialize_file_ftype _initialize_amd_dbgapi_target;
-
-void
-_initialize_amd_dbgapi_target ()
+INIT_GDB_FILE (amd_dbgapi_target)
{
/* Make sure the loaded debugger library version is greater than or equal to
the one used to build GDB. */
@@ -2510,7 +2522,9 @@ _initialize_amd_dbgapi_target ()
gdb::observers::inferior_created.attach
(amd_dbgapi_target_inferior_created,
amd_dbgapi_target_inferior_created_observer_token, "amd-dbgapi");
- gdb::observers::inferior_execd.attach (amd_dbgapi_inferior_execd, "amd-dbgapi");
+ gdb::observers::inferior_execd.attach
+ (amd_dbgapi_inferior_execd, amd_dbgapi_target_inferior_execd_observer_token,
+ "amd-dbgapi");
gdb::observers::inferior_forked.attach (amd_dbgapi_inferior_forked, "amd-dbgapi");
gdb::observers::inferior_exit.attach (amd_dbgapi_inferior_exited, "amd-dbgapi");
gdb::observers::inferior_pre_detach.attach (amd_dbgapi_inferior_pre_detach, "amd-dbgapi");
diff --git a/gdb/amd-dbgapi-target.h b/gdb/amd-dbgapi-target.h
index dd37ba3..fe3a50b 100644
--- a/gdb/amd-dbgapi-target.h
+++ b/gdb/amd-dbgapi-target.h
@@ -54,6 +54,11 @@ using is_amd_dbgapi_handle
const gdb::observers::token &
get_amd_dbgapi_target_inferior_created_observer_token ();
+/* Get the token of amd-dbgapi's inferior_execd observer. */
+
+const gdb::observers::token &
+ get_amd_dbgapi_target_inferior_execd_observer_token ();
+
/* Comparison operators for amd-dbgapi handle types. */
template <typename T,
diff --git a/gdb/amd64-darwin-tdep.c b/gdb/amd64-darwin-tdep.c
index dde023e..c687b1f 100644
--- a/gdb/amd64-darwin-tdep.c
+++ b/gdb/amd64-darwin-tdep.c
@@ -113,12 +113,10 @@ x86_darwin_init_abi_64 (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->jb_pc_offset = 56;
- set_gdbarch_so_ops (gdbarch, &darwin_so_ops);
+ set_gdbarch_make_solib_ops (gdbarch, make_darwin_solib_ops);
}
-void _initialize_amd64_darwin_tdep ();
-void
-_initialize_amd64_darwin_tdep ()
+INIT_GDB_FILE (amd64_darwin_tdep)
{
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
GDB_OSABI_DARWIN, x86_darwin_init_abi_64);
diff --git a/gdb/amd64-dicos-tdep.c b/gdb/amd64-dicos-tdep.c
index 3e9b8c7..d7c211b 100644
--- a/gdb/amd64-dicos-tdep.c
+++ b/gdb/amd64-dicos-tdep.c
@@ -45,9 +45,7 @@ amd64_dicos_osabi_sniffer (bfd *abfd)
return GDB_OSABI_UNKNOWN;
}
-void _initialize_amd64_dicos_tdep ();
-void
-_initialize_amd64_dicos_tdep ()
+INIT_GDB_FILE (amd64_dicos_tdep)
{
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
amd64_dicos_osabi_sniffer);
diff --git a/gdb/amd64-fbsd-nat.c b/gdb/amd64-fbsd-nat.c
index a783a5d1..89bb049 100644
--- a/gdb/amd64-fbsd-nat.c
+++ b/gdb/amd64-fbsd-nat.c
@@ -324,9 +324,7 @@ amd64_fbsd_nat_target::read_description ()
return i386_target_description (X86_XSTATE_SSE_MASK, true);
}
-void _initialize_amd64fbsd_nat ();
-void
-_initialize_amd64fbsd_nat ()
+INIT_GDB_FILE (amd64fbsd_nat)
{
add_inf_child_target (&the_amd64_fbsd_nat_target);
diff --git a/gdb/amd64-fbsd-tdep.c b/gdb/amd64-fbsd-tdep.c
index eea0105..12f1e22 100644
--- a/gdb/amd64-fbsd-tdep.c
+++ b/gdb/amd64-fbsd-tdep.c
@@ -328,8 +328,7 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
amd64fbsd_core_read_description);
/* FreeBSD uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
@@ -337,9 +336,7 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
amd64fbsd_get_thread_local_address);
}
-void _initialize_amd64fbsd_tdep ();
-void
-_initialize_amd64fbsd_tdep ()
+INIT_GDB_FILE (amd64fbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
GDB_OSABI_FREEBSD, amd64fbsd_init_abi);
diff --git a/gdb/amd64-gnu-tdep.c b/gdb/amd64-gnu-tdep.c
index 602fa8e..2b7337b 100644
--- a/gdb/amd64-gnu-tdep.c
+++ b/gdb/amd64-gnu-tdep.c
@@ -218,13 +218,10 @@ amd64_gnu_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->sc_num_regs = ARRAY_SIZE (amd64_gnu_sc_reg_offset);
/* Hurd uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
}
-void _initialize_amd64_gnu_tdep ();
-void
-_initialize_amd64_gnu_tdep ()
+INIT_GDB_FILE (amd64_gnu_tdep)
{
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
GDB_OSABI_HURD, amd64_gnu_init_abi);
diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
index 75e63c6..e35527d 100644
--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -32,6 +32,7 @@
#include "amd64-tdep.h"
#include "amd64-linux-tdep.h"
#include "i386-linux-tdep.h"
+#include "x86-tdep.h"
#include "gdbsupport/x86-xstate.h"
#include "x86-linux-nat.h"
@@ -237,6 +238,14 @@ amd64_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
if (have_ptrace_getregset == TRIBOOL_TRUE)
{
+ if ((regnum == -1 && tdep->ssp_regnum != -1)
+ || (regnum != -1 && regnum == tdep->ssp_regnum))
+ {
+ x86_linux_fetch_ssp (regcache, tid);
+ if (regnum != -1)
+ return;
+ }
+
/* Pre-4.14 kernels have a bug (fixed by commit 0852b374173b
"x86/fpu: Add FPU state copying quirk to handle XRSTOR failure on
Intel Skylake CPUs") that sometimes causes the mxcsr location in
@@ -302,6 +311,14 @@ amd64_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
if (have_ptrace_getregset == TRIBOOL_TRUE)
{
gdb::byte_vector xstateregs (tdep->xsave_layout.sizeof_xsave);
+ if ((regnum == -1 && tdep->ssp_regnum != -1)
+ || (regnum != -1 && regnum == tdep->ssp_regnum))
+ {
+ x86_linux_store_ssp (regcache, tid);
+ if (regnum != -1)
+ return;
+ }
+
struct iovec iov;
iov.iov_base = xstateregs.data ();
@@ -424,9 +441,7 @@ amd64_linux_nat_target::low_siginfo_fixup (siginfo_t *ptrace,
return false;
}
-void _initialize_amd64_linux_nat ();
-void
-_initialize_amd64_linux_nat ()
+INIT_GDB_FILE (amd64_linux_nat)
{
amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index e5a2ab9..a21f8a9 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -33,6 +33,7 @@
#include "amd64-linux-tdep.h"
#include "i386-linux-tdep.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "svr4-tls-tdep.h"
#include "gdbsupport/x86-xstate.h"
#include "inferior.h"
@@ -46,6 +47,9 @@
#include "expop.h"
#include "arch/amd64-linux-tdesc.h"
#include "inferior.h"
+#include "x86-tdep.h"
+#include "dwarf2/frame.h"
+#include "frame-unwind.h"
/* The syscall's XML filename for i386. */
#define XML_SYSCALL_FILENAME_AMD64 "syscalls/amd64-linux.xml"
@@ -107,6 +111,7 @@ int amd64_linux_gregset_reg_offset[] =
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, /* PKEYS register pkru */
+ -1, /* CET user mode register PL3_SSP. */
/* End of hardware registers */
21 * 8, 22 * 8, /* fs_base and gs_base. */
@@ -1591,6 +1596,15 @@ amd64_linux_record_signal (struct gdbarch *gdbarch,
return 0;
}
+/* Return true if the core file ABFD contains shadow stack pointer state.
+ Otherwise, return false. */
+
+static bool
+amd64_linux_core_read_ssp_state_p (bfd *abfd)
+{
+ return bfd_get_section_by_name (abfd, ".reg-ssp") != nullptr;
+}
+
/* Get Linux/x86 target description from core dump. */
static const struct target_desc *
@@ -1600,11 +1614,14 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch,
{
/* Linux/x86-64. */
x86_xsave_layout layout;
- uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
- if (xcr0 == 0)
- xcr0 = X86_XSTATE_SSE_MASK;
+ uint64_t xstate_bv = i386_linux_core_read_xsave_info (abfd, layout);
+ if (xstate_bv == 0)
+ xstate_bv = X86_XSTATE_SSE_MASK;
- return amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK,
+ if (amd64_linux_core_read_ssp_state_p (abfd))
+ xstate_bv |= X86_XSTATE_CET_U;
+
+ return amd64_linux_read_description (xstate_bv & X86_XSTATE_ALL_MASK,
gdbarch_ptr_bit (gdbarch) == 32);
}
@@ -1635,6 +1652,37 @@ static const struct regset amd64_linux_xstateregset =
amd64_linux_collect_xstateregset
};
+/* Supply shadow stack pointer register from SSP to the register cache
+ REGCACHE. */
+
+static void
+amd64_linux_supply_ssp (const regset *regset,
+ regcache *regcache, int regnum,
+ const void *ssp, size_t len)
+{
+ gdb_assert (len == sizeof (uint64_t));
+ x86_supply_ssp (regcache, *static_cast<const uint64_t *> (ssp));
+}
+
+/* Collect the shadow stack pointer register from the register cache
+ REGCACHE and store it in SSP. */
+
+static void
+amd64_linux_collect_ssp (const regset *regset,
+ const regcache *regcache, int regnum,
+ void *ssp, size_t len)
+{
+ gdb_assert (len == sizeof (uint64_t));
+ x86_collect_ssp (regcache, *static_cast<uint64_t *> (ssp));
+}
+
+/* Shadow stack pointer register. */
+
+static const struct regset amd64_linux_ssp_register
+ {
+ NULL, amd64_linux_supply_ssp, amd64_linux_collect_ssp
+ };
+
/* Iterate over core file register note sections. */
static void
@@ -1651,6 +1699,14 @@ amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
tdep->xsave_layout.sizeof_xsave, &amd64_linux_xstateregset,
"XSAVE extended state", cb_data);
+
+ /* SSP can be unavailable. Thus, we need to check the register status
+ in case we write a core file (regcache != nullptr). */
+ if (tdep->ssp_regnum != -1
+ && (regcache == nullptr
+ || REG_VALID == regcache->get_register_status (tdep->ssp_regnum)))
+ cb (".reg-ssp", 8, 8, &amd64_linux_ssp_register,
+ "shadow stack pointer", cb_data);
}
/* The instruction sequences used in x86_64 machines for a
@@ -1867,9 +1923,165 @@ amd64_linux_get_tls_dtv_addr (struct gdbarch *gdbarch, ptid_t ptid,
return dtv_addr;
}
+/* Return the number of bytes required to update the shadow stack pointer
+ by one element. For x32 the shadow stack elements are still 64-bit
+ aligned. Thus, gdbarch_addr_bit cannot be used to compute the new
+ stack pointer. */
+
+static inline int
+amd64_linux_shadow_stack_element_size_aligned (gdbarch *gdbarch)
+{
+ const bfd_arch_info *binfo = gdbarch_bfd_arch_info (gdbarch);
+ return (binfo->bits_per_word / binfo->bits_per_byte);
+}
+
+/* Read the shadow stack pointer register and return its value, if
+ possible. */
+
+static std::optional<CORE_ADDR>
+amd64_linux_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache,
+ bool &shadow_stack_enabled)
+{
+ shadow_stack_enabled = false;
+ const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
+
+ if (tdep->ssp_regnum < 0)
+ return {};
+
+ CORE_ADDR ssp;
+ if (regcache_raw_read_unsigned (regcache, tdep->ssp_regnum, &ssp)
+ != REG_VALID)
+ return {};
+
+ /* Dependent on the target in case the shadow stack pointer is
+ unavailable, the ssp register can be invalid or 0x0 when shadow stack
+ is supported by HW and the linux kernel but not enabled for the
+ current thread. */
+ if (ssp == 0x0)
+ return {};
+
+ /* In case there is a shadow stack pointer available which is non-null,
+ the shadow stack feature is enabled. */
+ shadow_stack_enabled = true;
+ return ssp;
+}
+
+/* If shadow stack is enabled, push the address NEW_ADDR to the shadow
+ stack and increment the shadow stack pointer accordingly. */
+
+static void
+amd64_linux_shadow_stack_push (gdbarch *gdbarch, CORE_ADDR new_addr,
+ regcache *regcache)
+{
+ bool shadow_stack_enabled;
+ std::optional<CORE_ADDR> ssp
+ = amd64_linux_get_shadow_stack_pointer (gdbarch, regcache,
+ shadow_stack_enabled);
+
+ /* For amd64/Linux, if SSP has a value that means shadow stack is
+ enabled. */
+ if (!ssp.has_value ())
+ return;
+ else
+ gdb_assert (shadow_stack_enabled);
+
+ /* The shadow stack grows downwards. To push addresses to the stack,
+ we need to decrement SSP. */
+ const int element_size
+ = amd64_linux_shadow_stack_element_size_aligned (gdbarch);
+ const CORE_ADDR new_ssp = *ssp - element_size;
+
+ /* Using /proc/PID/smaps we can only check if NEW_SSP points to shadow
+ stack memory. If it doesn't, we assume the stack is full. */
+ std::pair<CORE_ADDR, CORE_ADDR> memrange;
+ if (!linux_address_in_shadow_stack_mem_range (new_ssp, &memrange))
+ error (_("No space left on the shadow stack."));
+
+ /* On x86 there can be a shadow stack token at bit 63. For x32, the
+ address size is only 32 bit. Always write back the full 8 bytes to
+ include the shadow stack token. */
+ const bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ write_memory_unsigned_integer (new_ssp, element_size, byte_order,
+ (ULONGEST) new_addr);
+
+ i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
+ gdb_assert (tdep->ssp_regnum > -1);
+
+ regcache_raw_write_unsigned (regcache, tdep->ssp_regnum, new_ssp);
+}
+
+/* Implement shadow stack pointer unwinding. For each new shadow stack
+ pointer check if its address is still in the shadow stack memory range.
+ If it's outside the range set the returned value to unavailable,
+ otherwise return a value containing the new shadow stack pointer. */
+
+static value *
+amd64_linux_dwarf2_prev_ssp (const frame_info_ptr &this_frame,
+ void **this_cache, int regnum)
+{
+ value *v = frame_unwind_got_register (this_frame, regnum, regnum);
+ gdb_assert (v != nullptr);
+
+ gdbarch *gdbarch = get_frame_arch (this_frame);
+
+ if (v->entirely_available () && !v->optimized_out ())
+ {
+ int size = register_size (gdbarch, regnum);
+ bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ CORE_ADDR ssp = extract_unsigned_integer (v->contents_all ().data (),
+ size, byte_order);
+
+ /* Using /proc/PID/smaps we can only check if the current shadow
+ stack pointer SSP points to shadow stack memory. Only if this is
+ the case a valid previous shadow stack pointer can be
+ calculated. */
+ std::pair<CORE_ADDR, CORE_ADDR> range;
+ if (linux_address_in_shadow_stack_mem_range (ssp, &range))
+ {
+ /* The shadow stack grows downwards. To compute the previous
+ shadow stack pointer, we need to increment SSP. */
+ CORE_ADDR new_ssp
+ = ssp + amd64_linux_shadow_stack_element_size_aligned (gdbarch);
+
+ /* There can be scenarios where we have a shadow stack pointer
+ but the shadow stack is empty, as no call instruction has
+ been executed yet. If NEW_SSP points to the end of or before
+ (<=) the current shadow stack memory range we consider
+ NEW_SSP as valid (but empty). */
+ if (new_ssp <= range.second)
+ return frame_unwind_got_address (this_frame, regnum, new_ssp);
+ }
+ }
+
+ /* Return a value which is marked as unavailable in case we could not
+ calculate a valid previous shadow stack pointer. */
+ value *retval
+ = value::allocate_register (get_next_frame_sentinel_okay (this_frame),
+ regnum, register_type (gdbarch, regnum));
+ retval->mark_bytes_unavailable (0, retval->type ()->length ());
+ return retval;
+}
+
+/* Implement the "init_reg" dwarf2_frame_ops method. */
+
static void
-amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch,
- int num_disp_step_buffers)
+amd64_init_reg (gdbarch *gdbarch, int regnum, dwarf2_frame_state_reg *reg,
+ const frame_info_ptr &this_frame)
+{
+ if (regnum == gdbarch_pc_regnum (gdbarch))
+ reg->how = DWARF2_FRAME_REG_RA;
+ else if (regnum == gdbarch_sp_regnum (gdbarch))
+ reg->how = DWARF2_FRAME_REG_CFA;
+ else if (regnum == AMD64_PL3_SSP_REGNUM)
+ {
+ reg->how = DWARF2_FRAME_REG_FN;
+ reg->loc.fn = amd64_linux_dwarf2_prev_ssp;
+ }
+}
+
+static void
+amd64_linux_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch,
+ int num_disp_step_buffers)
{
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
@@ -1924,6 +2136,11 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch,
set_gdbarch_remove_non_address_bits_watchpoint
(gdbarch, amd64_linux_remove_non_address_bits_watchpoint);
+
+ set_gdbarch_shadow_stack_push (gdbarch, amd64_linux_shadow_stack_push);
+ set_gdbarch_get_shadow_stack_pointer (gdbarch,
+ amd64_linux_get_shadow_stack_pointer);
+ dwarf2_frame_set_init_reg (gdbarch, amd64_init_reg);
}
static void
@@ -2130,8 +2347,7 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->i386_syscall_record = amd64_linux_syscall_record;
/* GNU/Linux uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_lp64_svr4_solib_ops);
/* Register DTrace handlers. */
set_gdbarch_dtrace_parse_probe_argument (gdbarch, amd64_dtrace_parse_probe_argument);
@@ -2344,13 +2560,10 @@ amd64_x32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->i386_syscall_record = amd64_x32_linux_syscall_record;
/* GNU/Linux uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
}
-void _initialize_amd64_linux_tdep ();
-void
-_initialize_amd64_linux_tdep ()
+INIT_GDB_FILE (amd64_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
GDB_OSABI_LINUX, amd64_linux_init_abi);
diff --git a/gdb/amd64-netbsd-nat.c b/gdb/amd64-netbsd-nat.c
index 92ad4b2..c960b3c 100644
--- a/gdb/amd64-netbsd-nat.c
+++ b/gdb/amd64-netbsd-nat.c
@@ -55,9 +55,7 @@ static int amd64nbsd32_r_reg_offset[] =
static amd64_bsd_nat_target<nbsd_nat_target> the_amd64_nbsd_nat_target;
-void _initialize_amd64nbsd_nat ();
-void
-_initialize_amd64nbsd_nat ()
+INIT_GDB_FILE (amd64nbsd_nat)
{
amd64_native_gregset32_reg_offset = amd64nbsd32_r_reg_offset;
amd64_native_gregset32_num_regs = ARRAY_SIZE (amd64nbsd32_r_reg_offset);
diff --git a/gdb/amd64-netbsd-tdep.c b/gdb/amd64-netbsd-tdep.c
index f4464b7..3dbbdd9 100644
--- a/gdb/amd64-netbsd-tdep.c
+++ b/gdb/amd64-netbsd-tdep.c
@@ -116,13 +116,10 @@ amd64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->sc_num_regs = ARRAY_SIZE (amd64nbsd_r_reg_offset);
/* NetBSD uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
}
-void _initialize_amd64nbsd_tdep ();
-void
-_initialize_amd64nbsd_tdep ()
+INIT_GDB_FILE (amd64nbsd_tdep)
{
/* The NetBSD/amd64 native dependent code makes this assumption. */
gdb_assert (ARRAY_SIZE (amd64nbsd_r_reg_offset) == AMD64_NUM_GREGS);
diff --git a/gdb/amd64-obsd-nat.c b/gdb/amd64-obsd-nat.c
index 93d38df..8471520 100644
--- a/gdb/amd64-obsd-nat.c
+++ b/gdb/amd64-obsd-nat.c
@@ -127,9 +127,7 @@ amd64obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
static amd64_bsd_nat_target<obsd_nat_target> the_amd64_obsd_nat_target;
-void _initialize_amd64obsd_nat ();
-void
-_initialize_amd64obsd_nat ()
+INIT_GDB_FILE (amd64obsd_nat)
{
amd64_native_gregset32_reg_offset = amd64obsd32_r_reg_offset;
amd64_native_gregset32_num_regs = ARRAY_SIZE (amd64obsd32_r_reg_offset);
diff --git a/gdb/amd64-obsd-tdep.c b/gdb/amd64-obsd-tdep.c
index 5acc380..6b60e0a 100644
--- a/gdb/amd64-obsd-tdep.c
+++ b/gdb/amd64-obsd-tdep.c
@@ -443,16 +443,13 @@ amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
bsd_uthread_set_collect_uthread (gdbarch, amd64obsd_collect_uthread);
/* OpenBSD uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
/* Unwind kernel trap frames correctly. */
frame_unwind_prepend_unwinder (gdbarch, &amd64obsd_trapframe_unwind);
}
-void _initialize_amd64obsd_tdep ();
-void
-_initialize_amd64obsd_tdep ()
+INIT_GDB_FILE (amd64obsd_tdep)
{
/* The OpenBSD/amd64 native dependent code makes this assumption. */
gdb_assert (ARRAY_SIZE (amd64obsd_r_reg_offset) == AMD64_NUM_GREGS);
diff --git a/gdb/amd64-sol2-tdep.c b/gdb/amd64-sol2-tdep.c
index 84d5f87..da551a1 100644
--- a/gdb/amd64-sol2-tdep.c
+++ b/gdb/amd64-sol2-tdep.c
@@ -96,13 +96,10 @@ amd64_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->sc_num_regs = tdep->gregset_num_regs;
/* Solaris uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
}
-void _initialize_amd64_sol2_tdep ();
-void
-_initialize_amd64_sol2_tdep ()
+INIT_GDB_FILE (amd64_sol2_tdep)
{
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
GDB_OSABI_SOLARIS, amd64_sol2_init_abi);
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index e495778..9245889 100644..100755
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -513,20 +513,19 @@ amd64_has_unaligned_fields (struct type *type)
if (type->code () == TYPE_CODE_STRUCT
|| type->code () == TYPE_CODE_UNION)
{
- for (int i = 0; i < type->num_fields (); i++)
+ for (const auto &field : type->fields ())
{
- struct type *subtype = check_typedef (type->field (i).type ());
+ struct type *subtype = check_typedef (field.type ());
/* Ignore static fields, empty fields (for example nested
empty structures), and bitfields (these are handled by
the caller). */
- if (type->field (i).is_static ()
- || (type->field (i).bitsize () == 0
- && subtype->length () == 0)
- || type->field (i).is_packed ())
+ if (field.is_static ()
+ || (field.bitsize () == 0 && subtype->length () == 0)
+ || field.is_packed ())
continue;
- int bitpos = type->field (i).loc_bitpos ();
+ int bitpos = field.loc_bitpos ();
if (bitpos % 8 != 0)
return true;
@@ -1182,6 +1181,15 @@ vex3_prefix_p (gdb_byte pfx)
return pfx == 0xc4;
}
+/* True if PFX is the start of an XOP prefix. */
+
+static bool
+xop_prefix_p (const gdb_byte *pfx)
+{
+ gdb_byte m = pfx[1] & 0x1f;
+ return pfx[0] == 0x8f && m >= 8;
+}
+
/* Return true if PFX is the start of the 4-byte EVEX prefix. */
static bool
@@ -1352,7 +1360,7 @@ amd64_get_insn_details (gdb_byte *insn, struct amd64_insn *details)
details->enc_prefix_offset = insn - start;
insn += 2;
}
- else if (vex3_prefix_p (*insn))
+ else if (vex3_prefix_p (*insn) || xop_prefix_p (insn))
{
details->enc_prefix_offset = insn - start;
insn += 3;
@@ -1384,13 +1392,12 @@ amd64_get_insn_details (gdb_byte *insn, struct amd64_insn *details)
}
else if (prefix != nullptr && vex2_prefix_p (*prefix))
{
- need_modrm = twobyte_has_modrm[*insn];
+ /* All VEX2 instructions need ModR/M, except vzeroupper/vzeroall. */
+ need_modrm = *insn != 0x77 ? 1 : 0;
details->opcode_len = 2;
}
else if (prefix != nullptr && vex3_prefix_p (*prefix))
{
- need_modrm = twobyte_has_modrm[*insn];
-
gdb_byte m = prefix[1] & 0x1f;
if (m == 0)
{
@@ -1399,12 +1406,16 @@ amd64_get_insn_details (gdb_byte *insn, struct amd64_insn *details)
}
else if (m == 1)
{
- /* Escape 0x0f. */
+ /* Escape 0x0f. All VEX3 instructions in this map need ModR/M,
+ except vzeroupper/vzeroall. */
+ need_modrm = *insn != 0x77 ? 1 : 0;
details->opcode_len = 2;
}
else if (m == 2 || m == 3)
{
- /* Escape 0x0f 0x38 or 0x0f 0x3a. */
+ /* Escape 0x0f 0x38 or 0x0f 0x3a. All VEX3 instructions in
+ this map need ModR/M. */
+ need_modrm = 1;
details->opcode_len = 3;
}
else if (m == 7)
@@ -1420,7 +1431,8 @@ amd64_get_insn_details (gdb_byte *insn, struct amd64_insn *details)
}
else if (prefix != nullptr && evex_prefix_p (*prefix))
{
- need_modrm = twobyte_has_modrm[*insn];
+ /* All EVEX instructions need ModR/M. */
+ need_modrm = 1;
gdb_byte m = prefix[1] & 0x7;
if (m == 1)
@@ -1439,6 +1451,11 @@ amd64_get_insn_details (gdb_byte *insn, struct amd64_insn *details)
return;
}
}
+ else if (prefix != nullptr && xop_prefix_p (prefix))
+ {
+ details->opcode_len = 1;
+ need_modrm = 1;
+ }
else if (*insn == TWO_BYTE_OPCODE_ESCAPE)
{
/* Two or three-byte opcode. */
@@ -1509,7 +1526,7 @@ fixup_riprel (const struct amd64_insn &details, gdb_byte *insn,
{
/* VEX.!B is set implicitly. */
}
- else if (vex3_prefix_p (pfx[0]))
+ else if (vex3_prefix_p (pfx[0]) || xop_prefix_p (pfx))
pfx[1] |= VEX3_NOT_B;
else if (evex_prefix_p (pfx[0]))
{
@@ -1917,6 +1934,22 @@ amd64_displaced_step_fixup (struct gdbarch *gdbarch,
displaced_debug_printf ("relocated return addr at %s to %s",
paddress (gdbarch, rsp),
paddress (gdbarch, retaddr));
+
+ /* If shadow stack is enabled, we need to correct the return address
+ on the shadow stack too. */
+ bool shadow_stack_enabled;
+ std::optional<CORE_ADDR> ssp
+ = gdbarch_get_shadow_stack_pointer (gdbarch, regs,
+ shadow_stack_enabled);
+ if (shadow_stack_enabled)
+ {
+ gdb_assert (ssp.has_value ());
+ write_memory_unsigned_integer (*ssp, retaddr_len, byte_order,
+ retaddr);
+ displaced_debug_printf ("relocated shadow stack return addr at %s "
+ "to %s", paddress (gdbarch, *ssp),
+ paddress (gdbarch, retaddr));
+ }
}
}
@@ -2129,6 +2162,30 @@ amd64_alloc_frame_cache (void)
return cache;
}
+/* Check whether PC is at "endbr64" instruction. If so, return PC past it.
+ Otherwise, return PC passed to this function. */
+
+static CORE_ADDR
+amd64_skip_endbr (gdbarch *gdbarch, CORE_ADDR pc)
+{
+ static const gdb_byte endbr64[4] = { 0xf3, 0x0f, 0x1e, 0xfa };
+
+ bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte buf[3];
+ gdb_byte op = read_code_unsigned_integer (pc, 1, byte_order);
+
+ /* Check for the `endbr64` instruction, skip it if found. */
+ if (op == endbr64[0])
+ {
+ read_code (pc + 1, buf, 3);
+
+ if (memcmp (buf, &endbr64[1], 3) == 0)
+ return pc + 4;
+ }
+
+ return pc;
+}
+
/* GCC 4.4 and later, can put code in the prologue to realign the
stack pointer. Check whether PC points to such code, and update
CACHE accordingly. Return the first instruction after the code
@@ -2466,35 +2523,18 @@ amd64_x32_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
return std::min (pc + offset + 2, current_pc);
}
-/* Do a limited analysis of the prologue at PC and update CACHE
- accordingly. Bail out early if CURRENT_PC is reached. Return the
- address where the analysis stopped.
-
- We will handle only functions beginning with:
-
- pushq %rbp 0x55
- movq %rsp, %rbp 0x48 0x89 0xe5 (or 0x48 0x8b 0xec)
-
- or (for the X32 ABI):
-
- pushq %rbp 0x55
- movl %esp, %ebp 0x89 0xe5 (or 0x8b 0xec)
+/* Analyze frame setup instructions at PC on behalf of amd64_analyze_prologue
+ and update CACHE accordingly. Bail out early if CURRENT_PC is reached.
+ Return the address where the analysis stopped.
- The `endbr64` instruction can be found before these sequences, and will be
- skipped if found.
-
- Any function that doesn't start with one of these sequences will be
- assumed to have no prologue and thus no valid frame pointer in
- %rbp. */
+ See comment on amd64_analyze_prologue for the sequences handled. The
+ movq/movl after the push of %rbp is considered optional. 'endbr64' is
+ handled before this function. */
static CORE_ADDR
-amd64_analyze_prologue (struct gdbarch *gdbarch,
- CORE_ADDR pc, CORE_ADDR current_pc,
- struct amd64_frame_cache *cache)
+amd64_analyze_frame_setup (gdbarch *gdbarch, CORE_ADDR pc,
+ CORE_ADDR current_pc, amd64_frame_cache *cache)
{
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- /* The `endbr64` instruction. */
- static const gdb_byte endbr64[4] = { 0xf3, 0x0f, 0x1e, 0xfa };
/* There are two variations of movq %rsp, %rbp. */
static const gdb_byte mov_rsp_rbp_1[3] = { 0x48, 0x89, 0xe5 };
static const gdb_byte mov_rsp_rbp_2[3] = { 0x48, 0x8b, 0xec };
@@ -2502,34 +2542,11 @@ amd64_analyze_prologue (struct gdbarch *gdbarch,
static const gdb_byte mov_esp_ebp_1[2] = { 0x89, 0xe5 };
static const gdb_byte mov_esp_ebp_2[2] = { 0x8b, 0xec };
+ bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[3];
- gdb_byte op;
-
- if (current_pc <= pc)
- return current_pc;
-
- if (gdbarch_ptr_bit (gdbarch) == 32)
- pc = amd64_x32_analyze_stack_align (pc, current_pc, cache);
- else
- pc = amd64_analyze_stack_align (pc, current_pc, cache);
-
- op = read_code_unsigned_integer (pc, 1, byte_order);
-
- /* Check for the `endbr64` instruction, skip it if found. */
- if (op == endbr64[0])
- {
- read_code (pc + 1, buf, 3);
-
- if (memcmp (buf, &endbr64[1], 3) == 0)
- pc += 4;
-
- op = read_code_unsigned_integer (pc, 1, byte_order);
- }
+ gdb_byte op = read_code_unsigned_integer (pc, 1, byte_order);
- if (current_pc <= pc)
- return current_pc;
-
- if (op == 0x55) /* pushq %rbp */
+ if (op == 0x55) /* pushq %rbp. */
{
/* Take into account that we've executed the `pushq %rbp' that
starts this instruction sequence. */
@@ -2569,6 +2586,176 @@ amd64_analyze_prologue (struct gdbarch *gdbarch,
return pc;
}
+/* Check whether PC points at code pushing registers onto the stack. If so,
+ update CACHE and return pc after those pushes or CURRENT_PC, whichever is
+ smaller. Otherwise, return PC passed to this function.
+
+ In AMD64 prologue, we only expect GPRs being pushed onto the stack. */
+
+static CORE_ADDR
+amd64_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
+ amd64_frame_cache *cache)
+{
+ gdb_byte op;
+
+ /* Limit iterating to 16 GPRs available. */
+ for (int i = 0; i < 16 && pc < current_pc; i++)
+ {
+ int reg = 0;
+ int pc_offset = 0;
+
+ if (target_read_code (pc, &op, 1) == -1)
+ return pc;
+
+ /* push %r8 - %r15 REX prefix. We expect only REX.B to be set, but
+ because, for example, REX.R would be "unused" if it were there,
+ we mask opcode with 0xF1 in case compilers don't get rid of it
+ "because it doesn't matter anyway". */
+ if ((op & 0xF1) == 0x41)
+ {
+ reg += 8;
+ pc_offset = 1;
+
+ if (target_read_code (pc + 1, &op, 1) == -1)
+ return pc;
+ }
+
+ /* push %rax|%rcx|%rdx|%rbx|%rsp|%rbp|%rsi|%rdi
+
+ or with 0x41 prefix:
+ push %r8|%r9|%r10|%r11|%r12|%r13|%r14|%r15. */
+ if (op < 0x50 || op > 0x57)
+ break;
+
+ reg += op - 0x50;
+
+ int regnum = amd64_arch_reg_to_regnum (reg);
+ cache->sp_offset += 8;
+ cache->saved_regs[regnum] = -cache->sp_offset;
+
+ pc += 1 + pc_offset;
+ }
+
+ return pc;
+}
+
+/* Check whether PC points at code allocating space on the stack.
+ If so, update CACHE and return pc past it or CURRENT_PC, whichever is
+ smaller. Otherwise, return PC passed to this function. */
+
+static CORE_ADDR
+amd64_analyze_stack_alloc (gdbarch *arch, CORE_ADDR pc, CORE_ADDR current_pc,
+ amd64_frame_cache *cache)
+{
+ static const gdb_byte sub_imm8_rsp[] = { 0x83, 0xec };
+ static const gdb_byte sub_imm32_rsp[] = { 0x81, 0xec };
+ static const gdb_byte lea_disp_rsp[] = { 0x8D, 0x64 };
+
+ bfd_endian byte_order = gdbarch_byte_order (arch);
+ const CORE_ADDR start_pc = pc;
+
+ gdb_byte op;
+ if (target_read_code (pc, &op, 1) == -1)
+ return pc;
+
+ /* Check for REX.W, indicating 64-bit operand size (in this case, for
+ %rsp). */
+ if (op == 0x48)
+ pc++;
+
+ if (current_pc <= pc)
+ return current_pc;
+
+ gdb_byte buf[2];
+ read_code (pc, buf, 2);
+
+ /* Check for instruction allocating space on the stack, which looks like
+ sub imm8/32, %rsp
+ or
+ lea -imm (%rsp), %rsp
+
+ and forward pc past it + update cache. */
+
+ /* sub imm8, %rsp. */
+ if (memcmp (buf, sub_imm8_rsp, 2) == 0)
+ {
+ /* Instruction is 3 bytes long. The imm8 arg is the 3rd, single
+ byte. */
+ cache->sp_offset += read_code_integer (pc + 2, 1, byte_order);
+ return pc + 3;
+ }
+ /* sub imm32, %rsp. */
+ else if (memcmp (buf, sub_imm32_rsp, 2) == 0)
+ {
+ /* Instruction is 6 bytes long. The imm32 arg is stored in 4 bytes,
+ starting from 3rd one. */
+ cache->sp_offset += read_code_integer (pc + 2, 4, byte_order);
+ return pc + 6;
+ }
+ /* lea -imm (%rsp), %rsp. */
+ else if (memcmp (buf, lea_disp_rsp, 2) == 0)
+ {
+ /* Instruction is 4 bytes long. The imm arg is the 4th, single
+ byte. */
+ cache->sp_offset += -1 * read_code_integer (pc + 3, 1, byte_order);
+ return pc + 4;
+ }
+
+ return start_pc;
+}
+
+/* Do a limited analysis of the prologue at PC and update CACHE
+ accordingly. Bail out early if CURRENT_PC is reached. Return the
+ address where the analysis stopped.
+
+ We will handle only functions beginning with:
+
+ pushq %rbp 0x55
+ movq %rsp, %rbp 0x48 0x89 0xe5 (or 0x48 0x8b 0xec)
+
+ or (for the X32 ABI):
+
+ pushq %rbp 0x55
+ movl %esp, %ebp 0x89 0xe5 (or 0x8b 0xec)
+
+ The `endbr64` instruction can be found before these sequences, and will be
+ skipped if found.
+
+ Any function that doesn't start with one of these sequences will be
+ assumed to have no prologue and thus no valid frame pointer in
+ %rbp. */
+
+static CORE_ADDR
+amd64_analyze_prologue (gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR current_pc,
+ amd64_frame_cache *cache)
+{
+ if (current_pc <= pc)
+ return current_pc;
+
+ /* If generated, 'endbr64' will be placed before stack alignment too. */
+ pc = amd64_skip_endbr (gdbarch, pc);
+ if (current_pc <= pc)
+ return current_pc;
+
+ if (gdbarch_ptr_bit (gdbarch) == 32)
+ pc = amd64_x32_analyze_stack_align (pc, current_pc, cache);
+ else
+ pc = amd64_analyze_stack_align (pc, current_pc, cache);
+
+ if (current_pc <= pc)
+ return current_pc;
+
+ pc = amd64_analyze_frame_setup (gdbarch, pc, current_pc, cache);
+ if (current_pc <= pc)
+ return current_pc;
+
+ pc = amd64_analyze_register_saves (pc, current_pc, cache);
+ if (current_pc <= pc)
+ return current_pc;
+
+ return amd64_analyze_stack_alloc (gdbarch, pc, current_pc, cache);
+}
+
/* Work around false termination of prologue - GCC PR debug/48827.
START_PC is the first instruction of a function, PC is its minimal already
@@ -3367,6 +3554,9 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch,
tdep->num_pkeys_regs = 1;
}
+ if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.pl3_ssp") != nullptr)
+ tdep->ssp_regnum = AMD64_PL3_SSP_REGNUM;
+
tdep->num_byte_regs = 20;
tdep->num_word_regs = 16;
tdep->num_dword_regs = 16;
@@ -3523,23 +3713,24 @@ amd64_x32_none_init_abi (gdbarch_info info, gdbarch *arch)
amd64_target_description (X86_XSTATE_SSE_MASK, true));
}
-/* Return the target description for a specified XSAVE feature mask. */
+/* See amd64-tdep.h. */
const struct target_desc *
-amd64_target_description (uint64_t xcr0, bool segments)
+amd64_target_description (uint64_t xstate_bv, bool segments)
{
static target_desc *amd64_tdescs \
- [2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
+ [2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*CET_U*/][2/*segments*/] = {};
target_desc **tdesc;
- tdesc = &amd64_tdescs[(xcr0 & X86_XSTATE_AVX) ? 1 : 0]
- [(xcr0 & X86_XSTATE_AVX512) ? 1 : 0]
- [(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]
+ tdesc = &amd64_tdescs[(xstate_bv & X86_XSTATE_AVX) ? 1 : 0]
+ [(xstate_bv & X86_XSTATE_AVX512) ? 1 : 0]
+ [(xstate_bv & X86_XSTATE_PKRU) ? 1 : 0]
+ [(xstate_bv & X86_XSTATE_CET_U) ? 1 : 0]
[segments ? 1 : 0];
if (*tdesc == NULL)
- *tdesc = amd64_create_target_description (xcr0, false, false,
- segments);
+ *tdesc = amd64_create_target_description (xstate_bv, false,
+ false, segments);
return *tdesc;
}
@@ -3728,6 +3919,42 @@ test_amd64_get_insn_details (void)
= { 0x62, 0xf1, 0x7c, 0x48, 0x28, 0x81, 0x00, 0xfc, 0xff, 0xff };
fixup_riprel (details, insn.data (), ECX_REG_NUM);
SELF_CHECK (insn == updated_insn);
+
+ /* INSN: vpblendw $0x7,%xmm4,%xmm6,%xmm2, vex3 prefix. */
+ insn = { 0xc4, 0xe3, 0x49, 0x0e, 0xd4, 0x07 };
+ amd64_get_insn_details (insn.data (), &details);
+ SELF_CHECK (details.opcode_len == 3);
+ SELF_CHECK (details.enc_prefix_offset == 0);
+ SELF_CHECK (details.opcode_offset == 3);
+ SELF_CHECK (details.modrm_offset == 4);
+
+ /* INSN: vpblendw $0x7,0xff(%rip),%ymm6,%ymm2, vex3 prefix. */
+ insn = { 0xc4, 0xe3, 0x4d, 0x0e, 0x15, 0xff, 0x00, 0x00, 0x00, 0x07 };
+ amd64_get_insn_details (insn.data (), &details);
+ SELF_CHECK (details.opcode_len == 3);
+ SELF_CHECK (details.enc_prefix_offset == 0);
+ SELF_CHECK (details.opcode_offset == 3);
+ SELF_CHECK (details.modrm_offset == 4);
+
+ /* INSN: vpblendw $0x7,0xff(%ecx),%ymm6,%ymm2, vex3 prefix. */
+ fixup_riprel (details, insn.data (), ECX_REG_NUM);
+ updated_insn
+ = { 0xc4, 0xe3, 0x4d, 0x0e, 0x91, 0xff, 0x00, 0x00, 0x00, 0x07 };
+ SELF_CHECK (insn == updated_insn);
+
+ /* INSN: vpcomtrueuq 0x0(%rip),%xmm7,%xmm0, xop prefix. */
+ insn = { 0x8f, 0xe8, 0x40, 0xef, 0x05, 0x00, 0x00, 0x00, 0x00, 0x07 };
+ amd64_get_insn_details (insn.data (), &details);
+ SELF_CHECK (details.opcode_len == 1);
+ SELF_CHECK (details.enc_prefix_offset == 0);
+ SELF_CHECK (details.opcode_offset == 3);
+ SELF_CHECK (details.modrm_offset == 4);
+
+ /* INSN: vpcomtrueuq 0x0(%ecx),%xmm7,%xmm0, xop prefix. */
+ fixup_riprel (details, insn.data (), ECX_REG_NUM);
+ updated_insn
+ = { 0x8f, 0xe8, 0x40, 0xef, 0x81, 0x00, 0x00, 0x00, 0x00, 0x07 };
+ SELF_CHECK (insn == updated_insn);
}
static void
@@ -3740,9 +3967,7 @@ amd64_insn_decode (void)
} // namespace selftests
#endif /* GDB_SELF_TEST */
-void _initialize_amd64_tdep ();
-void
-_initialize_amd64_tdep ()
+INIT_GDB_FILE (amd64_tdep)
{
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_NONE,
amd64_none_init_abi);
diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h
index cbf8a97..e663288 100644
--- a/gdb/amd64-tdep.h
+++ b/gdb/amd64-tdep.h
@@ -81,6 +81,7 @@ enum amd64_regnum
AMD64_ZMM0H_REGNUM,
AMD64_ZMM31H_REGNUM = AMD64_ZMM0H_REGNUM + 31,
AMD64_PKRU_REGNUM,
+ AMD64_PL3_SSP_REGNUM,
AMD64_FSBASE_REGNUM,
AMD64_GSBASE_REGNUM
};
@@ -108,8 +109,12 @@ extern void amd64_init_abi (struct gdbarch_info info,
extern void amd64_x32_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch,
const target_desc *default_tdesc);
-extern const struct target_desc *amd64_target_description (uint64_t xcr0,
- bool segments);
+
+/* Return the target description for the specified xsave features as
+ defined in XSTATE_BV and SEGMENTS. */
+
+extern const struct target_desc *amd64_target_description
+ (uint64_t xstate_bv, bool segments);
/* Fill register REGNUM in REGCACHE with the appropriate
floating-point or SSE register value from *FXSAVE. If REGNUM is
diff --git a/gdb/amd64-windows-nat.c b/gdb/amd64-windows-nat.c
index 223e078..f5c98f6 100644
--- a/gdb/amd64-windows-nat.c
+++ b/gdb/amd64-windows-nat.c
@@ -94,9 +94,7 @@ amd64_windows_segment_register_p (int regnum)
return regnum >= AMD64_CS_REGNUM && regnum <= AMD64_GS_REGNUM;
}
-void _initialize_amd64_windows_nat ();
-void
-_initialize_amd64_windows_nat ()
+INIT_GDB_FILE (amd64_windows_nat)
{
x86_set_debug_register_length (8);
}
diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index c4719dc..c7977d2 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -1404,9 +1404,7 @@ amd64_cygwin_core_osabi_sniffer (bfd *abfd)
return GDB_OSABI_UNKNOWN;
}
-void _initialize_amd64_windows_tdep ();
-void
-_initialize_amd64_windows_tdep ()
+INIT_GDB_FILE (amd64_windows_tdep)
{
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_WINDOWS,
amd64_windows_init_abi);
diff --git a/gdb/amdgpu-tdep.c b/gdb/amdgpu-tdep.c
index dc1b32f..26e5a27 100644
--- a/gdb/amdgpu-tdep.c
+++ b/gdb/amdgpu-tdep.c
@@ -1371,10 +1371,7 @@ amdgpu_register_type_parse_test ()
#endif
-void _initialize_amdgpu_tdep ();
-
-void
-_initialize_amdgpu_tdep ()
+INIT_GDB_FILE (amdgpu_tdep)
{
gdbarch_register (bfd_arch_amdgcn, amdgpu_gdbarch_init, NULL,
amdgpu_supports_arch_info);
diff --git a/gdb/annotate.c b/gdb/annotate.c
index ea0bfa9..55db2e2 100644
--- a/gdb/annotate.c
+++ b/gdb/annotate.c
@@ -627,9 +627,7 @@ breakpoint_changed (struct breakpoint *b)
annotate_breakpoints_invalid ();
}
-void _initialize_annotate ();
-void
-_initialize_annotate ()
+INIT_GDB_FILE (annotate)
{
gdb::observers::breakpoint_created.attach (breakpoint_changed, "annotate");
gdb::observers::breakpoint_deleted.attach (breakpoint_changed, "annotate");
diff --git a/gdb/arc-linux-nat.c b/gdb/arc-linux-nat.c
index 091a966..75fc4b7 100644
--- a/gdb/arc-linux-nat.c
+++ b/gdb/arc-linux-nat.c
@@ -309,9 +309,7 @@ ps_get_thread_area (struct ps_prochandle *ph, lwpid_t lwpid, int idx,
}
/* Suppress warning from -Wmissing-prototypes. */
-void _initialize_arc_linux_nat ();
-void
-_initialize_arc_linux_nat ()
+INIT_GDB_FILE (arc_linux_nat)
{
/* Register the target. */
linux_target = &the_arc_linux_nat_target;
diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
index adf6691..6a4f4b1 100644
--- a/gdb/arc-linux-tdep.c
+++ b/gdb/arc-linux-tdep.c
@@ -19,6 +19,7 @@
/* GDB header files. */
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "objfiles.h"
#include "opcode/arc.h"
#include "osabi.h"
@@ -727,7 +728,7 @@ arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
arc_linux_sw_breakpoint_from_kind);
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
- set_gdbarch_software_single_step (gdbarch, arc_linux_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, arc_linux_software_single_step);
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
set_gdbarch_skip_solib_resolver (gdbarch, arc_linux_skip_solib_resolver);
set_gdbarch_iterate_over_regset_sections
@@ -736,15 +737,10 @@ arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* GNU/Linux uses SVR4-style shared libraries, with 32-bit ints, longs
and pointers (ILP32). */
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
}
-/* Suppress warning from -Wmissing-prototypes. */
-extern initialize_file_ftype _initialize_arc_linux_tdep;
-
-void
-_initialize_arc_linux_tdep ()
+INIT_GDB_FILE (arc_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_arc, 0, GDB_OSABI_LINUX,
arc_linux_init_osabi);
diff --git a/gdb/arc-newlib-tdep.c b/gdb/arc-newlib-tdep.c
index fd80bfa..9a6f7a8 100644
--- a/gdb/arc-newlib-tdep.c
+++ b/gdb/arc-newlib-tdep.c
@@ -58,9 +58,7 @@ arc_newlib_osabi_sniffer (bfd *abfd)
return GDB_OSABI_UNKNOWN;
}
-void _initialize_arc_newlib_tdep ();
-void
-_initialize_arc_newlib_tdep ()
+INIT_GDB_FILE (arc_newlib_tdep)
{
gdbarch_register_osabi_sniffer (bfd_arch_arc, bfd_target_elf_flavour,
arc_newlib_osabi_sniffer);
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 8db6e7b..f5ae11c 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -2458,9 +2458,7 @@ dump_arc_instruction_command (const char *args, int from_tty)
arc_insn_dump (insn);
}
-void _initialize_arc_tdep ();
-void
-_initialize_arc_tdep ()
+INIT_GDB_FILE (arc_tdep)
{
gdbarch_register (bfd_arch_arc, arc_gdbarch_init, arc_dump_tdep);
diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index be0494f..f2af80e 100644
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -48,7 +48,7 @@
bool
default_displaced_step_hw_singlestep (struct gdbarch *gdbarch)
{
- return !gdbarch_software_single_step_p (gdbarch);
+ return !gdbarch_get_next_pcs_p (gdbarch);
}
CORE_ADDR
@@ -1218,6 +1218,16 @@ default_gdbarch_return_value
readbuf, writebuf);
}
+/* See arch-utils.h. */
+
+std::optional<CORE_ADDR>
+default_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache,
+ bool &shadow_stack_enabled)
+{
+ shadow_stack_enabled = false;
+ return {};
+}
+
obstack *gdbarch_obstack (gdbarch *arch)
{
return &arch->obstack;
@@ -1525,9 +1535,7 @@ core_file_exec_context::environment () const
return e;
}
-void _initialize_gdbarch_utils ();
-void
-_initialize_gdbarch_utils ()
+INIT_GDB_FILE (gdbarch_utils)
{
add_setshow_enum_cmd ("endian", class_support,
endian_enum, &set_endian_string,
diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h
index 1509cb7..14a84b7 100644
--- a/gdb/arch-utils.h
+++ b/gdb/arch-utils.h
@@ -414,4 +414,9 @@ extern enum return_value_convention default_gdbarch_return_value
struct regcache *regcache, struct value **read_value,
const gdb_byte *writebuf);
+/* Default implementation of gdbarch default_get_shadow_stack_pointer
+ method. */
+extern std::optional<CORE_ADDR> default_get_shadow_stack_pointer
+ (gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled);
+
#endif /* GDB_ARCH_UTILS_H */
diff --git a/gdb/arch/aarch64-gcs-linux.h b/gdb/arch/aarch64-gcs-linux.h
new file mode 100644
index 0000000..018ca37
--- /dev/null
+++ b/gdb/arch/aarch64-gcs-linux.h
@@ -0,0 +1,44 @@
+/* Common Linux target-dependent definitions for AArch64 GCS
+
+ Copyright (C) 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/>. */
+
+#ifndef GDB_ARCH_AARCH64_GCS_LINUX_H
+#define GDB_ARCH_AARCH64_GCS_LINUX_H
+
+#include <stdint.h>
+
+/* Feature check for Guarded Control Stack. */
+#ifndef HWCAP_GCS
+#define HWCAP_GCS (1ULL << 32)
+#endif
+
+/* Make sure we only define these if the kernel header doesn't. */
+#ifndef GCS_MAGIC
+
+/* GCS state (NT_ARM_GCS). */
+
+struct user_gcs
+{
+ uint64_t features_enabled;
+ uint64_t features_locked;
+ uint64_t gcspr_el0;
+};
+
+#endif /* GCS_MAGIC */
+
+#endif /* GDB_ARCH_AARCH64_GCS_LINUX_H */
diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c
index 3e1ca05..dff2bc1 100644
--- a/gdb/arch/aarch64.c
+++ b/gdb/arch/aarch64.c
@@ -26,6 +26,8 @@
#include "../features/aarch64-sme.c"
#include "../features/aarch64-sme2.c"
#include "../features/aarch64-tls.c"
+#include "../features/aarch64-gcs.c"
+#include "../features/aarch64-gcs-linux.c"
/* See arch/aarch64.h. */
@@ -65,6 +67,12 @@ aarch64_create_target_description (const aarch64_features &features)
if (features.sme2)
regnum = create_feature_aarch64_sme2 (tdesc.get (), regnum);
+ if (features.gcs)
+ regnum = create_feature_aarch64_gcs (tdesc.get (), regnum);
+
+ if (features.gcs_linux)
+ regnum = create_feature_aarch64_gcs_linux (tdesc.get (), regnum);
+
return tdesc.release ();
}
diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h
index ee18b74..679d845 100644
--- a/gdb/arch/aarch64.h
+++ b/gdb/arch/aarch64.h
@@ -51,6 +51,12 @@ struct aarch64_features
/* Whether SME2 is supported. */
bool sme2 = false;
+
+ /* Whether Guarded Control Stack is supported. */
+ bool gcs = false;
+
+ /* Whether Guarded Control Stack Linux features are supported. */
+ bool gcs_linux = false;
};
inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs)
@@ -60,7 +66,9 @@ inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs)
&& lhs.mte == rhs.mte
&& lhs.tls == rhs.tls
&& lhs.svq == rhs.svq
- && lhs.sme2 == rhs.sme2;
+ && lhs.sme2 == rhs.sme2
+ && lhs.gcs == rhs.gcs
+ && lhs.gcs_linux == rhs.gcs_linux;
}
namespace std
diff --git a/gdb/arch/amd64-linux-tdesc.c b/gdb/arch/amd64-linux-tdesc.c
index 91de758..8796662 100644
--- a/gdb/arch/amd64-linux-tdesc.c
+++ b/gdb/arch/amd64-linux-tdesc.c
@@ -26,34 +26,35 @@
/* See arch/amd64-linux-tdesc.h. */
const struct target_desc *
-amd64_linux_read_description (uint64_t xcr0, bool is_x32)
+amd64_linux_read_description (uint64_t xstate_bv, bool is_x32)
{
/* The type used for the amd64 and x32 target description caches. */
using tdesc_cache_type = std::unordered_map<uint64_t, const target_desc_up>;
/* Caches for the previously seen amd64 and x32 target descriptions,
- indexed by the xcr0 value that created the target description. These
- need to be static within this function to ensure they are initialised
- before first use. */
+ indexed by the xstate_bv value that created the target
+ description. These need to be static within this function to ensure
+ they are initialised before first use. */
static tdesc_cache_type amd64_tdesc_cache, x32_tdesc_cache;
tdesc_cache_type &tdesc_cache = is_x32 ? x32_tdesc_cache : amd64_tdesc_cache;
- /* Only some bits are checked when creating a tdesc, but the XCR0 value
- contains other feature bits that are not relevant for tdesc creation.
- When indexing into the TDESC_CACHE we need to use a consistent xcr0
- value otherwise we might fail to find an existing tdesc which has the
- same set of relevant bits set. */
- xcr0 &= is_x32
- ? x86_linux_x32_xcr0_feature_mask ()
- : x86_linux_amd64_xcr0_feature_mask ();
+ /* Only some bits are checked when creating a tdesc, but the
+ xstate_bv value contains other feature bits that are not
+ relevant for tdesc creation.
+ When indexing into the TDESC_CACHE we need to use a consistent
+ xstate_bv value otherwise we might fail to find an existing
+ tdesc which has the same set of relevant bits set. */
+ xstate_bv &= is_x32
+ ? x86_linux_x32_xstate_bv_feature_mask ()
+ : x86_linux_amd64_xstate_bv_feature_mask ();
- const auto it = tdesc_cache.find (xcr0);
+ const auto it = tdesc_cache.find (xstate_bv);
if (it != tdesc_cache.end ())
return it->second.get ();
/* Create the previously unseen target description. */
- target_desc_up tdesc (amd64_create_target_description (xcr0, is_x32,
+ target_desc_up tdesc (amd64_create_target_description (xstate_bv, is_x32,
true, true));
x86_linux_post_init_tdesc (tdesc.get (), true);
@@ -61,6 +62,6 @@ amd64_linux_read_description (uint64_t xcr0, bool is_x32)
target_desc_up. This is safe as the cache (and the pointers contained
within it) are not deleted until GDB exits. */
target_desc *ptr = tdesc.get ();
- tdesc_cache.emplace (xcr0, std::move (tdesc));
+ tdesc_cache.emplace (xstate_bv, std::move (tdesc));
return ptr;
}
diff --git a/gdb/arch/amd64-linux-tdesc.h b/gdb/arch/amd64-linux-tdesc.h
index 8806a13..4c0c591 100644
--- a/gdb/arch/amd64-linux-tdesc.h
+++ b/gdb/arch/amd64-linux-tdesc.h
@@ -22,9 +22,10 @@
struct target_desc;
-/* Return the AMD64 target descriptions corresponding to XCR0 and IS_X32. */
+/* Return the AMD64 target descriptions corresponding to XSTATE_BV and
+ IS_X32. */
-extern const target_desc *amd64_linux_read_description (uint64_t xcr0,
- bool is_x32);
+extern const target_desc *amd64_linux_read_description
+ (uint64_t xstate_bv, bool is_x32);
#endif /* GDB_ARCH_AMD64_LINUX_TDESC_H */
diff --git a/gdb/arch/amd64.c b/gdb/arch/amd64.c
index 252650b..9fbe802 100644
--- a/gdb/arch/amd64.c
+++ b/gdb/arch/amd64.c
@@ -28,16 +28,15 @@
#include "../features/i386/64bit-sse.c"
#include "../features/i386/pkeys.c"
+#include "../features/i386/64bit-ssp.c"
+#include "../features/i386/32bit-ssp.c"
#include "../features/i386/x32-core.c"
-/* Create amd64 target descriptions according to XCR0. If IS_X32 is
- true, create the x32 ones. If IS_LINUX is true, create target
- descriptions for Linux. If SEGMENTS is true, then include
- the "org.gnu.gdb.i386.segments" feature registers. */
+/* See arch/amd64.h. */
target_desc *
-amd64_create_target_description (uint64_t xcr0, bool is_x32, bool is_linux,
- bool segments)
+amd64_create_target_description (uint64_t xstate_bv, bool is_x32,
+ bool is_linux, bool segments)
{
target_desc_up tdesc = allocate_target_description ();
@@ -62,14 +61,22 @@ amd64_create_target_description (uint64_t xcr0, bool is_x32, bool is_linux,
if (segments)
regnum = create_feature_i386_64bit_segments (tdesc.get (), regnum);
- if (xcr0 & X86_XSTATE_AVX)
+ if (xstate_bv & X86_XSTATE_AVX)
regnum = create_feature_i386_64bit_avx (tdesc.get (), regnum);
- if (xcr0 & X86_XSTATE_AVX512)
+ if (xstate_bv & X86_XSTATE_AVX512)
regnum = create_feature_i386_64bit_avx512 (tdesc.get (), regnum);
- if (xcr0 & X86_XSTATE_PKRU)
+ if (xstate_bv & X86_XSTATE_PKRU)
regnum = create_feature_i386_pkeys (tdesc.get (), regnum);
+ if (xstate_bv & X86_XSTATE_CET_U)
+ {
+ if (!is_x32)
+ regnum = create_feature_i386_64bit_ssp (tdesc.get (), regnum);
+ else
+ regnum = create_feature_i386_32bit_ssp (tdesc.get (), regnum);
+ }
+
return tdesc.release ();
}
diff --git a/gdb/arch/amd64.h b/gdb/arch/amd64.h
index 695660c..60c17eb 100644
--- a/gdb/arch/amd64.h
+++ b/gdb/arch/amd64.h
@@ -21,7 +21,13 @@
#include "gdbsupport/tdesc.h"
#include <stdint.h>
-target_desc *amd64_create_target_description (uint64_t xcr0, bool is_x32,
- bool is_linux, bool segments);
+/* Create amd64 target descriptions according to XSTATE_BV. If
+ IS_X32 is true, create the x32 ones. If IS_LINUX is true, create
+ target descriptions for Linux. If SEGMENTS is true, then include
+ the "org.gnu.gdb.i386.segments" feature registers. */
+
+target_desc *amd64_create_target_description (uint64_t xstate_bv,
+ bool is_x32, bool is_linux,
+ bool segments);
#endif /* GDB_ARCH_AMD64_H */
diff --git a/gdb/arch/arc.c b/gdb/arch/arc.c
index efe7111..b7de1da 100644
--- a/gdb/arch/arc.c
+++ b/gdb/arch/arc.c
@@ -17,7 +17,6 @@
#include "arc.h"
-#include <stdlib.h>
#include <unordered_map>
#include <string>
diff --git a/gdb/arch/i386-linux-tdesc.c b/gdb/arch/i386-linux-tdesc.c
index 5151317..bd736eb 100644
--- a/gdb/arch/i386-linux-tdesc.c
+++ b/gdb/arch/i386-linux-tdesc.c
@@ -25,32 +25,35 @@
/* See arch/i386-linux-tdesc.h. */
const target_desc *
-i386_linux_read_description (uint64_t xcr0)
+i386_linux_read_description (uint64_t xstate_bv)
{
- /* Cache of previously seen i386 target descriptions, indexed by the xcr0
- value that created the target description. This needs to be static
- within this function to ensure it is initialised before first use. */
+ /* Cache of previously seen i386 target descriptions, indexed by the
+ xstate_bv value that created the target description. This
+ needs to be static within this function to ensure it is initialised
+ before first use. */
static std::unordered_map<uint64_t, const target_desc_up> i386_tdesc_cache;
- /* Only some bits are checked when creating a tdesc, but the XCR0 value
- contains other feature bits that are not relevant for tdesc creation.
- When indexing into the I386_TDESC_CACHE we need to use a consistent
- xcr0 value otherwise we might fail to find an existing tdesc which has
- the same set of relevant bits set. */
- xcr0 &= x86_linux_i386_xcr0_feature_mask ();
+ /* Only some bits are checked when creating a tdesc, but the
+ XSTATE_BV value contains other feature bits that are not relevant
+ for tdesc creation. When indexing into the I386_TDESC_CACHE
+ we need to use a consistent XSTATE_BV value otherwise we might fail
+ to find an existing tdesc which has the same set of relevant bits
+ set. */
+ xstate_bv &= x86_linux_i386_xstate_bv_feature_mask ();
- const auto it = i386_tdesc_cache.find (xcr0);
+ const auto it = i386_tdesc_cache.find (xstate_bv);
if (it != i386_tdesc_cache.end ())
return it->second.get ();
/* Create the previously unseen target description. */
- target_desc_up tdesc (i386_create_target_description (xcr0, true, false));
+ target_desc_up tdesc
+ (i386_create_target_description (xstate_bv, true, false));
x86_linux_post_init_tdesc (tdesc.get (), false);
/* Add to the cache, and return a pointer borrowed from the
target_desc_up. This is safe as the cache (and the pointers contained
within it) are not deleted until GDB exits. */
target_desc *ptr = tdesc.get ();
- i386_tdesc_cache.emplace (xcr0, std::move (tdesc));
+ i386_tdesc_cache.emplace (xstate_bv, std::move (tdesc));
return ptr;
}
diff --git a/gdb/arch/i386-linux-tdesc.h b/gdb/arch/i386-linux-tdesc.h
index 2c3c174..1cf2931 100644
--- a/gdb/arch/i386-linux-tdesc.h
+++ b/gdb/arch/i386-linux-tdesc.h
@@ -22,8 +22,9 @@
struct target_desc;
-/* Return the i386 target description corresponding to XCR0. */
+/* Return the i386 target description corresponding to XSTATE_BV. */
-extern const struct target_desc *i386_linux_read_description (uint64_t xcr0);
+extern const struct target_desc *i386_linux_read_description
+ (uint64_t xstate_bv);
#endif /* GDB_ARCH_I386_LINUX_TDESC_H */
diff --git a/gdb/arch/i386.c b/gdb/arch/i386.c
index 835df53..4ec4f10 100644
--- a/gdb/arch/i386.c
+++ b/gdb/arch/i386.c
@@ -28,11 +28,13 @@
#include "../features/i386/32bit-avx512.c"
#include "../features/i386/32bit-segments.c"
#include "../features/i386/pkeys.c"
+#include "../features/i386/32bit-ssp.c"
-/* Create i386 target descriptions according to XCR0. */
+/* See arch/i386.h. */
target_desc *
-i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
+i386_create_target_description (uint64_t xstate_bv, bool is_linux,
+ bool segments)
{
target_desc_up tdesc = allocate_target_description ();
@@ -44,10 +46,10 @@ i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
long regnum = 0;
- if (xcr0 & X86_XSTATE_X87)
+ if (xstate_bv & X86_XSTATE_X87)
regnum = create_feature_i386_32bit_core (tdesc.get (), regnum);
- if (xcr0 & X86_XSTATE_SSE)
+ if (xstate_bv & X86_XSTATE_SSE)
regnum = create_feature_i386_32bit_sse (tdesc.get (), regnum);
if (is_linux)
@@ -56,14 +58,17 @@ i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
if (segments)
regnum = create_feature_i386_32bit_segments (tdesc.get (), regnum);
- if (xcr0 & X86_XSTATE_AVX)
+ if (xstate_bv & X86_XSTATE_AVX)
regnum = create_feature_i386_32bit_avx (tdesc.get (), regnum);
- if (xcr0 & X86_XSTATE_AVX512)
+ if (xstate_bv & X86_XSTATE_AVX512)
regnum = create_feature_i386_32bit_avx512 (tdesc.get (), regnum);
- if (xcr0 & X86_XSTATE_PKRU)
+ if (xstate_bv & X86_XSTATE_PKRU)
regnum = create_feature_i386_pkeys (tdesc.get (), regnum);
+ if (xstate_bv & X86_XSTATE_CET_U)
+ regnum = create_feature_i386_32bit_ssp (tdesc.get (), regnum);
+
return tdesc.release ();
}
diff --git a/gdb/arch/i386.h b/gdb/arch/i386.h
index 1fc4101..91a581f 100644
--- a/gdb/arch/i386.h
+++ b/gdb/arch/i386.h
@@ -21,7 +21,12 @@
#include "gdbsupport/tdesc.h"
#include <stdint.h>
-target_desc *i386_create_target_description (uint64_t xcr0, bool is_linux,
+/* Create i386 target descriptions according to XSTATE_BV. If IS_LINUX is
+ true, create target descriptions for Linux. If SEGMENTS is true, then
+ include the "org.gnu.gdb.i386.segments" feature registers. */
+
+target_desc *i386_create_target_description (uint64_t xstate_bv,
+ bool is_linux,
bool segments);
#endif /* GDB_ARCH_I386_H */
diff --git a/gdb/arch/loongarch.c b/gdb/arch/loongarch.c
index 07c6d4d..25e698d 100644
--- a/gdb/arch/loongarch.c
+++ b/gdb/arch/loongarch.c
@@ -16,7 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "loongarch.h"
-#include <stdlib.h>
#include <unordered_map>
/* Target description features. */
diff --git a/gdb/arch/riscv.c b/gdb/arch/riscv.c
index a6188ea..c698fa2 100644
--- a/gdb/arch/riscv.c
+++ b/gdb/arch/riscv.c
@@ -16,7 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "riscv.h"
-#include <stdlib.h>
#include <unordered_map>
#include "../features/riscv/32bit-cpu.c"
diff --git a/gdb/arch/x86-linux-tdesc-features.c b/gdb/arch/x86-linux-tdesc-features.c
index f65920c..bc34378 100644
--- a/gdb/arch/x86-linux-tdesc-features.c
+++ b/gdb/arch/x86-linux-tdesc-features.c
@@ -28,18 +28,21 @@
We want to cache target descriptions, and this is currently done in
three separate caches, one each for i386, amd64, and x32. Additionally,
- the caching we're discussing here is Linux only, and for Linux, the only
- thing that has an impact on target description creation is the xcr0
- value.
-
- In order to ensure the cache functions correctly we need to filter out
- only those xcr0 feature bits that are relevant, we can then cache target
- descriptions based on the relevant feature bits. Two xcr0 values might
- be different, but have the same relevant feature bits. In this case we
- would expect the two xcr0 values to map to the same cache entry. */
+ the caching we're discussing here is Linux only. Currently for Linux,
+ the only thing that has an impact on target description creation are
+ the supported features in xsave which are modelled by a xstate_bv
+ value, which has the same format than the state component bitmap.
+
+ In order to ensure the cache functions correctly we need to filter only
+ those xstate_bv feature bits that are relevant, we can then cache
+ target descriptions based on the relevant feature bits. Two xstate_bv
+ values might be different, but have the same relevant feature bits. In
+ this case we would expect the two xstate_bv values to map to the same
+ cache entry. */
struct x86_xstate_feature {
- /* The xstate feature mask. This is a mask against an xcr0 value. */
+ /* The xstate feature mask. This is a mask against the state component
+ bitmap. */
uint64_t feature;
/* Is this feature checked when creating an i386 target description. */
@@ -56,12 +59,13 @@ struct x86_xstate_feature {
checked when building a target description for i386, amd64, or x32.
If in the future, due to simplifications or refactoring, this table ever
- ends up with 'true' for every xcr0 feature on every target type, then this
- is an indication that this table should probably be removed, and that the
- rest of the code in this file can be simplified. */
+ ends up with 'true' for every xsave feature on every target type, then
+ this is an indication that this table should probably be removed, and
+ that the rest of the code in this file can be simplified. */
static constexpr x86_xstate_feature x86_linux_all_xstate_features[] = {
/* Feature, i386, amd64, x32. */
+ { X86_XSTATE_CET_U, false, true, true },
{ X86_XSTATE_PKRU, true, true, true },
{ X86_XSTATE_AVX512, true, true, true },
{ X86_XSTATE_AVX, true, true, true },
@@ -73,7 +77,7 @@ static constexpr x86_xstate_feature x86_linux_all_xstate_features[] = {
that are checked for when building an i386 target description. */
static constexpr uint64_t
-x86_linux_i386_xcr0_feature_mask_1 ()
+x86_linux_i386_xstate_bv_feature_mask_1 ()
{
uint64_t mask = 0;
@@ -88,7 +92,7 @@ x86_linux_i386_xcr0_feature_mask_1 ()
that are checked for when building an amd64 target description. */
static constexpr uint64_t
-x86_linux_amd64_xcr0_feature_mask_1 ()
+x86_linux_amd64_xstate_bv_feature_mask_1 ()
{
uint64_t mask = 0;
@@ -103,7 +107,7 @@ x86_linux_amd64_xcr0_feature_mask_1 ()
that are checked for when building an x32 target description. */
static constexpr uint64_t
-x86_linux_x32_xcr0_feature_mask_1 ()
+x86_linux_x32_xstate_bv_feature_mask_1 ()
{
uint64_t mask = 0;
@@ -117,25 +121,25 @@ x86_linux_x32_xcr0_feature_mask_1 ()
/* See arch/x86-linux-tdesc-features.h. */
uint64_t
-x86_linux_i386_xcr0_feature_mask ()
+x86_linux_i386_xstate_bv_feature_mask ()
{
- return x86_linux_i386_xcr0_feature_mask_1 ();
+ return x86_linux_i386_xstate_bv_feature_mask_1 ();
}
/* See arch/x86-linux-tdesc-features.h. */
uint64_t
-x86_linux_amd64_xcr0_feature_mask ()
+x86_linux_amd64_xstate_bv_feature_mask ()
{
- return x86_linux_amd64_xcr0_feature_mask_1 ();
+ return x86_linux_amd64_xstate_bv_feature_mask_1 ();
}
/* See arch/x86-linux-tdesc-features.h. */
uint64_t
-x86_linux_x32_xcr0_feature_mask ()
+x86_linux_x32_xstate_bv_feature_mask ()
{
- return x86_linux_x32_xcr0_feature_mask_1 ();
+ return x86_linux_x32_xstate_bv_feature_mask_1 ();
}
#ifdef GDBSERVER
@@ -143,7 +147,7 @@ x86_linux_x32_xcr0_feature_mask ()
/* See arch/x86-linux-tdesc-features.h. */
int
-x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0)
+x86_linux_xstate_bv_to_tdesc_idx (uint64_t xstate_bv)
{
/* The following table shows which features are checked for when creating
the target descriptions (see nat/x86-linux-tdesc.c), the feature order
@@ -160,7 +164,7 @@ x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0)
for (int i = 0; i < ARRAY_SIZE (x86_linux_all_xstate_features); ++i)
{
- if ((xcr0 & x86_linux_all_xstate_features[i].feature)
+ if ((xstate_bv & x86_linux_all_xstate_features[i].feature)
== x86_linux_all_xstate_features[i].feature)
idx |= (1 << i);
}
@@ -250,17 +254,17 @@ x86_linux_i386_tdesc_count ()
/* See arch/x86-linux-tdesc-features.h. */
uint64_t
-x86_linux_tdesc_idx_to_xcr0 (int idx)
+x86_linux_tdesc_idx_to_xstate_bv (int idx)
{
- uint64_t xcr0 = 0;
+ uint64_t xstate_bv = 0;
for (int i = 0; i < ARRAY_SIZE (x86_linux_all_xstate_features); ++i)
{
if ((idx & (1 << i)) != 0)
- xcr0 |= x86_linux_all_xstate_features[i].feature;
+ xstate_bv |= x86_linux_all_xstate_features[i].feature;
}
- return xcr0;
+ return xstate_bv;
}
#endif /* IN_PROCESS_AGENT */
diff --git a/gdb/arch/x86-linux-tdesc-features.h b/gdb/arch/x86-linux-tdesc-features.h
index 89fe7ce..bc72727 100644
--- a/gdb/arch/x86-linux-tdesc-features.h
+++ b/gdb/arch/x86-linux-tdesc-features.h
@@ -27,17 +27,20 @@
the set of features which are checked for when creating the target
description for each of amd64, x32, and i386. */
-extern uint64_t x86_linux_amd64_xcr0_feature_mask ();
-extern uint64_t x86_linux_x32_xcr0_feature_mask ();
-extern uint64_t x86_linux_i386_xcr0_feature_mask ();
+extern uint64_t x86_linux_amd64_xstate_bv_feature_mask ();
+extern uint64_t x86_linux_x32_xstate_bv_feature_mask ();
+extern uint64_t x86_linux_i386_xstate_bv_feature_mask ();
#ifdef GDBSERVER
-/* Convert an xcr0 value into an integer. The integer will be passed from
- gdbserver to the in-process-agent where it will then be passed through
- x86_linux_tdesc_idx_to_xcr0 to get back the original xcr0 value. */
+/* Convert an XSTATE_BV value into an integer. XSTATE_BV has the same
+ format than the state component bitmap and does include user and
+ supervisor state components. The integer will be passed from gdbserver
+ to the in-process-agent where it will then be passed through
+ x86_linux_tdesc_idx_to_xstate_bv to get back the original value. */
-extern int x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0);
+
+extern int x86_linux_xstate_bv_to_tdesc_idx (uint64_t xstate_bv);
#endif /* GDBSERVER */
@@ -51,11 +54,13 @@ extern int x86_linux_amd64_tdesc_count ();
extern int x86_linux_x32_tdesc_count ();
extern int x86_linux_i386_tdesc_count ();
-/* Convert an index number (as returned from x86_linux_xcr0_to_tdesc_idx)
- into an xcr0 value which can then be used to create a target
- description. */
+/* Convert an index number (as returned from
+ x86_linux_xstate_bv_to_tdesc_idx) into an xstate_bv value which can
+ then be used to create a target description.
+ The return mask has the same format than the state component bitmap
+ and does include user and supervisor state components. */
-extern uint64_t x86_linux_tdesc_idx_to_xcr0 (int idx);
+extern uint64_t x86_linux_tdesc_idx_to_xstate_bv (int idx);
#endif /* IN_PROCESS_AGENT */
diff --git a/gdb/arm-fbsd-nat.c b/gdb/arm-fbsd-nat.c
index 2b7b75a..e068023 100644
--- a/gdb/arm-fbsd-nat.c
+++ b/gdb/arm-fbsd-nat.c
@@ -104,9 +104,7 @@ arm_fbsd_nat_target::read_description ()
return desc;
}
-void _initialize_arm_fbsd_nat ();
-void
-_initialize_arm_fbsd_nat ()
+INIT_GDB_FILE (arm_fbsd_nat)
{
add_inf_child_target (&the_arm_fbsd_nat_target);
}
diff --git a/gdb/arm-fbsd-tdep.c b/gdb/arm-fbsd-tdep.c
index c9a466f..fc81818 100644
--- a/gdb/arm-fbsd-tdep.c
+++ b/gdb/arm-fbsd-tdep.c
@@ -300,8 +300,7 @@ arm_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tramp_frame_prepend_unwinder (gdbarch, &arm_fbsd_sigframe);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
tdep->jb_pc = 24;
tdep->jb_elt_size = 4;
@@ -319,12 +318,10 @@ arm_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
}
/* Single stepping. */
- set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, arm_software_single_step);
}
-void _initialize_arm_fbsd_tdep ();
-void
-_initialize_arm_fbsd_tdep ()
+INIT_GDB_FILE (arm_fbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_FREEBSD,
arm_fbsd_init_abi);
diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
index 3ff9fc6..dc5165e 100644
--- a/gdb/arm-linux-nat.c
+++ b/gdb/arm-linux-nat.c
@@ -90,8 +90,6 @@ public:
bool stopped_data_address (CORE_ADDR *) override;
- bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override;
-
const struct target_desc *read_description () override;
/* Override linux_nat_target low methods. */
@@ -1206,14 +1204,6 @@ arm_linux_nat_target::stopped_by_watchpoint ()
return stopped_data_address (&addr);
}
-bool
-arm_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr,
- CORE_ADDR start,
- int length)
-{
- return start <= addr && start + length - 1 >= addr;
-}
-
/* Handle thread creation. We need to copy the breakpoints and watchpoints
in the parent thread to the child thread. */
void
@@ -1393,9 +1383,7 @@ arm_linux_nat_target::low_new_fork (struct lwp_info *parent, pid_t child_pid)
*child_state = *parent_state;
}
-void _initialize_arm_linux_nat ();
-void
-_initialize_arm_linux_nat ()
+INIT_GDB_FILE (arm_linux_nat)
{
/* Register the target. */
linux_target = &the_arm_linux_nat_target;
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 485a5d9..ff20ed8 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -41,6 +41,7 @@
#include "arm-tdep.h"
#include "arm-linux-tdep.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "glibc-tdep.h"
#include "arch-utils.h"
#include "inferior.h"
@@ -55,7 +56,6 @@
#include "stap-probe.h"
#include "parser-defs.h"
#include "user-regs.h"
-#include <ctype.h>
#include "elf/common.h"
/* Under ARM GNU/Linux the traditional way of performing a breakpoint
@@ -1166,10 +1166,10 @@ arm_linux_displaced_step_copy_insn (struct gdbarch *gdbarch,
static int
arm_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
{
- return (*s == '#' || *s == '$' || isdigit (*s) /* Literal number. */
+ return (*s == '#' || *s == '$' || c_isdigit (*s) /* Literal number. */
|| *s == '[' /* Register indirection or
displacement. */
- || isalpha (*s)); /* Register value. */
+ || c_isalpha (*s)); /* Register value. */
}
/* This routine is used to parse a special token in ARM's assembly.
@@ -1201,7 +1201,7 @@ arm_stap_parse_special_token (struct gdbarch *gdbarch,
start = tmp;
/* Register name. */
- while (isalnum (*tmp))
+ while (c_isalnum (*tmp))
++tmp;
if (*tmp != ',')
@@ -1211,7 +1211,7 @@ arm_stap_parse_special_token (struct gdbarch *gdbarch,
regname = (char *) alloca (len + 2);
offset = 0;
- if (isdigit (*start))
+ if (c_isdigit (*start))
{
/* If we are dealing with a register whose name begins with a
digit, it means we should prefix the name with the letter
@@ -1801,11 +1801,10 @@ arm_linux_init_abi (struct gdbarch_info info,
}
tdep->jb_elt_size = ARM_LINUX_JB_ELEMENT_SIZE;
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
/* Single stepping. */
- set_gdbarch_software_single_step (gdbarch, arm_linux_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, arm_linux_software_single_step);
/* Shared library handling. */
set_gdbarch_skip_trampoline_code (gdbarch, arm_linux_skip_trampoline_code);
@@ -2026,9 +2025,7 @@ arm_linux_init_abi (struct gdbarch_info info,
set_gdbarch_gcc_target_options (gdbarch, arm_linux_gcc_target_options);
}
-void _initialize_arm_linux_tdep ();
-void
-_initialize_arm_linux_tdep ()
+INIT_GDB_FILE (arm_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_LINUX,
arm_linux_init_abi);
diff --git a/gdb/arm-netbsd-nat.c b/gdb/arm-netbsd-nat.c
index 3a24f51..ebf4084 100644
--- a/gdb/arm-netbsd-nat.c
+++ b/gdb/arm-netbsd-nat.c
@@ -354,9 +354,7 @@ arm_netbsd_nat_target::read_description ()
return arm_read_description (ARM_FP_TYPE_VFPV3, false);
}
-void _initialize_arm_netbsd_nat ();
-void
-_initialize_arm_netbsd_nat ()
+INIT_GDB_FILE (arm_netbsd_nat)
{
add_inf_child_target (&the_arm_netbsd_nat_target);
}
diff --git a/gdb/arm-netbsd-tdep.c b/gdb/arm-netbsd-tdep.c
index a162054..571d6f2 100644
--- a/gdb/arm-netbsd-tdep.c
+++ b/gdb/arm-netbsd-tdep.c
@@ -139,7 +139,7 @@ arm_netbsd_init_abi_common (struct gdbarch_info info,
set_gdbarch_iterate_over_regset_sections
(gdbarch, arm_nbsd_iterate_over_regset_sections);
/* Single stepping. */
- set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, arm_software_single_step);
}
static void
@@ -156,13 +156,10 @@ arm_netbsd_elf_init_abi (struct gdbarch_info info,
tdep->fp_model = ARM_FLOAT_SOFT_VFP;
/* NetBSD ELF uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
}
-void _initialize_arm_netbsd_tdep ();
-void
-_initialize_arm_netbsd_tdep ()
+INIT_GDB_FILE (arm_netbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NETBSD,
arm_netbsd_elf_init_abi);
diff --git a/gdb/arm-none-tdep.c b/gdb/arm-none-tdep.c
index 81db22f..3ffcd2b 100644
--- a/gdb/arm-none-tdep.c
+++ b/gdb/arm-none-tdep.c
@@ -204,9 +204,7 @@ arm_none_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Initialize ARM bare-metal target support. */
-void _initialize_arm_none_tdep ();
-void
-_initialize_arm_none_tdep ()
+INIT_GDB_FILE (arm_none_tdep)
{
gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NONE,
arm_none_init_abi);
diff --git a/gdb/arm-obsd-tdep.c b/gdb/arm-obsd-tdep.c
index 6fd4c85..8a48b95 100644
--- a/gdb/arm-obsd-tdep.c
+++ b/gdb/arm-obsd-tdep.c
@@ -83,8 +83,7 @@ armobsd_init_abi (struct gdbarch_info info,
tramp_frame_prepend_unwinder (gdbarch, &armobsd_sigframe);
/* OpenBSD/arm uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
tdep->jb_pc = 24;
@@ -97,7 +96,7 @@ armobsd_init_abi (struct gdbarch_info info,
tdep->struct_return = pcc_struct_return;
/* Single stepping. */
- set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, arm_software_single_step);
/* Breakpoints. */
switch (info.byte_order)
@@ -114,9 +113,7 @@ armobsd_init_abi (struct gdbarch_info info,
}
}
-void _initialize_armobsd_tdep ();
-void
-_initialize_armobsd_tdep ()
+INIT_GDB_FILE (armobsd_tdep)
{
gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_OPENBSD,
armobsd_init_abi);
diff --git a/gdb/arm-pikeos-tdep.c b/gdb/arm-pikeos-tdep.c
index 428bb7d..8d24342 100644
--- a/gdb/arm-pikeos-tdep.c
+++ b/gdb/arm-pikeos-tdep.c
@@ -26,7 +26,7 @@ static void
arm_pikeos_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
/* Single stepping. */
- set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, arm_software_single_step);
}
/* The ARM PikeOS OSABI sniffer (see gdbarch_register_osabi_sniffer).
@@ -73,9 +73,7 @@ arm_pikeos_osabi_sniffer (bfd *abfd)
return GDB_OSABI_UNKNOWN;
}
-void _initialize_arm_pikeos_tdep ();
-void
-_initialize_arm_pikeos_tdep ()
+INIT_GDB_FILE (arm_pikeos_tdep)
{
/* Register the sniffer for the PikeOS targets. */
gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_elf_flavour,
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 5450056..940d05f 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -18,7 +18,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include <ctype.h>
#include "extract-store-integer.h"
#include "frame.h"
@@ -1669,7 +1668,7 @@ arm_analyze_load_stack_chk_guard(CORE_ADDR pc, struct gdbarch *gdbarch,
ldr Rn, .Label
....
- .Lable:
+ .Label:
.word __stack_chk_guard
Since ldr/str is a very popular instruction, we can't use them as
@@ -2504,15 +2503,15 @@ static const registry<bfd>::key<arm_exidx_data> arm_exidx_data_key;
static struct obj_section *
arm_obj_section_from_vma (struct objfile *objfile, bfd_vma vma)
{
- for (obj_section *osect : objfile->sections ())
- if (bfd_section_flags (osect->the_bfd_section) & SEC_ALLOC)
+ for (obj_section &osect : objfile->sections ())
+ if (bfd_section_flags (osect.the_bfd_section) & SEC_ALLOC)
{
bfd_vma start, size;
- start = bfd_section_vma (osect->the_bfd_section);
- size = bfd_section_size (osect->the_bfd_section);
+ start = bfd_section_vma (osect.the_bfd_section);
+ size = bfd_section_size (osect.the_bfd_section);
if (start <= vma && vma < start + size)
- return osect;
+ return &osect;
}
return NULL;
@@ -11015,9 +11014,7 @@ static void arm_analyze_prologue_test ();
}
#endif
-void _initialize_arm_tdep ();
-void
-_initialize_arm_tdep ()
+INIT_GDB_FILE (arm_tdep)
{
long length;
int i, j;
diff --git a/gdb/arm-wince-tdep.c b/gdb/arm-wince-tdep.c
index b1e1304..f14c8e8 100644
--- a/gdb/arm-wince-tdep.c
+++ b/gdb/arm-wince-tdep.c
@@ -135,7 +135,7 @@ arm_wince_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_skip_trampoline_code (gdbarch, arm_pe_skip_trampoline_code);
/* Single stepping. */
- set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, arm_software_single_step);
/* Skip call to __gccmain that gcc places in main. */
set_gdbarch_skip_main_prologue (gdbarch, arm_wince_skip_main_prologue);
@@ -152,9 +152,7 @@ arm_wince_osabi_sniffer (bfd *abfd)
return GDB_OSABI_UNKNOWN;
}
-void _initialize_arm_wince_tdep ();
-void
-_initialize_arm_wince_tdep ()
+INIT_GDB_FILE (arm_wince_tdep)
{
gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_coff_flavour,
arm_wince_osabi_sniffer);
diff --git a/gdb/auto-load.c b/gdb/auto-load.c
index 4fc5b08..8817bd1 100644
--- a/gdb/auto-load.c
+++ b/gdb/auto-load.c
@@ -17,7 +17,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include <ctype.h>
#include "auto-load.h"
#include "gdbsupport/gdb_vecs.h"
#include "progspace.h"
@@ -41,6 +40,7 @@
#include <algorithm>
#include "gdbsupport/pathstuff.h"
#include "cli/cli-style.h"
+#include "gdbsupport/selftest.h"
/* The section to look in for auto-loaded scripts (in file formats that
support sections).
@@ -162,6 +162,67 @@ show_auto_load_dir (struct ui_file *file, int from_tty,
value);
}
+/* Substitute all occurrences of string FROM by string TO in STRING.
+ STRING will be updated in place as needed. FROM needs to be
+ delimited by IS_DIR_SEPARATOR or DIRNAME_SEPARATOR (or be located
+ at the start or end of STRING. */
+
+static void
+substitute_path_component (std::string &string, std::string_view from,
+ std::string_view to)
+{
+ for (size_t s = 0;;)
+ {
+ s = string.find (from, s);
+ if (s == std::string::npos)
+ break;
+
+ if ((s == 0 || IS_DIR_SEPARATOR (string[s - 1])
+ || string[s - 1] == DIRNAME_SEPARATOR)
+ && (s + from.size () == string.size ()
+ || IS_DIR_SEPARATOR (string[s + from.size ()])
+ || string[s + from.size ()] == DIRNAME_SEPARATOR))
+ {
+ string.replace (s, from.size (), to);
+ s += to.size ();
+ }
+ else
+ s++;
+ }
+}
+
+#if GDB_SELF_TEST
+
+namespace selftests {
+namespace subst_path {
+
+static void
+test_substitute_path_component ()
+{
+ auto test = [] (std::string s, const char *from, const char *to,
+ const char *expected)
+ {
+ substitute_path_component (s, from, to);
+ SELF_CHECK (s == expected);
+ };
+
+ test ("/abc/$def/g", "abc", "xyz", "/xyz/$def/g");
+ test ("abc/$def/g", "abc", "xyz", "xyz/$def/g");
+ test ("/abc/$def/g", "$def", "xyz", "/abc/xyz/g");
+ test ("/abc/$def/g", "g", "xyz", "/abc/$def/xyz");
+ test ("/abc/$def/g", "ab", "xyz", "/abc/$def/g");
+ test ("/abc/$def/g", "def", "xyz", "/abc/$def/g");
+ test ("/abc/$def/g", "abc", "abc", "/abc/$def/g");
+ test ("/abc/$def/g", "abc", "", "//$def/g");
+ test ("/abc/$def/g", "abc/$def", "xyz", "/xyz/g");
+ test ("/abc/$def/abc", "abc", "xyz", "/xyz/$def/xyz");
+}
+
+}
+}
+
+#endif /* GDB_SELF_TEST */
+
/* Directory list safe to hold auto-loaded files. It is not checked for
absolute paths but they are strongly recommended. It is initialized by
_initialize_auto_load. */
@@ -178,16 +239,15 @@ static std::vector<gdb::unique_xmalloc_ptr<char>> auto_load_safe_path_vec;
static std::vector<gdb::unique_xmalloc_ptr<char>>
auto_load_expand_dir_vars (const char *string)
{
- char *s = xstrdup (string);
- substitute_path_component (&s, "$datadir", gdb_datadir.c_str ());
- substitute_path_component (&s, "$debugdir", debug_file_directory.c_str ());
+ std::string s = string;
+ substitute_path_component (s, "$datadir", gdb_datadir.c_str ());
+ substitute_path_component (s, "$debugdir", debug_file_directory.c_str ());
- if (debug_auto_load && strcmp (s, string) != 0)
- auto_load_debug_printf ("Expanded $-variables to \"%s\".", s);
+ if (debug_auto_load && s != string)
+ auto_load_debug_printf ("Expanded $-variables to \"%s\".", s.c_str ());
std::vector<gdb::unique_xmalloc_ptr<char>> dir_vec
- = dirnames_to_char_ptr_vec (s);
- xfree(s);
+ = dirnames_to_char_ptr_vec (s.c_str ());
return dir_vec;
}
@@ -984,7 +1044,7 @@ execute_script_contents (struct auto_load_pspace_info *pspace_info,
buf = name_holder.c_str ();
for (p = buf; *p != '\0'; ++p)
{
- if (isspace (*p))
+ if (c_isspace (*p))
break;
}
/* We don't allow nameless scripts, they're not helpful to the user. */
@@ -1507,9 +1567,7 @@ found and/or loaded."),
gdb::observers::token auto_load_new_objfile_observer_token;
-void _initialize_auto_load ();
-void
-_initialize_auto_load ()
+INIT_GDB_FILE (auto_load)
{
struct cmd_list_element *cmd;
gdb::unique_xmalloc_ptr<char> scripts_directory_help, gdb_name_help,
@@ -1650,4 +1708,9 @@ When non-zero, debugging output for files of 'set auto-load ...'\n\
is displayed."),
NULL, show_debug_auto_load,
&setdebuglist, &showdebuglist);
+
+#if GDB_SELF_TEST
+ selftests::register_test ("substitute_path_component",
+ selftests::subst_path::test_substitute_path_component);
+#endif
}
diff --git a/gdb/auxv.c b/gdb/auxv.c
index 5ec39ea..06e2fb0 100644
--- a/gdb/auxv.c
+++ b/gdb/auxv.c
@@ -609,9 +609,7 @@ info_auxv_command (const char *cmd, int from_tty)
}
}
-void _initialize_auxv ();
-void
-_initialize_auxv ()
+INIT_GDB_FILE (auxv)
{
add_info ("auxv", info_auxv_command,
_("Display the inferior's auxiliary vector.\n\
diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c
index 36e6ec4..6274529 100644
--- a/gdb/avr-tdep.c
+++ b/gdb/avr-tdep.c
@@ -1629,9 +1629,7 @@ avr_io_reg_read_command (const char *args, int from_tty)
}
}
-void _initialize_avr_tdep ();
-void
-_initialize_avr_tdep ()
+INIT_GDB_FILE (avr_tdep)
{
gdbarch_register (bfd_arch_avr, avr_gdbarch_init);
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index e572465..54717bf 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -525,7 +525,7 @@ gen_var_ref (struct agent_expr *ax, struct axs_value *value, struct symbol *var)
return computed_ops->tracepoint_var_ref (var, ax, value);
/* I'm imitating the code in read_var_value. */
- switch (var->aclass ())
+ switch (var->loc_class ())
{
case LOC_CONST: /* A constant, like an enum value. */
ax_const_l (ax, (LONGEST) var->value_longest ());
@@ -538,8 +538,7 @@ gen_var_ref (struct agent_expr *ax, struct axs_value *value, struct symbol *var)
break;
case LOC_CONST_BYTES:
- internal_error (_("gen_var_ref: LOC_CONST_BYTES "
- "symbols are not supported"));
+ error (_("gen_var_ref: LOC_CONST_BYTES symbols are not supported"));
/* Variable at a fixed location in memory. Easy. */
case LOC_STATIC:
@@ -2634,9 +2633,7 @@ maint_agent_printf_command (const char *cmdrest, int from_tty)
/* Initialization code. */
-void _initialize_ax_gdb ();
-void
-_initialize_ax_gdb ()
+INIT_GDB_FILE (ax_gdb)
{
add_cmd ("agent", class_maintenance, maint_agent_command,
_("\
diff --git a/gdb/bfin-linux-tdep.c b/gdb/bfin-linux-tdep.c
index 3ba3146..d84f800 100644
--- a/gdb/bfin-linux-tdep.c
+++ b/gdb/bfin-linux-tdep.c
@@ -161,9 +161,7 @@ bfin_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
bfin_linux_get_syscall_number);
}
-void _initialize_bfin_linux_tdep ();
-void
-_initialize_bfin_linux_tdep ()
+INIT_GDB_FILE (bfin_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_bfin, 0, GDB_OSABI_LINUX,
bfin_linux_init_abi);
diff --git a/gdb/bfin-tdep.c b/gdb/bfin-tdep.c
index 32d9371..3a96e9f 100644
--- a/gdb/bfin-tdep.c
+++ b/gdb/bfin-tdep.c
@@ -837,9 +837,7 @@ bfin_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_bfin_tdep ();
-void
-_initialize_bfin_tdep ()
+INIT_GDB_FILE (bfin_tdep)
{
gdbarch_register (bfd_arch_bfin, bfin_gdbarch_init);
}
diff --git a/gdb/block.c b/gdb/block.c
index fdf209c..2450ebd 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -618,7 +618,7 @@ block_iterator_next (struct block_iterator *iterator)
bool
best_symbol (struct symbol *a, const domain_search_flags domain)
{
- if (a->aclass () == LOC_UNRESOLVED)
+ if (a->loc_class () == LOC_UNRESOLVED)
return false;
if ((domain & SEARCH_VAR_DOMAIN) != 0)
@@ -644,10 +644,10 @@ better_symbol (struct symbol *a, struct symbol *b,
if (b->matches (domain) && !a->matches (domain))
return b;
- if (a->aclass () != LOC_UNRESOLVED && b->aclass () == LOC_UNRESOLVED)
+ if (a->loc_class () != LOC_UNRESOLVED && b->loc_class () == LOC_UNRESOLVED)
return a;
- if (b->aclass () != LOC_UNRESOLVED && a->aclass () == LOC_UNRESOLVED)
+ if (b->loc_class () != LOC_UNRESOLVED && a->loc_class () == LOC_UNRESOLVED)
return b;
return a;
@@ -670,22 +670,9 @@ block_lookup_symbol (const struct block *block, const lookup_name_info &name,
{
if (!block->function ())
{
- struct symbol *other = NULL;
-
- for (struct symbol *sym : block_iterator_range (block, &name))
- {
- /* See comment related to PR gcc/debug/91507 in
- block_lookup_symbol_primary. */
- if (best_symbol (sym, domain))
- return sym;
- /* This is a bit of a hack, but symbol_matches_domain might ignore
- STRUCT vs VAR domain symbols. So if a matching symbol is found,
- make sure there is no "better" matching symbol, i.e., one with
- exactly the same domain. PR 16253. */
- if (sym->matches (domain))
- other = better_symbol (other, sym, domain);
- }
- return other;
+ best_symbol_tracker tracker;
+ tracker.search (nullptr, block, name, domain);
+ return tracker.currently_best.symbol;
}
else
{
@@ -717,24 +704,13 @@ block_lookup_symbol (const struct block *block, const lookup_name_info &name,
/* See block.h. */
-struct symbol *
-block_lookup_symbol_primary (const struct block *block, const char *name,
+bool
+best_symbol_tracker::search (compunit_symtab *symtab,
+ const struct block *block,
+ const lookup_name_info &name,
const domain_search_flags domain)
{
- struct symbol *sym, *other;
- struct mdict_iterator mdict_iter;
-
- lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
-
- /* Verify BLOCK is STATIC_BLOCK or GLOBAL_BLOCK. */
- gdb_assert (block->superblock () == NULL
- || block->superblock ()->superblock () == NULL);
-
- other = NULL;
- for (sym = mdict_iter_match_first (block->multidict (), lookup_name,
- &mdict_iter);
- sym != NULL;
- sym = mdict_iter_match_next (lookup_name, &mdict_iter))
+ for (symbol *sym : block_iterator_range (block, &name))
{
/* With the fix for PR gcc/debug/91507, we get for:
...
@@ -764,17 +740,28 @@ block_lookup_symbol_primary (const struct block *block, const char *name,
the only option to make this work is improve the fallback to use the
size of the minimal symbol. Filed as PR exp/24989. */
if (best_symbol (sym, domain))
- return sym;
+ {
+ best_symtab = symtab;
+ currently_best = { sym, block };
+ return true;
+ }
/* This is a bit of a hack, but 'matches' might ignore
STRUCT vs VAR domain symbols. So if a matching symbol is found,
make sure there is no "better" matching symbol, i.e., one with
exactly the same domain. PR 16253. */
if (sym->matches (domain))
- other = better_symbol (other, sym, domain);
+ {
+ symbol *better = better_symbol (sym, currently_best.symbol, domain);
+ if (better != currently_best.symbol)
+ {
+ best_symtab = symtab;
+ currently_best = { better, block };
+ }
+ }
}
- return other;
+ return false;
}
/* See block.h. */
@@ -924,9 +911,7 @@ maintenance_info_blocks (const char *arg, int from_tty)
-void _initialize_block ();
-void
-_initialize_block ()
+INIT_GDB_FILE (block)
{
add_cmd ("blocks", class_maintenance, maintenance_info_blocks,
_("\
diff --git a/gdb/block.h b/gdb/block.h
index 76fa203..4ea5294 100644
--- a/gdb/block.h
+++ b/gdb/block.h
@@ -630,14 +630,27 @@ extern struct symbol *block_lookup_symbol (const struct block *block,
const lookup_name_info &name,
const domain_search_flags domain);
-/* Search BLOCK for symbol NAME in DOMAIN but only in primary symbol table of
- BLOCK. BLOCK must be STATIC_BLOCK or GLOBAL_BLOCK. Function is useful if
- one iterates all global/static blocks of an objfile. */
+/* When searching for a symbol, the "best" symbol is preferred over
+ one that is merely acceptable. See 'best_symbol'. This class
+ keeps track of this distinction while searching. */
-extern struct symbol *block_lookup_symbol_primary
- (const struct block *block,
- const char *name,
- const domain_search_flags domain);
+struct best_symbol_tracker
+{
+ /* The symtab in which the currently best symbol appears. */
+ compunit_symtab *best_symtab = nullptr;
+
+ /* The currently best (really "better") symbol. */
+ block_symbol currently_best {};
+
+ /* Search BLOCK (which must have come from SYMTAB) for a symbol
+ matching NAME and DOMAIN. When a symbol is found, update
+ 'currently_best'. If a best symbol is found, return true.
+ Otherwise, return false. SYMTAB can be nullptr if the caller
+ does not care about this tracking. */
+ bool search (compunit_symtab *symtab,
+ const block *block, const lookup_name_info &name,
+ domain_search_flags domain);
+};
/* Find symbol NAME in BLOCK and in DOMAIN. This will return a
matching symbol whose type is not a "opaque", see TYPE_IS_OPAQUE.
diff --git a/gdb/bpf-tdep.c b/gdb/bpf-tdep.c
index 2c95607..be01e8b 100644
--- a/gdb/bpf-tdep.c
+++ b/gdb/bpf-tdep.c
@@ -368,9 +368,7 @@ bpf_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_bpf_tdep ();
-void
-_initialize_bpf_tdep ()
+INIT_GDB_FILE (bpf_tdep)
{
gdbarch_register (bfd_arch_bpf, bpf_gdbarch_init);
diff --git a/gdb/break-catch-exec.c b/gdb/break-catch-exec.c
index 6716437..9bfdb44 100644
--- a/gdb/break-catch-exec.c
+++ b/gdb/break-catch-exec.c
@@ -164,7 +164,7 @@ ep_parse_optional_if_clause (const char **arg)
{
const char *cond_string;
- if (((*arg)[0] != 'i') || ((*arg)[1] != 'f') || !isspace ((*arg)[2]))
+ if (((*arg)[0] != 'i') || ((*arg)[1] != 'f') || !c_isspace ((*arg)[2]))
return NULL;
/* Skip the "if" keyword. */
@@ -204,7 +204,7 @@ catch_exec_command_1 (const char *arg, int from_tty,
First, check if there's an if clause. */
cond_string = ep_parse_optional_if_clause (&arg);
- if ((*arg != '\0') && !isspace (*arg))
+ if ((*arg != '\0') && !c_isspace (*arg))
error (_("Junk at end of arguments."));
std::unique_ptr<exec_catchpoint> c
@@ -213,9 +213,7 @@ catch_exec_command_1 (const char *arg, int from_tty,
install_breakpoint (0, std::move (c), 1);
}
-void _initialize_break_catch_exec ();
-void
-_initialize_break_catch_exec ()
+INIT_GDB_FILE (break_catch_exec)
{
add_catch_command ("exec", _("Catch calls to exec."),
catch_exec_command_1,
diff --git a/gdb/break-catch-fork.c b/gdb/break-catch-fork.c
index cba3753..535040c9 100644
--- a/gdb/break-catch-fork.c
+++ b/gdb/break-catch-fork.c
@@ -221,7 +221,7 @@ catch_fork_command_1 (const char *arg, int from_tty,
First, check if there's an if clause. */
cond_string = ep_parse_optional_if_clause (&arg);
- if ((*arg != '\0') && !isspace (*arg))
+ if ((*arg != '\0') && !c_isspace (*arg))
error (_("Junk at end of arguments."));
/* If this target supports it, create a fork or vfork catchpoint
@@ -242,9 +242,7 @@ catch_fork_command_1 (const char *arg, int from_tty,
}
}
-void _initialize_break_catch_fork ();
-void
-_initialize_break_catch_fork ()
+INIT_GDB_FILE (break_catch_fork)
{
add_catch_command ("fork", _("Catch calls to fork."),
catch_fork_command_1,
diff --git a/gdb/break-catch-load.c b/gdb/break-catch-load.c
index 5e290fd..b5594c2 100644
--- a/gdb/break-catch-load.c
+++ b/gdb/break-catch-load.c
@@ -22,9 +22,8 @@
#include "arch-utils.h"
#include "breakpoint.h"
#include "cli/cli-decode.h"
-#include "mi/mi-common.h"
#include "progspace.h"
-#include "solist.h"
+#include "solib.h"
#include "target.h"
#include "valprint.h"
@@ -119,7 +118,7 @@ solib_catchpoint::check_status (struct bpstat *bs)
for (solib *iter : current_program_space->added_solibs)
{
if (!regex
- || compiled->exec (iter->so_name.c_str (), 0, nullptr, 0) == 0)
+ || compiled->exec (iter->name.c_str (), 0, nullptr, 0) == 0)
return;
}
}
@@ -264,9 +263,7 @@ catch_unload_command_1 (const char *arg, int from_tty,
catch_load_or_unload (arg, from_tty, 0, command);
}
-void _initialize_break_catch_load ();
-void
-_initialize_break_catch_load ()
+INIT_GDB_FILE (break_catch_load)
{
add_catch_command ("load", _("Catch loads of shared libraries.\n\
Usage: catch load [REGEX]\n\
diff --git a/gdb/break-catch-sig.c b/gdb/break-catch-sig.c
index fb5d202..9e1c6d6 100644
--- a/gdb/break-catch-sig.c
+++ b/gdb/break-catch-sig.c
@@ -18,9 +18,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "arch-utils.h"
-#include <ctype.h>
#include "breakpoint.h"
-#include "cli/cli-cmds.h"
#include "inferior.h"
#include "infrun.h"
#include "annotate.h"
@@ -409,9 +407,7 @@ catch_signal_command (const char *arg, int from_tty,
create_signal_catchpoint (tempflag, std::move (filter), catch_all);
}
-void _initialize_break_catch_sig ();
-void
-_initialize_break_catch_sig ()
+INIT_GDB_FILE (break_catch_sig)
{
add_catch_command ("signal", _("\
Catch signals by their names and/or numbers.\n\
diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c
index 348ff41..fad76e7 100644
--- a/gdb/break-catch-syscall.c
+++ b/gdb/break-catch-syscall.c
@@ -17,9 +17,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/>. */
-#include <ctype.h>
#include "breakpoint.h"
-#include "cli/cli-cmds.h"
#include "inferior.h"
#include "cli/cli-utils.h"
#include "annotate.h"
@@ -370,7 +368,7 @@ catch_syscall_split_args (const char *arg)
/* Skip whitespace. */
arg = skip_spaces (arg);
- for (i = 0; i < 127 && arg[i] && !isspace (arg[i]); ++i)
+ for (i = 0; i < 127 && arg[i] && !c_isspace (arg[i]); ++i)
cur_name[i] = arg[i];
cur_name[i] = '\0';
arg += i;
@@ -423,7 +421,7 @@ catch_syscall_command_1 (const char *arg, int from_tty,
struct syscall s;
struct gdbarch *gdbarch = get_current_arch ();
- /* Checking if the feature if supported. */
+ /* Checking if the feature is supported. */
if (gdbarch_get_syscall_number_p (gdbarch) == 0)
error (_("The feature 'catch syscall' is not supported on \
this architecture yet."));
@@ -570,9 +568,7 @@ clear_syscall_counts (struct inferior *inf)
inf_data->syscalls_counts.clear ();
}
-void _initialize_break_catch_syscall ();
-void
-_initialize_break_catch_syscall ()
+INIT_GDB_FILE (break_catch_syscall)
{
gdb::observers::inferior_exit.attach (clear_syscall_counts,
"break-catch-syscall");
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 41213e4..1a45d7c 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -18,19 +18,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "arch-utils.h"
-#include <ctype.h>
#include "breakpoint.h"
#include "exceptions.h"
#include "inferior.h"
#include "annotate.h"
#include "valprint.h"
#include "cli/cli-utils.h"
-#include "completer.h"
-#include "gdbsupport/gdb_obstack.h"
#include "mi/mi-common.h"
-#include "linespec.h"
#include "probe.h"
-#include "objfiles.h"
#include "cp-abi.h"
#include "gdbsupport/gdb_regex.h"
#include "cp-support.h"
@@ -424,7 +419,7 @@ catch_exception_event (enum exception_event_kind ex_event,
cond_string = ep_parse_optional_if_clause (&arg);
- if ((*arg != '\0') && !isspace (*arg))
+ if ((*arg != '\0') && !c_isspace (*arg))
error (_("Junk at end of arguments."));
if (ex_event != EX_EVENT_THROW
@@ -499,9 +494,7 @@ static const struct internalvar_funcs exception_funcs =
-void _initialize_break_catch_throw ();
-void
-_initialize_break_catch_throw ()
+INIT_GDB_FILE (break_catch_throw)
{
/* Add catch and tcatch sub-commands. */
add_catch_command ("catch", _("\
diff --git a/gdb/break-cond-parse.c b/gdb/break-cond-parse.c
index 705f4f6..b771344 100644
--- a/gdb/break-cond-parse.c
+++ b/gdb/break-cond-parse.c
@@ -23,7 +23,6 @@
#include "break-cond-parse.h"
#include "tid-parse.h"
#include "ada-lang.h"
-#include "exceptions.h"
/* When parsing tokens from a string, which direction are we parsing?
@@ -67,12 +66,12 @@ find_next_token (const char **curr, parse_direction direction)
{
gdb_assert (direction == parse_direction::backward);
- while (isspace (**curr))
+ while (c_isspace (**curr))
--(*curr);
tok_end = *curr;
- while (!isspace (**curr))
+ while (!c_isspace (**curr))
--(*curr);
tok_start = (*curr) + 1;
@@ -569,10 +568,10 @@ test (const char *input, const char *condition, int thread = -1,
gdb::unique_xmalloc_ptr<char> extracted_rest;
int extracted_thread, extracted_inferior, extracted_task;
bool extracted_force_condition;
- std::string exception_msg, error_str;
+ std::string exception_msg;
- if (error_msg != nullptr)
- error_str = std::string (error_msg) + "\n";
+ if (error_msg == nullptr)
+ error_msg = "";
try
{
@@ -584,10 +583,7 @@ test (const char *input, const char *condition, int thread = -1,
}
catch (const gdb_exception_error &ex)
{
- string_file buf;
-
- exception_print (&buf, ex);
- exception_msg = buf.release ();
+ exception_msg = ex.what ();
}
if ((condition == nullptr) != (extracted_condition.get () == nullptr)
@@ -599,7 +595,7 @@ test (const char *input, const char *condition, int thread = -1,
|| inferior != extracted_inferior
|| task != extracted_task
|| force != extracted_force_condition
- || exception_msg != error_str)
+ || exception_msg != error_msg)
{
if (run_verbose ())
{
@@ -687,9 +683,7 @@ create_breakpoint_parse_arg_string_tests ()
} /* namespace selftests */
#endif /* GDB_SELF_TEST */
-void _initialize_break_cond_parse ();
-void
-_initialize_break_cond_parse ()
+INIT_GDB_FILE (break_cond_parse)
{
#if GDB_SELF_TEST
selftests::register_test
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 23e5051..5d87fb9 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -18,7 +18,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "arch-utils.h"
-#include <ctype.h>
#include "event-top.h"
#include "exceptions.h"
#include "gdbsupport/gdb_vecs.h"
@@ -50,7 +49,6 @@
#include "cli/cli-script.h"
#include "block.h"
#include "solib.h"
-#include "solist.h"
#include "observable.h"
#include "memattr.h"
#include "ada-lang.h"
@@ -255,14 +253,22 @@ DIAGNOSTIC_POP
static std::string
breakpoint_location_address_str (const bp_location *bl)
{
- std::string str = string_printf ("Breakpoint %d (%s) at address %s",
+ std::string str = string_printf ("Breakpoint %d (%s) ",
bl->owner->number,
- host_address_to_string (bl),
- paddress (bl->gdbarch, bl->address));
+ host_address_to_string (bl));
- std::string loc_string = bl->to_string ();
- if (!loc_string.empty ())
- str += string_printf (" %s", loc_string.c_str ());
+ if (bl_address_is_meaningful (bl))
+ {
+ gdb_assert (bl->gdbarch != nullptr);
+ str += string_printf ("at address %s",
+ paddress (bl->gdbarch, bl->address));
+
+ std::string loc_string = bl->to_string ();
+ if (!loc_string.empty ())
+ str += string_printf (" %s", loc_string.c_str ());
+ }
+ else
+ str += "with dummy location";
return str;
}
@@ -721,7 +727,8 @@ all_tracepoints ()
tracepoint_iterator (breakpoint_chain.end ()));
}
-/* Array is sorted by bp_location_is_less_than - primarily by the ADDRESS. */
+/* Array is sorted by bp_location_ptr_is_less_than - primarily by the
+ ADDRESS. */
static std::vector<bp_location *> bp_locations;
@@ -1280,7 +1287,7 @@ condition_completer (struct cmd_list_element *cmd,
{
tracker.advance_custom_word_point_by (1);
/* We don't support completion of history indices. */
- if (!isdigit (text[1]))
+ if (!c_isdigit (text[1]))
complete_internalvar (tracker, &text[1]);
return;
}
@@ -5136,7 +5143,7 @@ print_solib_event (bool is_catchpoint)
if (!first)
current_uiout->text (" ");
first = false;
- current_uiout->field_string ("library", iter->so_name);
+ current_uiout->field_string ("library", iter->name);
current_uiout->text ("\n");
}
}
@@ -7504,7 +7511,7 @@ breakpoint_locations_match (const struct bp_location *loc1,
else
/* We compare bp_location.length in order to cover ranged
breakpoints. Keep this in sync with
- bp_location_is_less_than. */
+ bp_location_ptr_is_less_than. */
return (breakpoint_address_match (loc1->pspace->aspace.get (),
loc1->address,
loc2->pspace->aspace.get (),
@@ -8144,7 +8151,7 @@ disable_breakpoints_in_unloaded_shlib (program_space *pspace, const solib &solib
target_terminal::ours_for_output ();
warning (_("Temporarily disabling breakpoints "
"for unloaded shared library \"%s\""),
- solib.so_name.c_str ());
+ solib.name.c_str ());
disabled_shlib_breaks = true;
}
}
@@ -10289,7 +10296,7 @@ masked_watchpoint::print_recreate (struct ui_file *fp) const
}
gdb_printf (fp, " %s mask 0x%s", exp_string.get (),
- phex (hw_wp_mask, sizeof (CORE_ADDR)));
+ phex (hw_wp_mask));
print_recreate_thread (fp);
}
@@ -10457,7 +10464,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
int len;
len = exp_end - exp_start;
- while (len > 0 && isspace (exp_start[len - 1]))
+ while (len > 0 && c_isspace (exp_start[len - 1]))
len--;
error (_("Cannot watch constant value `%.*s'."), len, exp_start);
}
@@ -11205,14 +11212,17 @@ breakpoint_auto_delete (bpstat *bs)
delete_breakpoint (&b);
}
-/* A comparison function for bp_location AP and BP being interfaced to
- std::sort. Sort elements primarily by their ADDRESS (no matter what
- bl_address_is_meaningful says), secondarily by ordering first
- permanent elements and tertiarily just ensuring the array is sorted
- stable way despite std::sort being an unstable algorithm. */
+/* A comparison function for bp_location pointers A and B being interfaced to
+ std::sort, for instance to sort an std::vector<bp_location *>. Sort
+ elements:
+ - primarily by their ADDRESS (no matter what bl_address_is_meaningful
+ says),
+ - secondarily by ordering first permanent elements, and
+ - tertiarily just ensuring the array is sorted in a stable way despite
+ std::sort being an unstable algorithm. */
-static int
-bp_location_is_less_than (const bp_location *a, const bp_location *b)
+static bool
+bp_location_ptr_is_less_than (const bp_location *a, const bp_location *b)
{
if (a->address != b->address)
return a->address < b->address;
@@ -11250,6 +11260,15 @@ bp_location_is_less_than (const bp_location *a, const bp_location *b)
return a < b;
}
+/* A comparison function for bp_locations A and B being interfaced to
+ std::sort, for instance to sort an std::vector<bp_location>. */
+
+static bool
+bp_location_is_less_than (const bp_location &a, const bp_location &b)
+{
+ return bp_location_ptr_is_less_than (&a, &b);
+}
+
/* Set bp_locations_placed_address_before_address_max and
bp_locations_shadow_len_after_address_max according to the current
content of the bp_locations array. */
@@ -11455,7 +11474,7 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
handle_automatic_hardware_breakpoints (loc);
std::sort (bp_locations.begin (), bp_locations.end (),
- bp_location_is_less_than);
+ bp_location_ptr_is_less_than);
bp_locations_target_extensions_update ();
@@ -11903,9 +11922,7 @@ breakpoint::add_location (bp_location &loc)
auto ub = std::upper_bound (m_locations.begin (), m_locations.end (),
loc,
- [] (const bp_location &left,
- const bp_location &right)
- { return left.address < right.address; });
+ bp_location_is_less_than);
m_locations.insert (ub, loc);
}
@@ -13986,9 +14003,7 @@ int
insert_single_step_breakpoints (struct gdbarch *gdbarch)
{
regcache *regcache = get_thread_regcache (inferior_thread ());
- std::vector<CORE_ADDR> next_pcs;
-
- next_pcs = gdbarch_software_single_step (gdbarch, regcache);
+ std::vector<CORE_ADDR> next_pcs = gdbarch_get_next_pcs (gdbarch, regcache);
if (!next_pcs.empty ())
{
@@ -14095,7 +14110,7 @@ strace_command (const char *arg, int from_tty)
/* Decide if we are dealing with a static tracepoint marker (`-m'),
or with a normal static tracepoint. */
- if (arg && startswith (arg, "-m") && isspace (arg[2]))
+ if (arg && startswith (arg, "-m") && c_isspace (arg[2]))
{
ops = &strace_marker_breakpoint_ops;
locspec = new_linespec_location_spec (&arg,
@@ -14747,9 +14762,7 @@ static struct cmd_list_element *enablebreaklist = NULL;
cmd_list_element *commands_cmd_element = nullptr;
-void _initialize_breakpoint ();
-void
-_initialize_breakpoint ()
+INIT_GDB_FILE (breakpoint)
{
struct cmd_list_element *c;
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 6b421f2..9341112 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -425,7 +425,9 @@ public:
simplicity is more important than memory usage for breakpoints. */
/* Architecture associated with this location's address. May be
- different from the breakpoint architecture. */
+ different from the breakpoint architecture. Not every location has
+ an address (e.g. see add_dummy_location), so not every location has
+ an associated gdbarch -- this can be NULL for a valid location. */
struct gdbarch *gdbarch = NULL;
/* The program space associated with this breakpoint location
diff --git a/gdb/bsd-kvm.c b/gdb/bsd-kvm.c
index 5158fb6..baffa76 100644
--- a/gdb/bsd-kvm.c
+++ b/gdb/bsd-kvm.c
@@ -388,11 +388,11 @@ Generic command for manipulating the kernel memory interface."),
#ifndef HAVE_STRUCT_THREAD_TD_PCB
add_cmd ("proc", class_obscure, bsd_kvm_proc_cmd,
- _("Set current context from proc address"), &bsd_kvm_cmdlist);
+ _("Set current context from proc address."), &bsd_kvm_cmdlist);
#endif
add_cmd ("pcb", class_obscure, bsd_kvm_pcb_cmd,
/* i18n: PCB == "Process Control Block". */
- _("Set current context from pcb address"), &bsd_kvm_cmdlist);
+ _("Set current context from pcb address."), &bsd_kvm_cmdlist);
/* Some notes on the ptid usage on this target.
diff --git a/gdb/bsd-uthread.c b/gdb/bsd-uthread.c
index 51dafed..4509376 100644
--- a/gdb/bsd-uthread.c
+++ b/gdb/bsd-uthread.c
@@ -25,7 +25,6 @@
#include "observable.h"
#include "regcache.h"
#include "solib.h"
-#include "solist.h"
#include "symfile.h"
#include "target.h"
@@ -280,13 +279,13 @@ bsd_uthread_solib_loaded (solib &so)
for (names = bsd_uthread_solib_names; *names; names++)
{
- if (startswith (so.so_original_name, *names))
+ if (startswith (so.original_name, *names))
{
solib_read_symbols (so, 0);
if (bsd_uthread_activate (so.objfile))
{
- bsd_uthread_solib_name = so.so_original_name;
+ bsd_uthread_solib_name = so.original_name;
return;
}
}
@@ -300,7 +299,7 @@ bsd_uthread_solib_unloaded (program_space *pspace, const solib &so,
if (bsd_uthread_solib_name.empty () || still_in_use)
return;
- if (so.so_original_name == bsd_uthread_solib_name)
+ if (so.original_name == bsd_uthread_solib_name)
bsd_uthread_deactivate ();
}
@@ -536,14 +535,12 @@ bsd_uthread_target::pid_to_str (ptid_t ptid)
if (ptid.tid () != 0)
return string_printf ("process %d, thread 0x%s",
ptid.pid (),
- phex_nz (ptid.tid (), sizeof (ULONGEST)));
+ phex_nz (ptid.tid ()));
return normal_pid_to_str (ptid);
}
-void _initialize_bsd_uthread ();
-void
-_initialize_bsd_uthread ()
+INIT_GDB_FILE (bsd_uthread)
{
gdb::observers::inferior_created.attach (bsd_uthread_inferior_created,
"bsd-uthread");
diff --git a/gdb/btrace.c b/gdb/btrace.c
index 3d883c5..3d43261 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -39,7 +39,6 @@
#include "record-btrace.h"
#include <inttypes.h>
-#include <ctype.h>
#include <algorithm>
#include <string>
@@ -3258,7 +3257,7 @@ get_uint (const char **arg)
begin = *arg;
pos = skip_spaces (begin);
- if (!isdigit (*pos))
+ if (!c_isdigit (*pos))
error (_("Expected positive number, got: %s."), pos);
number = strtoul (pos, &end, 10);
@@ -3277,7 +3276,7 @@ get_context_size (const char **arg)
{
const char *pos = skip_spaces (*arg);
- if (!isdigit (*pos))
+ if (!c_isdigit (*pos))
error (_("Expected positive number, got: %s."), pos);
char *end;
@@ -3501,9 +3500,7 @@ show_maint_btrace_pt_skip_pad (struct ui_file *file, int from_tty,
/* Initialize btrace maintenance commands. */
-void _initialize_btrace ();
-void
-_initialize_btrace ()
+INIT_GDB_FILE (btrace)
{
add_cmd ("btrace", class_maintenance, maint_info_btrace_cmd,
_("Info about branch tracing data."), &maintenanceinfolist);
diff --git a/gdb/build-id.c b/gdb/build-id.c
index 02602af..0ecd79f 100644
--- a/gdb/build-id.c
+++ b/gdb/build-id.c
@@ -29,6 +29,7 @@
#include "gdbsupport/scoped_fd.h"
#include "debuginfod-support.h"
#include "extension.h"
+#include "inferior.h"
/* See build-id.h. */
@@ -128,8 +129,9 @@ build_id_to_debug_bfd_1 (const std::string &original_link,
if (supports_target_stat != TRIBOOL_FALSE)
{
struct stat sb;
- int res = target_fileio_stat (nullptr, link_on_target, &sb,
- &target_errno);
+ int res = target_fileio_lstat (current_inferior (),
+ link_on_target, &sb,
+ &target_errno);
if (res != 0 && target_errno != FILEIO_ENOSYS)
{
@@ -157,7 +159,7 @@ build_id_to_debug_bfd_1 (const std::string &original_link,
the path doesn't exist, but we just assume that anything
other than EINVAL indicates the path doesn't exist. */
std::optional<std::string> link_target
- = target_fileio_readlink (nullptr, link_on_target,
+ = target_fileio_readlink (current_inferior (), link_on_target,
&target_errno);
if (link_target.has_value ()
|| target_errno == FILEIO_EINVAL)
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index f53a138..11f0d88 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -35,7 +35,6 @@
%{
-#include <ctype.h>
#include "expression.h"
#include "value.h"
#include "parser-defs.h"
@@ -106,8 +105,35 @@ struct c_parse_state
/* The type stack. */
struct type_stack type_stack;
+
+ /* When set, a name token is not looked up. This can be useful when
+ the search domain is known by context. TYPE_CODE_UNDEF is used
+ to mean "unset" here -- typically only types with tags (enum,
+ struct, class, union) use this feature, but TYPE_CODE_VOID is
+ also used to avoid the lookup for field names. */
+ type_code assume_classification = TYPE_CODE_UNDEF;
+};
+
+/* Used for field names, which skip name lookup. */
+struct qualified_name_token
+{
+ /* The prefix, if any. This can be nullptr. */
+ const char *prefix;
+ /* The field name itself. */
+ const char *name;
+ /* True if the COMPLETE token was seen. */
+ bool complete;
};
+/* A convenient overload of copy_name. */
+static std::string
+copy_name (qualified_name_token token)
+{
+ if (token.prefix == nullptr)
+ return token.name;
+ return std::string (token.prefix) + "::" + token.name;
+}
+
/* This is set and cleared in c_parse. */
static struct c_parse_state *cpstate;
@@ -120,6 +146,8 @@ static void yyerror (const char *);
static int type_aggregate_p (struct type *);
+static void handle_qualified_field_name (qualified_name_token token);
+
using namespace expr;
%}
@@ -140,6 +168,7 @@ using namespace expr;
} typed_val_float;
struct type *tval;
struct stoken sval;
+ qualified_name_token qval;
struct typed_stoken tsval;
struct ttype tsym;
struct symtoken ssym;
@@ -160,7 +189,7 @@ using namespace expr;
static int parse_number (struct parser_state *par_state,
const char *, int, int, YYSTYPE *);
static struct stoken operator_stoken (const char *);
-static struct stoken typename_stoken (const char *);
+static qualified_name_token typename_stoken (const char *);
static void check_parameter_typelist (std::vector<struct type *> *);
#if defined(YYBISON) && YYBISON < 30800
@@ -171,7 +200,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value);
%type <voidval> exp exp1 type_exp start variable qualified_name lcurly function_method
%type <lval> rcurly
-%type <tval> type typebase scalar_type
+%type <tval> type typebase scalar_type tag_name_or_complete
%type <tvec> nonempty_typelist func_mod parameter_typelist
/* %type <bval> block */
@@ -202,7 +231,9 @@ static void c_print_token (FILE *file, int type, YYSTYPE value);
%token <voidval> COMPLETE
%token <tsym> TYPENAME
%token <theclass> CLASSNAME /* ObjC Class name */
-%type <sval> name field_name
+%type <sval> name
+%type <qval> qual_field_name field_name field_name_or_complete
+%type <qval> field_or_destructor
%type <svec> string_exp
%type <ssym> name_not_typename
%type <tsym> type_name
@@ -364,117 +395,73 @@ exp : ALIGNOF '(' type_exp ')' %prec UNARY
{ pstate->wrap<unop_alignof_operation> (); }
;
-exp : exp ARROW field_name
+exp : exp ARROW
{
- pstate->push_new<structop_ptr_operation>
- (pstate->pop (), copy_name ($3));
+ cpstate->assume_classification = TYPE_CODE_VOID;
}
- ;
-
-exp : exp ARROW field_name COMPLETE
+ field_name_or_complete
{
- structop_base_operation *op
- = new structop_ptr_operation (pstate->pop (),
- copy_name ($3));
- pstate->mark_struct_expression (op);
- pstate->push (operation_up (op));
- }
- ;
+ cpstate->assume_classification = TYPE_CODE_UNDEF;
-exp : exp ARROW COMPLETE
- {
- structop_base_operation *op
- = new structop_ptr_operation (pstate->pop (), "");
- pstate->mark_struct_expression (op);
- pstate->push (operation_up (op));
- }
- ;
-
-exp : exp ARROW '~' name
- {
- pstate->push_new<structop_ptr_operation>
- (pstate->pop (), "~" + copy_name ($4));
- }
- ;
-
-exp : exp ARROW '~' name COMPLETE
- {
- structop_base_operation *op
- = new structop_ptr_operation (pstate->pop (),
- "~" + copy_name ($4));
- pstate->mark_struct_expression (op);
- pstate->push (operation_up (op));
+ if ($4.prefix != nullptr)
+ {
+ handle_qualified_field_name ($4);
+ /* exp->type::name becomes exp->*(&type::name) */
+ /* Note: this doesn't work if name is a
+ static member! FIXME */
+ pstate->wrap<unop_addr_operation> ();
+ pstate->wrap2<structop_mptr_operation> ();
+ }
+ else
+ {
+ structop_base_operation *op
+ = new structop_ptr_operation (pstate->pop (),
+ copy_name ($4));
+ if ($4.complete)
+ pstate->mark_struct_expression (op);
+ pstate->push (operation_up (op));
+ }
}
;
-exp : exp ARROW qualified_name
- { /* exp->type::name becomes exp->*(&type::name) */
- /* Note: this doesn't work if name is a
- static member! FIXME */
- pstate->wrap<unop_addr_operation> ();
- pstate->wrap2<structop_mptr_operation> (); }
- ;
-
exp : exp ARROW_STAR exp
{ pstate->wrap2<structop_mptr_operation> (); }
;
-exp : exp '.' field_name
- {
- if (pstate->language ()->la_language
- == language_opencl)
- pstate->push_new<opencl_structop_operation>
- (pstate->pop (), copy_name ($3));
- else
- pstate->push_new<structop_operation>
- (pstate->pop (), copy_name ($3));
- }
- ;
-
-exp : exp '.' field_name COMPLETE
- {
- structop_base_operation *op
- = new structop_operation (pstate->pop (),
- copy_name ($3));
- pstate->mark_struct_expression (op);
- pstate->push (operation_up (op));
- }
- ;
-
-exp : exp '.' COMPLETE
+exp : exp '.'
{
- structop_base_operation *op
- = new structop_operation (pstate->pop (), "");
- pstate->mark_struct_expression (op);
- pstate->push (operation_up (op));
+ cpstate->assume_classification = TYPE_CODE_VOID;
}
- ;
-
-exp : exp '.' '~' name
+ field_name_or_complete
{
- pstate->push_new<structop_operation>
- (pstate->pop (), "~" + copy_name ($4));
- }
- ;
+ cpstate->assume_classification = TYPE_CODE_UNDEF;
-exp : exp '.' '~' name COMPLETE
- {
- structop_base_operation *op
- = new structop_operation (pstate->pop (),
- "~" + copy_name ($4));
- pstate->mark_struct_expression (op);
- pstate->push (operation_up (op));
+ if ($4.prefix != nullptr)
+ {
+ handle_qualified_field_name ($4);
+ /* exp.type::name becomes exp.*(&type::name) */
+ /* Note: this doesn't work if name is a
+ static member! FIXME */
+ pstate->wrap<unop_addr_operation> ();
+ pstate->wrap2<structop_member_operation> ();
+ }
+ else if (pstate->language ()->la_language
+ == language_opencl
+ && !$4.complete)
+ pstate->push_new<opencl_structop_operation>
+ (pstate->pop (), copy_name ($4));
+ else
+ {
+ structop_base_operation *op
+ = new structop_operation (pstate->pop (),
+ copy_name ($4));
+ if ($4.complete)
+ pstate->mark_struct_expression (op);
+ pstate->push (operation_up (op));
+ }
}
;
-exp : exp '.' qualified_name
- { /* exp.type::name becomes exp.*(&type::name) */
- /* Note: this doesn't work if name is a
- static member! FIXME */
- pstate->wrap<unop_addr_operation> ();
- pstate->wrap2<structop_member_operation> (); }
- ;
-
exp : exp DOT_STAR exp
{ pstate->wrap2<structop_member_operation> (); }
;
@@ -1261,12 +1248,12 @@ single_qualifier:
{ cpstate->type_stack.insert (tp_restrict); }
| '@' NAME
{
- cpstate->type_stack.insert (pstate,
+ cpstate->type_stack.insert (pstate->gdbarch (),
copy_name ($2.stoken).c_str ());
}
| '@' UNKNOWN_CPP_NAME
{
- cpstate->type_stack.insert (pstate,
+ cpstate->type_stack.insert (pstate->gdbarch (),
copy_name ($2.stoken).c_str ());
}
;
@@ -1316,15 +1303,13 @@ direct_abs_decl: '(' abs_decl ')'
| direct_abs_decl array_mod
{
cpstate->type_stack.push ($1);
- cpstate->type_stack.push ($2);
- cpstate->type_stack.push (tp_array);
+ cpstate->type_stack.push (tp_array, $2);
$$ = cpstate->type_stack.create ();
cpstate->type_stacks.emplace_back ($$);
}
| array_mod
{
- cpstate->type_stack.push ($1);
- cpstate->type_stack.push (tp_array);
+ cpstate->type_stack.push (tp_array, $1);
$$ = cpstate->type_stack.create ();
cpstate->type_stacks.emplace_back ($$);
}
@@ -1504,71 +1489,37 @@ typebase
{
$$ = init_complex_type (nullptr, $2);
}
- | STRUCT name
- { $$
- = lookup_struct (copy_name ($2).c_str (),
- pstate->expression_context_block);
- }
- | STRUCT COMPLETE
+ | STRUCT
{
- pstate->mark_completion_tag (TYPE_CODE_STRUCT,
- "", 0);
- $$ = NULL;
+ cpstate->assume_classification = TYPE_CODE_STRUCT;
}
- | STRUCT name COMPLETE
+ tag_name_or_complete
{
- pstate->mark_completion_tag (TYPE_CODE_STRUCT,
- $2.ptr, $2.length);
- $$ = NULL;
+ $$ = $3;
}
- | CLASS name
- { $$ = lookup_struct
- (copy_name ($2).c_str (),
- pstate->expression_context_block);
- }
- | CLASS COMPLETE
+ | CLASS
{
- pstate->mark_completion_tag (TYPE_CODE_STRUCT,
- "", 0);
- $$ = NULL;
+ cpstate->assume_classification = TYPE_CODE_STRUCT;
}
- | CLASS name COMPLETE
+ tag_name_or_complete
{
- pstate->mark_completion_tag (TYPE_CODE_STRUCT,
- $2.ptr, $2.length);
- $$ = NULL;
- }
- | UNION name
- { $$
- = lookup_union (copy_name ($2).c_str (),
- pstate->expression_context_block);
+ $$ = $3;
}
- | UNION COMPLETE
+ | ENUM
{
- pstate->mark_completion_tag (TYPE_CODE_UNION,
- "", 0);
- $$ = NULL;
+ cpstate->assume_classification = TYPE_CODE_ENUM;
}
- | UNION name COMPLETE
+ tag_name_or_complete
{
- pstate->mark_completion_tag (TYPE_CODE_UNION,
- $2.ptr, $2.length);
- $$ = NULL;
+ $$ = $3;
}
- | ENUM name
- { $$ = lookup_enum (copy_name ($2).c_str (),
- pstate->expression_context_block);
- }
- | ENUM COMPLETE
+ | UNION
{
- pstate->mark_completion_tag (TYPE_CODE_ENUM, "", 0);
- $$ = NULL;
+ cpstate->assume_classification = TYPE_CODE_UNION;
}
- | ENUM name COMPLETE
+ tag_name_or_complete
{
- pstate->mark_completion_tag (TYPE_CODE_ENUM, $2.ptr,
- $2.length);
- $$ = NULL;
+ $$ = $3;
}
/* It appears that this rule for templates is never
reduced; template recognition happens by lookahead
@@ -1793,13 +1744,66 @@ oper: OPERATOR NEW
}
;
+qual_field_name:
+ qual_field_name COLONCOLON name
+ {
+ $$.complete = false;
+ if ($1.prefix == nullptr)
+ $$.prefix = $1.name;
+ else
+ $$.prefix = obconcat (&cpstate->expansion_obstack,
+ $1.prefix, "::", $1.name, nullptr);
+ $$.name = obstack_strndup (&cpstate->expansion_obstack,
+ $3.ptr, $3.length);
+ }
+ | name
+ {
+ $$.complete = false;
+ $$.prefix = nullptr;
+ $$.name = obstack_strndup (&cpstate->expansion_obstack,
+ $1.ptr, $1.length);
+ }
+ ;
+
+field_or_destructor:
+ qual_field_name
+ | qual_field_name COLONCOLON '~' name
+ {
+ $$.complete = false;
+ if ($1.prefix == nullptr)
+ $$.prefix = $1.name;
+ else
+ $$.prefix = obconcat (&cpstate->expansion_obstack,
+ $1.prefix, "::", $1.name, nullptr);
+ char *name
+ = (char *) obstack_alloc (&cpstate->expansion_obstack,
+ $4.length + 2);
+ name[0] = '~';
+ memcpy (&name[1], $4.ptr, $4.length);
+ name[$4.length + 1] = '\0';
+ $$.name = name;
+ }
+ | '~' name
+ {
+ $$.complete = false;
+ $$.prefix = nullptr;
+ char *name
+ = (char *) obstack_alloc (&cpstate->expansion_obstack,
+ $2.length + 2);
+ name[0] = '~';
+ memcpy (&name[1], $2.ptr, $2.length);
+ name[$2.length + 1] = '\0';
+ $$.name = name;
+ }
+ ;
+
/* This rule exists in order to allow some tokens that would not normally
match the 'name' rule to appear as fields within a struct. The example
that initially motivated this was the RISC-V target which models the
floating point registers as a union with fields called 'float' and
'double'. */
field_name
- : name
+ : field_or_destructor
| DOUBLE_KEYWORD { $$ = typename_stoken ("double"); }
| FLOAT_KEYWORD { $$ = typename_stoken ("float"); }
| INT_KEYWORD { $$ = typename_stoken ("int"); }
@@ -1809,6 +1813,61 @@ field_name
| UNSIGNED { $$ = typename_stoken ("unsigned"); }
;
+field_name_or_complete
+ : field_name
+ | field_name COMPLETE
+ {
+ $$ = $1;
+ $$.complete = true;
+ }
+ | COMPLETE
+ {
+ $$ = typename_stoken ("");
+ $$.complete = true;
+ }
+ ;
+
+/* This rule is used when the preceding token is a keyword that takes
+ a tag name (e.g., "struct"). The "caller" should disable name
+ lookup, see c_parse_state::assume_classification. */
+tag_name_or_complete
+ : NAME
+ {
+ switch (cpstate->assume_classification)
+ {
+ case TYPE_CODE_STRUCT:
+ $$ = lookup_struct (copy_name ($1.stoken).c_str (),
+ pstate->expression_context_block);
+ break;
+ case TYPE_CODE_ENUM:
+ $$ = lookup_enum (copy_name ($1.stoken).c_str (),
+ pstate->expression_context_block);
+ break;
+ case TYPE_CODE_UNION:
+ $$ = lookup_union (copy_name ($1.stoken).c_str (),
+ pstate->expression_context_block);
+ break;
+ default:
+ gdb_assert_not_reached ();
+ }
+ cpstate->assume_classification = TYPE_CODE_UNDEF;
+ }
+ | COMPLETE
+ {
+ pstate->mark_completion_tag (cpstate->assume_classification,
+ "", 0);
+ cpstate->assume_classification = TYPE_CODE_UNDEF;
+ $$ = nullptr;
+ }
+ | NAME COMPLETE
+ {
+ pstate->mark_completion_tag (cpstate->assume_classification,
+ $1.stoken.ptr, $1.stoken.length);
+ cpstate->assume_classification = TYPE_CODE_UNDEF;
+ $$ = nullptr;
+ }
+ ;
+
name : NAME { $$ = $1.stoken; }
| BLOCKNAME { $$ = $1.stoken; }
| TYPENAME { $$ = $1.stoken; }
@@ -1866,12 +1925,10 @@ operator_stoken (const char *op)
/* Returns a stoken of the type named TYPE. */
-static struct stoken
+static qualified_name_token
typename_stoken (const char *type)
{
- struct stoken st = { type, 0 };
- st.length = strlen (type);
- return st;
+ return qualified_name_token { nullptr, type, false };
};
/* Return true if the type is aggregate-like. */
@@ -1969,13 +2026,13 @@ parse_number (struct parser_state *par_state,
len -= 2;
}
/* Handle suffixes: 'f' for float, 'l' for long double. */
- else if (len >= 1 && TOLOWER (buf[len - 1]) == 'f')
+ else if (len >= 1 && c_tolower (buf[len - 1]) == 'f')
{
putithere->typed_val_float.type
= parse_type (par_state)->builtin_float;
len -= 1;
}
- else if (len >= 1 && TOLOWER (buf[len - 1]) == 'l')
+ else if (len >= 1 && c_tolower (buf[len - 1]) == 'l')
{
putithere->typed_val_float.type
= parse_type (par_state)->builtin_long_double;
@@ -2181,9 +2238,9 @@ c_parse_escape (const char **ptr, struct obstack *output)
if (output)
obstack_grow_str (output, "\\x");
++tokptr;
- if (!ISXDIGIT (*tokptr))
+ if (!c_isxdigit (*tokptr))
error (_("\\x escape without a following hex digit"));
- while (ISXDIGIT (*tokptr))
+ while (c_isxdigit (*tokptr))
{
if (output)
obstack_1grow (output, *tokptr);
@@ -2206,7 +2263,7 @@ c_parse_escape (const char **ptr, struct obstack *output)
if (output)
obstack_grow_str (output, "\\");
for (i = 0;
- i < 3 && ISDIGIT (*tokptr) && *tokptr != '8' && *tokptr != '9';
+ i < 3 && c_isdigit (*tokptr) && *tokptr != '8' && *tokptr != '9';
++i)
{
if (output)
@@ -2231,9 +2288,9 @@ c_parse_escape (const char **ptr, struct obstack *output)
obstack_1grow (output, *tokptr);
}
++tokptr;
- if (!ISXDIGIT (*tokptr))
+ if (!c_isxdigit (*tokptr))
error (_("\\%c escape without a following hex digit"), c);
- for (i = 0; i < len && ISXDIGIT (*tokptr); ++i)
+ for (i = 0; i < len && c_isxdigit (*tokptr); ++i)
{
if (output)
obstack_1grow (output, *tokptr);
@@ -2818,7 +2875,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
size_t len = strlen ("selector");
if (strncmp (p, "selector", len) == 0
- && (p[len] == '\0' || ISSPACE (p[len])))
+ && (p[len] == '\0' || c_isspace (p[len])))
{
pstate->lexptr = p + len;
return SELECTOR;
@@ -2827,7 +2884,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
goto parse_string;
}
- while (ISSPACE (*p))
+ while (c_isspace (*p))
p++;
size_t len = strlen ("entry");
if (strncmp (p, "entry", len) == 0 && !c_ident_is_alnum (p[len])
@@ -3042,15 +3099,11 @@ classify_name (struct parser_state *par_state, const struct block *block,
std::string copy = copy_name (yylval.sval);
- /* Initialize this in case we *don't* use it in this call; that way
- we can refer to it unconditionally below. */
- memset (&is_a_field_of_this, 0, sizeof (is_a_field_of_this));
-
bsym = lookup_symbol (copy.c_str (), block, SEARCH_VFT,
par_state->language ()->name_of_this ()
? &is_a_field_of_this : NULL);
- if (bsym.symbol && bsym.symbol->aclass () == LOC_BLOCK)
+ if (bsym.symbol && bsym.symbol->loc_class () == LOC_BLOCK)
{
yylval.ssym.sym = bsym;
yylval.ssym.is_a_field_of_this = is_a_field_of_this.type != NULL;
@@ -3098,7 +3151,7 @@ classify_name (struct parser_state *par_state, const struct block *block,
}
}
- if (bsym.symbol && bsym.symbol->aclass () == LOC_TYPEDEF)
+ if (bsym.symbol && bsym.symbol->loc_class () == LOC_TYPEDEF)
{
yylval.tsym.type = bsym.symbol->type ();
return TYPENAME;
@@ -3193,7 +3246,7 @@ classify_inner_name (struct parser_state *par_state,
return ERROR;
}
- switch (yylval.ssym.sym.symbol->aclass ())
+ switch (yylval.ssym.sym.symbol->loc_class ())
{
case LOC_BLOCK:
case LOC_LABEL:
@@ -3222,6 +3275,48 @@ classify_inner_name (struct parser_state *par_state,
internal_error (_("not reached"));
}
+/* A helper function for the specific case of a qualified field name,
+ like "obj->type1::type2::field". This takes the type prefix
+ ("type1::type2" in the example) and finds the corresponding type.
+ It will either throw an exception, or push a scope_operation on the
+ operation stack. */
+static void
+handle_qualified_field_name (qualified_name_token token)
+{
+ struct type *type = nullptr;
+ std::string accum;
+ for (const auto name : split_name (token.prefix, split_style::CXX))
+ {
+ std::string current (name);
+
+ if (accum.empty ())
+ accum = name;
+ else
+ accum = accum + "::" + current;
+
+ yylval.ssym.stoken.ptr = current.c_str ();
+ yylval.ssym.stoken.length = current.size ();
+ yylval.ssym.sym = {};
+ yylval.ssym.is_a_field_of_this = 0;
+
+ int kind = classify_inner_name (pstate,
+ pstate->expression_context_block,
+ type);
+ if (kind != TYPENAME)
+ error (_("could not find type '%s'"), accum.c_str ());
+
+ type = yylval.tsym.type;
+ }
+
+ type = check_typedef (type);
+ if (!type_aggregate_p (type))
+ error (_("`%s' is not defined as an aggregate type."),
+ TYPE_SAFE_NAME (type));
+ if (token.name[0] == '~')
+ destructor_name_p (token.name, type);
+ pstate->push_new<scope_operation> (type, token.name);
+}
+
/* The outer level of a two-level lexer. This calls the inner lexer
to return tokens. It then either returns these tokens, or
aggregates them into a larger token. This lets us work around a
@@ -3254,12 +3349,16 @@ yylex (void)
subsequent code is C++-only; but also depends on seeing a "::" or
name-like token. */
current.token = lex_one_token (pstate, &is_quoted_name);
- if (current.token == NAME)
+ if (cpstate->assume_classification == TYPE_CODE_UNDEF
+ && current.token == NAME)
current.token = classify_name (pstate, pstate->expression_context_block,
is_quoted_name, last_lex_was_structop);
if (pstate->language ()->la_language != language_cplus
|| (current.token != TYPENAME && current.token != COLONCOLON
- && current.token != FILENAME))
+ && current.token != FILENAME
+ && (cpstate->assume_classification == TYPE_CODE_UNDEF
+ || current.token != NAME))
+ || cpstate->assume_classification == TYPE_CODE_VOID)
return current.token;
/* Read any sequence of alternating "::" and name-like tokens into
@@ -3300,7 +3399,8 @@ yylex (void)
search_block = NULL;
else
{
- gdb_assert (current.token == TYPENAME);
+ gdb_assert (current.token == TYPENAME
+ || cpstate->assume_classification != TYPE_CODE_UNDEF);
search_block = pstate->expression_context_block;
obstack_grow (&name_obstack, current.value.sval.ptr,
current.value.sval.length);
@@ -3323,8 +3423,11 @@ yylex (void)
int classification;
yylval = next.value;
- classification = classify_inner_name (pstate, search_block,
- context_type);
+ if (cpstate->assume_classification != TYPE_CODE_UNDEF)
+ classification = NAME;
+ else
+ classification = classify_inner_name (pstate, search_block,
+ context_type);
/* We keep going until we either run out of names, or until
we have a qualified name which is not a type. */
if (classification != TYPENAME && classification != NAME)
@@ -3334,7 +3437,7 @@ yylex (void)
checkpoint = next_to_examine;
/* Update the partial name we are constructing. */
- if (context_type != NULL)
+ if (next_to_examine > 1)
{
/* We don't want to put a leading "::" into the name. */
obstack_grow_str (&name_obstack, "::");
@@ -3349,7 +3452,8 @@ yylex (void)
last_was_coloncolon = 0;
- if (classification == NAME)
+ if (cpstate->assume_classification == TYPE_CODE_UNDEF
+ && classification == NAME)
break;
context_type = yylval.tsym.type;
@@ -3396,18 +3500,18 @@ c_parse (struct parser_state *par_state)
c_parse_state cstate;
scoped_restore cstate_restore = make_scoped_restore (&cpstate, &cstate);
- gdb::unique_xmalloc_ptr<struct macro_scope> macro_scope;
+ macro_scope macro_scope;
if (par_state->expression_context_block)
macro_scope
= sal_macro_scope (find_pc_line (par_state->expression_context_pc, 0));
else
macro_scope = default_macro_scope ();
- if (! macro_scope)
+ if (!macro_scope.is_valid ())
macro_scope = user_macro_scope ();
scoped_restore restore_macro_scope
- = make_scoped_restore (&expression_macro_scope, macro_scope.get ());
+ = make_scoped_restore (&expression_macro_scope, &macro_scope);
scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
par_state->debug);
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index f052401..e8e66a6 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -33,7 +33,6 @@
#include "cp-abi.h"
#include "cp-support.h"
#include "gdbsupport/gdb_obstack.h"
-#include <ctype.h>
#include "gdbcore.h"
#include "gdbarch.h"
#include "c-exp.h"
@@ -408,7 +407,7 @@ convert_ucn (const char *p, const char *limit, const char *dest_charset,
gdb_byte data[4];
int i;
- for (i = 0; i < length && p < limit && ISXDIGIT (*p); ++i, ++p)
+ for (i = 0; i < length && p < limit && c_isxdigit (*p); ++i, ++p)
result = (result << 4) + fromhex (*p);
for (i = 3; i >= 0; --i)
@@ -450,7 +449,7 @@ convert_octal (struct type *type, const char *p,
unsigned long value = 0;
for (i = 0;
- i < 3 && p < limit && ISDIGIT (*p) && *p != '8' && *p != '9';
+ i < 3 && p < limit && c_isdigit (*p) && *p != '8' && *p != '9';
++i)
{
value = 8 * value + fromhex (*p);
@@ -473,7 +472,7 @@ convert_hex (struct type *type, const char *p,
{
unsigned long value = 0;
- while (p < limit && ISXDIGIT (*p))
+ while (p < limit && c_isxdigit (*p))
{
value = 16 * value + fromhex (*p);
++p;
@@ -484,13 +483,6 @@ convert_hex (struct type *type, const char *p,
return p;
}
-#define ADVANCE \
- do { \
- ++p; \
- if (p == limit) \
- error (_("Malformed escape sequence")); \
- } while (0)
-
/* Convert an escape sequence to a target format. TYPE is the target
character type to use, and DEST_CHARSET is the name of the target
character set. The backslash of the escape sequence is at *P, and
@@ -502,19 +494,30 @@ static const char *
convert_escape (struct type *type, const char *dest_charset,
const char *p, const char *limit, struct obstack *output)
{
+ auto advance = [&] ()
+ {
+ ++p;
+ if (p == limit)
+ error (_("Malformed escape sequence"));
+ };
+
/* Skip the backslash. */
- ADVANCE;
+ advance ();
switch (*p)
{
case '\\':
- obstack_1grow (output, '\\');
+ /* Convert the backslash itself. This is probably overkill but
+ it doesn't hurt to do the full conversion. */
+ convert_between_encodings (host_charset (), dest_charset,
+ (const gdb_byte *) p, 1, 1,
+ output, translit_none);
++p;
break;
case 'x':
- ADVANCE;
- if (!ISXDIGIT (*p))
+ advance ();
+ if (!c_isxdigit (*p))
error (_("\\x used with no following hex digits."));
p = convert_hex (type, p, limit, output);
break;
@@ -535,8 +538,8 @@ convert_escape (struct type *type, const char *dest_charset,
{
int length = *p == 'u' ? 4 : 8;
- ADVANCE;
- if (!ISXDIGIT (*p))
+ advance ();
+ if (!c_isxdigit (*p))
error (_("\\u used with no following hex digits"));
p = convert_ucn (p, limit, dest_charset, output, length);
}
diff --git a/gdb/c-support.h b/gdb/c-support.h
index 47f4066..5fd1118 100644
--- a/gdb/c-support.h
+++ b/gdb/c-support.h
@@ -19,9 +19,7 @@
#ifndef GDB_C_SUPPORT_H
#define GDB_C_SUPPORT_H
-#include "safe-ctype.h"
-
-/* Like ISALPHA, but also returns true for the union of all UTF-8
+/* Like isalpha, but also returns true for the union of all UTF-8
multi-byte sequence bytes and non-ASCII characters in
extended-ASCII charsets (e.g., Latin1). I.e., returns true if the
high bit is set. Note that not all UTF-8 ranges are allowed in C++
@@ -32,15 +30,15 @@
static inline bool
c_ident_is_alpha (unsigned char ch)
{
- return ISALPHA (ch) || ch >= 0x80;
+ return c_isalpha (ch) || ch >= 0x80;
}
-/* Similarly, but Like ISALNUM. */
+/* Similarly, but Like isalnum. */
static inline bool
c_ident_is_alnum (unsigned char ch)
{
- return ISALNUM (ch) || ch >= 0x80;
+ return c_isalnum (ch) || ch >= 0x80;
}
#endif /* GDB_C_SUPPORT_H */
diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
index df7bdbe..be19987 100644
--- a/gdb/c-typeprint.c
+++ b/gdb/c-typeprint.c
@@ -251,8 +251,8 @@ cp_type_print_method_args (struct type *mtype, const char *prefix,
enum language language,
const struct type_print_options *flags)
{
- struct field *args = mtype->fields ();
- int nargs = mtype->num_fields ();
+ auto args = mtype->fields ();
+ int nargs = args.size ();
int varargs = mtype->has_varargs ();
int i;
@@ -515,16 +515,15 @@ c_type_print_args (struct type *type, struct ui_file *stream,
int linkage_name, enum language language,
const struct type_print_options *flags)
{
- int i;
int printed_any = 0;
gdb_printf (stream, "(");
- for (i = 0; i < type->num_fields (); i++)
+ for (const auto &field : type->fields ())
{
struct type *param_type;
- if (type->field (i).is_artificial () && linkage_name)
+ if (field.is_artificial () && linkage_name)
continue;
if (printed_any)
@@ -533,7 +532,7 @@ c_type_print_args (struct type *type, struct ui_file *stream,
stream->wrap_here (4);
}
- param_type = type->field (i).type ();
+ param_type = field.type ();
if (language == language_cplus && linkage_name)
{
@@ -815,7 +814,7 @@ c_type_print_template_args (const struct type_print_options *flags,
{
struct symbol *sym = TYPE_TEMPLATE_ARGUMENT (type, i);
- if (sym->aclass () != LOC_TYPEDEF)
+ if (sym->loc_class () != LOC_TYPEDEF)
continue;
if (first)
diff --git a/gdb/charset.c b/gdb/charset.c
index 3e37ec9..fe725ef 100644
--- a/gdb/charset.c
+++ b/gdb/charset.c
@@ -24,7 +24,6 @@
#include "charset-list.h"
#include "gdbsupport/environ.h"
#include "arch-utils.h"
-#include <ctype.h>
#ifdef USE_WIN32API
#include <windows.h>
@@ -983,9 +982,7 @@ intermediate_encoding (void)
#endif /* USE_INTERMEDIATE_ENCODING_FUNCTION */
-void _initialize_charset ();
-void
-_initialize_charset ()
+INIT_GDB_FILE (charset)
{
/* The first element is always "auto". */
charsets.charsets.push_back (xstrdup ("auto"));
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 9a5021f..d353654 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -51,6 +51,7 @@
#include "cli/cli-cmds.h"
#include "cli/cli-style.h"
#include "cli/cli-utils.h"
+#include "terminal.h"
#include "extension.h"
#include "gdbsupport/pathstuff.h"
@@ -300,8 +301,8 @@ with_command_completer_1 (const char *set_cmd_prefix,
command as if it was a "set" command. */
if (delim == text
|| delim == nullptr
- || !isspace (delim[-1])
- || !(isspace (delim[2]) || delim[2] == '\0'))
+ || !c_isspace (delim[-1])
+ || !(c_isspace (delim[2]) || delim[2] == '\0'))
{
std::string new_text = std::string (set_cmd_prefix) + text;
tracker.advance_custom_word_point_by (-(int) strlen (set_cmd_prefix));
@@ -784,14 +785,14 @@ source_command (const char *args, int from_tty)
if (args[0] != '-')
break;
- if (args[1] == 'v' && isspace (args[2]))
+ if (args[1] == 'v' && c_isspace (args[2]))
{
source_verbose = 1;
/* Skip passed -v. */
args = &args[3];
}
- else if (args[1] == 's' && isspace (args[2]))
+ else if (args[1] == 's' && c_isspace (args[2]))
{
search_path = 1;
@@ -949,9 +950,27 @@ shell_escape (const char *arg, int from_tty)
static void
shell_command (const char *arg, int from_tty)
{
+ scoped_gdb_ttystate save_restore_gdb_ttystate;
+ restore_initial_gdb_ttystate ();
+
shell_escape (arg, from_tty);
}
+/* Completion for the shell command. Currently, this just uses filename
+ completion, but we could, potentially, complete command names from $PATH
+ for the first word, which would make this even more shell like. */
+
+static void
+shell_command_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char * /* word */)
+{
+ tracker.set_use_custom_word_point (true);
+ const char *word
+ = advance_to_filename_maybe_quoted_complete_word_point (tracker, text);
+ filename_maybe_quoted_completer (ignore, tracker, text, word);
+}
+
static void
edit_command (const char *arg, int from_tty)
{
@@ -1165,7 +1184,7 @@ pipe_command_completer (struct cmd_list_element *ignore,
delimiter = opts.delimiter.c_str ();
/* Check if we're past option values already. */
- if (text > org_text && !isspace (text[-1]))
+ if (text > org_text && !c_isspace (text[-1]))
return;
const char *delim = strstr (text, delimiter);
@@ -1178,8 +1197,32 @@ pipe_command_completer (struct cmd_list_element *ignore,
return;
}
- /* We're past the delimiter. What follows is a shell command, which
- we don't know how to complete. */
+ /* We're past the delimiter now, or at least, DELIM points to the
+ delimiter string. Update TEXT to point to the start of whatever
+ appears after the delimiter. */
+ text = skip_spaces (delim + strlen (delimiter));
+
+ /* We really are past the delimiter now, so offer completions. This is
+ like GDB's "shell" command, currently we only offer filename
+ completion, but in the future this could be improved by offering
+ completion of command names from $PATH.
+
+ What we don't do here is offer completions for the empty string. It
+ is assumed that the first word after the delimiter is going to be a
+ command name from $PATH, not a filename, so if the user has typed
+ nothing (yet) and tries to complete, there's no point offering a list
+ of files from the current directory.
+
+ Once the user has started to type something though, then we do start
+ offering filename completions. */
+ if (*text == '\0')
+ return;
+
+ tracker.set_use_custom_word_point (true);
+ tracker.advance_custom_word_point_by (text - org_text);
+ const char *word
+ = advance_to_filename_maybe_quoted_complete_word_point (tracker, text);
+ filename_maybe_quoted_completer (ignore, tracker, text, word);
}
/* Helper for the list_command function. Prints the lines around (and
@@ -1626,7 +1669,7 @@ disassemble_command (const char *arg, int from_tty)
if (*p == '\0')
error (_("Missing modifier."));
- while (*p && ! isspace (*p))
+ while (*p && ! c_isspace (*p))
{
switch (*p++)
{
@@ -1895,8 +1938,8 @@ alias_command_completer (struct cmd_list_element *ignore,
typing COMMAND DEFAULT-ARGS... */
if (delim != text
&& delim != nullptr
- && isspace (delim[-1])
- && (isspace (delim[1]) || delim[1] == '\0'))
+ && c_isspace (delim[-1])
+ && (c_isspace (delim[1]) || delim[1] == '\0'))
{
std::string new_text = std::string (delim + 1);
@@ -2578,9 +2621,7 @@ shell_internal_fn (struct gdbarch *gdbarch,
return value::allocate_optimized_out (int_type);
}
-void _initialize_cli_cmds ();
-void
-_initialize_cli_cmds ()
+INIT_GDB_FILE (cli_cmds)
{
struct cmd_list_element *c;
@@ -2803,7 +2844,7 @@ the previous command number shown."),
= add_com ("shell", class_support, shell_command, _("\
Execute the rest of the line as a shell command.\n\
With no arguments, run an inferior shell."));
- set_cmd_completer (shell_cmd, deprecated_filename_completer);
+ set_cmd_completer_handle_brkchars (shell_cmd, shell_command_completer);
add_com_alias ("!", shell_cmd, class_support, 0);
@@ -2861,6 +2902,7 @@ This can be changed using \"set listsize\", and the current value\n\
can be shown using \"show listsize\"."));
add_com_alias ("l", list_cmd, class_files, 1);
+ set_cmd_completer(list_cmd, location_completer);
c = add_com ("disassemble", class_vars, disassemble_command, _("\
Disassemble a specified section of memory.\n\
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index 48a3466..2b30a6e 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -16,7 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "symtab.h"
-#include <ctype.h>
#include "gdbsupport/gdb_regex.h"
#include "completer.h"
#include "ui-out.h"
@@ -2053,8 +2052,8 @@ print_doc_line (struct ui_file *stream, const char *str,
if (for_value_prefix)
{
char &c = (*line_buffer)[0];
- if (islower (c))
- c = toupper (c);
+ if (c_islower (c))
+ c = c_toupper (c);
if (line_buffer->back () == '.')
line_buffer->pop_back ();
}
@@ -2227,7 +2226,7 @@ valid_cmd_char_p (int c)
/* Alas "42" is a legitimate user-defined command.
In the interests of not breaking anything we preserve that. */
- return isalnum (c) || c == '-' || c == '_' || c == '.';
+ return c_isalnum (c) || c == '-' || c == '_' || c == '.';
}
/* See command.h. */
@@ -2491,7 +2490,7 @@ lookup_cmd (const char **line, struct cmd_list_element *list,
}
else
{
- if (c->type == set_cmd && **line != '\0' && !isspace (**line))
+ if (c->type == set_cmd && **line != '\0' && !c_isspace (**line))
error (_("Argument must be preceded by space."));
/* We've got something. It may still not be what the caller
diff --git a/gdb/cli/cli-dump.c b/gdb/cli/cli-dump.c
index 3055734..3cdd9a3 100644
--- a/gdb/cli/cli-dump.c
+++ b/gdb/cli/cli-dump.c
@@ -23,7 +23,6 @@
#include "cli/cli-cmds.h"
#include "value.h"
#include "completer.h"
-#include <ctype.h>
#include "target.h"
#include "readline/tilde.h"
#include "gdbcore.h"
@@ -564,9 +563,7 @@ restore_command (const char *args, int from_tty)
}
}
-void _initialize_cli_dump ();
-void
-_initialize_cli_dump ()
+INIT_GDB_FILE (cli_dump)
{
struct cmd_list_element *c;
diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
index 32ba9d9..d7b73df 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -321,9 +321,7 @@ cli_interp_factory (const char *name)
/* Standard gdb initialization hook. */
-void _initialize_cli_interp ();
-void
-_initialize_cli_interp ()
+INIT_GDB_FILE (cli_interp)
{
interp_factory_register (INTERP_CONSOLE, cli_interp_factory);
}
diff --git a/gdb/cli/cli-logging.c b/gdb/cli/cli-logging.c
index d225533..d6eb6c2 100644
--- a/gdb/cli/cli-logging.c
+++ b/gdb/cli/cli-logging.c
@@ -202,9 +202,7 @@ show_logging_enabled (struct ui_file *file, int from_tty,
gdb_printf (file, _("off: Logging is disabled.\n"));
}
-void _initialize_cli_logging ();
-void
-_initialize_cli_logging ()
+INIT_GDB_FILE (cli_logging)
{
static struct cmd_list_element *set_logging_cmdlist, *show_logging_cmdlist;
diff --git a/gdb/cli/cli-option.c b/gdb/cli/cli-option.c
index a30261e..5da8c73 100644
--- a/gdb/cli/cli-option.c
+++ b/gdb/cli/cli-option.c
@@ -227,7 +227,7 @@ parse_option (gdb::array_view<const option_def_group> options_group,
match = &o;
match_ctx = grp.ctx;
- if ((isspace (arg[len]) || arg[len] == '\0')
+ if ((c_isspace (arg[len]) || arg[len] == '\0')
&& strlen (o.name) == len)
break; /* Exact match. */
}
@@ -635,7 +635,7 @@ complete_options (completion_tracker &tracker,
if (ov
&& !tracker.have_completions ()
&& **args == '\0'
- && *args > text && !isspace ((*args)[-1]))
+ && *args > text && !c_isspace ((*args)[-1]))
{
tracker.advance_custom_word_point_by
(*args - text);
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index bdbf850..048d391 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -19,7 +19,6 @@
#include "event-top.h"
#include "value.h"
-#include <ctype.h>
#include "ui-out.h"
#include "top.h"
@@ -829,7 +828,7 @@ locate_arg (const char *p)
while ((p = strchr (p, '$')))
{
if (startswith (p, "$arg")
- && (isdigit (p[4]) || p[4] == 'c'))
+ && (c_isdigit (p[4]) || p[4] == 'c'))
return p;
p++;
}
@@ -1324,9 +1323,9 @@ validate_comname (const char **comname)
/* Find the last word of the argument. */
p = *comname + strlen (*comname);
- while (p > *comname && isspace (p[-1]))
+ while (p > *comname && c_isspace (p[-1]))
p--;
- while (p > *comname && !isspace (p[-1]))
+ while (p > *comname && !c_isspace (p[-1]))
p--;
last_word = p;
@@ -1751,9 +1750,7 @@ show_user_1 (struct cmd_list_element *c, const char *prefix, const char *name,
}
-void _initialize_cli_script ();
-void
-_initialize_cli_script ()
+INIT_GDB_FILE (cli_script)
{
struct cmd_list_element *c;
diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c
index 4d4695f..8528ac5 100644
--- a/gdb/cli/cli-setshow.c
+++ b/gdb/cli/cli-setshow.c
@@ -17,7 +17,6 @@
#include "readline/tilde.h"
#include "value.h"
-#include <ctype.h>
#include "arch-utils.h"
#include "observable.h"
#include "interps.h"
@@ -49,7 +48,7 @@ parse_auto_binary_operation (const char *arg)
{
int length = strlen (arg);
- while (isspace (arg[length - 1]) && length > 0)
+ while (c_isspace (arg[length - 1]) && length > 0)
length--;
/* Note that "o" is ambiguous. */
diff --git a/gdb/cli/cli-style.c b/gdb/cli/cli-style.c
index 30c7afb..d6829f0 100644
--- a/gdb/cli/cli-style.c
+++ b/gdb/cli/cli-style.c
@@ -23,6 +23,7 @@
#include "cli/cli-style.h"
#include "source-cache.h"
#include "observable.h"
+#include "charset.h"
/* True if styling is enabled. */
@@ -42,6 +43,10 @@ bool source_styling = true;
bool disassembler_styling = true;
+/* User-settable variable controlling emoji output. */
+
+static auto_boolean emoji_styling = AUTO_BOOLEAN_AUTO;
+
/* Names of intensities; must correspond to
ui_file_style::intensity. */
static const char * const cli_intensities[] = {
@@ -410,9 +415,86 @@ show_style_disassembler (struct ui_file *file, int from_tty,
gdb_printf (file, _("Disassembler output styling is disabled.\n"));
}
-void _initialize_cli_style ();
+/* Implement 'show style emoji'. */
+
+static void
+show_emoji_styling (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ if (emoji_styling == AUTO_BOOLEAN_TRUE)
+ gdb_printf (file, _("CLI emoji styling is enabled.\n"));
+ else if (emoji_styling == AUTO_BOOLEAN_FALSE)
+ gdb_printf (file, _("CLI emoji styling is disabled.\n"));
+ else
+ gdb_printf (file, _("CLI emoji styling is automatic (currently %s).\n"),
+ emojis_ok () ? _("enabled") : _("disabled"));
+}
+
+/* See cli-style.h. */
+
+bool
+emojis_ok ()
+{
+ if (!cli_styling || emoji_styling == AUTO_BOOLEAN_FALSE)
+ return false;
+ if (emoji_styling == AUTO_BOOLEAN_TRUE)
+ return true;
+ return strcmp (host_charset (), "UTF-8") == 0;
+}
+
+/* See cli-style.h. */
+
+void
+no_emojis ()
+{
+ emoji_styling = AUTO_BOOLEAN_FALSE;
+}
+
+/* Emoji warning prefix. */
+static std::string warning_prefix = "⚠️ ";
+
+/* Implement 'show style warning-prefix'. */
+
+static void
+show_warning_prefix (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ gdb_printf (file, _("Warning prefix is \"%s\".\n"),
+ warning_prefix.c_str ());
+}
+
+/* See cli-style.h. */
+
+void
+print_warning_prefix (ui_file *file)
+{
+ if (emojis_ok ())
+ gdb_puts (warning_prefix.c_str (), file);
+}
+
+/* Emoji error prefix. */
+static std::string error_prefix = "❌️ ";
+
+/* Implement 'show style error-prefix'. */
+
+static void
+show_error_prefix (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ gdb_printf (file, _("Error prefix is \"%s\".\n"),
+ error_prefix.c_str ());
+}
+
+/* See cli-style.h. */
+
void
-_initialize_cli_style ()
+print_error_prefix (ui_file *file)
+{
+ if (emojis_ok ())
+ gdb_puts (error_prefix.c_str (), file);
+}
+
+INIT_GDB_FILE (cli_style)
{
add_setshow_prefix_cmd ("style", no_class,
_("\
@@ -431,6 +513,13 @@ If enabled, output to the terminal is styled."),
set_style_enabled, show_style_enabled,
&style_set_list, &style_show_list);
+ add_setshow_auto_boolean_cmd ("emoji", no_class, &emoji_styling, _("\
+Set whether emoji output is enabled."), _("\
+Show whether emoji output is enabled."), _("\
+If enabled, emojis may be displayed."),
+ nullptr, show_emoji_styling,
+ &style_set_list, &style_show_list);
+
add_setshow_boolean_cmd ("sources", no_class, &source_styling, _("\
Set whether source code styling is enabled."), _("\
Show whether source code styling is enabled."), _("\
@@ -627,4 +716,23 @@ coming from your source code."),
&style_disasm_set_list);
add_alias_cmd ("symbol", function_prefix_cmds.show, no_class, 0,
&style_disasm_show_list);
+
+ add_setshow_string_cmd ("warning-prefix", no_class,
+ &warning_prefix,
+ _("Set the warning prefix text."),
+ _("Show the warning prefix text."),
+ _("\
+The warning prefix text is displayed before any warning, when\n\
+emoji output is enabled."),
+ nullptr, show_warning_prefix,
+ &style_set_list, &style_show_list);
+ add_setshow_string_cmd ("error-prefix", no_class,
+ &error_prefix,
+ _("Set the error prefix text."),
+ _("Show the error prefix text."),
+ _("\
+The error prefix text is displayed before any error, when\n\
+emoji output is enabled."),
+ nullptr, show_error_prefix,
+ &style_set_list, &style_show_list);
}
diff --git a/gdb/cli/cli-style.h b/gdb/cli/cli-style.h
index 77f4ac2..b1a950a 100644
--- a/gdb/cli/cli-style.h
+++ b/gdb/cli/cli-style.h
@@ -190,4 +190,18 @@ private:
bool m_old_value;
};
+/* Return true if emoji styling is allowed. */
+extern bool emojis_ok ();
+
+/* Disable emoji styling. This is here so that Windows can disable
+ emoji when the console is in use. It shouldn't be called
+ elsewhere. */
+extern void no_emojis ();
+
+/* Print the warning prefix, if desired. */
+extern void print_warning_prefix (ui_file *file);
+
+/* Print the error prefix, if desired. */
+extern void print_error_prefix (ui_file *file);
+
#endif /* GDB_CLI_CLI_STYLE_H */
diff --git a/gdb/cli/cli-utils.c b/gdb/cli/cli-utils.c
index 23706e0..d0ca594 100644
--- a/gdb/cli/cli-utils.c
+++ b/gdb/cli/cli-utils.c
@@ -20,7 +20,6 @@
#include "cli/cli-utils.h"
#include "value.h"
-#include <ctype.h>
/* See documentation in cli-utils.h. */
@@ -46,7 +45,7 @@ get_ulongest (const char **pp, int trailer)
/* Internal variable. Make a copy of the name, so we can
null-terminate it to pass to lookup_internalvar(). */
const char *start = ++p;
- while (isalnum (*p) || *p == '_')
+ while (c_isalnum (*p) || *p == '_')
p++;
std::string varname (start, p - start);
if (!get_internalvar_integer (lookup_internalvar (varname.c_str ()),
@@ -67,7 +66,7 @@ get_ulongest (const char **pp, int trailer)
p = end;
}
- if (!(isspace (*p) || *p == '\0' || *p == trailer))
+ if (!(c_isspace (*p) || *p == '\0' || *p == trailer))
error (_("Trailing junk at: %s"), p);
p = skip_spaces (p);
*pp = p;
@@ -111,7 +110,7 @@ get_number_trailer (const char **pp, int trailer)
const char *start = ++p;
LONGEST longest_val;
- while (isalnum (*p) || *p == '_')
+ while (c_isalnum (*p) || *p == '_')
p++;
varname = (char *) alloca (p - start + 1);
strncpy (varname, start, p - start);
@@ -136,7 +135,7 @@ get_number_trailer (const char **pp, int trailer)
/* There is no number here. (e.g. "cond a == b"). */
{
/* Skip non-numeric token. */
- while (*p && !isspace((int) *p))
+ while (*p && !c_isspace((int) *p))
++p;
/* Return zero, which caller must interpret as error. */
retval = 0;
@@ -144,10 +143,10 @@ get_number_trailer (const char **pp, int trailer)
else
retval = atoi (p1);
}
- if (!(isspace (*p) || *p == '\0' || *p == trailer))
+ if (!(c_isspace (*p) || *p == '\0' || *p == trailer))
{
/* Trailing junk: return 0 and let caller print error msg. */
- while (!(isspace (*p) || *p == '\0' || *p == trailer))
+ while (!(c_isspace (*p) || *p == '\0' || *p == trailer))
++p;
retval = 0;
}
@@ -262,8 +261,8 @@ number_or_range_parser::get_number ()
option rather than an incomplete range, so check for end of
string as well. */
if (m_cur_tok[0] == '-'
- && !(isspace (m_cur_tok[-1])
- && (isalpha (m_cur_tok[1])
+ && !(c_isspace (m_cur_tok[-1])
+ && (c_isalpha (m_cur_tok[1])
|| m_cur_tok[1] == '-'
|| m_cur_tok[1] == '\0')))
{
@@ -293,7 +292,7 @@ number_or_range_parser::get_number ()
}
else
{
- if (isdigit (*(m_cur_tok + 1)))
+ if (c_isdigit (*(m_cur_tok + 1)))
error (_("negative value"));
if (*(m_cur_tok + 1) == '$')
{
@@ -330,9 +329,9 @@ number_or_range_parser::finished () const
integer, convenience var or negative convenience var. */
return (m_cur_tok == NULL || *m_cur_tok == '\0'
|| (!m_in_range
- && !(isdigit (*m_cur_tok) || *m_cur_tok == '$')
+ && !(c_isdigit (*m_cur_tok) || *m_cur_tok == '$')
&& !(*m_cur_tok == '-'
- && (isdigit (m_cur_tok[1]) || m_cur_tok[1] == '$'))));
+ && (c_isdigit (m_cur_tok[1]) || m_cur_tok[1] == '$'))));
}
/* Accept a number and a string-form list of numbers such as is
@@ -370,7 +369,7 @@ number_is_in_list (const char *list, int number)
const char *
remove_trailing_whitespace (const char *start, const char *s)
{
- while (s > start && isspace (*(s - 1)))
+ while (s > start && c_isspace (*(s - 1)))
--s;
return s;
@@ -420,7 +419,7 @@ int
check_for_argument (const char **str, const char *arg, int arg_len)
{
if (strncmp (*str, arg, arg_len) == 0
- && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
+ && ((*str)[arg_len] == '\0' || c_isspace ((*str)[arg_len])))
{
*str += arg_len;
*str = skip_spaces (*str);
diff --git a/gdb/coff-pe-read.c b/gdb/coff-pe-read.c
index 3a3611e..9255555 100644
--- a/gdb/coff-pe-read.c
+++ b/gdb/coff-pe-read.c
@@ -35,7 +35,6 @@
#include "gdbsupport/common-utils.h"
#include "coff/internal.h"
-#include <ctype.h>
/* Internal section information */
@@ -189,7 +188,7 @@ add_pe_forwarded_sym (minimal_symbol_reader &reader,
int i;
for (i = 0; i < forward_dll_name_len; i++)
- forward_qualified_name[i] = tolower (forward_qualified_name[i]);
+ forward_qualified_name[i] = c_tolower (forward_qualified_name[i]);
msymbol = lookup_minimal_symbol (current_program_space,
forward_qualified_name.c_str ());
}
@@ -694,9 +693,7 @@ show_debug_coff_pe_read (struct ui_file *file, int from_tty,
/* Adds "Set/show debug coff_pe_read" commands. */
-void _initialize_coff_pe_read ();
-void
-_initialize_coff_pe_read ()
+INIT_GDB_FILE (coff_pe_read)
{
add_setshow_zuinteger_cmd ("coff-pe-read", class_maintenance,
&debug_coff_pe_read,
diff --git a/gdb/coffread.c b/gdb/coffread.c
index 8a87e9c..44e761a 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -25,7 +25,6 @@
#include "bfd.h"
#include "gdbsupport/gdb_obstack.h"
-#include <ctype.h>
#include "coff/internal.h"
#include "libcoff.h"
@@ -336,7 +335,7 @@ coff_locate_sections (bfd *abfd, asection *sectp, void *csip)
/* We can have multiple .stab sections if linked with
--split-by-reloc. */
for (s = name + sizeof ".stab" - 1; *s != '\0'; s++)
- if (!isdigit (*s))
+ if (!c_isdigit (*s))
break;
if (*s == '\0')
csi->stabsects->push_back (sectp);
@@ -525,9 +524,9 @@ is_import_fixup_symbol (struct coff_symbol *cs,
/* The name must start with "__fu<digits>__". */
if (!startswith (cs->c_name, "__fu"))
return 0;
- if (! isdigit (cs->c_name[4]))
+ if (! c_isdigit (cs->c_name[4]))
return 0;
- for (i = 5; cs->c_name[i] != '\0' && isdigit (cs->c_name[i]); i++)
+ for (i = 5; cs->c_name[i] != '\0' && c_isdigit (cs->c_name[i]); i++)
/* Nothing, just incrementing index past all digits. */;
if (cs->c_name[i] != '_' || cs->c_name[i + 1] != '_')
return 0;
@@ -1567,7 +1566,7 @@ patch_opaque_types (struct symtab *s)
Remove syms from the chain when their types are stored,
but search the whole chain, as there may be several syms
from different files with the same name. */
- if (real_sym->aclass () == LOC_TYPEDEF
+ if (real_sym->loc_class () == LOC_TYPEDEF
&& real_sym->domain () == TYPE_DOMAIN
&& real_sym->type ()->code () == TYPE_CODE_PTR
&& real_sym->type ()->target_type ()->length () != 0)
@@ -1614,7 +1613,7 @@ static const struct symbol_register_ops coff_register_funcs = {
coff_reg_to_regnum
};
-/* The "aclass" index for computed COFF symbols. */
+/* The "loc_class" index for computed COFF symbols. */
static int coff_register_index;
@@ -1646,7 +1645,7 @@ process_coff_symbol (struct coff_symbol *cs,
(lookup_function_type (decode_function_type (cs, cs->c_type,
aux, objfile)));
- sym->set_aclass_index (LOC_BLOCK);
+ sym->set_loc_class_index (LOC_BLOCK);
if (cs->c_sclass == C_STAT || cs->c_sclass == C_THUMBSTAT
|| cs->c_sclass == C_THUMBSTATFUNC)
add_symbol_to_list (sym, get_file_symbols ());
@@ -1663,14 +1662,14 @@ process_coff_symbol (struct coff_symbol *cs,
break;
case C_AUTO:
- sym->set_aclass_index (LOC_LOCAL);
+ sym->set_loc_class_index (LOC_LOCAL);
add_symbol_to_list (sym, get_local_symbols ());
break;
case C_THUMBEXT:
case C_THUMBEXTFUNC:
case C_EXT:
- sym->set_aclass_index (LOC_STATIC);
+ sym->set_loc_class_index (LOC_STATIC);
sym->set_value_address ((CORE_ADDR) cs->c_value
+ objfile->section_offsets[SECT_OFF_TEXT (objfile)]);
add_symbol_to_list (sym, get_global_symbols ());
@@ -1679,7 +1678,7 @@ process_coff_symbol (struct coff_symbol *cs,
case C_THUMBSTAT:
case C_THUMBSTATFUNC:
case C_STAT:
- sym->set_aclass_index (LOC_STATIC);
+ sym->set_loc_class_index (LOC_STATIC);
sym->set_value_address ((CORE_ADDR) cs->c_value
+ objfile->section_offsets[SECT_OFF_TEXT (objfile)]);
if (within_function)
@@ -1698,7 +1697,7 @@ process_coff_symbol (struct coff_symbol *cs,
case C_GLBLREG:
#endif
case C_REG:
- sym->set_aclass_index (coff_register_index);
+ sym->set_loc_class_index (coff_register_index);
sym->set_value_longest (cs->c_value);
add_symbol_to_list (sym, get_local_symbols ());
break;
@@ -1708,20 +1707,20 @@ process_coff_symbol (struct coff_symbol *cs,
break;
case C_ARG:
- sym->set_aclass_index (LOC_ARG);
+ sym->set_loc_class_index (LOC_ARG);
sym->set_is_argument (1);
add_symbol_to_list (sym, get_local_symbols ());
break;
case C_REGPARM:
- sym->set_aclass_index (coff_register_index);
+ sym->set_loc_class_index (coff_register_index);
sym->set_is_argument (1);
sym->set_value_longest (cs->c_value);
add_symbol_to_list (sym, get_local_symbols ());
break;
case C_TPDEF:
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_domain (TYPE_DOMAIN);
/* If type has no name, give it one. */
@@ -1776,7 +1775,7 @@ process_coff_symbol (struct coff_symbol *cs,
case C_STRTAG:
case C_UNTAG:
case C_ENTAG:
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_domain (STRUCT_DOMAIN);
/* Some compilers try to be helpful by inventing "fake"
@@ -2165,7 +2164,7 @@ coff_read_enum_type (int index, int length, int lastsym,
name = obstack_strdup (&objfile->objfile_obstack, name);
sym->set_linkage_name (name);
- sym->set_aclass_index (LOC_CONST);
+ sym->set_loc_class_index (LOC_CONST);
sym->set_domain (VAR_DOMAIN);
sym->set_value_longest (ms->c_value);
add_symbol_to_list (sym, symlist);
@@ -2248,9 +2247,7 @@ static const struct sym_fns coff_sym_fns =
NULL, /* sym_probe_fns */
};
-void _initialize_coffread ();
-void
-_initialize_coffread ()
+INIT_GDB_FILE (coffread)
{
add_symtab_fns (bfd_target_coff_flavour, &coff_sym_fns);
diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c
index 0d32350..ac8888f 100644
--- a/gdb/compile/compile-c-support.c
+++ b/gdb/compile/compile-c-support.c
@@ -185,18 +185,18 @@ static void
write_macro_definitions (const struct block *block, CORE_ADDR pc,
struct ui_file *file)
{
- gdb::unique_xmalloc_ptr<struct macro_scope> scope;
+ macro_scope scope;
if (block != NULL)
scope = sal_macro_scope (find_pc_line (pc, 0));
else
scope = default_macro_scope ();
- if (scope == NULL)
+ if (!scope.is_valid ())
scope = user_macro_scope ();
- if (scope != NULL && scope->file != NULL && scope->file->table != NULL)
+ if (scope.is_valid () && scope.file->table != nullptr)
{
- macro_for_each_in_scope (scope->file, scope->line,
+ macro_for_each_in_scope (scope.file, scope.line,
[&] (const char *name,
const macro_definition *macro,
macro_source_file *source,
diff --git a/gdb/compile/compile-c-symbols.c b/gdb/compile/compile-c-symbols.c
index b31592f..6578977 100644
--- a/gdb/compile/compile-c-symbols.c
+++ b/gdb/compile/compile-c-symbols.c
@@ -61,7 +61,7 @@ convert_one_symbol (compile_c_instance *context,
context->error_symbol_once (sym.symbol);
- if (sym.symbol->aclass () == LOC_LABEL)
+ if (sym.symbol->loc_class () == LOC_LABEL)
sym_type = 0;
else
sym_type = context->convert_type (sym.symbol->type ());
@@ -79,7 +79,7 @@ convert_one_symbol (compile_c_instance *context,
CORE_ADDR addr = 0;
gdb::unique_xmalloc_ptr<char> symbol_name;
- switch (sym.symbol->aclass ())
+ switch (sym.symbol->loc_class ())
{
case LOC_TYPEDEF:
kind = GCC_C_SYMBOL_TYPEDEF;
@@ -536,7 +536,7 @@ generate_c_for_for_one_variable (compile_instance *compiler,
}
else
{
- switch (sym->aclass ())
+ switch (sym->loc_class ())
{
case LOC_REGISTER:
case LOC_ARG:
diff --git a/gdb/compile/compile-cplus-symbols.c b/gdb/compile/compile-cplus-symbols.c
index b03c4b9..96ebd84 100644
--- a/gdb/compile/compile-cplus-symbols.c
+++ b/gdb/compile/compile-cplus-symbols.c
@@ -53,7 +53,7 @@ convert_one_symbol (compile_cplus_instance *instance,
instance->error_symbol_once (sym.symbol);
- if (sym.symbol->aclass () == LOC_LABEL)
+ if (sym.symbol->loc_class () == LOC_LABEL)
sym_type = 0;
else
sym_type = instance->convert_type (sym.symbol->type ());
@@ -70,7 +70,7 @@ convert_one_symbol (compile_cplus_instance *instance,
std::string name;
gdb::unique_xmalloc_ptr<char> symbol_name;
- switch (sym.symbol->aclass ())
+ switch (sym.symbol->loc_class ())
{
case LOC_TYPEDEF:
if (sym.symbol->type ()->code () == TYPE_CODE_TYPEDEF)
diff --git a/gdb/compile/compile-cplus-types.c b/gdb/compile/compile-cplus-types.c
index 56ef033..cf70fe4 100644
--- a/gdb/compile/compile-cplus-types.c
+++ b/gdb/compile/compile-cplus-types.c
@@ -1395,9 +1395,7 @@ gcc_cp_plugin::pop_binding_level (const char *debug_name)
return pop_binding_level ();
}
-void _initialize_compile_cplus_types ();
-void
-_initialize_compile_cplus_types ()
+INIT_GDB_FILE (compile_cplus_types)
{
add_setshow_boolean_cmd ("compile-cplus-types", no_class,
&debug_compile_cplus_types, _("\
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index ab4cb0b..5d81ec1 100644
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -45,6 +45,7 @@
#include "gdbsupport/pathstuff.h"
#include "gdbsupport/scoped_ignore_signal.h"
#include "gdbsupport/buildargv.h"
+#include "gdbsupport/cleanups.h"
/* Hold "compile" commands. */
@@ -868,9 +869,7 @@ compile_command (const char *args, int from_tty)
/* See compile.h. */
cmd_list_element *compile_cmd_element = nullptr;
-void _initialize_compile ();
-void
-_initialize_compile ()
+INIT_GDB_FILE (compile)
{
compile_cmd_element = add_prefix_cmd ("compile", class_obscure,
compile_command,
diff --git a/gdb/complaints.c b/gdb/complaints.c
index 2f58af2..3c7f9bc 100644
--- a/gdb/complaints.c
+++ b/gdb/complaints.c
@@ -188,9 +188,7 @@ test_complaints ()
} /* namespace selftests */
#endif /* GDB_SELF_TEST */
-void _initialize_complaints ();
-void
-_initialize_complaints ()
+INIT_GDB_FILE (complaints)
{
add_setshow_zinteger_cmd ("complaints", class_support,
&stop_whining, _("\
diff --git a/gdb/completer.c b/gdb/completer.c
index 658a0c6..b919b4c 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -1008,7 +1008,7 @@ complete_files_symbols (completion_tracker &tracker,
name, they cannot be asking for completion on files. */
if (strcspn (text, gdb_completer_file_name_break_characters)
== text_len)
- fn_list = make_source_files_completion_list (text, text);
+ fn_list = make_source_files_completion_list (text);
}
if (!fn_list.empty () && !tracker.have_completions ())
@@ -1059,7 +1059,7 @@ complete_source_filenames (const char *text)
the user cannot be asking for completion on files. */
if (strcspn (text, gdb_completer_file_name_break_characters)
== text_len)
- return make_source_files_completion_list (text, text);
+ return make_source_files_completion_list (text);
return {};
}
@@ -1142,7 +1142,7 @@ collect_explicit_location_matches (completion_tracker &tracker,
const char *source
= string_or_empty (explicit_loc->source_filename.get ());
completion_list matches
- = make_source_files_completion_list (source, source);
+ = make_source_files_completion_list (source);
tracker.add_completions (std::move (matches));
}
break;
@@ -3006,7 +3006,7 @@ gdb_printable_part (char *pathname)
temp = strrchr (pathname, '/');
#if defined (__MSDOS__)
- if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':')
+ if (temp == 0 && c_isalpha (pathname[0]) && pathname[1] == ':')
temp = pathname + 1;
#endif
@@ -3513,9 +3513,7 @@ skip_over_slash_fmt (completion_tracker &tracker, const char **args)
return false;
}
-void _initialize_completer ();
-void
-_initialize_completer ()
+INIT_GDB_FILE (completer)
{
/* Setup some readline completion globals. */
rl_completion_word_break_hook = gdb_completion_word_break_characters;
diff --git a/gdb/config.in b/gdb/config.in
index 426947e..efc3100 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -39,6 +39,9 @@
/* Define to BFD's default target vector. */
#undef DEFAULT_BFD_VEC
+/* defined if dwarf format was requested. */
+#undef DWARF_FORMAT_AVAILABLE
+
/* Handle .ctf type-info sections */
#undef ENABLE_LIBCTF
@@ -93,6 +96,9 @@
/* Define if amd-dbgapi is being linked in. */
#undef HAVE_AMD_DBGAPI
+/* Define to 1 if you have the <asm/termios.h> header file. */
+#undef HAVE_ASM_TERMIOS_H
+
/* Define to 1 if you have the `btowc' function. */
#undef HAVE_BTOWC
@@ -244,6 +250,9 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
+/* Define to 1 if you have the <IOKit/serial/ioss.h> header file. */
+#undef HAVE_IOKIT_SERIAL_IOSS_H
+
/* Define to 1 if you have the `kinfo_getfile' function. */
#undef HAVE_KINFO_GETFILE
@@ -639,6 +648,9 @@
*/
#undef LT_OBJDIR
+/* defined if mdebug format was requested. */
+#undef MDEBUG_FORMAT_AVAILABLE
+
/* Name of this package. */
#undef PACKAGE
@@ -733,6 +745,9 @@
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
+/* Which binary file formats were requested at configure time. */
+#undef SUPPORTED_BINARY_FILE_FORMATS
+
/* automatically load a system-wide gdbinit file */
#undef SYSTEM_GDBINIT
diff --git a/gdb/configure b/gdb/configure
index 5ee1982..d0bdba6 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -706,6 +706,7 @@ LIBGUI
LTLIBLZMA
LIBLZMA
HAVE_LIBLZMA
+FORMAT_SRCS
SER_HARDWIRE
WERROR_CFLAGS
WARN_CFLAGS
@@ -932,6 +933,9 @@ with_relocated_sources
with_auto_load_dir
with_auto_load_safe_path
enable_targets
+enable_binary_file_formats
+enable_gdb_mdebug_support
+enable_gdb_dwarf_support
with_amd_dbgapi
enable_tui
enable_gdbtk
@@ -1643,6 +1647,16 @@ Optional Features:
--disable-nls do not use Native Language Support
--enable-targets=TARGETS
alternative target configurations
+ --enable-binary-file-formats=FORMATS
+ enable support for selected file formats (default
+ 'all') available formats: coff, dbx, elf, macho,
+ mips, xcoff, all
+ --enable-gdb-mdebug-support
+ Enable support for the mdebug debuginfo format
+ (default 'yes')
+ --enable-gdb-dwarf-support
+ Enable support for the dwarf debuginfo format
+ (default 'yes')
--enable-tui enable full-screen terminal user interface (TUI)
--enable-gdbtk enable gdbtk graphical user interface (GUI)
--enable-profiling enable profiling of GDB
@@ -11499,7 +11513,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11502 "configure"
+#line 11516 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11605,7 +11619,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11608 "configure"
+#line 11622 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -19223,118 +19237,6 @@ fi
# Set the 'development' global.
. $srcdir/../bfd/development.sh
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-
-fi
-
# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
# for constant arguments. Useless!
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5
@@ -24874,6 +24776,68 @@ esac
fi
+# Check whether --enable-binary_file_formats was given.
+if test "${enable_binary_file_formats+set}" = set; then :
+ enableval=$enable_binary_file_formats; case "${enableval}" in
+ yes | "") as_fn_error $? "enable-binary-file-formats option must specify file formats or 'all'" "$LINENO" 5
+ ;;
+ no) enable_binary_file_formats= ;;
+ *) enable_binary_file_formats=$enableval ;;
+esac
+else
+ enable_binary_file_formats=all
+fi
+
+
+# Check whether to support mdebug/ecoff debug information.
+# Check whether --enable-gdb-mdebug-support was given.
+if test "${enable_gdb_mdebug_support+set}" = set; then :
+ enableval=$enable_gdb_mdebug_support;
+ case $enableval in
+ yes | no)
+ ;;
+ *)
+ as_fn_error $? "bad value $enableval for --enable-gdb-mdebug-support" "$LINENO" 5
+ ;;
+ esac
+
+else
+ enable_gdb_mdebug_support=yes
+fi
+
+
+if test "x${enable_gdb_mdebug_support}" != "xno"; then
+ CONFIG_SRCS="$CONFIG_SRCS mdebugread.c"
+ CONFIG_OBS="$CONFIG_OBS mdebugread.o"
+
+$as_echo "#define MDEBUG_FORMAT_AVAILABLE 1" >>confdefs.h
+
+fi
+
+# Check whether to support dwarf debug information
+# Check whether --enable-gdb-dwarf-support was given.
+if test "${enable_gdb_dwarf_support+set}" = set; then :
+ enableval=$enable_gdb_dwarf_support;
+ case $enableval in
+ yes | no)
+ ;;
+ *)
+ as_fn_error $? "bad value $enableval for --enable-gdb-dwarf-support" "$LINENO" 5
+ ;;
+ esac
+
+else
+ enable_gdb_dwarf_support=yes
+fi
+
+
+if test "x${enable_gdb_dwarf_support}" != "xno"; then
+
+$as_echo "#define DWARF_FORMAT_AVAILABLE 1" >>confdefs.h
+
+ CONFIG_SRCS="$CONFIG_SRCS \$(DWARF2_SRCS)"
+ CONFIG_OBS="$CONFIG_OBS \$(DWARF2_OBS)"
+fi
# See whether 64-bit bfd lib has been enabled.
OLD_CPPFLAGS=$CPPFLAGS
@@ -24928,10 +24892,21 @@ TARGET_OBS=
all_targets=
HAVE_NATIVE_GCORE_TARGET=
+# File formats that will be enabled based on the selected
+# target(s). These are chosen because they are required to
+# compile one or more of the selected targets.
+target_formats=
+
+# If all targets were requested, this is all formats that should
+# accompany them. These are just the ones required for compilation
+# to succeed, not the formats suggested based on targets.
+all_target_formats="coff xcoff"
+
for targ_alias in `echo $target_alias $enable_targets | sed 's/,/ /g'`
do
if test "$targ_alias" = "all"; then
all_targets=true
+ target_formats=$all_target_formats
else
# Canonicalize the secondary target names.
result=`$ac_config_sub $targ_alias 2>/dev/null`
@@ -28167,8 +28142,8 @@ int
main ()
{
- #if PY_MAJOR_VERSION != 3
- # error "We only support Python 3"
+ #if PY_VERSION_HEX < 0x03040000
+ # error "Minimum supported Python version is 3.4"
#endif
Py_Initialize ();
@@ -28944,11 +28919,20 @@ if test "${enable_gdb_compile+set}" = set; then :
esac
else
- enable_gdb_compile=yes
+ enable_gdb_compile=default
fi
-if test "${enable_gdb_compile}" = yes; then
+if test "${enable_gdb_compile}" = "default"; then
+ enable_gdb_compile=${enable_gdb_dwarf_support}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Defaulting compile support to '${enable_gdb_dwarf_support}'" >&5
+$as_echo "$as_me: WARNING: Defaulting compile support to '${enable_gdb_dwarf_support}'" >&2;}
+fi
+
+if test "${enable_gdb_compile}" = "yes"; then
+ if test "${enable_gdb_dwarf_support}" = "no"; then
+ as_fn_error $? "enabling gdb compile requires dwarf support" "$LINENO" 5
+ fi
$as_echo "#define HAVE_COMPILE 1" >>confdefs.h
@@ -29083,119 +29067,9 @@ fi
# Checks for header files. #
# ------------------------- #
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-
-fi
-
for ac_header in \
+ IOKit/serial/ioss.h \
+ asm/termios.h \
machine/reg.h \
nlist.h \
ptrace.h \
@@ -31559,6 +31433,12 @@ fi
# Note that WIN32APILIBS is set by GDB_AC_COMMON.
WIN32LIBS="$WIN32LIBS $WIN32APILIBS"
+# Object files to be used when building with support for all file formats.
+# This should not have elf or macho, as support for those formats depends
+# on BFD enabling them as well.
+all_binary_file_srcs="\$(dbx_SRCS) \$(mips_SRCS) \$(coff_SRCS) \$(xcoff_SRCS)"
+
+bfd_supports_elf=no
# Add ELF support to GDB, but only if BFD includes ELF support.
OLD_CFLAGS=$CFLAGS
@@ -31576,7 +31456,7 @@ WIN32LIBS="$WIN32LIBS $WIN32APILIBS"
CC="./libtool --quiet --mode=link $CC"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ELF support in BFD" >&5
$as_echo_n "checking for ELF support in BFD... " >&6; }
-if ${gdb_cv_var_elf+:} false; then :
+if ${gdb_cv_var_bfd_elf+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -31595,28 +31475,27 @@ return bfd_get_elf_phdr_upper_bound (NULL);
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- gdb_cv_var_elf=yes
+ gdb_cv_var_bfd_elf=yes
else
- gdb_cv_var_elf=no
+ gdb_cv_var_bfd_elf=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_var_elf" >&5
-$as_echo "$gdb_cv_var_elf" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_var_bfd_elf" >&5
+$as_echo "$gdb_cv_var_bfd_elf" >&6; }
CC=$OLD_CC
CFLAGS=$OLD_CFLAGS
LDFLAGS=$OLD_LDFLAGS
LIBS=$OLD_LIBS
-if test "$gdb_cv_var_elf" = yes; then
- CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o dtrace-probe.o \
- gcore-elf.o elf-none-tdep.o"
+if test "$gdb_cv_var_bfd_elf" = yes; then
+ CONFIG_OBS="$CONFIG_OBS gcore-elf.o elf-none-tdep.o"
$as_echo "#define HAVE_ELF 1" >>confdefs.h
- # -ldl is provided by bfd/Makfile.am (LIBDL) <PLUGINS>.
+ # -ldl is provided by bfd/Makefile.am (LIBDL) <PLUGINS>.
if test "$plugins" = "yes"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
$as_echo_n "checking for library containing dlopen... " >&6; }
@@ -31675,9 +31554,12 @@ if test "$ac_res" != no; then :
fi
fi
+ bfd_supports_elf=yes
+ all_binary_file_srcs="$all_binary_file_srcs \$(elf_SRCS)"
fi
# Add macho support to GDB, but only if BFD includes it.
+bfd_supports_macho=no
OLD_CFLAGS=$CFLAGS
OLD_LDFLAGS=$LDFLAGS
@@ -31694,7 +31576,7 @@ fi
CC="./libtool --quiet --mode=link $CC"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Mach-O support in BFD" >&5
$as_echo_n "checking for Mach-O support in BFD... " >&6; }
-if ${gdb_cv_var_macho+:} false; then :
+if ${gdb_cv_var_bfd_macho+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -31713,30 +31595,81 @@ return bfd_mach_o_lookup_command (NULL, 0, NULL);
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- gdb_cv_var_macho=yes
+ gdb_cv_var_bfd_macho=yes
else
- gdb_cv_var_macho=no
+ gdb_cv_var_bfd_macho=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_var_macho" >&5
-$as_echo "$gdb_cv_var_macho" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_var_bfd_macho" >&5
+$as_echo "$gdb_cv_var_bfd_macho" >&6; }
CC=$OLD_CC
CFLAGS=$OLD_CFLAGS
LDFLAGS=$OLD_LDFLAGS
LIBS=$OLD_LIBS
-if test "$gdb_cv_var_macho" = yes; then
- CONFIG_OBS="$CONFIG_OBS machoread.o"
+if test "$gdb_cv_var_bfd_macho" = yes; then
+ bfd_supports_macho=yes
+ all_binary_file_srcs="$all_binary_file_srcs \$(macho_SRCS)"
fi
+FORMAT_SRCS=
+
+if test "$enable_binary_file_formats" != "all"; then
+ # Formats that are required by some requested target(s).
+ # Warn users that they are added, so no one is surprised.
+ for req in $target_formats; do
+ case ,$enable_binary_file_formats, in
+ *,$req,*)
+ # Do nothing.
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"$req is required to support one or more requested targets. Adding it\"" >&5
+$as_echo "$as_me: WARNING: \"$req is required to support one or more requested targets. Adding it\"" >&2;}
+ enable_binary_file_formats="${enable_binary_file_formats},$req"
+ ;;
+ esac
+ done
+
+
+cat >>confdefs.h <<_ACEOF
+#define SUPPORTED_BINARY_FILE_FORMATS "$enable_binary_file_formats"
+_ACEOF
+
+fi
+
+enable_binary_file_formats=$(echo $enable_binary_file_formats | sed 's/,/ /g')
+
+# Go through all requested and required binary file formats to compile
+# GDB, and double check that we can compile them.
+for format in $enable_binary_file_formats
+do
+ if test "$format" = "elf" && test "$bfd_supports_elf" != "yes"; then
+ as_fn_error but BFD does not support it." "\"elf support was requested" "$LINENO" 5;
+ elif test "$format" = "macho" && test "$bfd_supports_macho" != "yes"; then
+ as_fn_error but BFD does not support it." "\"Mach-O support was requested" "$LINENO" 5;
+ fi
+
+ if test "$format" = "all"; then
+ FORMAT_SRCS="$all_binary_file_srcs"
+ # We don't break here in case the user requested Mach-O or ELF, but
+ # BFD is not configured to support it. If we were to break, we would
+ # silently drop the requested support instead of erroring out.
+ else
+ fmt=$(echo "$format _SRCS" | sed 's/ //')
+ FORMAT_SRCS="$FORMAT_SRCS \$($fmt)"
+ fi
+done
+
+
+
# Add any host-specific objects to GDB.
CONFIG_OBS="${CONFIG_OBS} ${gdb_host_obs}"
# If building on ELF, look for lzma support for embedded compressed debug info.
-if test "$gdb_cv_var_elf" = yes; then
+if test "$gdb_cv_var_bfd_elf" = yes; then
# Check whether --with-lzma was given.
if test "${with_lzma+set}" = set; then :
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 5870a61..5292410 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -191,6 +191,44 @@ AS_HELP_STRING([--enable-targets=TARGETS], [alternative target configurations]),
;;
esac])
+AC_ARG_ENABLE(binary_file_formats,
+ AS_HELP_STRING([--enable-binary-file-formats=FORMATS],
+ [enable support for selected file formats (default 'all')
+ available formats: coff, dbx, elf, macho, mips, xcoff, all]),
+[case "${enableval}" in
+ yes | "") AC_MSG_ERROR(enable-binary-file-formats option must specify file formats or 'all')
+ ;;
+ no) enable_binary_file_formats= ;;
+ *) enable_binary_file_formats=$enableval ;;
+esac], [enable_binary_file_formats=all])
+
+# Check whether to support mdebug/ecoff debug information.
+AC_ARG_ENABLE(gdb-mdebug-support,
+AS_HELP_STRING([--enable-gdb-mdebug-support],
+ [Enable support for the mdebug debuginfo format (default 'yes')]),
+[GDB_CHECK_YES_NO_VAL([$enableval], [--enable-gdb-mdebug-support])],
+[enable_gdb_mdebug_support=yes])
+
+if test "x${enable_gdb_mdebug_support}" != "xno"; then
+ CONFIG_SRCS="$CONFIG_SRCS mdebugread.c"
+ CONFIG_OBS="$CONFIG_OBS mdebugread.o"
+ AC_DEFINE(MDEBUG_FORMAT_AVAILABLE, 1,
+ [defined if mdebug format was requested.])
+fi
+
+# Check whether to support dwarf debug information
+AC_ARG_ENABLE(gdb-dwarf-support,
+AS_HELP_STRING([--enable-gdb-dwarf-support],
+ [Enable support for the dwarf debuginfo format (default 'yes')]),
+[GDB_CHECK_YES_NO_VAL([$enableval], [--enable-gdb-dwarf-support])],
+[enable_gdb_dwarf_support=yes])
+
+if test "x${enable_gdb_dwarf_support}" != "xno"; then
+ AC_DEFINE(DWARF_FORMAT_AVAILABLE, 1,
+ [defined if dwarf format was requested.])
+ CONFIG_SRCS="$CONFIG_SRCS \$(DWARF2_SRCS)"
+ CONFIG_OBS="$CONFIG_OBS \$(DWARF2_OBS)"
+fi
BFD_64_BIT
@@ -212,10 +250,21 @@ TARGET_OBS=
all_targets=
HAVE_NATIVE_GCORE_TARGET=
+# File formats that will be enabled based on the selected
+# target(s). These are chosen because they are required to
+# compile one or more of the selected targets.
+target_formats=
+
+# If all targets were requested, this is all formats that should
+# accompany them. These are just the ones required for compilation
+# to succeed, not the formats suggested based on targets.
+all_target_formats="coff xcoff"
+
for targ_alias in `echo $target_alias $enable_targets | sed 's/,/ /g'`
do
if test "$targ_alias" = "all"; then
all_targets=true
+ target_formats=$all_target_formats
else
# Canonicalize the secondary target names.
result=`$ac_config_sub $targ_alias 2>/dev/null`
@@ -740,8 +789,8 @@ AC_DEFUN([AC_TRY_LIBPYTHON],
found_usable_python=no
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "Python.h"]],
[[
- #if PY_MAJOR_VERSION != 3
- # error "We only support Python 3"
+ #if PY_VERSION_HEX < 0x03040000
+ # error "Minimum supported Python version is 3.4"
#endif
Py_Initialize ();
]])],
@@ -1220,9 +1269,17 @@ AC_ARG_ENABLE([gdb-compile],
AS_HELP_STRING([--enable-gdb-compile],
[enable support for the compile subsystem, default 'yes']),
[GDB_CHECK_YES_NO_VAL([$enableval], [--enable-gdb-compile])],
- [enable_gdb_compile=yes])
+ [enable_gdb_compile=default])
-if test "${enable_gdb_compile}" = yes; then
+if test "${enable_gdb_compile}" = "default"; then
+ enable_gdb_compile=${enable_gdb_dwarf_support}
+ AC_MSG_WARN([Defaulting compile support to '${enable_gdb_dwarf_support}'])
+fi
+
+if test "${enable_gdb_compile}" = "yes"; then
+ if test "${enable_gdb_dwarf_support}" = "no"; then
+ AC_MSG_ERROR([enabling gdb compile requires dwarf support])
+ fi
AC_DEFINE(HAVE_COMPILE, 1, [Define if compiling support to gdb compile.])
CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_GCC_COMPILE_OBS)"
else
@@ -1319,8 +1376,9 @@ AC_SUBST(SRCHIGH_CFLAGS)
# Checks for header files. #
# ------------------------- #
-AC_HEADER_STDC
AC_CHECK_HEADERS([ \
+ IOKit/serial/ioss.h \
+ asm/termios.h \
machine/reg.h \
nlist.h \
ptrace.h \
@@ -1914,32 +1972,87 @@ fi
# Note that WIN32APILIBS is set by GDB_AC_COMMON.
WIN32LIBS="$WIN32LIBS $WIN32APILIBS"
+# Object files to be used when building with support for all file formats.
+# This should not have elf or macho, as support for those formats depends
+# on BFD enabling them as well.
+all_binary_file_srcs="\$(dbx_SRCS) \$(mips_SRCS) \$(coff_SRCS) \$(xcoff_SRCS)"
+
+bfd_supports_elf=no
# Add ELF support to GDB, but only if BFD includes ELF support.
-GDB_AC_CHECK_BFD([for ELF support in BFD], gdb_cv_var_elf,
+GDB_AC_CHECK_BFD([for ELF support in BFD], gdb_cv_var_bfd_elf,
[bfd_get_elf_phdr_upper_bound (NULL)], elf-bfd.h)
-if test "$gdb_cv_var_elf" = yes; then
- CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o dtrace-probe.o \
- gcore-elf.o elf-none-tdep.o"
+if test "$gdb_cv_var_bfd_elf" = yes; then
+ CONFIG_OBS="$CONFIG_OBS gcore-elf.o elf-none-tdep.o"
AC_DEFINE(HAVE_ELF, 1,
[Define if ELF support should be included.])
- # -ldl is provided by bfd/Makfile.am (LIBDL) <PLUGINS>.
+ # -ldl is provided by bfd/Makefile.am (LIBDL) <PLUGINS>.
if test "$plugins" = "yes"; then
AC_SEARCH_LIBS(dlopen, dl)
fi
+ bfd_supports_elf=yes
+ all_binary_file_srcs="$all_binary_file_srcs \$(elf_SRCS)"
fi
# Add macho support to GDB, but only if BFD includes it.
-GDB_AC_CHECK_BFD([for Mach-O support in BFD], gdb_cv_var_macho,
+bfd_supports_macho=no
+GDB_AC_CHECK_BFD([for Mach-O support in BFD], gdb_cv_var_bfd_macho,
[bfd_mach_o_lookup_command (NULL, 0, NULL)], mach-o.h)
-if test "$gdb_cv_var_macho" = yes; then
- CONFIG_OBS="$CONFIG_OBS machoread.o"
+if test "$gdb_cv_var_bfd_macho" = yes; then
+ bfd_supports_macho=yes
+ all_binary_file_srcs="$all_binary_file_srcs \$(macho_SRCS)"
+fi
+
+FORMAT_SRCS=
+
+if test "$enable_binary_file_formats" != "all"; then
+ # Formats that are required by some requested target(s).
+ # Warn users that they are added, so no one is surprised.
+ for req in $target_formats; do
+ case ,$enable_binary_file_formats, in
+ *,$req,*)
+ # Do nothing.
+ ;;
+ *)
+ AC_MSG_WARN("$req is required to support one or more requested targets. Adding it")
+ enable_binary_file_formats="${enable_binary_file_formats},$req"
+ ;;
+ esac
+ done
+
+ AC_DEFINE_UNQUOTED(SUPPORTED_BINARY_FILE_FORMATS, "$enable_binary_file_formats",
+ Which binary file formats were requested at configure time. )
fi
+enable_binary_file_formats=$(echo $enable_binary_file_formats | sed 's/,/ /g')
+
+# Go through all requested and required binary file formats to compile
+# GDB, and double check that we can compile them.
+for format in $enable_binary_file_formats
+do
+ if test "$format" = "elf" && test "$bfd_supports_elf" != "yes"; then
+ AC_MSG_ERROR("elf support was requested, but BFD does not support it.");
+ elif test "$format" = "macho" && test "$bfd_supports_macho" != "yes"; then
+ AC_MSG_ERROR("Mach-O support was requested, but BFD does not support it.");
+ fi
+
+ if test "$format" = "all"; then
+ FORMAT_SRCS="$all_binary_file_srcs"
+ # We don't break here in case the user requested Mach-O or ELF, but
+ # BFD is not configured to support it. If we were to break, we would
+ # silently drop the requested support instead of erroring out.
+ else
+ fmt=$(echo "$format _SRCS" | sed 's/ //')
+ FORMAT_SRCS="$FORMAT_SRCS \$($fmt)"
+ fi
+done
+
+AC_SUBST(FORMAT_SRCS)
+
# Add any host-specific objects to GDB.
CONFIG_OBS="${CONFIG_OBS} ${gdb_host_obs}"
# If building on ELF, look for lzma support for embedded compressed debug info.
-if test "$gdb_cv_var_elf" = yes; then
+if test "$gdb_cv_var_bfd_elf" = yes; then
AC_ARG_WITH(lzma,
AS_HELP_STRING([--with-lzma], [support lzma compression (auto/yes/no)]),
[], [with_lzma=auto])
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index e9b3068..34ae503 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -150,14 +150,15 @@ aarch64*-*-linux*)
arch/aarch64-scalable-linux.o \
arch/arm.o arch/arm-linux.o arch/arm-get-next-pcs.o \
arm-tdep.o arm-linux-tdep.o \
- glibc-tdep.o linux-tdep.o solib-svr4.o svr4-tls-tdep.o \
+ glibc-tdep.o linux-tdep.o solib-svr4.o \
+ solib-svr4-linux.o svr4-tls-tdep.o \
symfile-mem.o linux-record.o"
;;
alpha*-*-linux*)
# Target: Little-endian Alpha running Linux
gdb_target_obs="alpha-mdebug-tdep.o alpha-linux-tdep.o \
- linux-tdep.o solib-svr4.o"
+ linux-tdep.o solib-svr4.o solib-svr4-linux.o"
;;
alpha*-*-netbsd* | alpha*-*-knetbsd*-gnu)
# Target: NetBSD/alpha
@@ -179,7 +180,7 @@ amdgcn*-*-*)
am33_2.0*-*-linux*)
# Target: Matsushita mn10300 (AM33) running Linux
gdb_target_obs="mn10300-tdep.o mn10300-linux-tdep.o linux-tdep.o \
- solib-svr4.o"
+ solib-svr4.o solib-svr4-linux.o"
;;
arc*-*-elf32)
@@ -189,7 +190,8 @@ arc*-*-elf32)
arc*-*-linux*)
# Target: ARC machine running Linux
- gdb_target_obs="arc-linux-tdep.o linux-tdep.o solib-svr4.o"
+ gdb_target_obs="arc-linux-tdep.o linux-tdep.o solib-svr4.o \
+ solib-svr4-linux.o"
;;
arm*-wince-pe | arm*-*-mingw32ce*)
@@ -199,7 +201,8 @@ arm*-wince-pe | arm*-*-mingw32ce*)
arm*-*-linux*)
# Target: ARM based machine running GNU/Linux
gdb_target_obs="arch/arm-linux.o arm-linux-tdep.o glibc-tdep.o \
- solib-svr4.o symfile-mem.o linux-tdep.o linux-record.o"
+ solib-svr4.o solib-svr4-linux.o symfile-mem.o \
+ linux-tdep.o linux-record.o"
;;
arm*-*-freebsd*)
# Target: FreeBSD/arm
@@ -239,13 +242,14 @@ bpf-*-*)
cris*)
# Target: CRIS
- gdb_target_obs="cris-tdep.o cris-linux-tdep.o linux-tdep.o solib-svr4.o"
+ gdb_target_obs="cris-tdep.o cris-linux-tdep.o linux-tdep.o \
+ solib-svr4.o solib-svr4-linux.o"
;;
csky*-*-linux*)
# Target: CSKY running GNU/Linux
gdb_target_obs="csky-tdep.o csky-linux-tdep.o glibc-tdep.o \
- linux-tdep.o solib-svr4.o"
+ linux-tdep.o solib-svr4.o solib-svr4-linux.o"
;;
csky*-*-*)
@@ -270,7 +274,8 @@ h8300-*-*)
hppa*-*-linux*)
# Target: HP PA-RISC running Linux
gdb_target_obs="hppa-linux-tdep.o glibc-tdep.o \
- linux-tdep.o solib-svr4.o symfile-mem.o"
+ linux-tdep.o solib-svr4.o solib-svr4-linux.o \
+ symfile-mem.o"
;;
hppa*-*-netbsd*)
# Target: NetBSD/hppa
@@ -315,13 +320,13 @@ i[34567]86-*-linux*)
# Target: Intel 386 running GNU/Linux
gdb_target_obs="i386-linux-tdep.o \
glibc-tdep.o \
- solib-svr4.o symfile-mem.o \
+ solib-svr4.o solib-svr4-linux.o symfile-mem.o \
linux-tdep.o linux-record.o \
arch/i386-linux-tdesc.o \
arch/x86-linux-tdesc-features.o"
if test "x$have_64_bit_bfd" = "xyes"; then
# Target: GNU/Linux x86-64
- gdb_target_obs="amd64-linux-tdep.o \
+ gdb_target_obs="amd64-linux-tdep.o svr4-tls-tdep.o \
arch/amd64-linux-tdesc.o ${gdb_target_obs}"
fi
;;
@@ -345,7 +350,7 @@ i[34567]86-*-go32* | i[34567]86-*-msdosdjgpp*)
ia64-*-linux*)
# Target: Intel IA-64 running GNU/Linux
gdb_target_obs="ia64-linux-tdep.o linux-tdep.o \
- solib-svr4.o symfile-mem.o"
+ solib-svr4.o solib-svr4-linux.o symfile-mem.o"
;;
ia64-*-*vms*)
# Target: Intel IA-64 running OpenVMS
@@ -363,7 +368,8 @@ lm32-*-*)
loongarch*-*-linux*)
# Target: LoongArch running Linux
gdb_target_obs="loongarch-linux-tdep.o glibc-tdep.o \
- linux-tdep.o solib-svr4.o linux-record.o"
+ linux-tdep.o solib-svr4.o solib-svr4-linux.o \
+ linux-record.o"
;;
m32c-*-*)
@@ -374,8 +380,8 @@ m32c-*-*)
m32r*-*-linux*)
# Target: Renesas M32R running GNU/Linux
gdb_target_obs="m32r-tdep.o m32r-linux-tdep.o \
- glibc-tdep.o solib-svr4.o symfile-mem.o \
- linux-tdep.o"
+ glibc-tdep.o solib-svr4.o solib-svr4-linux.o \
+ symfile-mem.o linux-tdep.o"
;;
m32r*-*-*)
# Target: Renesas m32r processor
@@ -395,7 +401,8 @@ fido-*-elf*)
m68*-*-linux*)
# Target: Motorola m68k with a.out and ELF
gdb_target_obs="m68k-tdep.o m68k-linux-tdep.o solib-svr4.o \
- linux-tdep.o glibc-tdep.o symfile-mem.o"
+ solib-svr4-linux.o linux-tdep.o glibc-tdep.o \
+ symfile-mem.o"
;;
m68*-*-netbsd* | m68*-*-knetbsd*-gnu)
# Target: NetBSD/m68k
@@ -415,7 +422,7 @@ mep-*-*)
microblaze*-linux-*|microblaze*-*-linux*)
# Target: Xilinx MicroBlaze running Linux
gdb_target_obs="microblaze-tdep.o microblaze-linux-tdep.o solib-svr4.o \
- symfile-mem.o linux-tdep.o"
+ solib-svr4-linux.o symfile-mem.o linux-tdep.o"
;;
microblaze*-*-*)
# Target: Xilinx MicroBlaze running standalone
@@ -425,7 +432,8 @@ microblaze*-*-*)
mips*-*-linux*)
# Target: Linux/MIPS
gdb_target_obs="mips-tdep.o mips-linux-tdep.o glibc-tdep.o \
- solib-svr4.o symfile-mem.o linux-tdep.o"
+ solib-svr4.o solib-svr4-linux.o symfile-mem.o \
+ linux-tdep.o"
;;
mips*-*-netbsd* | mips*-*-knetbsd*-gnu)
# Target: MIPS running NetBSD
@@ -469,7 +477,8 @@ nds32*-*-elf)
or1k*-*-linux*)
# Target: OpenCores OpenRISC 1000 32-bit running Linux
gdb_target_obs="or1k-tdep.o or1k-linux-tdep.o solib-svr4.o \
- symfile-mem.o glibc-tdep.o linux-tdep.o"
+ solib-svr4-linux.o symfile-mem.o glibc-tdep.o \
+ linux-tdep.o"
;;
or1k-*-* | or1knd-*-*)
@@ -496,14 +505,15 @@ powerpc-*-openbsd*)
;;
powerpc-*-aix* | rs6000-*-* | powerpc64-*-aix*)
# Target: PowerPC running AIX
- gdb_target_obs="rs6000-tdep.o rs6000-aix-tdep.o xcoffread.o \
+ gdb_target_obs="rs6000-tdep.o rs6000-aix-tdep.o \
ppc-sysv-tdep.o solib-aix.o \
ravenscar-thread.o ppc-ravenscar-thread.o"
;;
powerpc*-*-linux*)
# Target: PowerPC running Linux
gdb_target_obs="rs6000-tdep.o ppc-linux-tdep.o ppc-sysv-tdep.o \
- ppc64-tdep.o solib-svr4.o svr4-tls-tdep.o \
+ ppc64-tdep.o solib-svr4.o solib-svr4-linux.o \
+ svr4-tls-tdep.o \
glibc-tdep.o symfile-mem.o linux-tdep.o \
ravenscar-thread.o ppc-ravenscar-thread.o \
linux-record.o \
@@ -512,8 +522,8 @@ powerpc*-*-linux*)
powerpc-*-lynx*178)
# Target: PowerPC running Lynx178.
gdb_target_obs="rs6000-tdep.o rs6000-lynx178-tdep.o \
- xcoffread.o ppc-sysv-tdep.o \
- ravenscar-thread.o ppc-ravenscar-thread.o"
+ ppc-sysv-tdep.o ravenscar-thread.o \
+ ppc-ravenscar-thread.o"
;;
powerpc*-*-*)
# Target: PowerPC running eabi
@@ -524,6 +534,7 @@ powerpc*-*-*)
s390*-*-linux*)
# Target: S390 running Linux
gdb_target_obs="s390-linux-tdep.o s390-tdep.o solib-svr4.o \
+ solib-svr4-linux.o \
linux-tdep.o linux-record.o symfile-mem.o \
svr4-tls-tdep.o"
;;
@@ -536,7 +547,8 @@ riscv*-*-freebsd*)
riscv*-*-linux*)
# Target: Linux/RISC-V
gdb_target_obs="riscv-linux-tdep.o riscv-canonicalize-syscall-gen.o \
- glibc-tdep.o linux-tdep.o solib-svr4.o symfile-mem.o \
+ glibc-tdep.o linux-tdep.o solib-svr4.o solib-svr4-linux.o \
+ symfile-mem.o \
linux-record.o svr4-tls-tdep.o"
;;
@@ -558,7 +570,7 @@ rx-*-*)
sh*-*-linux*)
# Target: GNU/Linux Super-H
gdb_target_obs="sh-tdep.o sh-linux-tdep.o \
- solib-svr4.o symfile-mem.o \
+ solib-svr4.o solib-svr4-linux.o symfile-mem.o \
glibc-tdep.o linux-tdep.o"
;;
sh*-*-netbsd* | sh*-*-knetbsd*-gnu)
@@ -577,7 +589,8 @@ sh*)
sparc-*-linux*)
# Target: GNU/Linux SPARC
gdb_target_obs="sparc-tdep.o \
- sparc-linux-tdep.o solib-svr4.o symfile-mem.o \
+ sparc-linux-tdep.o solib-svr4.o solib-svr4-linux.o \
+ symfile-mem.o \
linux-tdep.o \
ravenscar-thread.o sparc-ravenscar-thread.o"
if test "x$have_64_bit_bfd" = "xyes"; then
@@ -590,7 +603,8 @@ sparc64-*-linux*)
# Target: GNU/Linux UltraSPARC
gdb_target_obs="sparc64-tdep.o \
sparc64-linux-tdep.o sparc-tdep.o \
- sparc-linux-tdep.o solib-svr4.o linux-tdep.o \
+ sparc-linux-tdep.o solib-svr4.o solib-svr4-linux.o \
+ linux-tdep.o \
ravenscar-thread.o sparc-ravenscar-thread.o"
;;
sparc*-*-freebsd* | sparc*-*-kfreebsd*-gnu)
@@ -658,6 +672,7 @@ tic6x-*-*)
tilegx-*-linux*)
# Target: TILE-Gx
gdb_target_obs="tilegx-tdep.o tilegx-linux-tdep.o solib-svr4.o \
+ solib-svr4-linux.o \
symfile-mem.o glibc-tdep.o linux-tdep.o"
;;
@@ -708,7 +723,8 @@ x86_64-*-linux*)
# Target: GNU/Linux x86-64
gdb_target_obs="amd64-linux-tdep.o ${i386_tobjs} \
i386-linux-tdep.o glibc-tdep.o svr4-tls-tdep.o \
- solib-svr4.o symfile-mem.o linux-tdep.o linux-record.o \
+ solib-svr4.o solib-svr4-linux.o symfile-mem.o \
+ linux-tdep.o linux-record.o \
arch/i386-linux-tdesc.o arch/amd64-linux-tdesc.o \
arch/x86-linux-tdesc-features.o"
;;
@@ -738,7 +754,7 @@ x86_64-*-rtems*)
;;
x86_64-*-gnu*)
# Target: x86_64 running the GNU Hurd
- gdb_target_obs="amd64-gnu-tdep.o glibc-tdep.o solib-svr4.o"
+ gdb_target_obs="amd64-gnu-tdep.o i386-gnu-tdep.o glibc-tdep.o solib-svr4.o"
;;
xtensa*-*-*linux*)
# Target: GNU/Linux Xtensa
@@ -819,3 +835,17 @@ for t in x ${gdb_target_obs}; do
gdb_have_gcore=true
fi
done
+
+# Decide which file formats are absolutely required based on
+# the requested targets. Warn later that they are added, in
+# case the user didn't manually request them, or all readers.
+# It's fine to add the same format multiple times since the
+# loop that reads the options to FORMAT_OBS will ensure that
+# they are only added once.
+for i in $gdb_target_obs; do
+ case "${i}" in
+ *"windows-tdep.o" ) target_formats="${target_formats} coff";;
+ "rs6000-aix-tdep.o" ) target_formats="${target_formats} xcoff";;
+ "rs6000-lynx178-tdep.o" ) target_formats="${target_formats} xcoff";;
+ esac
+done
diff --git a/gdb/contrib/ari/create-web-ari-in-src.sh b/gdb/contrib/ari/create-web-ari-in-src.sh
index 4ea0398..b479ce5 100644
--- a/gdb/contrib/ari/create-web-ari-in-src.sh
+++ b/gdb/contrib/ari/create-web-ari-in-src.sh
@@ -50,7 +50,7 @@ if [ -z "${tempdir}" ] ; then
fi
fi
-# Default location of generate index.hmtl web page.
+# Default location of generated index.html web page.
if [ -z "${webdir}" ] ; then
# Use 'branch' subdir name if Tag contains branch
if [ -f "${srcdir}/gdb/CVS/Tag" ] ; then
diff --git a/gdb/contrib/ari/gdb_ari.sh b/gdb/contrib/ari/gdb_ari.sh
index f539ed1..e10bbe0 100755
--- a/gdb/contrib/ari/gdb_ari.sh
+++ b/gdb/contrib/ari/gdb_ari.sh
@@ -60,7 +60,7 @@ Options:
-Werror Treat all problems as errors.
-Wall Report all problems.
-Wari Report problems that should be fixed in new code.
- -WCATEGORY Report problems in the specifed category. The category
+ -WCATEGORY Report problems in the specified category. The category
can be prefixed with "no-". Valid categories
are: ${all}
EOF
@@ -159,7 +159,7 @@ BEGIN {
PWD = "'`pwd`'"
}
-# Print the error message for BUG. Append SUPLEMENT if non-empty.
+# Print the error message for BUG. Append SUPPLEMENT if non-empty.
function print_bug(file,line,prefix,category,bug,doc,supplement, suffix,idx) {
if (print_idx) {
idx = bug ": "
diff --git a/gdb/contrib/ari/update-web-ari.sh b/gdb/contrib/ari/update-web-ari.sh
index 6e7b5ff..b9ef184 100644
--- a/gdb/contrib/ari/update-web-ari.sh
+++ b/gdb/contrib/ari/update-web-ari.sh
@@ -176,7 +176,7 @@ fi
# THIS HAS SUFFERED BIT ROT
if ${check_indent_p} && test -d "${srcdir}"
then
- printf "Analizing file indentation:" 1>&2
+ printf "Analyzing file indentation:" 1>&2
( cd "${srcdir}" && /bin/sh ${aridir}/gdb_find.sh ${project} | while read f
do
if /bin/sh ${aridir}/gdb_indent.sh < ${f} 2>/dev/null | cmp -s - ${f}
@@ -550,7 +550,7 @@ function print_heading (nb_file, where, bug_i) {
for (bug_i = 1; bug_i <= nr_bug; bug_i++) {
bug = i2bug[bug_i];
printf "<th>"
- # The title names are offset by one. Otherwize, when the browser
+ # The title names are offset by one. Otherwise, when the browser
# jumps to the name it leaves out half the relevant column.
#printf "<a name=\",%s\">&nbsp;</a>", bug
printf "<a name=\",%s\">&nbsp;</a>", i2bug[bug_i-1]
@@ -851,7 +851,7 @@ EOF
print_toc 0 -1 deprecate Deprecate <<EOF
Mechanisms that are a candidate for being made obsolete. Once core
GDB no longer depends on these mechanisms and/or there is a
-replacement available, these mechanims can be deprecated (adding the
+replacement available, these mechanisms can be deprecated (adding the
deprecated prefix) obsoleted (put into category obsolete) or deleted.
See obsolete and deprecated.
EOF
diff --git a/gdb/contrib/codespell-dictionary.txt b/gdb/contrib/codespell-dictionary.txt
new file mode 100644
index 0000000..09bc309
--- /dev/null
+++ b/gdb/contrib/codespell-dictionary.txt
@@ -0,0 +1 @@
+gdbsever->gdbserver
diff --git a/gdb/contrib/codespell-ignore-words.txt b/gdb/contrib/codespell-ignore-words.txt
index 2d6e13a..881b1d2 100644
--- a/gdb/contrib/codespell-ignore-words.txt
+++ b/gdb/contrib/codespell-ignore-words.txt
@@ -1,2 +1,3 @@
configury
SME
+Synopsys
diff --git a/gdb/contrib/setup.cfg b/gdb/contrib/setup.cfg
index d6be386..5541a01 100644
--- a/gdb/contrib/setup.cfg
+++ b/gdb/contrib/setup.cfg
@@ -4,6 +4,7 @@
skip = */ChangeLog*,*/configure,gdbsupport/Makefile.in,*.dat,*.eps,gdb/features/*.c,gdb/ada-casefold.h,gdb/copying.c,gdb/gdbarch-gen.h,gdb/gdbarch-gen.c,gdb/target-delegates-gen.c
ignore-words = gdb/contrib/codespell-ignore-words.txt
+dictionary = gdb/contrib/codespell-dictionary.txt,-
# Ignore all URLs.
uri-ignore-words-list = *
diff --git a/gdb/copying.c b/gdb/copying.c
index af465e5..a198030 100644
--- a/gdb/copying.c
+++ b/gdb/copying.c
@@ -639,9 +639,7 @@ show_warranty_command (const char *ignore, int from_tty)
gdb_printf ("\n");
}
-void _initialize_copying ();
-void
-_initialize_copying ()
+INIT_GDB_FILE (copying)
{
add_cmd ("copying", no_set_class, show_copying_command,
_("Conditions for redistributing copies of GDB."),
diff --git a/gdb/copyright.py b/gdb/copyright.py
index bd854dc..425b7d2 100755
--- a/gdb/copyright.py
+++ b/gdb/copyright.py
@@ -191,11 +191,20 @@ def main(argv: list[str]) -> int | None:
if BY_HAND:
print()
print(
- "\033[31mREMINDER: The following files must be updated by hand." "\033[0m"
+ "\033[31mREMINDER: The following files must be updated by hand:" "\033[0m"
)
for filename in BY_HAND:
print(" ", filename)
+ print()
+ print(
+ "\033[31mREMINDER: The following files contain code to print a copyright "
+ "notice at runtime, they must be updated by hand:\033[0m"
+ )
+ print(" gdb/top.c")
+ print(" gdbserver/gdbreplay.cc")
+ print(" gdbserver/server.cc")
+
############################################################################
#
diff --git a/gdb/corefile.c b/gdb/corefile.c
index 9f27f14..a2c75c0 100644
--- a/gdb/corefile.c
+++ b/gdb/corefile.c
@@ -391,9 +391,7 @@ set_gnutarget (const char *newtarget)
set_gnutarget_command (NULL, 0, NULL);
}
-void _initialize_core ();
-void
-_initialize_core ()
+INIT_GDB_FILE (core)
{
cmd_list_element *core_file_cmd
= add_cmd ("core-file", class_files, core_file_command, _("\
diff --git a/gdb/corelow.c b/gdb/corelow.c
index 4518781..29eafe8 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -37,7 +37,6 @@
#include "exec.h"
#include "readline/tilde.h"
#include "solib.h"
-#include "solist.h"
#include "filenames.h"
#include "progspace.h"
#include "objfiles.h"
@@ -452,11 +451,8 @@ core_target::build_file_mappings ()
const bfd_build_id *core_build_id
= build_id_bfd_get (current_program_space->core_bfd ());
- for (const auto &iter : mapped_files)
+ for (const auto &[filename, file_data] : mapped_files)
{
- const std::string &filename = iter.first;
- const mapped_file &file_data = iter.second;
-
/* If this mapped file has the same build-id as was discovered for
the core-file itself, then we assume this is the main
executable. Record the filename as we can use this later. */
@@ -794,10 +790,13 @@ core_file_command (const char *filename, int from_tty)
.reg/1, .reg2/1, .reg/2, .reg2/2
After calling this function the rest of the core file handling code can
- treat this core file just like any other core file. */
+ treat this core file just like any other core file.
+
+ CBFD is the core file being loaded, and INF is the inferior through
+ which the core file will be examined. */
static void
-rename_vmcore_idle_reg_sections (bfd *abfd, inferior *inf)
+rename_vmcore_idle_reg_sections (bfd *cbfd, inferior *inf)
{
/* Map from the bfd section to its lwpid (the /NN number). */
std::vector<std::pair<asection *, int>> sections_and_lwpids;
@@ -812,7 +811,7 @@ rename_vmcore_idle_reg_sections (bfd *abfd, inferior *inf)
/* Look for all the .reg sections. Record the section object and the
lwpid which is extracted from the section name. Spot if any have an
lwpid of zero. */
- for (asection *sect : gdb_bfd_sections (current_program_space->core_bfd ()))
+ for (asection *sect : gdb_bfd_sections (cbfd))
{
if (startswith (bfd_section_name (sect), ".reg/"))
{
@@ -845,7 +844,7 @@ rename_vmcore_idle_reg_sections (bfd *abfd, inferior *inf)
std::string replacement_lwpid_str;
auto iter = sections_and_lwpids.begin ();
int replacement_lwpid = 0;
- for (asection *sect : gdb_bfd_sections (current_program_space->core_bfd ()))
+ for (asection *sect : gdb_bfd_sections (cbfd))
{
if (iter != sections_and_lwpids.end () && sect == iter->first)
{
@@ -883,7 +882,7 @@ rename_vmcore_idle_reg_sections (bfd *abfd, inferior *inf)
static_cast<int> (len - 2),
name, replacement_lwpid);
char *name_buf
- = static_cast<char *> (bfd_alloc (abfd, name_str.size () + 1));
+ = static_cast<char *> (bfd_alloc (cbfd, name_str.size () + 1));
if (name_buf == nullptr)
error (_("failed to allocate space for section name '%s'"),
name_str.c_str ());
@@ -957,7 +956,7 @@ locate_exec_from_corefile_exec_context (bfd *cbfd,
execbfd = open_and_check_build_id (exec_name);
else
{
- std::string p = (ldirname (bfd_get_filename (cbfd))
+ std::string p = (gdb_ldirname (bfd_get_filename (cbfd))
+ '/'
+ exec_name);
execbfd = open_and_check_build_id (p.c_str ());
@@ -971,7 +970,7 @@ locate_exec_from_corefile_exec_context (bfd *cbfd,
if (execbfd == nullptr)
{
const char *base_name = lbasename (exec_name);
- std::string p = (ldirname (bfd_get_filename (cbfd))
+ std::string p = (gdb_ldirname (bfd_get_filename (cbfd))
+ '/'
+ base_name);
execbfd = open_and_check_build_id (p.c_str ());
@@ -1053,16 +1052,17 @@ core_target_open (const char *arg, int from_tty)
target_preopen (from_tty);
+ /* The target_preopen call will remove any existing process stratum
+ target, which includes any existing core_target. */
+ gdb_assert (current_inferior ()->process_target () == nullptr);
+
+ /* Which will clear up any existing core file BFD. */
+ gdb_assert (current_program_space->core_bfd () == nullptr);
+
std::string filename = extract_single_filename_arg (arg);
if (filename.empty ())
- {
- if (current_program_space->core_bfd ())
- error (_("No core file specified. (Use `detach' "
- "to stop debugging a core file.)"));
- else
- error (_("No core file specified."));
- }
+ error (_("No core file specified."));
if (!IS_ABSOLUTE_PATH (filename.c_str ()))
filename = gdb_abspath (filename);
@@ -1181,7 +1181,7 @@ core_target_open (const char *arg, int from_tty)
if (current_program_space->exec_bfd () == nullptr)
set_gdbarch_from_file (current_program_space->core_bfd ());
- post_create_inferior (from_tty);
+ post_create_inferior (from_tty, true);
/* Now go through the target stack looking for threads since there
may be a thread_stratum target loaded on top of target core by
@@ -1632,9 +1632,9 @@ core_target::xfer_partial (enum target_object object, const char *annex,
return TARGET_XFER_E_IO;
else
{
- *xfered_len = gdbarch_core_xfer_shared_libraries (m_core_gdbarch,
- readbuf,
- offset, len);
+ *xfered_len = gdbarch_core_xfer_shared_libraries
+ (m_core_gdbarch, *current_program_space->core_bfd (),
+ readbuf, offset, len);
if (*xfered_len == 0)
return TARGET_XFER_EOF;
@@ -1653,9 +1653,9 @@ core_target::xfer_partial (enum target_object object, const char *annex,
else
{
*xfered_len
- = gdbarch_core_xfer_shared_libraries_aix (m_core_gdbarch,
- readbuf, offset,
- len);
+ = gdbarch_core_xfer_shared_libraries_aix
+ (m_core_gdbarch, *current_program_space->core_bfd (),
+ readbuf, offset, len);
if (*xfered_len == 0)
return TARGET_XFER_EOF;
@@ -1671,8 +1671,10 @@ core_target::xfer_partial (enum target_object object, const char *annex,
if (m_core_gdbarch != nullptr
&& gdbarch_core_xfer_siginfo_p (m_core_gdbarch))
{
- LONGEST l = gdbarch_core_xfer_siginfo (m_core_gdbarch, readbuf,
- offset, len);
+ struct bfd *cbfd = current_program_space->core_bfd ();
+ gdb_assert (cbfd != nullptr);
+ LONGEST l = gdbarch_core_xfer_siginfo (m_core_gdbarch, *cbfd,
+ readbuf, offset, len);
if (l >= 0)
{
@@ -1798,7 +1800,11 @@ core_target::thread_name (struct thread_info *thr)
{
if (m_core_gdbarch != nullptr
&& gdbarch_core_thread_name_p (m_core_gdbarch))
- return gdbarch_core_thread_name (m_core_gdbarch, thr);
+ {
+ bfd *cbfd = current_program_space->core_bfd ();
+ gdb_assert (cbfd != nullptr);
+ return gdbarch_core_thread_name (m_core_gdbarch, *cbfd, thr);
+ }
return NULL;
}
@@ -1830,7 +1836,8 @@ core_target::info_proc (const char *args, enum info_proc_what request)
/* Since this is the core file target, call the 'core_info_proc'
method on gdbarch, not 'info_proc'. */
if (gdbarch_core_info_proc_p (gdbarch))
- gdbarch_core_info_proc (gdbarch, args, request);
+ gdbarch_core_info_proc (gdbarch, current_program_space->core_bfd (),
+ args, request);
return true;
}
@@ -1905,7 +1912,9 @@ core_target::fetch_x86_xsave_layout ()
gdbarch_core_read_x86_xsave_layout_p (m_core_gdbarch))
{
x86_xsave_layout layout;
- if (!gdbarch_core_read_x86_xsave_layout (m_core_gdbarch, layout))
+ bfd *cbfd = current_program_space->core_bfd ();
+ gdb_assert (cbfd != nullptr);
+ if (!gdbarch_core_read_x86_xsave_layout (m_core_gdbarch, *cbfd, layout))
return {};
return layout;
@@ -2158,9 +2167,7 @@ core_target_find_mapped_file (const char *filename,
return targ->lookup_mapped_file_info (filename, addr);
}
-void _initialize_corelow ();
-void
-_initialize_corelow ()
+INIT_GDB_FILE (corelow)
{
add_target (core_target_info, core_target_open,
filename_maybe_quoted_completer);
diff --git a/gdb/cp-abi.c b/gdb/cp-abi.c
index 8f2067b..d8cfc08 100644
--- a/gdb/cp-abi.c
+++ b/gdb/cp-abi.c
@@ -384,9 +384,7 @@ show_cp_abi_cmd (const char *args, int from_tty)
uiout->text (").\n");
}
-void _initialize_cp_abi ();
-void
-_initialize_cp_abi ()
+INIT_GDB_FILE (cp_abi)
{
struct cmd_list_element *c;
diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y
index e7317b7..7221b78 100644
--- a/gdb/cp-name-parser.y
+++ b/gdb/cp-name-parser.y
@@ -39,7 +39,6 @@
#include <unistd.h>
-#include "gdbsupport/gdb-safe-ctype.h"
#include "demangle.h"
#include "cp-support.h"
#include "c-support.h"
@@ -374,6 +373,22 @@ function
| colon_ext_only function_arglist start_opt
{ $$ = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
if ($3) $$ = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $3); }
+ | colon_ext_only
+ {
+ /* This production is a hack to handle
+ something like "name::operator new[]" --
+ without arguments, this ordinarily would
+ not parse, but canonicalizing it is
+ important. So we infer the "()" and then
+ remove it when converting back to string.
+ Note that this works because this
+ production is terminal. */
+ demangle_component *comp
+ = state->fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE,
+ nullptr, nullptr);
+ $$ = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, comp);
+ state->demangle_info->added_parens = true;
+ }
| conversion_op_name start_opt
{ $$ = $1.comp;
@@ -1346,7 +1361,7 @@ cpname_state::parse_number (const char *p, int len, int parsed_float,
/* See if it has `f' or `l' suffix (float or long double). */
- c = TOLOWER (p[len - 1]);
+ c = c_tolower (p[len - 1]);
if (c == 'f')
{
@@ -1358,7 +1373,7 @@ cpname_state::parse_number (const char *p, int len, int parsed_float,
len--;
type = make_builtin_type ("long double");
}
- else if (ISDIGIT (c) || c == '.')
+ else if (c_isdigit (c) || c == '.')
type = make_builtin_type ("double");
else
return ERROR;
@@ -1423,10 +1438,10 @@ cpname_state::parse_number (const char *p, int len, int parsed_float,
for (int off = 0; off < len; ++off)
{
int dig;
- if (ISDIGIT (p[off]))
+ if (c_isdigit (p[off]))
dig = p[off] - '0';
else
- dig = TOLOWER (p[off]) - 'a' + 10;
+ dig = c_tolower (p[off]) - 'a' + 10;
if (dig >= base)
return ERROR;
value *= base;
@@ -1753,7 +1768,7 @@ yylex (YYSTYPE *lvalp, cpname_state *state)
}
/* We will take any letters or digits. parse_number will
complain if past the radix, or if L or U are not final. */
- else if (! ISALNUM (*p))
+ else if (! c_isalnum (*p))
break;
if (no_tick.has_value ())
no_tick->push_back (*p);
@@ -2047,9 +2062,11 @@ cp_demangled_name_to_comp (const char *demangled_name,
auto result = std::make_unique<demangle_parse_info> ();
cpname_state state (demangled_name, result.get ());
- scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
- parser_debug);
-
+ /* Note that we can't set yydebug here, as is done in the other
+ parsers. Bison implements yydebug as a global, even with a pure
+ parser, and this parser is run from worker threads. So, changing
+ yydebug causes TSan reports. If you need to debug this parser,
+ debug gdb and set the global from the outer gdb. */
if (yyparse (&state))
{
if (state.global_errmsg && errmsg)
@@ -2109,13 +2126,17 @@ canonicalize_tests ()
should_be_the_same ("Foozle<int>::fogey<Empty<int> > (Empty<int>)",
"Foozle<int>::fogey<Empty<int>> (Empty<int>)");
+
+ should_be_the_same ("something :: operator new [ ]",
+ "something::operator new[]");
+ should_be_the_same ("something :: operator new",
+ "something::operator new");
+ should_be_the_same ("operator()", "operator ()");
}
#endif
-void _initialize_cp_name_parser ();
-void
-_initialize_cp_name_parser ()
+INIT_GDB_FILE (cp_name_parser)
{
#if GDB_SELF_TEST
selftests::register_test ("canonicalize", canonicalize_tests);
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index d285e86..009ea4b 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -1049,9 +1049,7 @@ maintenance_cplus_namespace (const char *args, int from_tty)
gdb_printf (_("The `maint namespace' command was removed.\n"));
}
-void _initialize_cp_namespace ();
-void
-_initialize_cp_namespace ()
+INIT_GDB_FILE (cp_namespace)
{
struct cmd_list_element *cmd;
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index c71b8d9..7cfb545 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -35,7 +35,6 @@
#include "namespace.h"
#include <signal.h>
#include "gdbsupport/gdb_setjmp.h"
-#include "gdbsupport/gdb-safe-ctype.h"
#include "gdbsupport/selftest.h"
#include "gdbsupport/gdb-sigmask.h"
#include <atomic>
@@ -105,7 +104,7 @@ static int
cp_already_canonical (const char *string)
{
/* Identifier start character [a-zA-Z_]. */
- if (!ISIDST (string[0]))
+ if (!c_isalpha (string[0]) || string[0] == '_')
return 0;
/* These are the only two identifiers which canonicalize to other
@@ -117,7 +116,7 @@ cp_already_canonical (const char *string)
return 0;
/* Identifier character [a-zA-Z0-9_]. */
- while (ISIDNUM (string[1]))
+ while (c_isalpha (string[1]) || c_isdigit (string[1]) || string[1] == '_')
string++;
if (string[1] == '\0')
@@ -150,7 +149,8 @@ inspect_type (struct demangle_parse_info *info,
try
{
- sym = lookup_symbol (name, 0, SEARCH_VFT, 0).symbol;
+ sym = lookup_symbol (name, 0, (SEARCH_TYPE_DOMAIN
+ | SEARCH_STRUCT_DOMAIN), 0).symbol;
}
catch (const gdb_exception &except)
{
@@ -504,7 +504,8 @@ replace_typedefs (struct demangle_parse_info *info,
try
{
sym = lookup_symbol (local_name.get (), 0,
- SEARCH_VFT, 0).symbol;
+ (SEARCH_TYPE_DOMAIN
+ | SEARCH_STRUCT_DOMAIN), 0).symbol;
}
catch (const gdb_exception &except)
{
@@ -573,6 +574,17 @@ replace_typedefs (struct demangle_parse_info *info,
}
}
+/* A helper to strip a trailing "()" from PTR. The string is modified
+ in place. */
+
+static void
+maybe_strip_parens (char *ptr)
+{
+ size_t len = strlen (ptr);
+ if (len > 2 && ptr[len - 2] == '(' && ptr[len - 1] == ')')
+ ptr[len - 2] = '\0';
+}
+
/* Parse STRING and convert it to canonical form, resolving any
typedefs. If parsing fails, or if STRING is already canonical,
return nullptr. Otherwise return the canonical form. If
@@ -599,6 +611,9 @@ cp_canonicalize_string_full (const char *string,
estimated_len);
gdb_assert (us);
+ if (info->added_parens)
+ maybe_strip_parens (us.get ());
+
/* Finally, compare the original string with the computed
name, returning NULL if they are the same. */
if (strcmp (us.get (), string) == 0)
@@ -647,6 +662,9 @@ cp_canonicalize_string (const char *string)
return nullptr;
}
+ if (info->added_parens)
+ maybe_strip_parens (us.get ());
+
if (strcmp (us.get (), string) == 0)
return nullptr;
@@ -1118,7 +1136,7 @@ cp_find_first_component_aux (const char *name, int permissive)
&& startswith (name + index, CP_OPERATOR_STR))
{
index += CP_OPERATOR_LEN;
- while (ISSPACE(name[index]))
+ while (c_isspace(name[index]))
++index;
switch (name[index])
{
@@ -1455,17 +1473,14 @@ add_symbol_overload_list_qualified (const char *func_name,
? selected_block->objfile ()
: nullptr);
- gdbarch_iterate_over_objfiles_in_search_order
- (current_objfile ? current_objfile->arch () : current_inferior ()->arch (),
- [func_name, surrounding_static_block, &overload_list]
+ lookup_name_info base_lookup (func_name, symbol_name_match_type::FULL);
+ lookup_name_info lookup_name = base_lookup.make_ignore_params ();
+
+ current_program_space->iterate_over_objfiles_in_search_order
+ ([func_name, surrounding_static_block, &overload_list, lookup_name]
(struct objfile *obj)
{
- /* Look through the partial symtabs for all symbols which
- begin by matching FUNC_NAME. Make sure we read that
- symbol table in. */
- obj->expand_symtabs_for_function (func_name);
-
- for (compunit_symtab *cust : obj->compunits ())
+ auto callback = [&] (compunit_symtab *cust)
{
QUIT;
const struct block *b = cust->blockvector ()->global_block ();
@@ -1473,11 +1488,17 @@ add_symbol_overload_list_qualified (const char *func_name,
b = cust->blockvector ()->static_block ();
/* Don't do this block twice. */
- if (b == surrounding_static_block)
- continue;
+ if (b != surrounding_static_block)
+ add_symbol_overload_list_block (func_name, b, overload_list);
+ return true;
+ };
- add_symbol_overload_list_block (func_name, b, overload_list);
- }
+ /* Look through the partial symtabs for all symbols which
+ begin by matching FUNC_NAME. Make sure we read that
+ symbol table in. */
+ obj->search (nullptr, &lookup_name, nullptr, callback,
+ SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
+ SEARCH_FUNCTION_DOMAIN);
return 0;
}, current_objfile);
@@ -1501,7 +1522,7 @@ cp_lookup_rtti_type (const char *name, const struct block *block)
return NULL;
}
- if (rtti_sym->aclass () != LOC_TYPEDEF)
+ if (rtti_sym->loc_class () != LOC_TYPEDEF)
{
warning (_("RTTI symbol for class '%s' is not a type"), name);
return NULL;
@@ -2332,7 +2353,7 @@ find_toplevel_char (const char *s, char c)
scan += CP_OPERATOR_LEN;
if (*scan == c)
return scan;
- while (ISSPACE (*scan))
+ while (c_isspace (*scan))
{
++scan;
if (*scan == c)
@@ -2370,9 +2391,7 @@ find_toplevel_char (const char *s, char c)
return 0;
}
-void _initialize_cp_support ();
-void
-_initialize_cp_support ()
+INIT_GDB_FILE (cp_support)
{
cmd_list_element *maintenance_cplus
= add_basic_prefix_cmd ("cplus", class_maintenance,
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 3ed354c..ffe0ba1 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -63,6 +63,10 @@ struct demangle_parse_info
/* Any memory used during processing. */
auto_obstack obstack;
+ /* True if the parser had to add a dummy '()' at the end of the
+ input text to make it parse. */
+ bool added_parens = false;
+
/* Any other objects referred to by this object, and whose storage
lifetime must be linked. */
std::vector<std::unique_ptr<demangle_parse_info>> infos;
diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index 2117718..252072b 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -797,9 +797,7 @@ test_print_fields (gdbarch *arch)
#endif
-void _initialize_cp_valprint ();
-void
-_initialize_cp_valprint ()
+INIT_GDB_FILE (cp_valprint)
{
#if GDB_SELF_TEST
selftests::register_test_foreach_arch ("print-fields", test_print_fields);
diff --git a/gdb/cris-linux-tdep.c b/gdb/cris-linux-tdep.c
index b2ac80d..a39441e 100644
--- a/gdb/cris-linux-tdep.c
+++ b/gdb/cris-linux-tdep.c
@@ -23,6 +23,7 @@
#include "osabi.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "solib-svr4.h"
#include "symtab.h"
#include "gdbarch.h"
@@ -41,14 +42,10 @@ cris_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- linux_ilp32_fetch_link_map_offsets);
-
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
}
-void _initialize_cris_linux_tdep ();
-void
-_initialize_cris_linux_tdep ()
+INIT_GDB_FILE (cris_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_cris, 0, GDB_OSABI_LINUX,
cris_linux_init_abi);
diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c
index 722c0a4..9cfc1eb 100644
--- a/gdb/cris-tdep.c
+++ b/gdb/cris-tdep.c
@@ -3816,9 +3816,7 @@ static void cris_iterate_over_regset_sections (struct gdbarch *gdbarch,
&cris_regset, NULL, cb_data);
}
-void _initialize_cris_tdep ();
-void
-_initialize_cris_tdep ()
+INIT_GDB_FILE (cris_tdep)
{
gdbarch_register (bfd_arch_cris, cris_gdbarch_init, cris_dump_tdep);
@@ -3995,7 +3993,7 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_cannot_store_register (gdbarch, cris_cannot_store_register);
set_gdbarch_cannot_fetch_register (gdbarch, cris_cannot_fetch_register);
- set_gdbarch_software_single_step (gdbarch, cris_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, cris_software_single_step);
break;
case 32:
diff --git a/gdb/csky-linux-tdep.c b/gdb/csky-linux-tdep.c
index 2afb358..0651645 100644
--- a/gdb/csky-linux-tdep.c
+++ b/gdb/csky-linux-tdep.c
@@ -22,6 +22,7 @@
#include "osabi.h"
#include "glibc-tdep.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "gdbarch.h"
#include "solib-svr4.h"
#include "regset.h"
@@ -407,8 +408,7 @@ csky_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Shared library handling. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
@@ -426,9 +426,7 @@ csky_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
&csky_linux_rt_sigreturn_tramp_frame_kernel_4x);
}
-void _initialize_csky_linux_tdep ();
-void
-_initialize_csky_linux_tdep ()
+INIT_GDB_FILE (csky_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_csky, 0, GDB_OSABI_LINUX,
csky_linux_init_abi);
diff --git a/gdb/csky-tdep.c b/gdb/csky-tdep.c
index 350612f..e6c6e2c 100644
--- a/gdb/csky-tdep.c
+++ b/gdb/csky-tdep.c
@@ -2882,9 +2882,7 @@ csky_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_csky_tdep ();
-void
-_initialize_csky_tdep ()
+INIT_GDB_FILE (csky_tdep)
{
gdbarch_register (bfd_arch_csky, csky_gdbarch_init);
diff --git a/gdb/ctfread.c b/gdb/ctfread.c
index e568f15..4761b36 100644
--- a/gdb/ctfread.c
+++ b/gdb/ctfread.c
@@ -328,7 +328,7 @@ set_symbol_address (struct objfile *of, struct symbol *sym, const char *name)
if (msym.minsym != NULL)
{
sym->set_value_address (msym.value_address ());
- sym->set_aclass_index (LOC_STATIC);
+ sym->set_loc_class_index (LOC_STATIC);
sym->set_section_index (msym.minsym->section_index ());
}
}
@@ -447,7 +447,7 @@ ctf_add_enum_member_cb (const char *name, int enum_value, void *arg)
sym->set_language (language_c, &ccp->of->objfile_obstack);
sym->compute_and_set_names (name, false, ccp->of->per_bfd);
- sym->set_aclass_index (LOC_CONST);
+ sym->set_loc_class_index (LOC_CONST);
sym->set_domain (VAR_DOMAIN);
sym->set_type (fip->ptype);
add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
@@ -477,7 +477,7 @@ new_symbol (struct ctf_context *ccp, struct type *type, ctf_id_t tid)
sym->set_language (language_c, &objfile->objfile_obstack);
sym->compute_and_set_names (name, false, objfile->per_bfd);
sym->set_domain (VAR_DOMAIN);
- sym->set_aclass_index (LOC_OPTIMIZED_OUT);
+ sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
if (type != nullptr)
sym->set_type (type);
@@ -488,11 +488,11 @@ new_symbol (struct ctf_context *ccp, struct type *type, ctf_id_t tid)
case CTF_K_STRUCT:
case CTF_K_UNION:
case CTF_K_ENUM:
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_domain (STRUCT_DOMAIN);
break;
case CTF_K_FUNCTION:
- sym->set_aclass_index (LOC_STATIC);
+ sym->set_loc_class_index (LOC_STATIC);
set_symbol_address (objfile, sym, sym->linkage_name ());
break;
case CTF_K_CONST:
@@ -502,7 +502,7 @@ new_symbol (struct ctf_context *ccp, struct type *type, ctf_id_t tid)
case CTF_K_TYPEDEF:
case CTF_K_INTEGER:
case CTF_K_FLOAT:
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_domain (TYPE_DOMAIN);
break;
case CTF_K_POINTER:
@@ -516,7 +516,7 @@ new_symbol (struct ctf_context *ccp, struct type *type, ctf_id_t tid)
break;
}
- add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
+ add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
}
return sym;
@@ -1169,9 +1169,9 @@ ctf_add_var_cb (const char *name, ctf_id_t id, void *arg)
OBJSTAT (ccp->of, n_syms++);
sym->set_type (type);
sym->set_domain (VAR_DOMAIN);
- sym->set_aclass_index (LOC_OPTIMIZED_OUT);
+ sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
sym->compute_and_set_names (name, false, ccp->of->per_bfd);
- add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
+ add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
break;
default:
complaint (_("ctf_add_var_cb: kind unsupported (%d)"), kind);
@@ -1205,7 +1205,7 @@ add_stt_entries (struct ctf_context *ccp, int functions)
OBJSTAT (ccp->of, n_syms++);
sym->set_type (type);
sym->set_domain (VAR_DOMAIN);
- sym->set_aclass_index (LOC_STATIC);
+ sym->set_loc_class_index (LOC_STATIC);
sym->compute_and_set_names (tname, false, ccp->of->per_bfd);
add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
set_symbol_address (ccp->of, sym, tname);
@@ -1309,7 +1309,7 @@ ctf_psymtab_add_stt_entries (ctf_dict_t *cfp, ctf_psymtab *pst,
while ((tid = ctf_symbol_next (cfp, &i, &tname, functions)) != CTF_ERR)
{
uint32_t kind = ctf_type_kind (cfp, tid);
- address_class aclass;
+ location_class loc_class;
domain_enum tdomain;
switch (kind)
{
@@ -1324,14 +1324,14 @@ ctf_psymtab_add_stt_entries (ctf_dict_t *cfp, ctf_psymtab *pst,
}
if (kind == CTF_K_FUNCTION)
- aclass = LOC_STATIC;
+ loc_class = LOC_STATIC;
else if (kind == CTF_K_CONST)
- aclass = LOC_CONST;
+ loc_class = LOC_CONST;
else
- aclass = LOC_TYPEDEF;
+ loc_class = LOC_TYPEDEF;
pst->add_psymbol (tname, true,
- tdomain, aclass, -1,
+ tdomain, loc_class, -1,
psymbol_placement::GLOBAL,
unrelocated_addr (0),
language_c, pst->context.partial_symtabs, of);
@@ -1465,7 +1465,7 @@ ctf_psymtab_type_cb (ctf_id_t tid, void *arg)
ccp = (struct ctf_context *) arg;
domain_enum domain = UNDEF_DOMAIN;
- enum address_class aclass = LOC_UNDEF;
+ location_class loc_class = LOC_UNDEF;
kind = ctf_type_kind (ccp->fp, tid);
switch (kind)
{
@@ -1475,29 +1475,29 @@ ctf_psymtab_type_cb (ctf_id_t tid, void *arg)
case CTF_K_STRUCT:
case CTF_K_UNION:
domain = STRUCT_DOMAIN;
- aclass = LOC_TYPEDEF;
+ loc_class = LOC_TYPEDEF;
break;
case CTF_K_FUNCTION:
case CTF_K_FORWARD:
domain = VAR_DOMAIN;
- aclass = LOC_STATIC;
+ loc_class = LOC_STATIC;
section = SECT_OFF_TEXT (ccp->of);
break;
case CTF_K_CONST:
domain = VAR_DOMAIN;
- aclass = LOC_STATIC;
+ loc_class = LOC_STATIC;
break;
case CTF_K_TYPEDEF:
case CTF_K_POINTER:
case CTF_K_VOLATILE:
case CTF_K_RESTRICT:
domain = VAR_DOMAIN;
- aclass = LOC_TYPEDEF;
+ loc_class = LOC_TYPEDEF;
break;
case CTF_K_INTEGER:
case CTF_K_FLOAT:
domain = VAR_DOMAIN;
- aclass = LOC_TYPEDEF;
+ loc_class = LOC_TYPEDEF;
break;
case CTF_K_ARRAY:
case CTF_K_UNKNOWN:
@@ -1509,8 +1509,8 @@ ctf_psymtab_type_cb (ctf_id_t tid, void *arg)
return 0;
ccp->pst->add_psymbol (name, false,
- domain, aclass, section,
- psymbol_placement::STATIC,
+ domain, loc_class, section,
+ psymbol_placement::GLOBAL,
unrelocated_addr (0),
language_c, ccp->partial_symtabs, ccp->of);
diff --git a/gdb/d-exp.y b/gdb/d-exp.y
index e0ee758..e774dee 100644
--- a/gdb/d-exp.y
+++ b/gdb/d-exp.y
@@ -38,7 +38,6 @@
%{
-#include <ctype.h>
#include "expression.h"
#include "value.h"
#include "parser-defs.h"
@@ -444,7 +443,7 @@ PrimaryExpression:
sym = lookup_symbol (copy.c_str (),
pstate->expression_context_block,
SEARCH_VFT, &is_a_field_of_this);
- if (sym.symbol && sym.symbol->aclass () != LOC_TYPEDEF)
+ if (sym.symbol && sym.symbol->loc_class () != LOC_TYPEDEF)
{
if (symbol_read_needs_frame (sym.symbol))
pstate->block_tracker->update (sym);
@@ -614,11 +613,9 @@ BasicType2:
| '*' BasicType2
{ type_stack->push (tp_pointer); }
| '[' INTEGER_LITERAL ']'
- { type_stack->push ($2.val);
- type_stack->push (tp_array); }
+ { type_stack->push (tp_array, $2.val); }
| '[' INTEGER_LITERAL ']' BasicType2
- { type_stack->push ($2.val);
- type_stack->push (tp_array); }
+ { type_stack->push (tp_array, $2.val); }
;
BasicType:
@@ -684,15 +681,15 @@ parse_number (struct parser_state *ps, const char *p,
len = strlen (s);
/* Check suffix for `i' , `fi' or `li' (idouble, ifloat or ireal). */
- if (len >= 1 && tolower (s[len - 1]) == 'i')
+ if (len >= 1 && c_tolower (s[len - 1]) == 'i')
{
- if (len >= 2 && tolower (s[len - 2]) == 'f')
+ if (len >= 2 && c_tolower (s[len - 2]) == 'f')
{
putithere->typed_val_float.type
= parse_d_type (ps)->builtin_ifloat;
len -= 2;
}
- else if (len >= 2 && tolower (s[len - 2]) == 'l')
+ else if (len >= 2 && c_tolower (s[len - 2]) == 'l')
{
putithere->typed_val_float.type
= parse_d_type (ps)->builtin_ireal;
@@ -706,13 +703,13 @@ parse_number (struct parser_state *ps, const char *p,
}
}
/* Check suffix for `f' or `l'' (float or real). */
- else if (len >= 1 && tolower (s[len - 1]) == 'f')
+ else if (len >= 1 && c_tolower (s[len - 1]) == 'f')
{
putithere->typed_val_float.type
= parse_d_type (ps)->builtin_float;
len -= 1;
}
- else if (len >= 1 && tolower (s[len - 1]) == 'l')
+ else if (len >= 1 && c_tolower (s[len - 1]) == 'l')
{
putithere->typed_val_float.type
= parse_d_type (ps)->builtin_real;
@@ -1133,8 +1130,8 @@ lex_one_token (struct parser_state *par_state)
/* Hex exponents start with 'p', because 'e' is a valid hex
digit and thus does not indicate a floating point number
when the radix is hex. */
- if ((!hex && !got_e && tolower (p[0]) == 'e')
- || (hex && !got_e && tolower (p[0] == 'p')))
+ if ((!hex && !got_e && c_tolower (p[0]) == 'e')
+ || (hex && !got_e && c_tolower (p[0] == 'p')))
got_dot = got_e = 1;
/* A '.' always indicates a decimal floating point number
regardless of the radix. If we have a '..' then its the
@@ -1142,7 +1139,8 @@ lex_one_token (struct parser_state *par_state)
else if (!got_dot && (p[0] == '.' && p[1] != '.'))
got_dot = 1;
/* This is the sign of the exponent, not the end of the number. */
- else if (got_e && (tolower (p[-1]) == 'e' || tolower (p[-1]) == 'p')
+ else if (got_e && (c_tolower (p[-1]) == 'e'
+ || c_tolower (p[-1]) == 'p')
&& (*p == '-' || *p == '+'))
continue;
/* We will take any letters or digits, ignoring any embedded '_'.
@@ -1167,9 +1165,9 @@ lex_one_token (struct parser_state *par_state)
const char *p = &tokstart[1];
size_t len = strlen ("entry");
- while (isspace (*p))
+ while (c_isspace (*p))
p++;
- if (strncmp (p, "entry", len) == 0 && !isalnum (p[len])
+ if (strncmp (p, "entry", len) == 0 && !c_isalnum (p[len])
&& p[len] != '_')
{
pstate->lexptr = &p[len];
@@ -1334,7 +1332,7 @@ classify_name (struct parser_state *par_state, const struct block *block)
std::string copy = copy_name (yylval.sval);
sym = lookup_symbol (copy.c_str (), block, SEARCH_VFT, &is_a_field_of_this);
- if (sym.symbol && sym.symbol->aclass () == LOC_TYPEDEF)
+ if (sym.symbol && sym.symbol->loc_class () == LOC_TYPEDEF)
{
yylval.tsym.type = sym.symbol->type ();
return TYPENAME;
@@ -1383,7 +1381,7 @@ classify_inner_name (struct parser_state *par_state,
if (yylval.ssym.sym.symbol == NULL)
return ERROR;
- if (yylval.ssym.sym.symbol->aclass () == LOC_TYPEDEF)
+ if (yylval.ssym.sym.symbol->loc_class () == LOC_TYPEDEF)
{
yylval.tsym.type = yylval.ssym.sym.symbol->type ();
return TYPENAME;
diff --git a/gdb/darwin-nat-info.c b/gdb/darwin-nat-info.c
index b5784be..3ec49af 100644
--- a/gdb/darwin-nat-info.c
+++ b/gdb/darwin-nat-info.c
@@ -839,9 +839,7 @@ info_mach_exceptions_command (const char *args, int from_tty)
}
}
-void _initialize_darwin_info_commands ();
-void
-_initialize_darwin_info_commands ()
+INIT_GDB_FILE (darwin_info_commands)
{
add_info ("mach-tasks", info_mach_tasks_command,
_("Get list of tasks in system."));
diff --git a/gdb/darwin-nat.c b/gdb/darwin-nat.c
index 6bc0e4f..e73b5a1 100644
--- a/gdb/darwin-nat.c
+++ b/gdb/darwin-nat.c
@@ -47,7 +47,6 @@
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
-#include <ctype.h>
#include <sys/sysctl.h>
#include <sys/proc.h>
#include <libproc.h>
@@ -1853,7 +1852,7 @@ copy_shell_to_cache (const char *shell, const std::string &new_name)
error (_("Could not open shell (%s) for reading: %s"),
shell, safe_strerror (errno));
- std::string new_dir = ldirname (new_name.c_str ());
+ std::string new_dir = gdb_ldirname (new_name.c_str ());
if (!mkdir_recursive (new_dir.c_str ()))
error (_("Could not make cache directory \"%s\": %s"),
new_dir.c_str (), safe_strerror (errno));
@@ -2469,9 +2468,7 @@ darwin_nat_target::supports_multi_process ()
return true;
}
-void _initialize_darwin_nat ();
-void
-_initialize_darwin_nat ()
+INIT_GDB_FILE (darwin_nat)
{
kern_return_t kret;
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index 8d0ebab..260f583 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -248,9 +248,7 @@ static const struct sym_fns aout_sym_fns =
NULL, /* sym_probe_fns */
};
-void _initialize_dbxread ();
-void
-_initialize_dbxread ()
+INIT_GDB_FILE (dbxread)
{
add_symtab_fns (bfd_target_aout_flavour, &aout_sym_fns);
}
diff --git a/gdb/dcache.c b/gdb/dcache.c
index 2c5484d..7a15278 100644
--- a/gdb/dcache.c
+++ b/gdb/dcache.c
@@ -679,9 +679,7 @@ set_dcache_line_size (const char *args, int from_tty,
target_dcache_invalidate (current_program_space->aspace);
}
-void _initialize_dcache ();
-void
-_initialize_dcache ()
+INIT_GDB_FILE (dcache)
{
add_setshow_boolean_cmd ("remotecache", class_support,
&dcache_enabled_p, _("\
diff --git a/gdb/debuginfod-support.c b/gdb/debuginfod-support.c
index d573b8d..e99c13b 100644
--- a/gdb/debuginfod-support.c
+++ b/gdb/debuginfod-support.c
@@ -18,6 +18,7 @@
#include "diagnostics.h"
#include <errno.h>
+#include "gdbsupport/cleanups.h"
#include "gdbsupport/scoped_fd.h"
#include "debuginfod-support.h"
#include <optional>
@@ -594,9 +595,7 @@ maint_get_debuginfod_download_sections ()
/* Register debuginfod commands. */
-void _initialize_debuginfod ();
-void
-_initialize_debuginfod ()
+INIT_GDB_FILE (debuginfod)
{
/* set/show debuginfod */
add_setshow_prefix_cmd ("debuginfod", class_run,
diff --git a/gdb/defs.h b/gdb/defs.h
index bda4ef6..bb1e119 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -190,8 +190,6 @@ extern std::string relocate_gdb_directory (const char *initial, bool relocatable
/* From top.c */
-typedef void initialize_file_ftype (void);
-
extern char *gdb_readline_wrapper (const char *);
extern const char *command_line_input (std::string &cmd_line_buffer,
@@ -407,4 +405,10 @@ DEF_ENUM_FLAGS_TYPE (enum user_selected_what_flag, user_selected_what);
#include "utils.h"
+/* File initialization macro. This is found by make-init-c and used
+ to construct the gdb initialization function. */
+#define INIT_GDB_FILE(NAME) \
+ extern void _initialize_ ## NAME (); \
+ void _initialize_ ## NAME ()
+
#endif /* GDB_DEFS_H */
diff --git a/gdb/dicos-tdep.c b/gdb/dicos-tdep.c
index 4dfac76..d6bc9a5 100644
--- a/gdb/dicos-tdep.c
+++ b/gdb/dicos-tdep.c
@@ -27,7 +27,7 @@
void
dicos_init_abi (struct gdbarch *gdbarch)
{
- set_gdbarch_so_ops (gdbarch, &solib_target_so_ops);
+ set_gdbarch_make_solib_ops (gdbarch, make_target_solib_ops);
/* Every process, although has its own address space, sees the same
list of shared libraries. There's no "main executable" in DICOS,
diff --git a/gdb/dictionary.c b/gdb/dictionary.c
index 91dafd1..e53331b 100644
--- a/gdb/dictionary.c
+++ b/gdb/dictionary.c
@@ -20,12 +20,10 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include <ctype.h>
#include "gdbsupport/gdb_obstack.h"
#include "symtab.h"
#include "buildsym.h"
#include "dictionary.h"
-#include "gdbsupport/gdb-safe-ctype.h"
#include "gdbsupport/unordered_map.h"
#include "language.h"
@@ -772,7 +770,7 @@ language_defn::search_name_hash (const char *string0) const
if (c == 'B' && string[3] == '_')
{
- for (string += 4; ISDIGIT (*string); ++string)
+ for (string += 4; c_isdigit (*string); ++string)
;
continue;
}
@@ -952,14 +950,9 @@ mdict_create_hashed (struct obstack *obstack,
retval->n_allocated_dictionaries = nsyms.size ();
int idx = 0;
- for (const auto &pair : nsyms)
- {
- enum language language = pair.first;
- std::vector<symbol *> symlist = pair.second;
-
- retval->dictionaries[idx++]
- = dict_create_hashed (obstack, language, symlist);
- }
+ for (const auto &[language, symlist] : nsyms)
+ retval->dictionaries[idx++] = dict_create_hashed (obstack, language,
+ symlist);
return retval;
}
@@ -997,14 +990,9 @@ mdict_create_linear (struct obstack *obstack,
retval->n_allocated_dictionaries = nsyms.size ();
int idx = 0;
- for (const auto &pair : nsyms)
- {
- enum language language = pair.first;
- std::vector<symbol *> symlist = pair.second;
-
- retval->dictionaries[idx++]
- = dict_create_linear (obstack, language, symlist);
- }
+ for (const auto &[language, symlist] : nsyms)
+ retval->dictionaries[idx++] = dict_create_linear (obstack, language,
+ symlist);
return retval;
}
@@ -1135,10 +1123,8 @@ mdict_add_pending (struct multidictionary *mdict,
gdb::unordered_map<enum language, std::vector<symbol *>> nsyms
= collate_pending_symbols_by_language (symbol_list);
- for (const auto &pair : nsyms)
+ for (const auto &[language, symlist] : nsyms)
{
- enum language language = pair.first;
- std::vector<symbol *> symlist = pair.second;
struct dictionary *dict = find_language_dictionary (mdict, language);
if (dict == nullptr)
diff --git a/gdb/disasm-selftests.c b/gdb/disasm-selftests.c
index 3ccc174..0d06065 100644
--- a/gdb/disasm-selftests.c
+++ b/gdb/disasm-selftests.c
@@ -418,9 +418,7 @@ disassemble_insn (gdbarch *gdbarch, gdb::byte_vector &insn,
} /* namespace selftests */
-void _initialize_disasm_selftests ();
-void
-_initialize_disasm_selftests ()
+INIT_GDB_FILE (disasm_selftests)
{
selftests::register_test_foreach_arch ("print_one_insn",
selftests::print_one_insn_test);
diff --git a/gdb/disasm.c b/gdb/disasm.c
index 2a7a80c..c8e830e 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -28,7 +28,6 @@
#include "cli/cli-cmds.h"
#include "dis-asm.h"
#include "source.h"
-#include "gdbsupport/gdb-safe-ctype.h"
#include <algorithm>
#include <optional>
#include "valprint.h"
@@ -1470,9 +1469,7 @@ disassembler_options_completer (struct cmd_list_element *ignore,
/* Initialization code. */
-void _initialize_disasm ();
-void
-_initialize_disasm ()
+INIT_GDB_FILE (disasm)
{
/* Add the command that controls the disassembler options. */
set_show_commands set_show_disas_opts
diff --git a/gdb/displaced-stepping.c b/gdb/displaced-stepping.c
index 7df45d6..6699296 100644
--- a/gdb/displaced-stepping.c
+++ b/gdb/displaced-stepping.c
@@ -315,9 +315,7 @@ displaced_step_buffers::restore_in_ptid (ptid_t ptid)
}
}
-void _initialize_displaced_stepping ();
-void
-_initialize_displaced_stepping ()
+INIT_GDB_FILE (displaced_stepping)
{
add_setshow_boolean_cmd ("displaced", class_maintenance,
&debug_displaced, _("\
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9b4aa5b..676143b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -898,14 +898,17 @@ debugger attached to a bare board, there may not be any notion of
``process'', and there is often no way to get a core dump. @value{GDBN}
will warn you if it is unable to attach or to read core dumps.
-You can optionally have @code{@value{GDBP}} pass any arguments after the
-executable file to the inferior using @code{--args}. This option stops
-option processing.
+You can optionally have @code{@value{GDBP}} pass any arguments after
+the executable file to the inferior using @code{--args} or
+@code{--no-escape-args}. These options stop option processing.
@smallexample
@value{GDBP} --args gcc -O2 -c foo.c
@end smallexample
This will cause @code{@value{GDBP}} to debug @code{gcc}, and to set
-@code{gcc}'s command-line arguments (@pxref{Arguments}) to @samp{-O2 -c foo.c}.
+@code{gcc}'s command-line arguments (@pxref{Arguments}) to @samp{-O2
+-c foo.c}. For the differences between @code{--args} and
+@code{--no-escape-args}, see @ref{--args and --no-escape-args options,
+,@code{--args} and @code{--no-escape-args}}.
You can run @code{@value{GDBP}} without printing the front material, which describes
@value{GDBN}'s non-warranty, by specifying @code{--silent}
@@ -1240,12 +1243,67 @@ that control @value{GDBN}, and level 2 has been deprecated.
The annotation mechanism has largely been superseded by @sc{gdb/mi}
(@pxref{GDB/MI}).
+@anchor{--args and --no-escape-args options}
@item --args
@cindex @code{--args}
Change interpretation of command line so that arguments following the
executable file are passed as command line arguments to the inferior.
This option stops option processing.
+Arguments supplied using @code{--args} will have backslashes applied
+to escape any special shell characters. This ensures that when the
+inferior starts it is passed arguments exactly as @value{GDBN}
+receives them.
+
+For example, consider the following command run under a shell:
+
+@smallexample
+$ @value{GDBP} --args ls *.c
+@end smallexample
+
+@noindent
+In this case the shell will expand @kbd{*.c} at the time @value{GDBN}
+is invoked, not at the time that the inferior is invoked. As a
+result, if an additional @kbd{.c} file is created after @value{GDBN}
+is started, but before the inferior is started, then the inferior will
+not show the file in its output; the list of matching files was
+resolved at the time @value{GDBN} was started.
+
+If you quote the @kbd{*} character used on the @value{GDBN} command
+line argument then this will prevent the shell that starts
+@value{GDBN} from expanding the @kbd{*.c} pattern, however, this
+quoting will also be passed to the shell that @value{GDBN} invokes in
+order to start the inferior (@pxref{set startup-with-shell}), and this
+will prevent the @kbd{*.c} pattern being expanded at this point either:
+
+@smallexample
+$ @value{GDBP} --args ls '*.c'
+(@value{GDBP}) show args
+Argument list to give program being debugged when it is started is "\*.log".
+@end smallexample
+
+@noindent
+If this quoting behaviour does not meet your needs, then you could use
+@code{--no-escape-args} instead, which is described below.
+
+@item --no-escape-args
+@cindex @code{--no-escape-args}
+Change interpretation of command line so that arguments following the
+executable file are passed as command line arguments to the inferior.
+This option stops option processing.
+
+Unlike @code{--args}, arguments after the executable name will not
+have any escaping applied to them. As a result, any special shell
+characters that are not expanded by the shell that invokes
+@value{GDBN} will be expanded by the shell that @value{GDBN} uses to
+start the inferior.
+
+@smallexample
+$ @value{GDBP} --no-escape-args ls '*.c'
+(@value{GDBP}) show args
+Argument list to give program being debugged when it is started is "*.log".
+@end smallexample
+
@item -baud @var{bps}
@itemx -b @var{bps}
@cindex @code{--baud}
@@ -3807,7 +3865,7 @@ Thread 1 "main" received signal SIGINT, Interrupt.
@table @code
@anchor{info_threads}
@kindex info threads
-@item info threads @r{[}-gid@r{]} @r{[}@var{thread-id-list}@r{]}
+@item info threads @r{[}-gid@r{]} @r{[}-stopped@r{]} @r{[}-running@r{]} @r{[}@var{thread-id-list}@r{]}
Display information about one or more threads. With no arguments
displays information about all threads. You can specify the list of
@@ -3857,6 +3915,14 @@ If you're debugging multiple inferiors, @value{GDBN} displays thread
IDs using the qualified @var{inferior-num}.@var{thread-num} format.
Otherwise, only @var{thread-num} is shown.
+If you specify the @samp{-stopped} option, @value{GDBN} filters the
+output of the command to print the stopped threads only. Similarly,
+if you specify the @samp{-running} option, @value{GDBN} filters the
+output to print the running threads only. These options can be
+helpful to reduce the output list if there is a large number of
+threads. If you specify both options, @value{GDBN} prints both
+stopped and running threads.
+
If you specify the @samp{-gid} option, @value{GDBN} displays a column
indicating each thread's global thread ID:
@@ -13096,17 +13162,17 @@ variable which may be @samp{truecolor} or @samp{24bit}. Other color spaces are
determined by the "Co" termcap which in turn depends on the @env{TERM}
environment variable.
-@vindex $_active_linker_namespaces@r{, convenience variable}
-@item $_active_linker_namespaces
-Number of active linkage namespaces in the inferior. In systems with no
-support for linkage namespaces, this variable will always be set to @samp{1}.
+@vindex $_linker_namespace_count@r{, convenience variable}
+@item $_linker_namespace_count
+Number of active linker namespaces in the inferior (@pxref{Files}). In systems
+with no support for linker namespaces or if the inferior hasn't started, this
+variable will always be set to @samp{0}.
-@vindex $_current_linker_namespace@r{, convenience variable}
-@item $_current_linker_namespace
-The namespace which contains the current location in the inferior. This
-returns GDB's internal identifier for namespaces, which is @samp{[[@var{n}]]}
-where @var{n} is a zero-based namespace number. In systems with no support
-for linkage namespaces, this variable will always be set to @samp{[[0]]}.
+@vindex $_linker_namespace@r{, convenience variable}
+@item $_linker_namespace
+The namespace which contains the current location in the inferior. This returns
+@value{GDBN}'s internal numbering for the namespace. In systems with no support
+for linker namespaces, this variable will always be set to @samp{0}.
@end table
@@ -22234,11 +22300,18 @@ be determined then the address range for the @code{.text} section from
the library will be listed. If the @code{.text} section cannot be
found then no addresses will be listed.
-On systems that support linkage namespaces, the output includes an
+On systems that support linker namespaces, the output includes an
additional column @code{NS} if the inferior has more than one active
-namespace when the command is used. This column the linkage namespace
+namespace when the command is used. This column the linker namespace
that the shared library was loaded into.
+@cindex linker namespaces
+@dfn{Linker namespaces} are a feature of some standard libraries, that allow
+shared objects to be loaded in isolated environment, eliminating the
+possibility that those objects may cross-talk. Each set of isolated
+shared objects is said to belong to a ``namespace'', and linker related
+actions such as relocations do not cross namespace boundaries.
+
@kindex info dll
@item info dll @var{regex}
This is an alias of @code{info sharedlibrary}.
@@ -24767,6 +24840,10 @@ future connections is shown. The available settings are:
@tab @code{vFile:stat}
@tab Host I/O
+@item @code{hostio-lstat-packet}
+@tab @code{vFile:lstat}
+@tab Host I/O
+
@item @code{hostio-setfs-packet}
@tab @code{vFile:setfs}
@tab Host I/O
@@ -26630,8 +26707,9 @@ Show whether AArch64 debugging messages are displayed.
@end table
-@subsubsection AArch64 SVE.
-@cindex AArch64 SVE.
+@subsubsection AArch64 Scalable Vector Extension
+@cindex Scalable Vector Extension, AArch64
+@cindex SVE, AArch64
When @value{GDBN} is debugging the AArch64 architecture, if the Scalable Vector
Extension (SVE) is present, then @value{GDBN} will provide the vector registers
@@ -26670,11 +26748,10 @@ internally by @value{GDBN} and the Linux Kernel.
@end itemize
-@subsubsection AArch64 SME.
+@subsubsection AArch64 Scalable Matrix Extension
@anchor{AArch64 SME}
-@cindex SME
-@cindex AArch64 SME
-@cindex Scalable Matrix Extension
+@cindex Scalable Matrix Extension, AArch64
+@cindex SME, AArch64
The Scalable Matrix Extension (@url{https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/scalable-matrix-extension-armv9-a-architecture, @acronym{SME}})
is an AArch64 architecture extension that expands on the concept of the
@@ -26866,11 +26943,10 @@ incorrect values for SVE registers (when in streaming mode).
This is the same limitation we have for the @acronym{SVE} registers, and there
are plans to address this limitation going forward.
-@subsubsection AArch64 SME2.
+@subsubsection AArch64 Scalable Matrix Extension 2
@anchor{AArch64 SME2}
-@cindex SME2
-@cindex AArch64 SME2
-@cindex Scalable Matrix Extension 2
+@cindex Scalable Matrix Extension 2, AArch64
+@cindex SME2, AArch64
The Scalable Matrix Extension 2 is an AArch64 architecture extension that
further expands the @acronym{SME} extension with the following:
@@ -26910,8 +26986,9 @@ For more information about @acronym{SME2}, please refer to the
official @url{https://developer.arm.com/documentation/ddi0487/latest,
architecture documentation}.
-@subsubsection AArch64 Pointer Authentication.
-@cindex AArch64 Pointer Authentication.
+@subsubsection AArch64 Pointer Authentication
+@cindex Pointer Authentication, AArch64
+@cindex PAC, AArch64
@anchor{AArch64 PAC}
When @value{GDBN} is debugging the AArch64 architecture, and the program is
@@ -26921,8 +26998,9 @@ When GDB prints a backtrace, any addresses that required unmasking will be
postfixed with the marker [PAC]. When using the MI, this is printed as part
of the @code{addr_flags} field.
-@subsubsection AArch64 Memory Tagging Extension.
-@cindex AArch64 Memory Tagging Extension.
+@subsubsection AArch64 Memory Tagging Extension
+@cindex Memory Tagging Extension, AArch64
+@cindex MTE, AArch64
When @value{GDBN} is debugging the AArch64 architecture, the program is
using the v8.5-A feature Memory Tagging Extension (MTE) and there is support
@@ -26976,6 +27054,32 @@ information automatically from the core file, and will show one of the above
messages depending on whether the synchronous or asynchronous mode is selected.
@xref{Memory Tagging}. @xref{Memory}.
+@subsubsection AArch64 Guarded Control Stack
+@cindex Guarded Control Stack, AArch64
+@cindex GCS, AArch64
+
+When @value{GDBN} is debugging the AArch64 architecture, the program is
+using the feature Guarded Control Stack (GCS), the operating system kernel
+is Linux and it supports GCS, @value{GDBN} will make a couple of special
+registers --- @code{gcs_features_enabled} and @code{gcs_features_locked}
+--- available through the @code{org.gnu.gdb.aarch64.gcs.linux} feature.
+These registers expose some options that can be controlled at runtime and
+emulate the @code{prctl} option @code{PR_SET_SHADOW_STACK_STATUS}. For
+further information, see the
+@uref{https://www.kernel.org/doc/html/latest/arch/arm64/gcs.html,ignored,
+documentation} in the Linux kernel.
+
+Naturally the Guarded Control Stack pointer at @code{EL0} is also
+available, as the @code{gcspr} register.
+
+To aid debugging, @value{GDBN} will note when SIGSEGV signals are generated
+as a result of a Guarded Control Stack error:
+
+@smallexample
+Program received signal SIGSEGV, Segmentation fault
+Guarded Control Stack error.
+@end smallexample
+
@node x86
@subsection x86
@@ -27017,6 +27121,46 @@ registers
@end itemize
+@subsubsection Intel Control-Flow Enforcement Technology.
+@cindex Intel Control-Flow Enforcement Technology.
+
+The @dfn{Intel Control-Flow Enforcement Technology} (@acronym{Intel CET})
+provides two capabilities to defend against ``Return-oriented Programming''
+and ``call/jmp-oriented programming'' style control-flow attacks:
+
+@itemize @bullet
+@item Shadow Stack:
+A shadow stack is a second stack for a program. It holds the return
+addresses pushed by the call instruction. The @code{RET} instruction pops the
+return addresses from both call and shadow stack. If the return addresses from
+the two stacks do not match, the processor signals a control protection
+exception.
+@item Indirect Branch Tracking (IBT):
+When IBT is enabled, the CPU implements a state machine that tracks
+indirect @code{JMP} and @code{CALL} instructions. The state machine can
+be either IDLE or WAIT_FOR_ENDBRANCH. When a @code{JMP} or @code{CALL} is
+executed the state machine chages to the WAIT_FOR_ENDBRANCH state. In
+WAIT_FOR_ENDBRANCH state the next instruction in the program stream
+must be an @code{ENDBR} instruction, otherwise the processor signals a
+control protection exception. After executing a @code{ENDBR} instruction
+the state machine returns to the IDLE state.
+@end itemize
+
+Impact on @value{GDBN} commands:
+@itemize @bullet
+@item Call/Print:
+Inferior calls in @value{GDBN} reset the current PC to the beginning of the
+function that is called. No call instruction is executed, but the @code{RET}
+instruction actually is. To avoid a control protection exception due to the
+missing return address on the shadow stack, @value{GDBN} pushes the new return
+address to the shadow stack and updates the shadow stack pointer.
+@item Step:
+With displaced stepping, @value{GDBN} may run an out of line copy of a call
+instruction. In this case, the wrong return address is pushed to the shadow
+stack. @value{GDBN} corrects this value to avoid a control protection
+exception. For more details on displaced stepping, see @ref{displaced-stepping}.
+@end itemize
+
@node Alpha
@subsection Alpha
@@ -27639,6 +27783,16 @@ or a prompt that does not.
@item set prompt @var{newprompt}
Directs @value{GDBN} to use @var{newprompt} as its prompt string henceforth.
+For example, this will set a blue-colored ``(gdb)'' prompt:
+
+@smallexample
+set prompt \001\033[0;34m\002(gdb)\001\033[0m\002
+@end smallexample
+
+It uses @samp{\001} and @samp{\002} to begin and end a sequence of
+non-printing characters, to make sure they're not counted in the string
+length.
+
@kindex show prompt
@item show prompt
Prints a line of the form: @samp{Gdb's prompt is: @var{your-prompt}}
@@ -27974,6 +28128,19 @@ value, then @value{GDBN} will change this to @samp{off} at startup.
@item show style enabled
Show the current state of styling.
+@item set style emoji @samp{auto|on|off}
+Enable or disable the use of emoji. On most hosts, the default is
+@samp{auto}, meaning that emoji will only be used if the host
+character set is @samp{UTF-8}; however, on Windows the default is
+@samp{off} when using the console. Note that disabling styling as a
+whole will also prevent emoji display.
+
+Currently, emoji are printed whenever @value{GDBN} reports an error or
+a warning.
+
+@item show style emoji
+Show the current state of emoji output.
+
@item set style sources @samp{on|off}
Enable or disable source code styling. This affects whether source
code, such as the output of the @code{list} command, is styled. The
@@ -27990,6 +28157,18 @@ then it will be used.
@item show style sources
Show the current state of source code styling.
+@anchor{warning-prefix}
+@item set style warning-prefix
+@itemx show style warning-prefix
+@itemx set style error-prefix
+@itemx show style error-prefix
+
+These commands control the prefix that is printed before warnings and
+errors, respectively. This functionality is intended for use with
+emoji display, and so the prefixes are only displayed if emoji styling
+is enabled. The defaults are the warning sign emoji for warnings, and
+and the cross mark emoji for errors.
+
@item set style tui-current-position @samp{on|off}
Enable or disable styling of the source and assembly code highlighted
by the TUI's current position indicator. The default is @samp{off}.
@@ -31292,138 +31471,13 @@ appropriate @code{set style} commands. @xref{Output Styling}.
@cindex Emacs
@cindex @sc{gnu} Emacs
-A special interface allows you to use @sc{gnu} Emacs to view (and
-edit) the source files for the program you are debugging with
-@value{GDBN}.
-
-To use this interface, use the command @kbd{M-x gdb} in Emacs. Give the
-executable file you want to debug as an argument. This command starts
-@value{GDBN} as a subprocess of Emacs, with input and output through a newly
-created Emacs buffer.
-@c (Do not use the @code{-tui} option to run @value{GDBN} from Emacs.)
-Running @value{GDBN} under Emacs can be just like running @value{GDBN} normally except for two
-things:
-
-@itemize @bullet
-@item
-All ``terminal'' input and output goes through an Emacs buffer, called
-the GUD buffer.
-
-This applies both to @value{GDBN} commands and their output, and to the input
-and output done by the program you are debugging.
-
-This is useful because it means that you can copy the text of previous
-commands and input them again; you can even use parts of the output
-in this way.
-
-All the facilities of Emacs' Shell mode are available for interacting
-with your program. In particular, you can send signals the usual
-way---for example, @kbd{C-c C-c} for an interrupt, @kbd{C-c C-z} for a
-stop.
-
-@item
-@value{GDBN} displays source code through Emacs.
-
-Each time @value{GDBN} displays a stack frame, Emacs automatically finds the
-source file for that frame and puts an arrow (@samp{=>}) at the
-left margin of the current line. Emacs uses a separate buffer for
-source display, and splits the screen to show both your @value{GDBN} session
-and the source.
-
-Explicit @value{GDBN} @code{list} or search commands still produce output as
-usual, but you probably have no reason to use them from Emacs.
-@end itemize
+In @sc{gnu} Emacs there is a special interface to @value{GDBN}, which
+facilitates viewing the source code for the program you are debugging.
+There is also an IDE-like interface to GDB, with specialized buffers for
+breakpoints, stack frames and other aspects of the debugger state.
-We call this @dfn{text command mode}. Emacs 22.1, and later, also uses
-a graphical mode, enabled by default, which provides further buffers
-that can control the execution and describe the state of your program.
-@xref{GDB Graphical Interface,,, Emacs, The @sc{gnu} Emacs Manual}.
-
-If you specify an absolute file name when prompted for the @kbd{M-x
-gdb} argument, then Emacs sets your current working directory to where
-your program resides. If you only specify the file name, then Emacs
-sets your current working directory to the directory associated
-with the previous buffer. In this case, @value{GDBN} may find your
-program by searching your environment's @env{PATH} variable, but on
-some operating systems it might not find the source. So, although the
-@value{GDBN} input and output session proceeds normally, the auxiliary
-buffer does not display the current source and line of execution.
-
-The initial working directory of @value{GDBN} is printed on the top
-line of the GUD buffer and this serves as a default for the commands
-that specify files for @value{GDBN} to operate on. @xref{Files,
-,Commands to Specify Files}.
-
-By default, @kbd{M-x gdb} calls the program called @file{gdb}. If you
-need to call @value{GDBN} by a different name (for example, if you
-keep several configurations around, with different names) you can
-customize the Emacs variable @code{gud-gdb-command-name} to run the
-one you want.
-
-In the GUD buffer, you can use these special Emacs commands in
-addition to the standard Shell mode commands:
-
-@table @kbd
-@item C-h m
-Describe the features of Emacs' GUD Mode.
-
-@item C-c C-s
-Execute to another source line, like the @value{GDBN} @code{step} command; also
-update the display window to show the current file and location.
-
-@item C-c C-n
-Execute to next source line in this function, skipping all function
-calls, like the @value{GDBN} @code{next} command. Then update the display window
-to show the current file and location.
-
-@item C-c C-i
-Execute one instruction, like the @value{GDBN} @code{stepi} command; update
-display window accordingly.
-
-@item C-c C-f
-Execute until exit from the selected stack frame, like the @value{GDBN}
-@code{finish} command.
-
-@item C-c C-r
-Continue execution of your program, like the @value{GDBN} @code{continue}
-command.
-
-@item C-c <
-Go up the number of frames indicated by the numeric argument
-(@pxref{Arguments, , Numeric Arguments, Emacs, The @sc{gnu} Emacs Manual}),
-like the @value{GDBN} @code{up} command.
-
-@item C-c >
-Go down the number of frames indicated by the numeric argument, like the
-@value{GDBN} @code{down} command.
-@end table
-
-In any source file, the Emacs command @kbd{C-x @key{SPC}} (@code{gud-break})
-tells @value{GDBN} to set a breakpoint on the source line point is on.
-
-In text command mode, if you type @kbd{M-x speedbar}, Emacs displays a
-separate frame which shows a backtrace when the GUD buffer is current.
-Move point to any frame in the stack and type @key{RET} to make it
-become the current frame and display the associated source in the
-source buffer. Alternatively, click @kbd{Mouse-2} to make the
-selected frame become the current one. In graphical mode, the
-speedbar displays watch expressions.
-
-If you accidentally delete the source-display buffer, an easy way to get
-it back is to type the command @code{f} in the @value{GDBN} buffer, to
-request a frame display; when you run under Emacs, this recreates
-the source buffer if necessary to show you the context of the current
-frame.
-
-The source files displayed in Emacs are in ordinary Emacs buffers
-which are visiting the source files in the usual way. You can edit
-the files with these buffers if you wish; but keep in mind that @value{GDBN}
-communicates with Emacs in terms of line numbers. If you add or
-delete lines from the text, the line numbers that @value{GDBN} knows cease
-to correspond properly with the code.
-
-A more detailed description of Emacs' interaction with @value{GDBN} is
+A detailed description of Emacs' interaction with @value{GDBN} is
given in the Emacs manual (@pxref{Debuggers,,, Emacs, The @sc{gnu}
Emacs Manual}).
@@ -38950,7 +39004,7 @@ Example output:
@smallexample
(gdb) -list-features
-^done,result=["feature1","feature2"]
+^done,features=["feature1","feature2"]
@end smallexample
The current list of features is:
@@ -39015,7 +39069,7 @@ Example output:
@smallexample
(gdb) -list-target-features
-^done,result=["async"]
+^done,features=["async"]
@end smallexample
The current list of features is:
@@ -41347,6 +41401,14 @@ Configure @value{GDBN} for cross-debugging programs running on the
specified list of targets. The special value @samp{all} configures
@value{GDBN} for debugging programs running on any target it supports.
+@item --enable-binary-file-formats=@r{[}@var{format}@r{]}@dots{}
+@itemx --enable-binary-file-formats=all
+Configure @value{GDBN} to support certain binary file formats. If a
+format is the main (or only) file format for a given target, the
+configure script may add support to it anyway, and warn the user.
+If not given, all file formats that @value{GDBN} supports are compiled
+in.
+
@item --with-gdb-datadir=@var{path}
Set the @value{GDBN}-specific data directory. @value{GDBN} will look
here for certain supporting files or scripts. This defaults to the
@@ -41434,7 +41496,7 @@ libpython is present and found at configure time.) Python makes
@value{GDBN} scripting much more powerful than the restricted CLI
scripting language. If your host does not have Python installed, you
can find it on @url{http://www.python.org/download/}. The oldest version
-of Python supported by GDB is 3.0.1. The optional argument @var{python}
+of Python supported by GDB is 3.4. The optional argument @var{python}
is used to find the Python headers and libraries. It can be either
the name of a Python executable, or the name of the directory in which
Python is installed.
@@ -41792,6 +41854,7 @@ GLOBAL Disassembler_2 (Matches current architecture)
@cindex out-of-line single-stepping
@item set displaced-stepping
@itemx show displaced-stepping
+@anchor{displaced-stepping}
Control whether or not @value{GDBN} will do @dfn{displaced stepping}
if the target supports it. Displaced stepping is a way to single-step
over breakpoints without removing them from the inferior, by executing
@@ -42835,6 +42898,23 @@ reports and error and the command is aborted.
@item show watchdog
Show the current setting of the target wait timeout.
+
+@kindex maint set console-translation-mode
+@kindex maint show console-translation-mode
+@item maint set console-translation-mode @r{[}binary|text@r{]}
+@itemx maint show console-translation-mode
+Controls the translation mode of @value{GDBN} stdout/stderr. MS-Windows
+only. Useful for running the @value{GDBN} testsuite.
+
+The translation mode values are as follows:
+@table @code
+@item binary
+No translation.
+@item text
+Translate @samp{\n} (LF, a single Line Feed) into @samp{\r\n} (CR-LF, a
+Carriage Return-Line Feed combination).
+@end table
+
@end table
@node Remote Protocol
@@ -43691,6 +43771,12 @@ command line. The file and arguments are hex-encoded strings. If
(e.g.@: the last program run). The program is created in the stopped
state.
+If @value{GDBN} sent the @samp{single-inf-arg} feature in the
+@samp{qSupported} packet (@pxref{single-inf-arg}), and the stub replied
+with @samp{single-inf-arg+}, then there will only be a single
+@var{argument} string, which includes all inferior arguments,
+separated with whitespace.
+
@c FIXME: What about non-stop mode?
This packet is only available in extended mode (@pxref{extended mode}).
@@ -44932,7 +45018,8 @@ packets.)
@anchor{qSearch memory}
Search @var{length} bytes at @var{address} for @var{search-pattern}.
Both @var{address} and @var{length} are encoded in hex;
-@var{search-pattern} is a sequence of bytes, also hex encoded.
+@var{search-pattern} is a sequence of binary-encoded bytes
+(@pxref{Binary Data}).
Reply:
@table @samp
@@ -45074,6 +45161,14 @@ didn't support @samp{E.@var{errtext}}, and older versions of
New packets should be written to support @samp{E.@var{errtext}}
regardless of this feature being true or not.
+
+@anchor{single-inf-arg}
+@item single-inf-arg
+This feature indicates that @value{GDBN} would like to send the
+inferior arguments as a single string within the @samp{vRun} packet.
+@value{GDBN} will not send the arguments as a single string unless the
+stub also reports that it supports this behaviour by including
+@samp{single-inf-arg+} in its @samp{qSupported} reply.
@end table
Stubs should ignore any unknown values for
@@ -45377,6 +45472,11 @@ These are the currently defined stub features and their properties:
@tab @samp{-}
@tab No
+@item @samp{single-inf-arg}
+@tab No
+@tab @samp{-}
+@tab No
+
@end multitable
These are the currently defined stub features, in more detail:
@@ -45626,6 +45726,12 @@ if it sent the @samp{error-message} feature.
@item binary-upload
The remote stub supports the @samp{x} packet (@pxref{x packet}).
+
+@item single-inf-arg
+The remote stub would like to receive the inferior arguments as a
+single string within the @samp{vRun} packet. The stub should only
+send this feature if @value{GDBN} sent @samp{single-inf-arg+} in the
+@samp{qSupported} packet.
@end table
@item qSymbol::
@@ -46811,12 +46917,28 @@ If an error occurs the return value is -1. The format of the
returned binary attachment is as described in @ref{struct stat}.
@item vFile:stat: @var{filename}
-Get information about the file @var{filename} on the target.
-On success the information is returned as a binary attachment
-and the return value is the size of this attachment in bytes.
-If an error occurs the return value is -1. The format of the
+Get information about the file @var{filename} on the target as if from
+a @samp{stat} call. On success the information is returned as a binary
+attachment and the return value is the size of this attachment in
+bytes. If an error occurs the return value is -1. The format of the
returned binary attachment is as described in @ref{struct stat}.
+If @var{filename} is a symbolic link, then the information returned is
+about the file the link refers to, this is inline with the @samp{stat}
+library call.
+
+@item vFile:lstat: @var{filename}
+Get information about the file @var{filename} on the target as if from
+an @samp{lstat} call. On success the information is returned as a
+binary attachment and the return value is the size of this attachment
+in bytes. If an error occurs the return value is -1. The format of
+the returned binary attachment is as described in @ref{struct stat}.
+
+This packet is identical to @samp{vFile:stat}, except if
+@var{filename} is a symbolic link, then this packet returns
+information about the link itself, not the file that the link refers
+to, this is inline with the @samp{lstat} library call.
+
@item vFile:unlink: @var{filename}
Delete the file at @var{filename} on the target. Return 0,
or -1 if an error occurs. The @var{filename} is a string.
@@ -49284,6 +49406,7 @@ registers using the capitalization used in the description.
@menu
* AArch64 Features::
+* Alpha Features::
* ARC Features::
* ARM Features::
* i386 Features::
@@ -49590,6 +49713,104 @@ of bytes.
Extra registers are allowed in this feature, but they will not affect
@value{GDBN}.
+@subsubsection AArch64 GCS registers feature
+
+The @samp{org.gnu.gdb.aarch64.gcs} feature is optional. If present, it
+means the target supports Guarded Control Stacks and must contain the
+following register:
+
+@itemize @minus
+
+@item
+@code{gcspr}, which points to the thread's Guarded Control Stack. It is 64
+bits in size and has a type of @samp{data_ptr}.
+
+@end itemize
+
+The @samp{org.gnu.gdb.aarch64.gcs.linux} feature is optional. If present,
+then the @samp{org.gnu.gdb.aarch64.gcs} feature must also be present. The
+@samp{org.gnu.gdb.aarch64.gcs.linux} feature represents facilities provided
+by the Linux kernel for GCS support and should contain the following:
+
+@itemize @minus
+
+@item
+@code{gcs_features_enabled} shows the features currently enabled via the
+prctl or ptrace system calls. It is represented as if it were a 64-bit
+register with a custom flags type.
+
+@item
+@code{gcs_features_locked} shows the features currently locked via the
+prctl or ptrace system calls. It is represented as if it were a 64-bit
+register with a custom flags type.
+
+@end itemize
+
+The custom flags type allows @value{GDBN} to print a human-friendly
+representation of the contents of @code{gcs_features_enabled} and
+@code{gcs_features_locked} and should contain:
+
+@itemize @minus
+
+@item
+@code{PR_SHADOW_STACK_ENABLE}
+
+@item
+@code{PR_SHADOW_STACK_WRITE}
+
+@item
+@code{PR_SHADOW_STACK_PUSH}
+
+@end itemize
+
+For further information, see the
+@uref{https://www.kernel.org/doc/html/latest/arch/arm64/gcs.html,ignored,
+documentation} in the Linux kernel.
+
+Extra registers are allowed in these features, but they will not affect
+@value{GDBN}.
+
+@node Alpha Features
+@subsection Alpha Features
+@cindex target descriptions, Alpha Features
+
+The @samp{org.gnu.gdb.alpha.core} feature is required for Alpha targets. It
+must contain the following 64-bit registers; note that @value{GDBN} uses the
+software names for Alpha registers:
+
+@itemize @minus
+@item
+@samp{v0}: function return value
+@item
+@samp{t0} through @samp{t12}: temporary registers
+@item
+@samp{s0} through @samp{s5}: saved registers
+@item
+@samp{fp}: frame pointer
+@item
+@samp{a0} through @samp{a5}: argument registers
+@item
+@samp{ra}: return address
+@item
+@samp{at}: assembler temporary register
+@item
+@samp{gp}: global pointer
+@item
+@samp{sp}: stack pointer
+@item
+@samp{zero}: always zero
+@item
+@samp{f0} through @samp{f30}: floating-point registers
+@item
+@samp{fpcr}: floating-point control register
+@item
+@samp{pc}: program counter
+@item
+@samp{}: an anonymous register for historical purpose
+@item
+@samp{unique}: PALcode memory slot
+@end itemize
+
@node ARC Features
@subsection ARC Features
@cindex target descriptions, ARC Features
@@ -50023,6 +50244,12 @@ The @samp{org.gnu.gdb.i386.pkeys} feature is optional. It should
describe a single register, @samp{pkru}. It is a 32-bit register
valid for i386 and amd64.
+The @samp{org.gnu.gdb.i386.pl3_ssp} feature is optional. It should
+describe the user mode register @samp{pl3_ssp} which has 64 bits on
+amd64, 32 bits on amd64 with 32-bit pointer size (X32) and 32 bits on i386.
+Following the restriction of the Linux kernel, only @value{GDBN} for amd64
+targets makes use of this feature for now.
+
@node LoongArch Features
@subsection LoongArch Features
@cindex target descriptions, LoongArch Features
@@ -50542,17 +50769,13 @@ unless otherwise noted:
@enumerate
@item
-The version number, currently 9. Versions 1, 2 and 3 are obsolete.
-Version 4 uses a different hashing function from versions 5 and 6.
-Version 6 includes symbols for inlined functions, whereas versions 4
-and 5 do not. Version 7 adds attributes to the CU indices in the
-symbol table. Version 8 specifies that symbols from DWARF type units
+The version number, currently 9. Versions 1 through 6 are obsolete.
+Version 7 adds attributes to the CU indices in the symbol table.
+Version 8 specifies that symbols from DWARF type units
(@samp{DW_TAG_type_unit}) refer to the type unit's symbol table and not the
compilation unit (@samp{DW_TAG_comp_unit}) using the type. Version 9 adds
the name and the language of the main function to the index.
-@value{GDBN} will only read version 4, 5, or 6 indices
-by specifying @code{set use-deprecated-index-sections on}.
GDB has a workaround for potentially broken version 7 indices so it is
currently not flagged as deprecated.
@@ -51096,9 +51319,10 @@ Note that targets that give their output via @value{GDBN}, as opposed to writing
directly to @code{stdout}, will also be made silent.
@item --args @var{prog} [@var{arglist}]
-Change interpretation of command line so that arguments following this
-option are passed as arguments to the inferior. As an example, take
-the following command:
+@itemx --no-escape-args @var{prog} [@var{arglist}]
+Change interpretation of command line so that arguments following
+either of these options are passed as arguments to the inferior. As
+an example, take the following command:
@smallexample
gdb ./a.out -q
@@ -51113,7 +51337,44 @@ gdb --args ./a.out -q
@end smallexample
@noindent
-starts @value{GDBN} with the introductory message, and passes the option to the inferior.
+starts @value{GDBN} with the introductory message, and passes the
+option @code{-q} to the inferior.
+
+The difference between @option{--args} and @option{--no-escape-args}
+is whether @value{GDBN} applies escapes to the arguments it sees:
+
+@smallexample
+gdb --args ./a.out *.c
+@end smallexample
+
+@noindent
+in this case the @code{*.c} is expanded by the shell that invokes
+@value{GDBN}, the list of matching files will be fixed in the inferior
+argument list. If instead this is used:
+
+@smallexample
+gdb --args ./a.out '*.c'
+@end smallexample
+
+@noindent
+then the shell that invokes @value{GDBN} will not expand @code{*.c},
+instead @value{GDBN} will escape the @code{*} character, so when a.out
+is invoked it will be passed a literal @code{*.c}. If instead this is
+used:
+
+@smallexample
+gdb --no-escape-args ./a.out '*.c'
+@end smallexample
+
+@noindent
+now @value{GDBN} will not escape the @code{*} character. When the
+inferior is invoked the @code{*.c} will be expanded, and the inferior
+will be passed the list of files as present at the time the inferior
+is invoked.
+
+This change of behaviour can be important if the list of matching
+files could change between the time that @value{GDBN} is started, and
+the time the inferior is started.
@item --pid=@var{pid}
Attach @value{GDBN} to an already running program, with the PID @var{pid}.
@@ -51455,6 +51716,18 @@ additional connections are possible. However, if you start @code{gdbserver}
with the @option{--once} option, it will stop listening for any further
connection attempts after connecting to the first @value{GDBN} session.
+@item --no-escape-args
+By default, inferior arguments passed on the @command{gdbserver}
+command line will have any special shell characters escaped by
+@command{gdbserver}. This ensures that when @command{gdbserver}
+invokes the inferior, the arguments passed to the inferior are
+identical to the arguments passed to @command{gdbserver}.
+
+To disable this escaping, use @option{--no-escape-args}. With this
+option special shell characters will not be escaped. When
+@command{gdbserver} starts a new shell in order to invoke the
+inferior, this new shell will expand any special shell characters.
+
@c --disable-packet is not documented for users.
@c --disable-randomization and --no-disable-randomization are superseded by
diff --git a/gdb/doc/guile.texi b/gdb/doc/guile.texi
index c6808ef..9677229 100644
--- a/gdb/doc/guile.texi
+++ b/gdb/doc/guile.texi
@@ -1772,6 +1772,16 @@ invoking it interactively. If this function throws an exception,
it is turned into a @value{GDBN} @code{error} call.
Otherwise, the return value is ignored.
+For non-prefix commands, @var{invoke} is required. For prefix
+commands @var{invoke} is optional. Only prefix commands that need to
+handle unknown sub-commands should supply @var{invoke}.
+
+For prefix commands that don't supply @var{invoke}, if the prefix
+command is used without a sub-command name then @value{GDBN} will
+display the help text for every sub-command, unless the prefix command
+is a @kbd{show} sub-command, in which case @value{GDBN} will list the
+values of all sub-commands.
+
The argument @var{command-class} is one of the @samp{COMMAND_} constants
defined below. This argument tells @value{GDBN} how to categorize the
new command in the help system. The default is @code{COMMAND_NONE}.
@@ -2098,8 +2108,10 @@ is the @code{<gdb:parameter>} object representing the parameter, and
This function must return a string, and will be displayed to the user.
@value{GDBN} will add a trailing newline.
-The argument @var{doc} is the help text for the new parameter.
-If there is no documentation string, a default value is used.
+The argument @var{doc} is the help text for the new parameter. If
+there is no documentation string, a default value is used. If the
+documentation string is empty, then @value{GDBN} will print just the
+@var{set-doc} and @var{show-doc} strings (see below).
The argument @var{set-doc} is the help text for this parameter's
@code{set} command.
@@ -3899,6 +3911,9 @@ Return string to change terminal's color to this.
If @var{is_foreground} is @code{#t}, then the returned sequence will change
foreground color. Otherwise, the returned sequence will change background
color.
+
+If styling is currently disabled (@pxref{Output Styling,,@kbd{set style
+enabled}}), then this procedure will return an empty string.
@end deffn
When color is initialized, its color space must be specified. The
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index afbd62f..3763eee 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -479,7 +479,7 @@ call this function and will automatically direct the output to the
relevant stream.
@end defun
-@defun gdb.flush (@r{[}, stream@r{]})
+@defun gdb.flush (@r{[}stream@r{]})
Flush the buffer of a @value{GDBN} paginated stream so that the
contents are displayed immediately. @value{GDBN} will flush the
contents of a stream automatically when it encounters a newline in the
@@ -509,6 +509,17 @@ Flushing @code{sys.stdout} or @code{sys.stderr} will automatically
call this function for the relevant stream.
@end defun
+@defun gdb.warning (text)
+Print a warning message to @value{GDBN}'s standard output stream. The
+warning message is the warning prefix (@pxref{warning-prefix}), the
+string @w{@samp{warning: }}, and then @var{text}, which must be a
+non-empty string.
+
+Due to the warning prefix, @var{text} should not begin with a capital
+letter (except for proper nouns), and @var{text} should end with a
+period.
+@end defun
+
@defun gdb.target_charset ()
Return the name of the current target character set (@pxref{Character
Sets}). This differs from @code{gdb.parameter('target-charset')} in
@@ -899,7 +910,26 @@ this attribute holds @code{None}.
@cindex optimized out value in Python
@defvar Value.is_optimized_out
This read-only boolean attribute is true if the compiler optimized out
-this value, thus it is not available for fetching from the inferior.
+this value, or any part of this value, and thus it is not available
+for fetching from the inferior.
+@end defvar
+
+@cindex unavailable values in Python
+@defvar Value.is_unavailable
+This read-only boolean attribute is true if this value, or any part of
+this value, is not available to @value{GDBN}. Where an optimized out
+value has been removed from the program by the compiler, an
+unavailable value does exist in the program, but @value{GDBN} is
+unable to fetch it.
+
+Some reasons why this might occur include, but are not limited to: a
+core file format that @value{GDBN} doesn't fully understand; during
+live debugging if the debug API has no mechanism to access the
+required state, e.g.@: the kernel gives an error when trying to read a
+particular register set; or reading a value from @value{GDBN}'s
+history, when only a partial value was stored, e.g.@: due to the
+@kbd{max-value-size} setting (@pxref{set
+max-value-size,,max-value-size}).
@end defvar
@defvar Value.type
@@ -4525,6 +4555,7 @@ You can implement new @value{GDBN} CLI commands in Python. A CLI
command is implemented using an instance of the @code{gdb.Command}
class, most commonly using a subclass.
+@anchor{Command.__init__}
@defun Command.__init__ (name, command_class @r{[}, completer_class @r{[}, prefix@r{]]})
The object initializer for @code{Command} registers the new command
with @value{GDBN}. This initializer is normally invoked from the
@@ -4558,6 +4589,7 @@ documentation string is provided, the default value @samp{This command
is not documented.} is used.
@end defun
+@anchor{Command.dont_repeat}
@cindex don't repeat Python command
@defun Command.dont_repeat ()
By default, a @value{GDBN} command is repeated when the user enters a
@@ -4568,6 +4600,7 @@ exception). This is similar to the user command @code{dont-repeat},
see @ref{Define, dont-repeat}.
@end defun
+@anchor{Command.invoke}
@defun Command.invoke (argument, from_tty)
This method is called by @value{GDBN} when this command is invoked.
@@ -4581,6 +4614,17 @@ that the command came from elsewhere.
If this method throws an exception, it is turned into a @value{GDBN}
@code{error} call. Otherwise, the return value is ignored.
+For non-prefix commands (@pxref{Command.__init__}), the @code{invoke}
+method is required. For prefix commands the @code{invoke} method is
+optional. Only prefix commands that need to handle unknown
+sub-commands should implement the @code{invoke} method.
+
+For prefix commands that don't implement @code{invoke}, if the prefix
+command is used without a sub-command name then @value{GDBN} will
+display the help text for every sub-command, unless the prefix command
+is a @kbd{show} sub-command, in which case @value{GDBN} will list the
+values of all sub-commands.
+
@findex gdb.string_to_argv
To break @var{argument} up into an argv-like string use
@code{gdb.string_to_argv}. This function behaves identically to
@@ -5079,7 +5123,9 @@ string from the parameter's class, if there is one. If there is no
documentation string, a default value is used. The documentation
string is included in the output of the parameters @code{help set} and
@code{help show} commands, and should be written taking this into
-account.
+account. If the documentation string for the parameter's class is the
+empty string then @value{GDBN} will only use @code{Parameter.set_doc}
+or @code{Parameter.show_doc} (see below) in the @kbd{help} output.
@end defun
@defvar Parameter.set_doc
@@ -5258,6 +5304,99 @@ constants provided when the parameter is created.
The value is @code{gdb.Color} instance.
@end table
+When creating multiple new parameters using @code{gdb.Parameter}, it
+is often desirable to create a prefix command that can be used to
+group related parameters together, for example, if you wished to add
+the parameters @kbd{plugin-name feature-1} and @kbd{plugin-name
+feature-2}, then the @kbd{plugin-name} would need to be a prefix
+command (@pxref{CLI Commands In Python}).
+
+However, when creating parameters, you will almost always need to
+create two prefix commands, one as a @kbd{set} sub-command, and one as
+a @kbd{show} sub-command. @value{GDBN} provides the
+@code{gdb.ParameterPrefix} helper class to make creation of these two
+prefixes easier.
+
+@defun ParameterPrefix.__init__ (name, command_class, doc = @code{None})
+The object initializer for @code{ParameterPrefix} registers two new
+@code{gdb.Command} prefixes, one as a @kbd{set} sub-command, and the
+other as a @kbd{show} sub-command.
+
+@var{name}, a string, is the name of the new prefix, without either
+@kbd{set} or @kbd{show}, similar to the @var{name} passed to
+@code{gdb.Parameter} (@pxref{Parameters In Python}). For example, to
+create the prefixes @kbd{set plugin-name} and @kbd{show plugin-name},
+you would pass the string @kbd{plugin-name}.
+
+@var{command_class} should be one of the @samp{COMMAND_} constants
+(@pxref{CLI Commands In Python}). This argument tells @value{GDBN} how to
+categorize the new parameter prefixes in the help system.
+
+There are a number of ways in which the help text for the two new
+prefix commands can be provided. If the @var{doc} parameter is not
+@code{None}, then this will be used as the documentation string for
+both prefix commands.
+
+If @var{doc} is @code{None}, but @code{gdb.ParameterPrefix} has been
+sub-classed, then the prefix command documentation will be taken from
+sub-classes documentation string (i.e., the @code{__doc__} attribute).
+
+If @var{doc} is @code{None}, and there is no @code{__doc__} string,
+then the default value @samp{This command is not documented.} is used.
+
+When writing the help text, keep in mind that the same text is used
+for both the @kbd{set} and @kbd{show} prefix commands.
+@end defun
+
+@defun ParameterPrefix.invoke_set (argument, from_tty)
+If a sub-class defines this method, then @value{GDBN} will call this
+when the prefix command is used with an unknown sub-command. The
+@var{argument} and @var{from_tty} parameters are the same as for
+@code{gdb.Command.invoke} (@pxref{Command.invoke}).
+
+If this method throws an exception, it is turned into a @value{GDBN}
+@code{error} call. Otherwise, the return value is ignored.
+
+It is not required that a @code{ParameterPrefix} sub-class override
+this method. Usually, a parameter prefix only exists as a means to
+group related parameters together. @value{GDBN} handles this use case
+automatically with no need to implement @code{invoke_set}.
+@end defun
+
+@defun ParameterPrefix.invoke_show (argument, from_tty)
+This is like the @code{invoke_set} method, but for the @kbd{show}
+prefix command. As with @code{invoke_set}, implementation of this
+method is optional, and usually not required.
+@end defun
+
+@cindex don't repeat Python command
+@defun ParameterPrefix.dont_repeat ()
+Like @code{Command.dont_repeat} (@pxref{Command.dont_repeat}), this
+can be called from @code{ParameterPrefix.invoke_set} or
+@code{ParameterPrefix.invoke_show} to prevent the prefix commands from
+being repeated.
+@end defun
+
+Here is a small example that uses @code{gdb.ParameterPrefix} along
+with @code{gdb.Parameter} to create two new parameters
+@kbd{plugin-name feature-1} and @kbd{plugin-name feature-2}. As
+neither @code{invoke_set} or @code{invoke_show} is needed, this
+example does not sub-class @code{gdb.ParameterPrefix}:
+
+@smallexample
+class ExampleParam(gdb.Parameter):
+ def __init__ (self, name):
+ super ().__init__ (name, gdb.COMMAND_DATA, gdb.PARAM_BOOLEAN)
+ self.value = True
+
+gdb.ParameterPrefix("plugin-name", gdb.COMMAND_NONE,
+ """An example parameter prefix.
+
+ This groups together some parameters.""")
+ExampleParam("plugin-name feature-1")
+ExampleParam("plugin-name feature-2")
+@end smallexample
+
@node Functions In Python
@subsubsection Writing new convenience functions
@@ -7101,6 +7240,9 @@ Returns string to change terminal's color to this.
If @var{is_foreground} is @code{True}, then the returned sequence will change
foreground color. Otherwise, the returned sequence will change background
color.
+
+If styling is currently disabled (@pxref{Output Styling,,@kbd{set style
+enabled}}), then this method will return an empty string.
@end defun
When color is initialized, its color space must be specified. The
diff --git a/gdb/dtrace-probe.c b/gdb/dtrace-probe.c
index fa60c34..c663571 100644
--- a/gdb/dtrace-probe.c
+++ b/gdb/dtrace-probe.c
@@ -889,9 +889,7 @@ info_probes_dtrace_command (const char *arg, int from_tty)
info_probes_for_spops (arg, from_tty, &dtrace_static_probe_ops);
}
-void _initialize_dtrace_probe ();
-void
-_initialize_dtrace_probe ()
+INIT_GDB_FILE (dtrace_probe)
{
all_static_probe_ops.push_back (&dtrace_static_probe_ops);
diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c
index f8440b3..445a7b4 100644
--- a/gdb/dummy-frame.c
+++ b/gdb/dummy-frame.c
@@ -425,9 +425,7 @@ maintenance_print_dummy_frames (const char *args, int from_tty)
}
}
-void _initialize_dummy_frame ();
-void
-_initialize_dummy_frame ()
+INIT_GDB_FILE (dummy_frame)
{
add_cmd ("dummy-frames", class_maintenance, maintenance_print_dummy_frames,
_("Print the contents of the internal dummy-frame stack."),
diff --git a/gdb/dwarf2/abbrev.c b/gdb/dwarf2/abbrev.c
index 5cfff69..e3c268e 100644
--- a/gdb/dwarf2/abbrev.c
+++ b/gdb/dwarf2/abbrev.c
@@ -108,6 +108,8 @@ abbrev_table::read (struct dwarf2_section_info *section,
cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
abbrev_ptr += 1;
+ cur_abbrev->maybe_ada_import = false;
+
unsigned int size = 0;
unsigned int sibling_offset = -1;
bool is_csize = true;
@@ -242,7 +244,12 @@ abbrev_table::read (struct dwarf2_section_info *section,
}
else if (has_hardcoded_declaration
&& (cur_abbrev->tag != DW_TAG_variable || !has_external))
- cur_abbrev->interesting = false;
+ {
+ cur_abbrev->interesting = false;
+ if (cur_abbrev->tag == DW_TAG_subprogram && has_name
+ && has_linkage_name)
+ cur_abbrev->maybe_ada_import = true;
+ }
else if (!tag_interesting_for_index (cur_abbrev->tag))
cur_abbrev->interesting = false;
else
diff --git a/gdb/dwarf2/abbrev.h b/gdb/dwarf2/abbrev.h
index 6fc61b1..a36bb8c 100644
--- a/gdb/dwarf2/abbrev.h
+++ b/gdb/dwarf2/abbrev.h
@@ -51,6 +51,14 @@ struct abbrev_info
/* True if the DIE has children. */
bool has_children;
bool interesting;
+ /* In Ada, an imported subprogram DIE will be marked as a
+ declaration, but will have both a name and a linkage name. This
+ declaration may be the only spot where that name is associated
+ with an object, so it has to show up in the index. But, because
+ abbrevs are CU-independent, we can't check the language when
+ computing them and instead we keep a separate flag to indicate
+ that the scanner should check this DIE. */
+ bool maybe_ada_import;
unsigned short size_if_constant;
unsigned short sibling_offset;
/* Number of attributes. */
diff --git a/gdb/dwarf2/ada-imported.c b/gdb/dwarf2/ada-imported.c
index 1e25966..48e6fcc 100644
--- a/gdb/dwarf2/ada-imported.c
+++ b/gdb/dwarf2/ada-imported.c
@@ -109,7 +109,7 @@ ada_alias_get_block_value (const struct symbol *sym)
if (real_symbol.symbol == nullptr)
error (_("could not find alias '%s' for function '%s'"),
name, sym->print_name ());
- if (real_symbol.symbol->aclass () != LOC_BLOCK)
+ if (real_symbol.symbol->loc_class () != LOC_BLOCK)
error (_("alias '%s' for function '%s' is not a function"),
name, sym->print_name ());
diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c
index 8ff0353..d2b5364 100644
--- a/gdb/dwarf2/attribute.c
+++ b/gdb/dwarf2/attribute.c
@@ -216,6 +216,22 @@ attribute::signed_constant () const
/* See attribute.h. */
+std::optional<LONGEST>
+attribute::confused_constant () const
+{
+ if (form_is_strictly_signed ())
+ return u.snd;
+ else if (form_is_constant ())
+ return u.unsnd;
+
+ /* For DW_FORM_data16 see attribute::form_is_constant. */
+ complaint (_("Attribute value is not a constant (%s)"),
+ dwarf_form_name (form));
+ return {};
+}
+
+/* See attribute.h. */
+
bool
attribute::form_is_unsigned () const
{
diff --git a/gdb/dwarf2/attribute.h b/gdb/dwarf2/attribute.h
index 31ff018..234de4e 100644
--- a/gdb/dwarf2/attribute.h
+++ b/gdb/dwarf2/attribute.h
@@ -123,6 +123,25 @@ struct attribute
empty value is returned. */
std::optional<LONGEST> signed_constant () const;
+ /* Return a signed constant value. However, for narrow forms like
+ DW_FORM_data1, sign extension is not done.
+
+ DWARF advises compilers to generally use DW_FORM_[su]data to
+ avoid ambiguity. However, both GCC and LLVM ignore this for
+ certain attributes. Furthermore in DWARF, whether a narrower
+ form causes sign-extension depends on the attribute -- for
+ attributes that can only assume non-negative values, sign
+ extension is not done.
+
+ Unfortunately, both compilers also emit certain attributes in a
+ "confused" way, using DW_FORM_sdata for signed values, and
+ possibly choosing a narrow form (e.g., DW_FORM_data1) otherwise
+ -- assuming that sign-extension will not be done.
+
+ This method should only be called when this "confused" treatment
+ is necessary. */
+ std::optional<LONGEST> confused_constant () const;
+
/* Return non-zero if ATTR's value falls in the 'constant' class, or
zero otherwise. When this function returns true, you can apply
the constant_value method to it.
diff --git a/gdb/dwarf2/call-site.h b/gdb/dwarf2/call-site.h
index e02cc5e..2cc4883 100644
--- a/gdb/dwarf2/call-site.h
+++ b/gdb/dwarf2/call-site.h
@@ -198,7 +198,7 @@ struct call_site
struct call_site *tail_call_next = nullptr;
/* * Describe DW_AT_call_target. Missing attribute uses
- FIELD_LOC_KIND_DWARF_BLOCK with FIELD_DWARF_BLOCK == NULL. */
+ m_loc_kind == DWARF_BLOCK with m_loc.dwarf_block == nullptr. */
struct call_site_target target {};
diff --git a/gdb/dwarf2/cooked-index-entry.c b/gdb/dwarf2/cooked-index-entry.c
index 52db851..0482b64 100644
--- a/gdb/dwarf2/cooked-index-entry.c
+++ b/gdb/dwarf2/cooked-index-entry.c
@@ -19,7 +19,6 @@
#include "dwarf2/cooked-index-entry.h"
#include "dwarf2/tag.h"
-#include "gdbsupport/gdb-safe-ctype.h"
#include "gdbsupport/selftest.h"
/* See cooked-index-entry.h. */
@@ -33,6 +32,7 @@ to_string (cooked_index_flag flags)
MAP_ENUM_FLAG (IS_LINKAGE),
MAP_ENUM_FLAG (IS_TYPE_DECLARATION),
MAP_ENUM_FLAG (IS_PARENT_DEFERRED),
+ MAP_ENUM_FLAG (IS_SYNTHESIZED),
};
return flags.to_string (mapping);
@@ -56,7 +56,7 @@ cooked_index_entry::compare (const char *stra, const char *strb,
template functions" section in the manual. */
if (c == '<')
return '\0';
- return TOLOWER ((unsigned char) c);
+ return c_tolower (c);
};
unsigned char a = munge (*stra);
@@ -188,8 +188,15 @@ cooked_index_entry::full_name (struct obstack *storage,
break;
case language_ada:
+ /* If GNAT emits hierarchical names (patches not in at the time
+ of writing), then we need to compute the linkage name here.
+ However for traditional GNAT, the linkage name will be in
+ 'name'. Detect this by looking for "__"; see also
+ cooked_index_shard::finalize. */
if ((name_flags & FOR_ADA_LINKAGE_NAME) != 0)
{
+ if (strstr (name, "__") != nullptr)
+ return name;
sep = "__";
break;
}
@@ -233,8 +240,7 @@ cooked_index_entry::write_scope (struct obstack *storage,
obstack_grow (storage, sep, strlen (sep));
}
-void _initialize_dwarf2_entry ();
-void _initialize_dwarf2_entry ()
+INIT_GDB_FILE (dwarf2_entry)
{
#if GDB_SELF_TEST
selftests::register_test ("cooked_index_entry::compare", test_compare);
diff --git a/gdb/dwarf2/cooked-index-shard.c b/gdb/dwarf2/cooked-index-shard.c
index c717bbb..e440d85 100644
--- a/gdb/dwarf2/cooked-index-shard.c
+++ b/gdb/dwarf2/cooked-index-shard.c
@@ -86,7 +86,21 @@ cooked_index_shard::add (sect_offset die_offset, enum dwarf_tag tag,
implicit "main" discovery. */
if ((flags & IS_MAIN) != 0)
m_main = result;
- else if ((flags & IS_PARENT_DEFERRED) == 0
+ /* The language check here is subtle: it exists solely to work
+ around a bug in .gdb_index. That index does not record
+ languages, but it might emit an entry for "main". However,
+ recognizing this "main" as being the main program would be wrong
+ -- for example, an Ada program has a C "main" but this is not the
+ desired target of the "start" command. Requiring the language to
+ be set here avoids over-eagerly setting the "main" when using
+ .gdb_index. Should .gdb_index ever be removed (PR symtab/31363),
+ the language_unknown check here could also be removed.
+
+ Note that this explicit check isn't truly needed (it is covered
+ by language_may_use_plain_main as well), but it's handy as a spot
+ to document. */
+ else if (lang != language_unknown
+ && (flags & IS_PARENT_DEFERRED) == 0
&& parent_entry.resolved == nullptr
&& m_main == nullptr
&& language_may_use_plain_main (lang)
@@ -108,7 +122,7 @@ cooked_index_shard::handle_gnat_encoded_entry
characters are left as-is. This is done to make name matching a
bit simpler; and for wide characters, it means the choice of Ada
source charset does not affect the indexer directly. */
- std::string canonical = ada_decode (entry->name, false, false, false);
+ std::string canonical = ada_decode (entry->name, false, false);
if (canonical.empty ())
{
entry->canonical = entry->name;
diff --git a/gdb/dwarf2/cooked-index-shard.h b/gdb/dwarf2/cooked-index-shard.h
index 925960b..3a8e34d 100644
--- a/gdb/dwarf2/cooked-index-shard.h
+++ b/gdb/dwarf2/cooked-index-shard.h
@@ -48,6 +48,13 @@ public:
cooked_index_entry_ref parent_entry,
dwarf2_per_cu *per_cu);
+ /* Add a copy of NAME to the index. Return a pointer to the
+ copy. */
+ const char *add (std::string_view name)
+ {
+ return m_names.insert (name);
+ }
+
/* Install a new fixed addrmap from the given mutable addrmap. */
void install_addrmap (addrmap_mutable *map)
{
diff --git a/gdb/dwarf2/cooked-index-worker.c b/gdb/dwarf2/cooked-index-worker.c
index 5d7fc46..09d80ef 100644
--- a/gdb/dwarf2/cooked-index-worker.c
+++ b/gdb/dwarf2/cooked-index-worker.c
@@ -246,7 +246,7 @@ void
cooked_index_worker::done_reading ()
{
{
- scoped_time_it time_it ("DWARF add parent map");
+ scoped_time_it time_it ("DWARF add parent map", m_per_command_time);
for (auto &one_result : m_results)
m_all_parents_map.add_map (*one_result.get_parent_map ());
diff --git a/gdb/dwarf2/cooked-index-worker.h b/gdb/dwarf2/cooked-index-worker.h
index df5c31d..433515b 100644
--- a/gdb/dwarf2/cooked-index-worker.h
+++ b/gdb/dwarf2/cooked-index-worker.h
@@ -25,6 +25,8 @@
#include "dwarf2/cooked-index-shard.h"
#include "dwarf2/types.h"
#include "dwarf2/read.h"
+#include "maint.h"
+#include "run-on-main-thread.h"
#if CXX_STD_THREAD
#include <mutex>
@@ -85,6 +87,13 @@ public:
name, parent_entry, per_cu);
}
+ /* Add a copy of NAME to the index. Return a pointer to the
+ copy. */
+ const char *add (std::string_view name)
+ {
+ return m_shard->add (name);
+ }
+
/* Install the current addrmap into the shard being constructed,
then transfer ownership of the index to the caller. */
cooked_index_shard_up release_shard ()
@@ -101,17 +110,32 @@ public:
return &m_addrmap;
}
+ /* Set the mutable addrmap. */
+ void set_addrmap (addrmap_mutable new_map)
+ {
+ m_addrmap = std::move (new_map);
+ }
+
/* Return the parent_map that is currently being created. */
parent_map *get_parent_map ()
{
return &m_parent_map;
}
- /* Add an exception to the list of exceptions caught while reading.
- These are passed forward and printed by the main thread. */
- void note_error (gdb_exception &&except)
+ /* Catch exceptions from calling F (), and add them to the list of caught
+ exceptions. These are passed forward and printed by the main thread. */
+ template <typename F>
+ void
+ catch_error (F &&f)
{
- m_exceptions.push_back (std::move (except));
+ try
+ {
+ f ();
+ }
+ catch (gdb_exception &ex)
+ {
+ m_exceptions.push_back (std::move (ex));
+ }
}
/* Called when the thread using this object is done with its work.
@@ -199,7 +223,7 @@ enum class cooked_state
This is an abstract base class that defines the basic behavior of
scanners. Separate concrete implementations exist for scanning
- .debug_names and .debug_info. */
+ .debug_names, .gdb_index, and .debug_info. */
class cooked_index_worker
{
@@ -207,8 +231,12 @@ public:
explicit cooked_index_worker (dwarf2_per_objfile *per_objfile)
: m_per_objfile (per_objfile),
- m_cache_store (global_index_cache, per_objfile->per_bfd)
- { }
+ m_cache_store (global_index_cache, per_objfile->per_bfd),
+ m_per_command_time (per_command_time)
+ {
+ /* Make sure we capture per_command_time from the main thread. */
+ gdb_assert (is_main_thread ());
+ }
virtual ~cooked_index_worker ()
{ }
DISABLE_COPY_AND_ASSIGN (cooked_index_worker);
@@ -298,6 +326,9 @@ protected:
std::optional<gdb_exception> m_failed;
/* An object used to write to the index cache. */
index_cache_store_context m_cache_store;
+
+ /* Captured value of per_command_time. */
+ bool m_per_command_time;
};
using cooked_index_worker_up = std::unique_ptr<cooked_index_worker>;
diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c
index 2c7e31e..6209590 100644
--- a/gdb/dwarf2/cooked-index.c
+++ b/gdb/dwarf2/cooked-index.c
@@ -104,7 +104,8 @@ cooked_index::set_contents ()
const parent_map_map *parent_maps = m_state->get_parent_map_map ();
finalizers.add_task ([=] ()
{
- scoped_time_it time_it ("DWARF finalize worker");
+ scoped_time_it time_it ("DWARF finalize worker",
+ m_state->m_per_command_time);
this_shard->finalize (parent_maps);
});
}
@@ -326,9 +327,7 @@ maintenance_wait_for_index_cache (const char *args, int from_tty)
wait_for_index_cache (0);
}
-void _initialize_cooked_index ();
-void
-_initialize_cooked_index ()
+INIT_GDB_FILE (cooked_index)
{
add_cmd ("wait-for-index-cache", class_maintenance,
maintenance_wait_for_index_cache, _("\
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
index 43b2723..42d7ec3 100644
--- a/gdb/dwarf2/cooked-index.h
+++ b/gdb/dwarf2/cooked-index.h
@@ -237,15 +237,15 @@ struct cooked_index_functions : public dwarf2_base_index_functions
dwarf2_base_index_functions::expand_all_symtabs (objfile);
}
- bool expand_symtabs_matching
+ bool search
(struct objfile *objfile,
- expand_symtabs_file_matcher file_matcher,
+ search_symtabs_file_matcher file_matcher,
const lookup_name_info *lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
+ search_symtabs_symbol_matcher symbol_matcher,
+ search_symtabs_expansion_listener listener,
block_search_flags search_flags,
domain_search_flags domain,
- expand_symtabs_lang_matcher lang_matcher) override;
+ search_symtabs_lang_matcher lang_matcher) override;
struct compunit_symtab *find_pc_sect_compunit_symtab
(struct objfile *objfile, bound_minimal_symbol msymbol,
diff --git a/gdb/dwarf2/cooked-indexer.c b/gdb/dwarf2/cooked-indexer.c
index c093984..913ff77 100644
--- a/gdb/dwarf2/cooked-indexer.c
+++ b/gdb/dwarf2/cooked-indexer.c
@@ -20,6 +20,9 @@
#include "dwarf2/cooked-indexer.h"
#include "dwarf2/cooked-index-worker.h"
#include "dwarf2/error.h"
+#include "dwarf2/read.h"
+#include "cp-support.h"
+#include "demangle.h"
/* See cooked-indexer.h. */
@@ -83,19 +86,17 @@ tag_can_have_linkage_name (enum dwarf_tag tag)
cutu_reader *
cooked_indexer::ensure_cu_exists (cutu_reader *reader,
- sect_offset sect_off, bool is_dwz,
+ const section_and_offset &sect_off,
bool for_scanning)
{
/* Lookups for type unit references are always in the CU, and
cross-CU references will crash. */
- if (reader->cu ()->per_cu->is_dwz == is_dwz
- && reader->cu ()->header.offset_in_unit_p (sect_off))
+ if (reader->section () == sect_off.section
+ && reader->cu ()->header.offset_in_unit_p (sect_off.offset))
return reader;
dwarf2_per_objfile *per_objfile = reader->cu ()->per_objfile;
- dwarf2_per_cu *per_cu
- = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
- per_objfile->per_bfd);
+ dwarf2_per_cu *per_cu = dwarf2_find_containing_unit (sect_off, per_objfile);
/* When scanning, we only want to visit a given CU a single time.
Doing this check here avoids self-imports as well. */
@@ -148,10 +149,8 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
bool *is_enum_class,
bool for_specification)
{
- bool origin_is_dwz = false;
bool is_declaration = false;
- sect_offset origin_offset {};
-
+ std::optional<section_and_offset> origin;
std::optional<unrelocated_addr> low_pc;
std::optional<unrelocated_addr> high_pc;
bool high_pc_relative = false;
@@ -221,8 +220,8 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
case DW_AT_specification:
case DW_AT_abstract_origin:
case DW_AT_extension:
- origin_offset = attr.get_ref_die_offset ();
- origin_is_dwz = attr.form_is_alt ();
+ origin = { &get_section_for_ref (attr, reader->cu ()),
+ attr.get_ref_die_offset () };
break;
case DW_AT_external:
@@ -301,7 +300,7 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
|| abbrev->tag == DW_TAG_namespace)
&& abbrev->has_children)
*flags |= IS_TYPE_DECLARATION;
- else
+ else if (!is_ada_import_or_export (reader->cu (), *name, *linkage_name))
{
*linkage_name = nullptr;
*name = nullptr;
@@ -311,19 +310,19 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
|| (*linkage_name == nullptr
&& tag_can_have_linkage_name (abbrev->tag))
|| (*parent_entry == nullptr && m_language != language_c))
- && origin_offset != sect_offset (0))
+ && origin.has_value ())
{
cutu_reader *new_reader
- = ensure_cu_exists (reader, origin_offset, origin_is_dwz, false);
+ = ensure_cu_exists (reader, *origin, false);
if (new_reader == nullptr)
error (_(DWARF_ERROR_PREFIX
"cannot follow reference to DIE at %s"
" [in module %s]"),
- sect_offset_str (origin_offset),
+ sect_offset_str (origin->offset),
bfd_get_filename (reader->abfd ()));
const gdb_byte *new_info_ptr
- = (new_reader->buffer () + to_underlying (origin_offset));
+ = (new_reader->buffer () + to_underlying (origin->offset));
if (*parent_entry == nullptr)
{
@@ -347,7 +346,7 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
if (new_abbrev == nullptr)
error (_(DWARF_ERROR_PREFIX
"Unexpected null DIE at offset %s [in module %s]"),
- sect_offset_str (origin_offset),
+ sect_offset_str (origin->offset),
bfd_get_filename (new_reader->abfd ()));
new_info_ptr += bytes_read;
@@ -411,8 +410,7 @@ cooked_indexer::index_imported_unit (cutu_reader *reader,
const gdb_byte *info_ptr,
const abbrev_info *abbrev)
{
- sect_offset sect_off {};
- bool is_dwz = false;
+ std::optional<section_and_offset> target;
for (int i = 0; i < abbrev->num_attrs; ++i)
{
@@ -421,19 +419,16 @@ cooked_indexer::index_imported_unit (cutu_reader *reader,
info_ptr = reader->read_attribute (&attr, &abbrev->attrs[i], info_ptr);
if (attr.name == DW_AT_import)
- {
- sect_off = attr.get_ref_die_offset ();
- is_dwz = (attr.form_is_alt ()
- || reader->cu ()->per_cu->is_dwz);
- }
+ target = { &get_section_for_ref (attr, reader->cu ()),
+ attr.get_ref_die_offset () };
}
/* Did not find DW_AT_import. */
- if (sect_off == sect_offset (0))
+ if (!target.has_value ())
return info_ptr;
cutu_reader *new_reader
- = ensure_cu_exists (reader, sect_off, is_dwz, true);
+ = ensure_cu_exists (reader, *target, true);
if (new_reader != nullptr)
{
index_dies (new_reader, new_reader->info_ptr (), nullptr, false);
@@ -514,7 +509,8 @@ cooked_indexer::index_dies (cutu_reader *reader,
/* If a DIE parent is a DW_TAG_subprogram, then the DIE is only
interesting if it's a DW_TAG_subprogram or a DW_TAG_entry_point. */
bool die_interesting
- = (abbrev->interesting
+ = ((abbrev->interesting
+ || (m_language == language_ada && abbrev->maybe_ada_import))
&& (parent_entry == nullptr
|| parent_entry->tag != DW_TAG_subprogram
|| abbrev->tag == DW_TAG_subprogram
@@ -550,6 +546,11 @@ cooked_indexer::index_dies (cutu_reader *reader,
flags &= ~IS_STATIC;
flags |= parent_entry->flags & IS_STATIC;
}
+ else if (abbrev->tag == DW_TAG_imported_declaration)
+ {
+ /* Match the full reader. */
+ flags &= ~IS_STATIC;
+ }
if (abbrev->tag == DW_TAG_namespace
&& m_language == language_cplus
@@ -562,6 +563,30 @@ cooked_indexer::index_dies (cutu_reader *reader,
name = nullptr;
}
+ /* An otherwise anonymous type might be given a name (via
+ typedef) for linkage purposes, and gdb tries to handle this
+ case. See anon-struct.exp. In this case, GCC will emit a
+ funny thing: a linkage name for the type, but in "type" form.
+ That is, it will not start with _Z. */
+ if ((abbrev->tag == DW_TAG_class_type
+ || abbrev->tag == DW_TAG_structure_type
+ || abbrev->tag == DW_TAG_union_type)
+ && m_language == language_cplus
+ && name == nullptr
+ && linkage_name != nullptr)
+ {
+ gdb::unique_xmalloc_ptr<char> dem
+ = gdb_demangle (linkage_name, DMGL_GNU_V3 | DMGL_TYPES);
+ if (dem != nullptr)
+ {
+ /* We're only interested in the last component. */
+ std::vector<std::string_view> split
+ = split_name (dem.get (), split_style::CXX);
+ name = m_index_storage->add (split.back ());
+ linkage_name = nullptr;
+ }
+ }
+
cooked_index_entry *this_entry = nullptr;
if (name != nullptr)
{
diff --git a/gdb/dwarf2/cooked-indexer.h b/gdb/dwarf2/cooked-indexer.h
index 904c55f..83cbf7f 100644
--- a/gdb/dwarf2/cooked-indexer.h
+++ b/gdb/dwarf2/cooked-indexer.h
@@ -30,6 +30,7 @@ struct cooked_index_worker_result;
struct cutu_reader;
struct dwarf2_per_cu;
struct dwarf2_per_objfile;
+struct section_and_offset;
/* An instance of this is created to index a CU. */
@@ -55,8 +56,7 @@ private:
the DIEs in the CU; when false, this use is assumed to be to look
up just a single DIE. */
cutu_reader *ensure_cu_exists (cutu_reader *reader,
- sect_offset sect_off,
- bool is_dwz,
+ const section_and_offset &sect_off,
bool for_scanning);
/* Index DIEs in the READER starting at INFO_PTR. PARENT is
diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h
index 5338dfe..68010a0 100644
--- a/gdb/dwarf2/cu.h
+++ b/gdb/dwarf2/cu.h
@@ -54,6 +54,11 @@ struct dwarf2_cu
DISABLE_COPY_AND_ASSIGN (dwarf2_cu);
+ /* The section the DIEs were effectively read from. This could be
+ .debug_info, .debug_types, or with split DWARF, their .dwo
+ variants. */
+ const dwarf2_section_info &section () const;
+
/* TU version of handle_DW_AT_stmt_list for read_type_unit_scope.
Create the set of symtabs used by this TU, or if this TU is sharing
symtabs with another TU and the symtabs have already been created
@@ -369,7 +374,7 @@ public:
right place. And since the DW_TAG_compile_unit DIE in the split-unit can't
have a DW_AT_ranges attribute, we can use the
- die->tag != DW_AT_compile_unit
+ die->tag != DW_TAG_compile_unit
to determine whether the base should be added or not. */
ULONGEST gnu_ranges_base = 0;
diff --git a/gdb/dwarf2/dwz.c b/gdb/dwarf2/dwz.c
index 583103b..1aa0d03 100644
--- a/gdb/dwarf2/dwz.c
+++ b/gdb/dwarf2/dwz.c
@@ -56,35 +56,37 @@ dwz_file::read_string (struct objfile *objfile, LONGEST str_offset)
/* A helper function to find the sections for a .dwz file. */
static void
-locate_dwz_sections (struct objfile *objfile, bfd *abfd, asection *sectp,
- dwz_file *dwz_file)
+locate_dwz_sections (objfile *objfile, dwz_file &dwz_file)
{
- dwarf2_section_info *sect = nullptr;
+ for (asection *sec : gdb_bfd_sections (dwz_file.dwz_bfd))
+ {
+ dwarf2_section_info *sect = nullptr;
- /* Note that we only support the standard ELF names, because .dwz
+ /* Note that we only support the standard ELF names, because .dwz
is ELF-only (at the time of writing). */
- if (dwarf2_elf_names.abbrev.matches (sectp->name))
- sect = &dwz_file->abbrev;
- else if (dwarf2_elf_names.info.matches (sectp->name))
- sect = &dwz_file->info;
- else if (dwarf2_elf_names.str.matches (sectp->name))
- sect = &dwz_file->str;
- else if (dwarf2_elf_names.line.matches (sectp->name))
- sect = &dwz_file->line;
- else if (dwarf2_elf_names.macro.matches (sectp->name))
- sect = &dwz_file->macro;
- else if (dwarf2_elf_names.gdb_index.matches (sectp->name))
- sect = &dwz_file->gdb_index;
- else if (dwarf2_elf_names.debug_names.matches (sectp->name))
- sect = &dwz_file->debug_names;
- else if (dwarf2_elf_names.types.matches (sectp->name))
- sect = &dwz_file->types;
-
- if (sect != nullptr)
- {
- sect->s.section = sectp;
- sect->size = bfd_section_size (sectp);
- sect->read (objfile);
+ if (dwarf2_elf_names.abbrev.matches (sec->name))
+ sect = &dwz_file.abbrev;
+ else if (dwarf2_elf_names.info.matches (sec->name))
+ sect = &dwz_file.info;
+ else if (dwarf2_elf_names.str.matches (sec->name))
+ sect = &dwz_file.str;
+ else if (dwarf2_elf_names.line.matches (sec->name))
+ sect = &dwz_file.line;
+ else if (dwarf2_elf_names.macro.matches (sec->name))
+ sect = &dwz_file.macro;
+ else if (dwarf2_elf_names.gdb_index.matches (sec->name))
+ sect = &dwz_file.gdb_index;
+ else if (dwarf2_elf_names.debug_names.matches (sec->name))
+ sect = &dwz_file.debug_names;
+ else if (dwarf2_elf_names.types.matches (sec->name))
+ sect = &dwz_file.types;
+
+ if (sect != nullptr)
+ {
+ sect->s.section = sec;
+ sect->size = bfd_section_size (sec);
+ sect->read (objfile);
+ }
}
}
@@ -341,7 +343,7 @@ dwz_file::read_dwz_file (dwarf2_per_objfile *per_objfile)
{
gdb::unique_xmalloc_ptr<char> abs = gdb_realpath (per_bfd->filename ());
- filename = ldirname (abs.get ()) + SLASH_STRING + filename;
+ filename = gdb_ldirname (abs.get ()) + SLASH_STRING + filename;
}
/* First try the file name given in the section. If that doesn't
@@ -392,9 +394,7 @@ dwz_file::read_dwz_file (dwarf2_per_objfile *per_objfile)
dwz_file_up result (new dwz_file (std::move (dwz_bfd)));
- for (asection *sec : gdb_bfd_sections (result->dwz_bfd))
- locate_dwz_sections (per_objfile->objfile, result->dwz_bfd.get (),
- sec, result.get ());
+ locate_dwz_sections (per_objfile->objfile, *result);
gdb_bfd_record_inclusion (per_bfd->obfd, result->dwz_bfd.get ());
bfd_cache_close (result->dwz_bfd.get ());
diff --git a/gdb/dwarf2/frame-tailcall.c b/gdb/dwarf2/frame-tailcall.c
index 6464ffb..e31ae10 100644
--- a/gdb/dwarf2/frame-tailcall.c
+++ b/gdb/dwarf2/frame-tailcall.c
@@ -478,9 +478,7 @@ const struct frame_unwind_legacy dwarf2_tailcall_frame_unwind (
tailcall_frame_prev_arch
);
-void _initialize_tailcall_frame ();
-void
-_initialize_tailcall_frame ()
+INIT_GDB_FILE (tailcall_frame)
{
cache_htab = htab_create_alloc (50, cache_hash, cache_eq, NULL, xcalloc,
xfree);
diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c
index 1b4de0d..7a37285 100644
--- a/gdb/dwarf2/frame.c
+++ b/gdb/dwarf2/frame.c
@@ -2247,9 +2247,7 @@ dwarf2_build_frame_info (struct objfile *objfile)
set_comp_unit (objfile, unit.release ());
}
-void _initialize_dwarf2_frame ();
-void
-_initialize_dwarf2_frame ()
+INIT_GDB_FILE (dwarf2_frame)
{
#if GDB_SELF_TEST
selftests::register_test_foreach_arch ("execute_cfa_program",
diff --git a/gdb/dwarf2/frame.h b/gdb/dwarf2/frame.h
index f8fd8e8..9357cc1 100644
--- a/gdb/dwarf2/frame.h
+++ b/gdb/dwarf2/frame.h
@@ -198,6 +198,15 @@ struct dwarf2_frame_state
bool armcc_cfa_offsets_reversed = false;
};
+/* If DWARF supoprt was requested, create the real prototype for the
+ append_unwinders function. Otherwise, create a fake inline function.
+
+ There is no need to emit a warning for some of these, because they aren't
+ actively reading DWARF when this is called, they're just initializing GDB.
+
+ These should probably be moved to dwarf2/public.h. */
+#if defined(DWARF_FORMAT_AVAILABLE)
+
/* Set the architecture-specific register state initialization
function for GDBARCH to INIT_REG. */
@@ -287,4 +296,56 @@ extern void *dwarf2_frame_get_fn_data (const frame_info_ptr &this_frame,
void **this_cache,
fn_prev_register cookie);
+#else /* DWARF_FORMAT_AVAILABLE */
+
+static inline void dwarf2_append_unwinders (struct gdbarch *gdbarch) { }
+
+static inline void dwarf2_frame_set_init_reg (
+ gdbarch *gdbarch, void (*init_reg) (struct gdbarch *,int,
+ dwarf2_frame_state_reg *,
+ const frame_info_ptr &)) { }
+
+static inline const struct frame_base *
+ dwarf2_frame_base_sniffer (const frame_info_ptr &this_frame)
+{
+ warning (_("No dwarf support available."));
+ return nullptr;
+}
+
+static inline void dwarf2_frame_set_signal_frame_p
+ (gdbarch *gdbarch, int (*signal_frame_p) (struct gdbarch *,
+ const frame_info_ptr &)) { }
+
+static inline void *dwarf2_frame_get_fn_data (const frame_info_ptr &this_frame,
+ void **this_cache,
+ fn_prev_register cookie)
+{
+ return nullptr;
+}
+
+static inline void *dwarf2_frame_allocate_fn_data
+ (const frame_info_ptr &this_frame, void **this_cache,
+ fn_prev_register cookie, unsigned long size)
+{
+ return nullptr;
+}
+
+static inline int dwarf2_fetch_cfa_info (struct gdbarch *gdbarch, CORE_ADDR pc,
+ struct dwarf2_per_cu_data *data,
+ int *regnum_out, LONGEST *offset_out,
+ CORE_ADDR *text_offset_out,
+ const gdb_byte **cfa_start_out,
+ const gdb_byte **cfa_end_out)
+{
+ return 0;
+}
+
+static inline void
+ dwarf2_frame_set_adjust_regnum (struct gdbarch *gdbarch,
+ int (*adjust_regnum) (struct gdbarch *,
+ int, int))
+{}
+
+#endif /* DWARF_FORMAT_AVAILABLE */
+
#endif /* GDB_DWARF2_FRAME_H */
diff --git a/gdb/dwarf2/index-cache.c b/gdb/dwarf2/index-cache.c
index 1715beb..cfe8ce9 100644
--- a/gdb/dwarf2/index-cache.c
+++ b/gdb/dwarf2/index-cache.c
@@ -342,9 +342,7 @@ show_index_cache_stats_command (const char *arg, int from_tty)
indent, global_index_cache.n_misses ());
}
-void _initialize_index_cache ();
-void
-_initialize_index_cache ()
+INIT_GDB_FILE (index_cache)
{
/* Set the default index cache directory. */
std::string cache_dir = get_standard_cache_dir ();
diff --git a/gdb/dwarf2/index-common.c b/gdb/dwarf2/index-common.c
index c24c8fc..a314ce7 100644
--- a/gdb/dwarf2/index-common.c
+++ b/gdb/dwarf2/index-common.c
@@ -31,7 +31,7 @@ mapped_index_string_hash (int index_version, const void *p)
while ((c = *str++) != 0)
{
if (index_version >= 5)
- c = tolower (c);
+ c = c_tolower (c);
r = r * 67 + c - 113;
}
@@ -45,12 +45,12 @@ dwarf5_djb_hash (const char *str_)
{
const unsigned char *str = (const unsigned char *) str_;
- /* Note: tolower here ignores UTF-8, which isn't fully compliant.
+ /* Note: c_tolower here ignores UTF-8, which isn't fully compliant.
See http://dwarfstd.org/ShowIssue.php?issue=161027.1. */
uint32_t hash = 5381;
while (int c = *str++)
- hash = hash * 33 + tolower (c);
+ hash = hash * 33 + c_tolower (c);
return hash;
}
@@ -59,11 +59,11 @@ dwarf5_djb_hash (const char *str_)
uint32_t
dwarf5_djb_hash (std::string_view str)
{
- /* Note: tolower here ignores UTF-8, which isn't fully compliant.
+ /* Note: c_tolower here ignores UTF-8, which isn't fully compliant.
See http://dwarfstd.org/ShowIssue.php?issue=161027.1. */
uint32_t hash = 5381;
for (char c : str)
- hash = hash * 33 + tolower (c & 0xff);
+ hash = hash * 33 + c_tolower (c & 0xff);
return hash;
}
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
index 614bdcd..37e66a5 100644
--- a/gdb/dwarf2/index-write.c
+++ b/gdb/dwarf2/index-write.c
@@ -55,7 +55,7 @@
#define DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE(cu_index, value) \
do { \
gdb_assert ((value) >= GDB_INDEX_SYMBOL_KIND_TYPE \
- && (value) <= GDB_INDEX_SYMBOL_KIND_OTHER); \
+ && (value) <= GDB_INDEX_SYMBOL_KIND_UNUSED5); \
GDB_INDEX_SYMBOL_KIND_SET_VALUE((cu_index), (value)); \
} while (0)
@@ -422,10 +422,47 @@ symtab_index_entry::minimize ()
if (name == nullptr || cu_indices.empty ())
return;
- std::sort (cu_indices.begin (), cu_indices.end ());
+ /* We sort the indexes in a funny way: GDB_INDEX_SYMBOL_KIND_UNUSED5
+ is always sorted last; then otherwise we sort by numeric value.
+ This ensures that we prefer the definition when both a definition
+ and a declaration (stub type) are seen. */
+ std::sort (cu_indices.begin (), cu_indices.end (),
+ [] (offset_type vala, offset_type valb)
+ {
+ auto kinda = GDB_INDEX_SYMBOL_KIND_VALUE (vala);
+ auto kindb = GDB_INDEX_SYMBOL_KIND_VALUE (valb);
+ if (kinda != kindb)
+ {
+ /* Declaration sorts last. */
+ if (kinda == GDB_INDEX_SYMBOL_KIND_UNUSED5)
+ return false;
+ if (kindb == GDB_INDEX_SYMBOL_KIND_UNUSED5)
+ return true;
+ }
+ return vala < valb;
+ });
auto from = std::unique (cu_indices.begin (), cu_indices.end ());
cu_indices.erase (from, cu_indices.end ());
+ /* Rewrite GDB_INDEX_SYMBOL_KIND_UNUSED5. This ensures that a type
+ declaration will be deleted by the subsequent squashing step, if
+ warranted. */
+ for (auto &val : cu_indices)
+ {
+ gdb_index_symbol_kind kind = GDB_INDEX_SYMBOL_KIND_VALUE (val);
+ if (kind != GDB_INDEX_SYMBOL_KIND_UNUSED5)
+ continue;
+
+ offset_type newval = 0;
+ DW2_GDB_INDEX_CU_SET_VALUE (newval, GDB_INDEX_CU_VALUE (val));
+ DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE
+ (newval, GDB_INDEX_SYMBOL_STATIC_VALUE (val));
+ DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE (newval,
+ GDB_INDEX_SYMBOL_KIND_TYPE);
+
+ val = newval;
+ }
+
/* We don't want to enter a type more than once, so
remove any such duplicates from the list as well. When doing
this, we want to keep the entry from the first CU -- but this is
@@ -720,7 +757,7 @@ public:
});
m_name_table_string_offs.push_back_reorder
- (m_debugstrlookup.lookup (name.c_str ())); /* ??? */
+ (m_debugstrlookup.lookup (name.c_str ()));
m_name_table_entry_offs.push_back_reorder (m_entry_pool.size ());
for (const cooked_index_entry *entry : these_entries)
@@ -872,7 +909,7 @@ public:
m_debugstrlookup.file_write (file_str);
}
- void add_cu (dwarf2_per_cu *per_cu, offset_type index)
+ void add_cu (const dwarf2_per_cu *per_cu, offset_type index)
{
m_cu_index_htab.emplace (per_cu, index);
}
@@ -885,10 +922,21 @@ private:
{
public:
- /* Object constructor to be called for current DWARF2_PER_BFD. */
- debug_str_lookup (dwarf2_per_bfd *per_bfd)
+ /* Object constructor to be called for current DWARF2_PER_BFD.
+ All .debug_str section strings are automatically stored. */
+ explicit debug_str_lookup (dwarf2_per_bfd *per_bfd)
: m_per_bfd (per_bfd)
{
+ gdb_assert (per_bfd->str.readin);
+ const gdb_byte *data = per_bfd->str.buffer;
+ if (data == nullptr)
+ return;
+ while (data < per_bfd->str.buffer + per_bfd->str.size)
+ {
+ const char *const s = reinterpret_cast<const char *> (data);
+ m_str_table.emplace (c_str_view (s), data - per_bfd->str.buffer);
+ data += strlen (s) + 1;
+ }
}
/* Return offset of symbol name S in the .debug_str section. Add
@@ -896,13 +944,6 @@ private:
yet. */
size_t lookup (const char *s)
{
- /* Most strings will have come from the string table
- already. */
- const gdb_byte *b = (const gdb_byte *) s;
- if (b >= m_per_bfd->str.buffer
- && b < m_per_bfd->str.buffer + m_per_bfd->str.size)
- return b - m_per_bfd->str.buffer;
-
const auto it = m_str_table.find (c_str_view (s));
if (it != m_str_table.end ())
return it->second;
@@ -1212,6 +1253,21 @@ write_cooked_index (cooked_index *table,
const cu_index_map &cu_index_htab,
struct mapped_symtab *symtab)
{
+ gdb::unordered_set<const cooked_index_entry *> required_decl_entries;
+ for (const cooked_index_entry *entry : table->all_entries ())
+ {
+ /* Any type declaration that is used as a (non-trivial) parent
+ entry must be written out. */
+ if ((entry->flags & IS_TYPE_DECLARATION) == 0)
+ {
+ for (const cooked_index_entry *parent = entry->get_parent ();
+ parent != nullptr;
+ parent = parent->get_parent ())
+ if ((parent->flags & IS_TYPE_DECLARATION) != 0)
+ required_decl_entries.insert (parent);
+ }
+ }
+
for (const cooked_index_entry *entry : table->all_entries ())
{
const auto it = cu_index_htab.find (entry->per_cu);
@@ -1237,11 +1293,10 @@ write_cooked_index (cooked_index *table,
be redundant are rare and not worth supporting. */
continue;
}
- else if ((entry->flags & IS_TYPE_DECLARATION) != 0)
- {
- /* Don't add type declarations to the index. */
- continue;
- }
+ /* Don't add most type declarations to the index. */
+ else if ((entry->flags & IS_TYPE_DECLARATION) != 0
+ && !required_decl_entries.contains (entry))
+ continue;
gdb_index_symbol_kind kind;
if (entry->tag == DW_TAG_subprogram
@@ -1252,7 +1307,16 @@ write_cooked_index (cooked_index *table,
|| entry->tag == DW_TAG_enumerator)
kind = GDB_INDEX_SYMBOL_KIND_VARIABLE;
else if (tag_is_type (entry->tag))
- kind = GDB_INDEX_SYMBOL_KIND_TYPE;
+ {
+ /* If we added a type declaration, we want to note this
+ fact for later, because we don't want a type declaration
+ to cause the real definition to be omitted from the
+ index. GDB_INDEX_SYMBOL_KIND_UNUSED5 is used here, but
+ rewritten later before the index is written. */
+ kind = ((entry->flags & IS_TYPE_DECLARATION) == 0
+ ? GDB_INDEX_SYMBOL_KIND_TYPE
+ : GDB_INDEX_SYMBOL_KIND_UNUSED5);
+ }
else
kind = GDB_INDEX_SYMBOL_KIND_OTHER;
@@ -1289,6 +1353,40 @@ write_shortcuts_table (cooked_index *table, data_buf &shortcuts,
shortcuts.append_offset (main_name_offset);
}
+/* Get sorted (by section offset) lists of comp units and type units. */
+
+static std::pair<std::vector<const dwarf2_per_cu *>,
+ std::vector<const signatured_type *>>
+get_unit_lists (const dwarf2_per_bfd &per_bfd)
+{
+ std::vector<const dwarf2_per_cu *> comp_units;
+ std::vector<const signatured_type *> type_units;
+
+ for (const auto &unit : per_bfd.all_units)
+ if (unit->is_debug_types)
+ type_units.emplace_back (static_cast<const signatured_type *>
+ (unit.get ()));
+ else
+ comp_units.emplace_back (unit.get ());
+
+ auto by_sect_off = [] (const dwarf2_per_cu *lhs, const dwarf2_per_cu *rhs)
+ { return lhs->sect_off < rhs->sect_off; };
+
+ /* Sort both lists, even though it is technically not always required:
+
+ - while .gdb_index requires the CU list to be sorted, DWARF 5 doesn't
+ say anything about the order of CUs in .debug_names.
+ - .gdb_index doesn't require the TU list to be sorted, and DWARF 5
+ doesn't say anything about the order of TUs in .debug_names.
+
+ However, it helps make sure that GDB produce a stable and predictable
+ output, which is nice. */
+ std::sort (comp_units.begin (), comp_units.end (), by_sect_off);
+ std::sort (type_units.begin (), type_units.end (), by_sect_off);
+
+ return {std::move (comp_units), std::move (type_units)};
+}
+
/* Write contents of a .gdb_index section for OBJFILE into OUT_FILE.
If OBJFILE has an associated dwz file, write contents of a .gdb_index
section for that dwz file into DWZ_OUT_FILE. If OBJFILE does not have an
@@ -1299,8 +1397,6 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
FILE *out_file, FILE *dwz_out_file)
{
mapped_symtab symtab;
- data_buf objfile_cu_list;
- data_buf dwz_cu_list;
/* While we're scanning CU's create a table that maps a dwarf2_per_cu (which
is what addrmap records) to its index (which is what is recorded in the
@@ -1308,40 +1404,44 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
cu_index_map cu_index_htab;
cu_index_htab.reserve (per_bfd->all_units.size ());
- /* Store out the .debug_type CUs, if any. */
- data_buf types_cu_list;
+ auto [comp_units, type_units] = get_unit_lists (*per_bfd);
+ int counter = 0;
- /* The CU list is already sorted, so we don't need to do additional
- work here. */
+ /* Write comp units. */
+ data_buf objfile_cu_list;
+ data_buf dwz_cu_list;
- int counter = 0;
- for (const dwarf2_per_cu_up &per_cu : per_bfd->all_units)
+ for (const dwarf2_per_cu *per_cu : comp_units)
{
- const auto insertpair = cu_index_htab.emplace (per_cu.get (), counter);
+ const auto insertpair = cu_index_htab.emplace (per_cu, counter);
gdb_assert (insertpair.second);
- /* See enhancement PR symtab/30838. */
- gdb_assert (!(per_cu->is_dwz && per_cu->is_debug_types));
-
/* The all_units list contains CUs read from the objfile as well as
from the eventual dwz file. We need to place the entry in the
corresponding index. */
- data_buf &cu_list = (per_cu->is_debug_types
- ? types_cu_list
- : per_cu->is_dwz ? dwz_cu_list : objfile_cu_list);
+ data_buf &cu_list = per_cu->is_dwz ? dwz_cu_list : objfile_cu_list;
cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
to_underlying (per_cu->sect_off));
- if (per_cu->is_debug_types)
- {
- signatured_type *sig_type = (signatured_type *) per_cu.get ();
- cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
- to_underlying (sig_type->type_offset_in_tu));
- cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
- sig_type->signature);
- }
- else
- cu_list.append_uint (8, BFD_ENDIAN_LITTLE, per_cu->length ());
+ cu_list.append_uint (8, BFD_ENDIAN_LITTLE, per_cu->length ());
+ ++counter;
+ }
+
+ /* Write type units. */
+ data_buf types_cu_list;
+
+ for (const signatured_type *sig_type : type_units)
+ {
+ const auto insertpair = cu_index_htab.emplace (sig_type, counter);
+ gdb_assert (insertpair.second);
+ /* See enhancement PR symtab/30838. */
+ gdb_assert (!sig_type->is_dwz);
+
+ types_cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
+ to_underlying (sig_type->sect_off));
+ types_cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
+ to_underlying (sig_type->type_offset_in_tu));
+ types_cu_list.append_uint (8, BFD_ENDIAN_LITTLE, sig_type->signature);
++counter;
}
@@ -1388,29 +1488,35 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table,
const enum bfd_endian dwarf5_byte_order
= bfd_big_endian (per_bfd->obfd) ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
- /* The CU list is already sorted, so we don't need to do additional
- work here. Also, the debug_types entries do not appear in
- all_units, but only in their own hash table. */
- data_buf cu_list;
- data_buf types_cu_list;
+ auto [comp_units, type_units] = get_unit_lists (*per_bfd);
debug_names nametable (per_bfd, dwarf5_is_dwarf64, dwarf5_byte_order);
- int counter = 0;
- int types_counter = 0;
- for (const dwarf2_per_cu_up &per_cu : per_bfd->all_units)
+ data_buf comp_unit_list;
+ int comp_unit_counter = 0;
+
+ for (const auto per_cu : comp_units)
+ {
+ nametable.add_cu (per_cu, comp_unit_counter);
+ comp_unit_list.append_uint (nametable.dwarf5_offset_size (),
+ dwarf5_byte_order,
+ to_underlying (per_cu->sect_off));
+ comp_unit_counter++;
+ }
+
+ data_buf type_unit_list;
+ int type_unit_counter = 0;
+
+ for (const auto per_cu : type_units)
{
- int &this_counter = per_cu->is_debug_types ? types_counter : counter;
- data_buf &this_list = per_cu->is_debug_types ? types_cu_list : cu_list;
-
- nametable.add_cu (per_cu.get (), this_counter);
- this_list.append_uint (nametable.dwarf5_offset_size (),
- dwarf5_byte_order,
- to_underlying (per_cu->sect_off));
- ++this_counter;
+ nametable.add_cu (per_cu, type_unit_counter);
+ type_unit_list.append_uint (nametable.dwarf5_offset_size (),
+ dwarf5_byte_order,
+ to_underlying (per_cu->sect_off));
+ type_unit_counter++;
}
/* Verify that all units are represented. */
- gdb_assert (counter == per_bfd->all_comp_units.size ());
- gdb_assert (types_counter == per_bfd->all_type_units.size ());
+ gdb_assert (comp_unit_counter == per_bfd->num_comp_units);
+ gdb_assert (type_unit_counter == per_bfd->num_type_units);
for (const cooked_index_entry *entry : table->all_entries ())
nametable.insert (entry);
@@ -1425,8 +1531,8 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table,
+ sizeof (dwarf5_augmentation_3));
size_t expected_bytes = 0;
expected_bytes += bytes_of_header;
- expected_bytes += cu_list.size ();
- expected_bytes += types_cu_list.size ();
+ expected_bytes += comp_unit_list.size ();
+ expected_bytes += type_unit_list.size ();
expected_bytes += nametable.bytes ();
data_buf header;
@@ -1449,11 +1555,11 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table,
header.append_uint (2, dwarf5_byte_order, 0);
/* comp_unit_count - The number of CUs in the CU list. */
- header.append_uint (4, dwarf5_byte_order, counter);
+ header.append_uint (4, dwarf5_byte_order, comp_unit_counter);
/* local_type_unit_count - The number of TUs in the local TU
list. */
- header.append_uint (4, dwarf5_byte_order, types_counter);
+ header.append_uint (4, dwarf5_byte_order, type_unit_counter);
/* foreign_type_unit_count - The number of TUs in the foreign TU
list. */
@@ -1481,8 +1587,8 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table,
gdb_assert (header.size () == bytes_of_header);
header.file_write (out_file);
- cu_list.file_write (out_file);
- types_cu_list.file_write (out_file);
+ comp_unit_list.file_write (out_file);
+ type_unit_list.file_write (out_file);
nametable.file_write (out_file, out_file_str);
assert_file_size (out_file, expected_bytes);
@@ -1768,9 +1874,7 @@ gdb_index ()
} /* selftests namespace. */
#endif
-void _initialize_dwarf_index_write ();
-void
-_initialize_dwarf_index_write ()
+INIT_GDB_FILE (dwarf_index_write)
{
#if GDB_SELF_TEST
selftests::register_test ("gdb_index", selftests::gdb_index);
diff --git a/gdb/dwarf2/line-program.c b/gdb/dwarf2/line-program.c
new file mode 100644
index 0000000..c30f70d
--- /dev/null
+++ b/gdb/dwarf2/line-program.c
@@ -0,0 +1,720 @@
+/* DWARF 2 debugging format support for GDB.
+
+ Copyright (C) 1994-2025 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "dwarf2/line-program.h"
+#include "dwarf2/cu.h"
+#include "dwarf2/line-header.h"
+#include "dwarf2/read.h"
+#include "buildsym.h"
+#include "complaints.h"
+#include "filenames.h"
+#include "gdbarch.h"
+
+static void
+dwarf2_debug_line_missing_file_complaint ()
+{
+ complaint (_(".debug_line section has line data without a file"));
+}
+
+static void
+dwarf2_debug_line_missing_end_sequence_complaint ()
+{
+ complaint (_(".debug_line section has line "
+ "program sequence without an end"));
+}
+
+/* State machine to track the state of the line number program. */
+
+class lnp_state_machine
+{
+public:
+ /* Initialize a machine state for the start of a line number
+ program. */
+ lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, line_header *lh);
+
+ file_entry *current_file ()
+ {
+ /* lh->file_names is 0-based, but the file name numbers in the
+ statement program are 1-based. */
+ return m_line_header->file_name_at (m_file);
+ }
+
+ /* Record the line in the state machine. END_SEQUENCE is true if
+ we're processing the end of a sequence. */
+ void record_line (bool end_sequence);
+
+ /* Check ADDRESS is -1, -2, or zero and less than UNRELOCATED_LOWPC, and if
+ true nop-out rest of the lines in this sequence. */
+ void check_line_address (struct dwarf2_cu *cu,
+ const gdb_byte *line_ptr,
+ unrelocated_addr unrelocated_lowpc,
+ unrelocated_addr address);
+
+ void handle_set_discriminator (unsigned int discriminator)
+ {
+ m_discriminator = discriminator;
+ m_line_has_non_zero_discriminator |= discriminator != 0;
+ }
+
+ /* Handle DW_LNE_set_address. */
+ void handle_set_address (unrelocated_addr address)
+ {
+ m_op_index = 0;
+ m_address
+ = (unrelocated_addr) gdbarch_adjust_dwarf2_line (m_gdbarch,
+ (CORE_ADDR) address,
+ false);
+ }
+
+ /* Handle DW_LNS_advance_pc. */
+ void handle_advance_pc (CORE_ADDR adjust);
+
+ /* Handle a special opcode. */
+ void handle_special_opcode (unsigned char op_code);
+
+ /* Handle DW_LNS_advance_line. */
+ void handle_advance_line (int line_delta)
+ {
+ advance_line (line_delta);
+ }
+
+ /* Handle DW_LNS_set_file. */
+ void handle_set_file (file_name_index file);
+
+ /* Handle DW_LNS_negate_stmt. */
+ void handle_negate_stmt ()
+ {
+ m_flags ^= LEF_IS_STMT;
+ }
+
+ /* Handle DW_LNS_const_add_pc. */
+ void handle_const_add_pc ();
+
+ /* Handle DW_LNS_fixed_advance_pc. */
+ void handle_fixed_advance_pc (CORE_ADDR addr_adj)
+ {
+ addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+ m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
+ m_op_index = 0;
+ }
+
+ /* Handle DW_LNS_copy. */
+ void handle_copy ()
+ {
+ record_line (false);
+ m_discriminator = 0;
+ m_flags &= ~LEF_PROLOGUE_END;
+ m_flags &= ~LEF_EPILOGUE_BEGIN;
+ }
+
+ /* Handle DW_LNE_end_sequence. */
+ void handle_end_sequence ()
+ {
+ m_currently_recording_lines = true;
+ }
+
+ /* Handle DW_LNS_set_prologue_end. */
+ void handle_set_prologue_end ()
+ {
+ m_flags |= LEF_PROLOGUE_END;
+ }
+
+ void handle_set_epilogue_begin ()
+ {
+ m_flags |= LEF_EPILOGUE_BEGIN;
+ }
+
+private:
+ /* Advance the line by LINE_DELTA. */
+ void advance_line (int line_delta)
+ {
+ m_line += line_delta;
+
+ if (line_delta != 0)
+ m_line_has_non_zero_discriminator = m_discriminator != 0;
+ }
+
+ bool record_line_p ();
+ void finish_line ();
+ void record_line_1 (unsigned int line, linetable_entry_flags flags);
+
+ struct dwarf2_cu *m_cu;
+
+ /* The builder associated with the CU. */
+ buildsym_compunit *m_builder;
+
+ gdbarch *m_gdbarch;
+
+ /* The line number header. */
+ line_header *m_line_header;
+
+ /* These are part of the standard DWARF line number state machine,
+ and initialized according to the DWARF spec. */
+
+ unsigned char m_op_index = 0;
+ /* The line table index of the current file. */
+ file_name_index m_file = 1;
+ unsigned int m_line = 1;
+
+ /* These are initialized in the constructor. */
+
+ unrelocated_addr m_address;
+ linetable_entry_flags m_flags;
+ unsigned int m_discriminator = 0;
+
+ /* Additional bits of state we need to track. */
+
+ /* The last file a line number was recorded for. */
+ struct subfile *m_last_subfile = NULL;
+
+ /* The address of the last line entry. */
+ unrelocated_addr m_last_address;
+
+ /* Set to true when a previous line at the same address (using
+ m_last_address) had LEF_IS_STMT set in m_flags. This is reset to false
+ when a line entry at a new address (m_address different to
+ m_last_address) is processed. */
+ bool m_stmt_at_address = false;
+
+ /* When true, record the lines we decode. */
+ bool m_currently_recording_lines = true;
+
+ /* The last line number that was recorded, used to coalesce
+ consecutive entries for the same line. This can happen, for
+ example, when discriminators are present. PR 17276. */
+ unsigned int m_last_line = 0;
+ bool m_line_has_non_zero_discriminator = false;
+};
+
+void
+lnp_state_machine::handle_advance_pc (CORE_ADDR adjust)
+{
+ CORE_ADDR addr_adj = (((m_op_index + adjust)
+ / m_line_header->maximum_ops_per_instruction)
+ * m_line_header->minimum_instruction_length);
+ addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+ m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
+ m_op_index = ((m_op_index + adjust)
+ % m_line_header->maximum_ops_per_instruction);
+}
+
+void
+lnp_state_machine::handle_special_opcode (unsigned char op_code)
+{
+ unsigned char adj_opcode = op_code - m_line_header->opcode_base;
+ unsigned char adj_opcode_d = adj_opcode / m_line_header->line_range;
+ unsigned char adj_opcode_r = adj_opcode % m_line_header->line_range;
+ CORE_ADDR addr_adj = (((m_op_index + adj_opcode_d)
+ / m_line_header->maximum_ops_per_instruction)
+ * m_line_header->minimum_instruction_length);
+ addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+ m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
+ m_op_index = ((m_op_index + adj_opcode_d)
+ % m_line_header->maximum_ops_per_instruction);
+
+ int line_delta = m_line_header->line_base + adj_opcode_r;
+ advance_line (line_delta);
+ record_line (false);
+ m_discriminator = 0;
+ m_flags &= ~LEF_PROLOGUE_END;
+ m_flags &= ~LEF_EPILOGUE_BEGIN;
+}
+
+void
+lnp_state_machine::handle_set_file (file_name_index file)
+{
+ m_file = file;
+
+ const file_entry *fe = current_file ();
+ if (fe == NULL)
+ dwarf2_debug_line_missing_file_complaint ();
+ else
+ {
+ m_line_has_non_zero_discriminator = m_discriminator != 0;
+ dwarf2_start_subfile (m_cu, *fe, *m_line_header);
+ }
+}
+
+void
+lnp_state_machine::handle_const_add_pc ()
+{
+ CORE_ADDR adjust
+ = (255 - m_line_header->opcode_base) / m_line_header->line_range;
+
+ CORE_ADDR addr_adj
+ = (((m_op_index + adjust)
+ / m_line_header->maximum_ops_per_instruction)
+ * m_line_header->minimum_instruction_length);
+
+ addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+ m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
+ m_op_index = ((m_op_index + adjust)
+ % m_line_header->maximum_ops_per_instruction);
+}
+
+/* Return true if we should add LINE to the line number table.
+ LINE is the line to add, LAST_LINE is the last line that was added,
+ LAST_SUBFILE is the subfile for LAST_LINE.
+ LINE_HAS_NON_ZERO_DISCRIMINATOR is non-zero if LINE has ever
+ had a non-zero discriminator.
+
+ We have to be careful in the presence of discriminators.
+ E.g., for this line:
+
+ for (i = 0; i < 100000; i++);
+
+ clang can emit four line number entries for that one line,
+ each with a different discriminator.
+ See gdb.dwarf2/dw2-single-line-discriminators.exp for an example.
+
+ However, we want gdb to coalesce all four entries into one.
+ Otherwise the user could stepi into the middle of the line and
+ gdb would get confused about whether the pc really was in the
+ middle of the line.
+
+ Things are further complicated by the fact that two consecutive
+ line number entries for the same line is a heuristic used by gcc
+ to denote the end of the prologue. So we can't just discard duplicate
+ entries, we have to be selective about it. The heuristic we use is
+ that we only collapse consecutive entries for the same line if at least
+ one of those entries has a non-zero discriminator. PR 17276.
+
+ Note: Addresses in the line number state machine can never go backwards
+ within one sequence, thus this coalescing is ok. */
+
+bool
+lnp_state_machine::record_line_p ()
+{
+ if (m_builder->get_current_subfile () != m_last_subfile)
+ return true;
+ if (m_line != m_last_line)
+ return true;
+ /* Same line for the same file that we've seen already.
+ As a last check, for pr 17276, only record the line if the line
+ has never had a non-zero discriminator. */
+ if (!m_line_has_non_zero_discriminator)
+ return true;
+ return false;
+}
+
+/* Use the CU's builder to record line number LINE with the given
+ flags. */
+
+void
+lnp_state_machine::record_line_1 (unsigned int line,
+ linetable_entry_flags flags)
+{
+ if (m_currently_recording_lines)
+ {
+ unrelocated_addr addr
+ = unrelocated_addr (gdbarch_addr_bits_remove (m_gdbarch,
+ (CORE_ADDR) m_address));
+
+ if (dwarf_line_debug)
+ gdb_printf (gdb_stdlog, "Recording line %u, file %s, address %s\n",
+ m_line, lbasename (m_last_subfile->name.c_str ()),
+ paddress (m_gdbarch, (CORE_ADDR) addr));
+
+ m_builder->record_line (m_last_subfile, line, addr, flags);
+ }
+}
+
+/* Subroutine of dwarf_decode_lines_1 to simplify it.
+ Mark the end of a set of line number records. */
+
+void
+lnp_state_machine::finish_line ()
+{
+ if (m_last_subfile == nullptr)
+ return;
+
+ if (dwarf_line_debug)
+ {
+ gdb_printf (gdb_stdlog,
+ "Finishing current line, file %s, address %s\n",
+ lbasename (m_last_subfile->name.c_str ()),
+ paddress (m_gdbarch, (CORE_ADDR) m_address));
+ }
+
+ record_line_1 (0, LEF_IS_STMT);
+}
+
+void
+lnp_state_machine::record_line (bool end_sequence)
+{
+ if (dwarf_line_debug)
+ {
+ gdb_printf (gdb_stdlog,
+ "Processing actual line %u: file %u,"
+ " address %s, is_stmt %u, prologue_end %u,"
+ " epilogue_begin %u, discrim %u%s\n",
+ m_line, m_file,
+ paddress (m_gdbarch, (CORE_ADDR) m_address),
+ (m_flags & LEF_IS_STMT) != 0,
+ (m_flags & LEF_PROLOGUE_END) != 0,
+ (m_flags & LEF_EPILOGUE_BEGIN) != 0,
+ m_discriminator,
+ (end_sequence ? "\t(end sequence)" : ""));
+ }
+
+ file_entry *fe = current_file ();
+
+ if (fe == NULL)
+ dwarf2_debug_line_missing_file_complaint ();
+ /* For now we ignore lines not starting on an instruction boundary.
+ But not when processing end_sequence for compatibility with the
+ previous version of the code. */
+ else if (m_op_index == 0 || end_sequence)
+ {
+ /* When we switch files we insert an end maker in the first file,
+ switch to the second file and add a new line entry. The
+ problem is that the end marker inserted in the first file will
+ discard any previous line entries at the same address. If the
+ line entries in the first file are marked as is-stmt, while
+ the new line in the second file is non-stmt, then this means
+ the end marker will discard is-stmt lines so we can have a
+ non-stmt line. This means that there are less addresses at
+ which the user can insert a breakpoint.
+
+ To improve this we track the last address in m_last_address,
+ and whether we have seen an is-stmt at this address. Then
+ when switching files, if we have seen a stmt at the current
+ address, and we are switching to create a non-stmt line, then
+ discard the new line. */
+ bool file_changed = m_last_subfile != m_builder->get_current_subfile ();
+ bool ignore_this_line
+ = ((file_changed && !end_sequence && m_last_address == m_address
+ && ((m_flags & LEF_IS_STMT) == 0)
+ && m_stmt_at_address)
+ || (!end_sequence && m_line == 0));
+
+ if ((file_changed && !ignore_this_line) || end_sequence)
+ finish_line ();
+
+ if (!end_sequence && !ignore_this_line)
+ {
+ linetable_entry_flags lte_flags = m_flags;
+ if (m_cu->producer_is_codewarrior ())
+ lte_flags |= LEF_IS_STMT;
+
+ if (record_line_p ())
+ {
+ m_last_subfile = m_builder->get_current_subfile ();
+ record_line_1 (m_line, lte_flags);
+ m_last_line = m_line;
+ }
+ }
+ }
+
+ /* Track whether we have seen any IS_STMT true at m_address in case we
+ have multiple line table entries all at m_address. */
+ if (m_last_address != m_address)
+ {
+ m_stmt_at_address = false;
+ m_last_address = m_address;
+ }
+ m_stmt_at_address |= (m_flags & LEF_IS_STMT) != 0;
+}
+
+lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
+ line_header *lh)
+ : m_cu (cu),
+ m_builder (cu->get_builder ()),
+ m_gdbarch (arch),
+ m_line_header (lh),
+ /* Call `gdbarch_adjust_dwarf2_line' on the initial 0 address as
+ if there was a line entry for it so that the backend has a
+ chance to adjust it and also record it in case it needs it.
+ This is currently used by MIPS code,
+ cf. `mips_adjust_dwarf2_line'. */
+ m_address ((unrelocated_addr) gdbarch_adjust_dwarf2_line (arch, 0, 0)),
+ m_flags (lh->default_is_stmt ? LEF_IS_STMT : (linetable_entry_flags) 0),
+ m_last_address (m_address)
+{
+}
+
+void
+lnp_state_machine::check_line_address (struct dwarf2_cu *cu,
+ const gdb_byte *line_ptr,
+ unrelocated_addr unrelocated_lowpc,
+ unrelocated_addr address)
+{
+ /* Linkers resolve a symbolic relocation referencing a GC'd function to 0,
+ -1 or -2 (-2 is used by certain lld versions, see
+ https://github.com/llvm/llvm-project/commit/e618ccbf431f6730edb6d1467a127c3a52fd57f7).
+ If ADDRESS is 0, ignoring the opcode will err if the text section is
+ located at 0x0. In this case, additionally check that if
+ ADDRESS < UNRELOCATED_LOWPC. */
+
+ if ((address == (unrelocated_addr) 0 && address < unrelocated_lowpc)
+ || address == (unrelocated_addr) -1
+ || address == (unrelocated_addr) -2)
+ {
+ /* This line table is for a function which has been
+ GCd by the linker. Ignore it. PR gdb/12528 */
+
+ struct objfile *objfile = cu->per_objfile->objfile;
+ long line_offset = line_ptr - get_debug_line_section (cu)->buffer;
+
+ complaint (_(".debug_line address at offset 0x%lx is 0 [in module %s]"),
+ line_offset, objfile_name (objfile));
+ m_currently_recording_lines = false;
+ /* Note: m_currently_recording_lines is left as false until we see
+ DW_LNE_end_sequence. */
+ }
+}
+
+/* Subroutine of dwarf_decode_lines to simplify it.
+ Process the line number information in LH. */
+
+static void
+dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
+ unrelocated_addr lowpc)
+{
+ const gdb_byte *line_ptr, *extended_end;
+ const gdb_byte *line_end;
+ unsigned int bytes_read, extended_len;
+ unsigned char op_code, extended_op;
+ struct objfile *objfile = cu->per_objfile->objfile;
+ bfd *abfd = objfile->obfd.get ();
+ struct gdbarch *gdbarch = objfile->arch ();
+
+ line_ptr = lh->statement_program_start;
+ line_end = lh->statement_program_end;
+
+ /* Read the statement sequences until there's nothing left. */
+ while (line_ptr < line_end)
+ {
+ /* The DWARF line number program state machine. Reset the state
+ machine at the start of each sequence. */
+ lnp_state_machine state_machine (cu, gdbarch, lh);
+ bool end_sequence = false;
+
+ /* Start a subfile for the current file of the state
+ machine. */
+ const file_entry *fe = state_machine.current_file ();
+
+ if (fe != NULL)
+ dwarf2_start_subfile (cu, *fe, *lh);
+
+ /* Decode the table. */
+ while (line_ptr < line_end && !end_sequence)
+ {
+ op_code = read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+
+ if (op_code >= lh->opcode_base)
+ {
+ /* Special opcode. */
+ state_machine.handle_special_opcode (op_code);
+ }
+ else switch (op_code)
+ {
+ case DW_LNS_extended_op:
+ extended_len = read_unsigned_leb128 (abfd, line_ptr,
+ &bytes_read);
+ line_ptr += bytes_read;
+ extended_end = line_ptr + extended_len;
+ extended_op = read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+ if (DW_LNE_lo_user <= extended_op
+ && extended_op <= DW_LNE_hi_user)
+ {
+ /* Vendor extension, ignore. */
+ line_ptr = extended_end;
+ break;
+ }
+ switch (extended_op)
+ {
+ case DW_LNE_end_sequence:
+ state_machine.handle_end_sequence ();
+ end_sequence = true;
+ break;
+ case DW_LNE_set_address:
+ {
+ unrelocated_addr address
+ = cu->header.read_address (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+
+ state_machine.check_line_address (cu, line_ptr, lowpc,
+ address);
+ state_machine.handle_set_address (address);
+ }
+ break;
+ case DW_LNE_define_file:
+ {
+ const char *cur_file;
+ unsigned int mod_time, length;
+ dir_index dindex;
+
+ cur_file = read_direct_string (abfd, line_ptr,
+ &bytes_read);
+ line_ptr += bytes_read;
+ dindex = (dir_index)
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ mod_time =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ length =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ lh->add_file_name (cur_file, dindex, mod_time, length);
+ }
+ break;
+ case DW_LNE_set_discriminator:
+ {
+ /* The discriminator is not interesting to the
+ debugger; just ignore it. We still need to
+ check its value though:
+ if there are consecutive entries for the same
+ (non-prologue) line we want to coalesce them.
+ PR 17276. */
+ unsigned int discr
+ = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+
+ state_machine.handle_set_discriminator (discr);
+ }
+ break;
+ default:
+ complaint (_("mangled .debug_line section"));
+ return;
+ }
+ /* Make sure that we parsed the extended op correctly. If e.g.
+ we expected a different address size than the producer used,
+ we may have read the wrong number of bytes. */
+ if (line_ptr != extended_end)
+ {
+ complaint (_("mangled .debug_line section"));
+ return;
+ }
+ break;
+ case DW_LNS_copy:
+ state_machine.handle_copy ();
+ break;
+ case DW_LNS_advance_pc:
+ {
+ CORE_ADDR adjust
+ = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+
+ state_machine.handle_advance_pc (adjust);
+ }
+ break;
+ case DW_LNS_advance_line:
+ {
+ int line_delta
+ = read_signed_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+
+ state_machine.handle_advance_line (line_delta);
+ }
+ break;
+ case DW_LNS_set_file:
+ {
+ file_name_index file
+ = (file_name_index) read_unsigned_leb128 (abfd, line_ptr,
+ &bytes_read);
+ line_ptr += bytes_read;
+
+ state_machine.handle_set_file (file);
+ }
+ break;
+ case DW_LNS_set_column:
+ (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ break;
+ case DW_LNS_negate_stmt:
+ state_machine.handle_negate_stmt ();
+ break;
+ case DW_LNS_set_basic_block:
+ break;
+ /* Add to the address register of the state machine the
+ address increment value corresponding to special opcode
+ 255. I.e., this value is scaled by the minimum
+ instruction length since special opcode 255 would have
+ scaled the increment. */
+ case DW_LNS_const_add_pc:
+ state_machine.handle_const_add_pc ();
+ break;
+ case DW_LNS_fixed_advance_pc:
+ {
+ CORE_ADDR addr_adj = read_2_bytes (abfd, line_ptr);
+ line_ptr += 2;
+
+ state_machine.handle_fixed_advance_pc (addr_adj);
+ }
+ break;
+ case DW_LNS_set_prologue_end:
+ state_machine.handle_set_prologue_end ();
+ break;
+ case DW_LNS_set_epilogue_begin:
+ state_machine.handle_set_epilogue_begin ();
+ break;
+ default:
+ {
+ /* Unknown standard opcode, ignore it. */
+ int i;
+
+ for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++)
+ {
+ (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ }
+ }
+ }
+ }
+
+ if (!end_sequence)
+ dwarf2_debug_line_missing_end_sequence_complaint ();
+
+ /* We got a DW_LNE_end_sequence (or we ran off the end of the buffer,
+ in which case we still finish recording the last line). */
+ state_machine.record_line (true);
+ }
+}
+
+/* See dwarf2/line-program.h. */
+
+void
+dwarf_decode_lines (struct line_header *lh, struct dwarf2_cu *cu,
+ unrelocated_addr lowpc, bool decode_mapping)
+{
+ if (decode_mapping)
+ dwarf_decode_lines_1 (lh, cu, lowpc);
+
+ /* Make sure a symtab is created for every file, even files
+ which contain only variables (i.e. no code with associated
+ line numbers). */
+ buildsym_compunit *builder = cu->get_builder ();
+ struct compunit_symtab *cust = builder->get_compunit_symtab ();
+
+ for (auto &fe : lh->file_names ())
+ {
+ dwarf2_start_subfile (cu, fe, *lh);
+ subfile *sf = builder->get_current_subfile ();
+
+ if (sf->symtab == nullptr)
+ sf->symtab = allocate_symtab (cust, sf->name.c_str (),
+ sf->name_for_id.c_str ());
+
+ fe.symtab = sf->symtab;
+ }
+}
diff --git a/gdb/dwarf2/line-program.h b/gdb/dwarf2/line-program.h
new file mode 100644
index 0000000..824f18f
--- /dev/null
+++ b/gdb/dwarf2/line-program.h
@@ -0,0 +1,47 @@
+/* DWARF 2 debugging format support for GDB.
+
+ Copyright (C) 1994-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/>. */
+
+#ifndef GDB_DWARF2_LINE_PROGRAM_H
+#define GDB_DWARF2_LINE_PROGRAM_H
+
+/* Decode the Line Number Program (LNP) for the given line_header
+ structure and CU. The actual information extracted and the type
+ of structures created from the LNP depends on the value of PST.
+
+ FND holds the CU file name and directory, if known.
+ It is used for relative paths in the line table.
+
+ NOTE: It is important that psymtabs have the same file name (via
+ strcmp) as the corresponding symtab. Since the directory is not
+ used in the name of the symtab we don't use it in the name of the
+ psymtabs we create. E.g. expand_line_sal requires this when
+ finding psymtabs to expand. A good testcase for this is
+ mb-inline.exp.
+
+ LOWPC is the lowest address in CU (or 0 if not known).
+
+ Boolean DECODE_MAPPING specifies we need to fully decode .debug_line
+ for its PC<->lines mapping information. Otherwise only the filename
+ table is read in. */
+
+extern void dwarf_decode_lines (struct line_header *lh,
+ struct dwarf2_cu *cu,
+ unrelocated_addr lowpc, bool decode_mapping);
+
+#endif /* GDB_DWARF2_LINE_PROGRAM_H */
diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c
index e1a5fdd..37c85d8 100644
--- a/gdb/dwarf2/loc.c
+++ b/gdb/dwarf2/loc.c
@@ -1732,11 +1732,10 @@ dwarf2_evaluate_property (const dynamic_prop *prop,
*value = prop->const_val ();
return true;
- case PROP_ADDR_OFFSET:
+ case PROP_FIELD:
{
const dwarf2_property_baton *baton = prop->baton ();
const struct property_addr_info *pinfo;
- struct value *val;
for (pinfo = addr_stack; pinfo != NULL; pinfo = pinfo->next)
{
@@ -1747,14 +1746,40 @@ dwarf2_evaluate_property (const dynamic_prop *prop,
}
if (pinfo == NULL)
error (_("cannot find reference address for offset property"));
- if (pinfo->valaddr.data () != NULL)
- val = value_from_contents
- (baton->offset_info.type,
- pinfo->valaddr.data () + baton->offset_info.offset);
- else
- val = value_at (baton->offset_info.type,
- pinfo->addr + baton->offset_info.offset);
- *value = value_as_address (val);
+
+ struct field resolved_field = baton->field;
+ resolve_dynamic_field (resolved_field, pinfo, initial_frame);
+
+ /* Storage for memory if we need to read it. */
+ gdb::byte_vector memory;
+ const gdb_byte *bytes = pinfo->valaddr.data ();
+ if (bytes == nullptr)
+ {
+ int bitpos = resolved_field.loc_bitpos ();
+ int bitsize = resolved_field.bitsize ();
+ if (bitsize == 0)
+ bitsize = check_typedef (resolved_field.type ())->length () * 8;
+
+ /* Read just the minimum number of bytes needed to satisfy
+ unpack_field_as_long. So, update the resolved field's
+ starting offset to remove any unnecessary leading
+ bytes. */
+ int byte_offset = bitpos / 8;
+
+ bitpos %= 8;
+ resolved_field.set_loc_bitpos (bitpos);
+
+ /* Make sure to include any remaining bit offset in the
+ size computation, in case the value straddles a
+ byte. */
+ int byte_length = align_up (bitsize + bitpos, 8) / 8;
+ memory.resize (byte_length);
+
+ read_memory (pinfo->addr + byte_offset, memory.data (),
+ byte_length);
+ bytes = memory.data ();
+ }
+ *value = unpack_field_as_long (bytes, &resolved_field);
return true;
}
@@ -4129,9 +4154,7 @@ const struct symbol_computed_ops dwarf2_loclist_funcs = {
loclist_generate_c_location
};
-void _initialize_dwarf2loc ();
-void
-_initialize_dwarf2loc ()
+INIT_GDB_FILE (dwarf2loc)
{
add_setshow_zuinteger_cmd ("entry-values", class_maintenance,
&entry_values_debug,
diff --git a/gdb/dwarf2/loc.h b/gdb/dwarf2/loc.h
index 30c528b..c672320 100644
--- a/gdb/dwarf2/loc.h
+++ b/gdb/dwarf2/loc.h
@@ -20,6 +20,7 @@
#ifndef GDB_DWARF2_LOC_H
#define GDB_DWARF2_LOC_H
+#include "gdbtypes.h"
#include "dwarf2/expr.h"
struct symbol_computed_ops;
@@ -99,31 +100,9 @@ struct property_addr_info
/* If not NULL, a pointer to the info for the object containing
the object described by this node. */
- struct property_addr_info *next;
+ const property_addr_info *next;
};
-/* Converts a dynamic property into a static one. FRAME is the frame in which
- the property is evaluated; if NULL, the selected frame (if any) is used
- instead.
-
- ADDR_STACK is the stack of addresses that might be needed to evaluate the
- property. When evaluating a property that is not related to a type, it can
- be NULL.
-
- Returns true if PROP could be converted and the static value is passed
- back into VALUE, otherwise returns false.
-
- Any values in PUSH_VALUES will be pushed before evaluating the location
- expression, PUSH_VALUES[0] will be pushed first, then PUSH_VALUES[1],
- etc. This means the during evaluation PUSH_VALUES[0] will be at the
- bottom of the stack. */
-
-bool dwarf2_evaluate_property (const struct dynamic_prop *prop,
- const frame_info_ptr &frame,
- const property_addr_info *addr_stack,
- CORE_ADDR *value,
- gdb::array_view<CORE_ADDR> push_values = {});
-
/* A helper for the compiler interface that compiles a single dynamic
property to C code.
@@ -167,6 +146,9 @@ struct dwarf2_locexpr_baton
directly. */
bool is_reference;
+ /* True if this object is actually a dwarf2_field_location_baton. */
+ bool is_field_location;
+
/* The objfile that was used when creating this. */
dwarf2_per_objfile *per_objfile;
@@ -175,6 +157,23 @@ struct dwarf2_locexpr_baton
dwarf2_per_cu *per_cu;
};
+/* If the DWARF location for a field used DW_AT_bit_size, then an
+ object of this type is created to represent the field location.
+ This is then used to apply the bit offset after computing the
+ field's byte offset. Objects of this type always set the
+ 'is_field_location' member in dwarf2_locexpr_baton. See also
+ apply_bit_offset_to_field. */
+
+struct dwarf2_field_location_baton : public dwarf2_locexpr_baton
+{
+ /* The bit offset, coming from DW_AT_bit_offset. */
+ LONGEST bit_offset;
+
+ /* The DW_AT_byte_size of the field. If no explicit byte size was
+ specified, this is 0. */
+ LONGEST explicit_byte_size;
+};
+
struct dwarf2_loclist_baton
{
/* The initial base address for the location list, based on the compilation
@@ -202,23 +201,6 @@ struct dwarf2_loclist_baton
unsigned char dwarf_version;
};
-/* The baton used when a dynamic property is an offset to a parent
- type. This can be used, for instance, then the bound of an array
- inside a record is determined by the value of another field inside
- that record. */
-
-struct dwarf2_offset_baton
-{
- /* The offset from the parent type where the value of the property
- is stored. In the example provided above, this would be the offset
- of the field being used as the array bound. */
- LONGEST offset;
-
- /* The type of the object whose property is dynamic. In the example
- provided above, this would the array's index type. */
- struct type *type;
-};
-
/* A dynamic property is either expressed as a single location expression
or a location list. If the property is an indirection, pointing to
another die, keep track of the targeted type in PROPERTY_TYPE.
@@ -241,8 +223,8 @@ struct dwarf2_property_baton
/* Location list to be evaluated in the context of PROPERTY_TYPE. */
struct dwarf2_loclist_baton loclist;
- /* The location is an offset to PROPERTY_TYPE. */
- struct dwarf2_offset_baton offset_info;
+ /* The location is stored in a field of PROPERTY_TYPE. */
+ struct field field;
};
};
@@ -307,8 +289,53 @@ extern struct value *indirect_synthetic_pointer
Function always returns non-NULL value. It throws NO_ENTRY_VALUE_ERROR if
it cannot resolve the parameter for any reason. */
+#if defined(DWARF_FORMAT_AVAILABLE)
+
+/* Converts a dynamic property into a static one. FRAME is the frame in which
+ the property is evaluated; if NULL, the selected frame (if any) is used
+ instead.
+
+ ADDR_STACK is the stack of addresses that might be needed to evaluate the
+ property. When evaluating a property that is not related to a type, it can
+ be NULL.
+
+ Returns true if PROP could be converted and the static value is passed
+ back into VALUE, otherwise returns false.
+
+ Any values in PUSH_VALUES will be pushed before evaluating the location
+ expression, PUSH_VALUES[0] will be pushed first, then PUSH_VALUES[1],
+ etc. This means the during evaluation PUSH_VALUES[0] will be at the
+ bottom of the stack. */
+
+bool dwarf2_evaluate_property (const struct dynamic_prop *prop,
+ const frame_info_ptr &frame,
+ const property_addr_info *addr_stack,
+ CORE_ADDR *value,
+ gdb::array_view<CORE_ADDR> push_values = {});
+
extern struct value *value_of_dwarf_reg_entry (struct type *type,
const frame_info_ptr &frame,
enum call_site_parameter_kind kind,
union call_site_parameter_u kind_u);
+
+#else /* DWARF_FORMAT_AVAILABLE */
+
+static inline bool
+dwarf2_evaluate_property (const struct dynamic_prop *, const frame_info_ptr &,
+ const property_addr_info *, CORE_ADDR *,
+ gdb::array_view<CORE_ADDR> = {})
+{
+ return false;
+}
+
+static inline struct value *
+value_of_dwarf_reg_entry (struct type *type, const frame_info_ptr &frame,
+ enum call_site_parameter_kind kind,
+ union call_site_parameter_u kind_u)
+{
+ error (_("No dwarf support available."));
+}
+
+#endif /* DWARF_FORMAT_AVAILABLE */
+
#endif /* GDB_DWARF2_LOC_H */
diff --git a/gdb/dwarf2/public.h b/gdb/dwarf2/public.h
index ed504c6..f9e7488 100644
--- a/gdb/dwarf2/public.h
+++ b/gdb/dwarf2/public.h
@@ -30,6 +30,8 @@ enum class dw_index_kind
DEBUG_NAMES,
};
+#if defined(DWARF_FORMAT_AVAILABLE)
+
/* Try to locate the sections we need for DWARF 2 debugging
information. If these are found, begin reading the DWARF and
return true. Otherwise, return false. NAMES points to the dwarf2
@@ -44,4 +46,27 @@ extern bool dwarf2_initialize_objfile
extern void dwarf2_build_frame_info (struct objfile *);
+/* Append the DWARF-2 frame unwinders to GDBARCH's list. */
+
+void dwarf2_append_unwinders (struct gdbarch *gdbarch);
+
+#else /* DWARF_FORMAT_AVAILABLE */
+
+static inline bool
+dwarf2_initialize_objfile (struct objfile *,
+ const struct dwarf2_debug_sections * = nullptr,
+ bool = false)
+{
+ warning (_("No dwarf support available."));
+ return false;
+}
+
+static inline void
+dwarf2_build_frame_info (struct objfile *)
+{
+ warning (_("No dwarf support available."));
+}
+
+#endif /* DWARF_FORMAT_AVAILABLE */
+
#endif /* GDB_DWARF2_PUBLIC_H */
diff --git a/gdb/dwarf2/read-debug-names.c b/gdb/dwarf2/read-debug-names.c
index 11de986..ddf4935 100644
--- a/gdb/dwarf2/read-debug-names.c
+++ b/gdb/dwarf2/read-debug-names.c
@@ -114,6 +114,14 @@ struct mapped_debug_names_reader
gdb::unordered_map<ULONGEST, index_val> abbrev_map;
+ /* List of CUs in the same order as found in the index header (DWARF 5 section
+ 6.1.1.4.2). */
+ std::vector<dwarf2_per_cu *> comp_units;
+
+ /* List of local TUs in the same order as found in the index (DWARF 5 section
+ 6.1.1.4.3). */
+ std::vector<dwarf2_per_cu *> type_units;
+
/* Even though the scanning of .debug_names and creation of the
cooked index entries is done serially, we create multiple shards
so that the finalization step can be parallelized. The shards
@@ -232,7 +240,7 @@ mapped_debug_names_reader::scan_one_entry (const char *name,
case DW_IDX_compile_unit:
{
/* Don't crash on bad data. */
- if (ull >= per_objfile->per_bfd->all_comp_units.size ())
+ if (ull >= this->comp_units.size ())
{
complaint (_(".debug_names entry has bad CU index %s"
" [in module %s]"),
@@ -240,30 +248,31 @@ mapped_debug_names_reader::scan_one_entry (const char *name,
bfd_get_filename (abfd));
continue;
}
+
+ per_cu = this->comp_units[ull];
+ break;
}
- per_cu = per_objfile->per_bfd->get_cu (ull);
- break;
case DW_IDX_type_unit:
- /* Don't crash on bad data. */
- if (ull >= per_objfile->per_bfd->all_type_units.size ())
- {
- complaint (_(".debug_names entry has bad TU index %s"
- " [in module %s]"),
- pulongest (ull),
- bfd_get_filename (abfd));
- continue;
- }
{
- int nr_cus = per_objfile->per_bfd->all_comp_units.size ();
- per_cu = per_objfile->per_bfd->get_cu (nr_cus + ull);
+ /* Don't crash on bad data. */
+ if (ull >= this->type_units.size ())
+ {
+ complaint (_(".debug_names entry has bad TU index %s"
+ " [in module %s]"),
+ pulongest (ull),
+ bfd_get_filename (abfd));
+ continue;
+ }
+
+ per_cu = this->type_units[ull];
+ break;
}
- break;
case DW_IDX_die_offset:
die_offset = sect_offset (ull);
/* In a per-CU index (as opposed to a per-module index), index
entries without CU attribute implicitly refer to the single CU. */
- if (per_cu == NULL)
- per_cu = per_objfile->per_bfd->get_cu (0);
+ if (per_cu == nullptr)
+ per_cu = this->comp_units[0];
break;
case DW_IDX_parent:
parent = ull;
@@ -416,15 +425,11 @@ cooked_index_worker_debug_names::do_reading ()
{
complaint_interceptor complaint_handler;
- try
+ /* Arbitrarily put all exceptions into the first result. */
+ m_map.indices[0].catch_error ([&] ()
{
m_map.scan_all_names ();
- }
- catch (gdb_exception &exc)
- {
- /* Arbitrarily put all exceptions into the first result. */
- m_map.indices[0].note_error (std::move (exc));
- }
+ });
bool first = true;
for (auto &iter : m_map.indices)
@@ -444,45 +449,45 @@ cooked_index_worker_debug_names::do_reading ()
bfd_thread_cleanup ();
}
-/* Check the signatured type hash table from .debug_names. */
+/* Build the list of TUs (mapped_debug_names_reader::type_units) from the index
+ header and verify that it matches the list of TUs read from the DIEs in
+ `.debug_info`.
+
+ Return true if they match, false otherwise. */
static bool
-check_signatured_type_table_from_debug_names
- (dwarf2_per_objfile *per_objfile,
- const mapped_debug_names_reader &map,
- struct dwarf2_section_info *section)
+build_and_check_tu_list_from_debug_names (dwarf2_per_objfile *per_objfile,
+ mapped_debug_names_reader &map,
+ dwarf2_section_info *section)
{
struct objfile *objfile = per_objfile->objfile;
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
- int nr_cus = per_bfd->all_comp_units.size ();
- int nr_cus_tus = per_bfd->all_units.size ();
section->read (objfile);
- uint32_t j = nr_cus;
for (uint32_t i = 0; i < map.tu_count; ++i)
{
+ /* Read one entry from the TU list. */
sect_offset sect_off
= (sect_offset) (extract_unsigned_integer
(map.tu_table_reordered + i * map.offset_size,
map.offset_size,
map.dwarf5_byte_order));
- bool found = false;
- for (; j < nr_cus_tus; j++)
- if (per_bfd->get_cu (j)->sect_off == sect_off)
- {
- found = true;
- break;
- }
- if (!found)
+ /* Find the matching dwarf2_per_cu. */
+ dwarf2_per_cu *per_cu = dwarf2_find_unit ({ section, sect_off },
+ per_bfd);
+
+ if (per_cu == nullptr || !per_cu->is_debug_types)
{
warning (_("Section .debug_names has incorrect entry in TU table,"
" ignoring .debug_names."));
return false;
}
- per_bfd->all_comp_units_index_tus.push_back (per_bfd->get_cu (j));
+
+ map.type_units.emplace_back (per_cu);
}
+
return true;
}
@@ -704,40 +709,11 @@ read_debug_names_from_section (dwarf2_per_objfile *per_objfile,
list. */
static bool
-check_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
- const mapped_debug_names_reader &map,
- dwarf2_section_info &section,
- bool is_dwz)
+build_and_check_cu_list_from_debug_names (dwarf2_per_bfd *per_bfd,
+ mapped_debug_names_reader &map,
+ dwarf2_section_info &section)
{
- int nr_cus = per_bfd->all_comp_units.size ();
-
- if (!map.augmentation_is_gdb)
- {
- uint32_t j = 0;
- for (uint32_t i = 0; i < map.cu_count; ++i)
- {
- sect_offset sect_off
- = (sect_offset) (extract_unsigned_integer
- (map.cu_table_reordered + i * map.offset_size,
- map.offset_size,
- map.dwarf5_byte_order));
- bool found = false;
- for (; j < nr_cus; j++)
- if (per_bfd->get_cu (j)->sect_off == sect_off)
- {
- found = true;
- break;
- }
- if (!found)
- {
- warning (_("Section .debug_names has incorrect entry in CU table,"
- " ignoring .debug_names."));
- return false;
- }
- per_bfd->all_comp_units_index_cus.push_back (per_bfd->get_cu (j));
- }
- return true;
- }
+ int nr_cus = per_bfd->num_comp_units;
if (map.cu_count != nr_cus)
{
@@ -753,43 +729,51 @@ check_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
(map.cu_table_reordered + i * map.offset_size,
map.offset_size,
map.dwarf5_byte_order));
- if (sect_off != per_bfd->get_cu (i)->sect_off)
+
+ /* Find the matching dwarf2_per_cu. */
+ dwarf2_per_cu *per_cu = dwarf2_find_unit ({ &section, sect_off }, per_bfd);
+
+ if (per_cu == nullptr || per_cu->is_debug_types)
{
warning (_("Section .debug_names has incorrect entry in CU table,"
" ignoring .debug_names."));
return false;
}
+
+ map.comp_units.emplace_back (per_cu);
}
return true;
}
-/* Read the CU list from the mapped index, and use it to create all
- the CU objects for this dwarf2_per_objfile. */
+/* Build the list of CUs (mapped_debug_names_reader::compile_units) from the
+ index header and verify that it matches the list of CUs read from the DIEs in
+ `.debug_info`.
+
+ Return true if they match, false otherwise. */
static bool
-check_cus_from_debug_names (dwarf2_per_bfd *per_bfd,
- const mapped_debug_names_reader &map,
- const mapped_debug_names_reader &dwz_map)
+build_and_check_cu_lists_from_debug_names (dwarf2_per_bfd *per_bfd,
+ mapped_debug_names_reader &map,
+ mapped_debug_names_reader &dwz_map)
{
- if (!check_cus_from_debug_names_list (per_bfd, map, per_bfd->infos[0],
- false /* is_dwz */))
+ if (!build_and_check_cu_list_from_debug_names (per_bfd, map,
+ per_bfd->infos[0]))
return false;
if (dwz_map.cu_count == 0)
return true;
dwz_file *dwz = per_bfd->get_dwz_file ();
- return check_cus_from_debug_names_list (per_bfd, dwz_map, dwz->info,
- true /* is_dwz */);
+ return build_and_check_cu_list_from_debug_names (per_bfd, dwz_map, dwz->info);
}
-/* This does all the work for dwarf2_read_debug_names, but putting it
- into a separate function makes some cleanup a bit simpler. */
+/* See read-debug-names.h. */
-static bool
-do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
+bool
+dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
{
+ scoped_remove_all_units remove_all_units (*per_objfile->per_bfd);
mapped_debug_names_reader map;
mapped_debug_names_reader dwz_map;
struct objfile *objfile = per_objfile->objfile;
@@ -819,7 +803,7 @@ do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
}
create_all_units (per_objfile);
- if (!check_cus_from_debug_names (per_bfd, map, dwz_map))
+ if (!build_and_check_cu_lists_from_debug_names (per_bfd, map, dwz_map))
return false;
if (map.tu_count != 0)
@@ -835,8 +819,8 @@ do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
? &per_bfd->types[0]
: &per_bfd->infos[0]);
- if (!check_signatured_type_table_from_debug_names (per_objfile,
- map, section))
+ if (!build_and_check_tu_list_from_debug_names (per_objfile, map,
+ section))
return false;
}
@@ -866,17 +850,7 @@ do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
(per_objfile, std::move (map)));
auto idx = std::make_unique<debug_names_index> (std::move (cidn));
per_bfd->start_reading (std::move (idx));
+ remove_all_units.disable ();
return true;
}
-
-/* See read-debug-names.h. */
-
-bool
-dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
-{
- bool result = do_dwarf2_read_debug_names (per_objfile);
- if (!result)
- per_objfile->per_bfd->all_units.clear ();
- return result;
-}
diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c
index 2029c3e..5354263 100644
--- a/gdb/dwarf2/read-gdb-index.c
+++ b/gdb/dwarf2/read-gdb-index.c
@@ -27,16 +27,67 @@
#include "event-top.h"
#include "gdb/gdb-index.h"
#include "gdbsupport/gdb-checked-static-cast.h"
-#include "mapped-index.h"
+#include "cooked-index.h"
#include "read.h"
#include "extract-store-integer.h"
#include "cp-support.h"
#include "symtab.h"
#include "gdbsupport/selftest.h"
+#include "tag.h"
/* When true, do not reject deprecated .gdb_index sections. */
static bool use_deprecated_index_sections = false;
+struct dwarf2_gdb_index : public cooked_index_functions
+{
+ /* This dumps minimal information about the index.
+ It is called via "mt print objfiles".
+ One use is to verify .gdb_index has been loaded by the
+ gdb.dwarf2/gdb-index.exp testcase. */
+ void dump (struct objfile *objfile) override;
+};
+
+/* This is a cooked index as ingested from .gdb_index. */
+
+class cooked_gdb_index : public cooked_index
+{
+public:
+
+ cooked_gdb_index (cooked_index_worker_up worker,
+ int version)
+ : cooked_index (std::move (worker)),
+ version (version)
+ { }
+
+ /* This can't be used to write an index. */
+ cooked_index *index_for_writing () override
+ { return nullptr; }
+
+ quick_symbol_functions_up make_quick_functions () const override
+ { return quick_symbol_functions_up (new dwarf2_gdb_index); }
+
+ bool version_check () const override
+ {
+ return version >= 8;
+ }
+
+ /* Index data format version. */
+ int version;
+};
+
+/* See above. */
+
+void
+dwarf2_gdb_index::dump (struct objfile *objfile)
+{
+ dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+
+ cooked_gdb_index *index = (gdb::checked_static_cast<cooked_gdb_index *>
+ (per_objfile->per_bfd->index_table.get ()));
+ gdb_printf (".gdb_index: version %d\n", index->version);
+ cooked_index_functions::dump (objfile);
+}
+
/* This is a view into the index that converts from bytes to an
offset_type, and allows indexing. Unaligned bytes are specifically
allowed here, and handled via unpacking. */
@@ -77,46 +128,18 @@ private:
gdb::array_view<const gdb_byte> m_bytes;
};
-/* An index into a (C++) symbol name component in a symbol name as
- recorded in the mapped_index's symbol table. For each C++ symbol
- in the symbol table, we record one entry for the start of each
- component in the symbol in a table of name components, and then
- sort the table, in order to be able to binary search symbol names,
- ignoring leading namespaces, both completion and regular look up.
- For example, for symbol "A::B::C", we'll have an entry that points
- to "A::B::C", another that points to "B::C", and another for "C".
- Note that function symbols in GDB index have no parameter
- information, just the function/method names. You can convert a
- name_component to a "const char *" using the
- 'mapped_index::symbol_name_at(offset_type)' method. */
-
-struct name_component
-{
- /* Offset in the symbol name where the component starts. Stored as
- a (32-bit) offset instead of a pointer to save memory and improve
- locality on 64-bit architectures. */
- offset_type name_offset;
-
- /* The symbol's index in the symbol and constant pool tables of a
- mapped_index. */
- offset_type idx;
-};
-
-/* A description of .gdb_index index. The file format is described in
- a comment by the code that writes the index. */
+/* A worker for reading .gdb_index. The file format is described in
+ the manual. */
-struct mapped_gdb_index : public dwarf_scanner_base
+struct mapped_gdb_index
{
- /* The name_component table (a sorted vector). See name_component's
- description above. */
- std::vector<name_component> name_components;
-
- /* How NAME_COMPONENTS is sorted. */
- enum case_sensitivity name_components_casing;
-
/* Index data format version. */
int version = 0;
+ /* Compile units followed by type units, in the order as found in the
+ index. Indices found in index entries can index directly into this. */
+ std::vector<dwarf2_per_cu *> units;
+
/* The address table data. */
gdb::array_view<const gdb_byte> address_table;
@@ -132,6 +155,15 @@ struct mapped_gdb_index : public dwarf_scanner_base
/* An address map that maps from PC to dwarf2_per_cu. */
addrmap_fixed *index_addrmap = nullptr;
+ /* The name of 'main', or nullptr if not known. */
+ const char *main_name = nullptr;
+
+ /* The language of 'main', if known. */
+ enum language main_lang = language_minimal;
+
+ /* The result we're constructing. */
+ cooked_index_worker_result result;
+
/* Return the index into the constant pool of the name of the IDXth
symbol in the symbol table. */
offset_type symbol_name_index (offset_type idx) const
@@ -148,221 +180,41 @@ struct mapped_gdb_index : public dwarf_scanner_base
/* Return whether the name at IDX in the symbol table should be
ignored. */
- virtual bool symbol_name_slot_invalid (offset_type idx) const
+ bool symbol_name_slot_invalid (offset_type idx) const
{
- return (symbol_name_index (idx) == 0
- && symbol_vec_index (idx) == 0);
+ return symbol_name_index (idx) == 0 && symbol_vec_index (idx) == 0;
}
/* Convenience method to get at the name of the symbol at IDX in the
symbol table. */
- virtual const char *symbol_name_at
- (offset_type idx, dwarf2_per_objfile *per_objfile) const
+ const char *symbol_name_at (offset_type idx,
+ dwarf2_per_objfile *per_objfile) const
{
return (const char *) (this->constant_pool.data ()
+ symbol_name_index (idx));
}
- virtual size_t symbol_name_count () const
+ size_t symbol_name_count () const
{ return this->symbol_table.size () / 2; }
+ /* Set the name and language of the main function from the shortcut
+ table. */
+ void set_main_name (dwarf2_per_objfile *per_objfile);
+
/* Build the symbol name component sorted vector, if we haven't
yet. */
void build_name_components (dwarf2_per_objfile *per_objfile);
-
- /* Returns the lower (inclusive) and upper (exclusive) bounds of the
- possible matches for LN_NO_PARAMS in the name component
- vector. */
- std::pair<std::vector<name_component>::const_iterator,
- std::vector<name_component>::const_iterator>
- find_name_components_bounds (const lookup_name_info &ln_no_params,
- enum language lang,
- dwarf2_per_objfile *per_objfile) const;
-
- quick_symbol_functions_up make_quick_functions () const override;
-
- bool version_check () const override
- {
- return version >= 8;
- }
-
- dwarf2_per_cu *lookup (unrelocated_addr addr) override
- {
- if (index_addrmap == nullptr)
- return nullptr;
-
- void *obj = index_addrmap->find (static_cast<CORE_ADDR> (addr));
- return static_cast<dwarf2_per_cu *> (obj);
- }
-
- cooked_index *index_for_writing () override
- { return nullptr; }
};
-
-/* Starting from a search name, return the string that finds the upper
- bound of all strings that start with SEARCH_NAME in a sorted name
- list. Returns the empty string to indicate that the upper bound is
- the end of the list. */
-
-static std::string
-make_sort_after_prefix_name (const char *search_name)
-{
- /* When looking to complete "func", we find the upper bound of all
- symbols that start with "func" by looking for where we'd insert
- the closest string that would follow "func" in lexicographical
- order. Usually, that's "func"-with-last-character-incremented,
- i.e. "fund". Mind non-ASCII characters, though. Usually those
- will be UTF-8 multi-byte sequences, but we can't be certain.
- Especially mind the 0xff character, which is a valid character in
- non-UTF-8 source character sets (e.g. Latin1 'ÿ'), and we can't
- rule out compilers allowing it in identifiers. Note that
- conveniently, strcmp/strcasecmp are specified to compare
- characters interpreted as unsigned char. So what we do is treat
- the whole string as a base 256 number composed of a sequence of
- base 256 "digits" and add 1 to it. I.e., adding 1 to 0xff wraps
- to 0, and carries 1 to the following more-significant position.
- If the very first character in SEARCH_NAME ends up incremented
- and carries/overflows, then the upper bound is the end of the
- list. The string after the empty string is also the empty
- string.
-
- Some examples of this operation:
-
- SEARCH_NAME => "+1" RESULT
-
- "abc" => "abd"
- "ab\xff" => "ac"
- "\xff" "a" "\xff" => "\xff" "b"
- "\xff" => ""
- "\xff\xff" => ""
- "" => ""
-
- Then, with these symbols for example:
-
- func
- func1
- fund
-
- completing "func" looks for symbols between "func" and
- "func"-with-last-character-incremented, i.e. "fund" (exclusive),
- which finds "func" and "func1", but not "fund".
-
- And with:
-
- funcÿ (Latin1 'ÿ' [0xff])
- funcÿ1
- fund
-
- completing "funcÿ" looks for symbols between "funcÿ" and "fund"
- (exclusive), which finds "funcÿ" and "funcÿ1", but not "fund".
-
- And with:
-
- ÿÿ (Latin1 'ÿ' [0xff])
- ÿÿ1
-
- completing "ÿ" or "ÿÿ" looks for symbols between between "ÿÿ" and
- the end of the list.
- */
- std::string after = search_name;
- while (!after.empty () && (unsigned char) after.back () == 0xff)
- after.pop_back ();
- if (!after.empty ())
- after.back () = (unsigned char) after.back () + 1;
- return after;
-}
-
-/* See declaration. */
-
-std::pair<std::vector<name_component>::const_iterator,
- std::vector<name_component>::const_iterator>
-mapped_gdb_index::find_name_components_bounds
- (const lookup_name_info &lookup_name_without_params, language lang,
- dwarf2_per_objfile *per_objfile) const
-{
- auto *name_cmp
- = this->name_components_casing == case_sensitive_on ? strcmp : strcasecmp;
-
- const char *lang_name
- = lookup_name_without_params.language_lookup_name (lang);
-
- /* Comparison function object for lower_bound that matches against a
- given symbol name. */
- auto lookup_compare_lower = [&] (const name_component &elem,
- const char *name)
- {
- const char *elem_qualified = this->symbol_name_at (elem.idx, per_objfile);
- const char *elem_name = elem_qualified + elem.name_offset;
- return name_cmp (elem_name, name) < 0;
- };
-
- /* Comparison function object for upper_bound that matches against a
- given symbol name. */
- auto lookup_compare_upper = [&] (const char *name,
- const name_component &elem)
- {
- const char *elem_qualified = this->symbol_name_at (elem.idx, per_objfile);
- const char *elem_name = elem_qualified + elem.name_offset;
- return name_cmp (name, elem_name) < 0;
- };
-
- auto begin = this->name_components.begin ();
- auto end = this->name_components.end ();
-
- /* Find the lower bound. */
- auto lower = [&] ()
- {
- if (lookup_name_without_params.completion_mode () && lang_name[0] == '\0')
- return begin;
- else
- return std::lower_bound (begin, end, lang_name, lookup_compare_lower);
- } ();
-
- /* Find the upper bound. */
- auto upper = [&] ()
- {
- if (lookup_name_without_params.completion_mode ())
- {
- /* In completion mode, we want UPPER to point past all
- symbols names that have the same prefix. I.e., with
- these symbols, and completing "func":
-
- function << lower bound
- function1
- other_function << upper bound
-
- We find the upper bound by looking for the insertion
- point of "func"-with-last-character-incremented,
- i.e. "fund". */
- std::string after = make_sort_after_prefix_name (lang_name);
- if (after.empty ())
- return end;
- return std::lower_bound (lower, end, after.c_str (),
- lookup_compare_lower);
- }
- else
- return std::upper_bound (lower, end, lang_name, lookup_compare_upper);
- } ();
-
- return {lower, upper};
-}
-
/* See declaration. */
void
mapped_gdb_index::build_name_components (dwarf2_per_objfile *per_objfile)
{
- if (!this->name_components.empty ())
- return;
+ std::vector<std::pair<std::string_view, std::vector<cooked_index_entry *>>>
+ need_parents;
+ gdb::unordered_map<std::string_view, cooked_index_entry *> by_name;
- this->name_components_casing = case_sensitivity;
- auto *name_cmp
- = this->name_components_casing == case_sensitive_on ? strcmp : strcasecmp;
-
- /* The code below only knows how to break apart components of C++
- symbol names (and other languages that use '::' as
- namespace/module separator) and Ada symbol names. */
auto count = this->symbol_name_count ();
for (offset_type idx = 0; idx < count; idx++)
{
@@ -371,813 +223,186 @@ mapped_gdb_index::build_name_components (dwarf2_per_objfile *per_objfile)
const char *name = this->symbol_name_at (idx, per_objfile);
- /* Add each name component to the name component table. */
- unsigned int previous_len = 0;
+ /* This code only knows how to break apart components of C++
+ symbol names (and other languages that use '::' as
+ namespace/module separator) and Ada symbol names.
+ It's unfortunate that we need the language, but since it is
+ really only used to rebuild full names, pairing it with the
+ split method is fine. */
+ enum language lang;
+ std::vector<std::string_view> components;
if (strstr (name, "::") != nullptr)
{
- for (unsigned int current_len = cp_find_first_component (name);
- name[current_len] != '\0';
- current_len += cp_find_first_component (name + current_len))
- {
- gdb_assert (name[current_len] == ':');
- this->name_components.push_back ({previous_len, idx});
- /* Skip the '::'. */
- current_len += 2;
- previous_len = current_len;
- }
+ components = split_name (name, split_style::CXX);
+ lang = language_cplus;
}
- else
+ else if (strchr (name, '<') != nullptr)
{
- /* Handle the Ada encoded (aka mangled) form here. */
- for (const char *iter = strstr (name, "__");
- iter != nullptr;
- iter = strstr (iter, "__"))
- {
- this->name_components.push_back ({previous_len, idx});
- iter += 2;
- previous_len = iter - name;
- }
+ /* Guess that this is a template and so a C++ name. */
+ components.emplace_back (name);
+ lang = language_cplus;
}
-
- this->name_components.push_back ({previous_len, idx});
- }
-
- /* Sort name_components elements by name. */
- auto name_comp_compare = [&] (const name_component &left,
- const name_component &right)
- {
- const char *left_qualified
- = this->symbol_name_at (left.idx, per_objfile);
- const char *right_qualified
- = this->symbol_name_at (right.idx, per_objfile);
-
- const char *left_name = left_qualified + left.name_offset;
- const char *right_name = right_qualified + right.name_offset;
-
- return name_cmp (left_name, right_name) < 0;
- };
-
- std::sort (this->name_components.begin (),
- this->name_components.end (),
- name_comp_compare);
-}
-
-/* Helper for dw2_expand_symtabs_matching that works with a
- mapped_index_base instead of the containing objfile. This is split
- to a separate function in order to be able to unit test the
- name_components matching using a mock mapped_index_base. For each
- symbol name that matches, calls MATCH_CALLBACK, passing it the
- symbol's index in the mapped_index_base symbol table. */
-
-static bool
-dw2_expand_symtabs_matching_symbol
- (mapped_gdb_index &index,
- const lookup_name_info &lookup_name_in,
- expand_symtabs_symbol_matcher symbol_matcher,
- gdb::function_view<bool (offset_type)> match_callback,
- dwarf2_per_objfile *per_objfile,
- expand_symtabs_lang_matcher lang_matcher)
-{
- lookup_name_info lookup_name_without_params
- = lookup_name_in.make_ignore_params ();
-
- /* Build the symbol name component sorted vector, if we haven't
- yet. */
- index.build_name_components (per_objfile);
-
- /* The same symbol may appear more than once in the range though.
- E.g., if we're looking for symbols that complete "w", and we have
- a symbol named "w1::w2", we'll find the two name components for
- that same symbol in the range. To be sure we only call the
- callback once per symbol, we first collect the symbol name
- indexes that matched in a temporary vector and ignore
- duplicates. */
- std::vector<offset_type> matches;
-
- struct name_and_matcher
- {
- symbol_name_matcher_ftype *matcher;
- const char *name;
-
- bool operator== (const name_and_matcher &other) const
- {
- return matcher == other.matcher && strcmp (name, other.name) == 0;
- }
- };
-
- /* A vector holding all the different symbol name matchers, for all
- languages. */
- std::vector<name_and_matcher> matchers;
-
- for (int i = 0; i < nr_languages; i++)
- {
- enum language lang_e = (enum language) i;
- if (lang_matcher != nullptr && !lang_matcher (lang_e))
- continue;
-
- const language_defn *lang = language_def (lang_e);
- symbol_name_matcher_ftype *name_matcher
- = lang->get_symbol_name_matcher (lookup_name_without_params);
-
- name_and_matcher key {
- name_matcher,
- lookup_name_without_params.language_lookup_name (lang_e)
- };
-
- /* Don't insert the same comparison routine more than once.
- Note that we do this linear walk. This is not a problem in
- practice because the number of supported languages is
- low. */
- if (std::find (matchers.begin (), matchers.end (), key)
- != matchers.end ())
- continue;
- matchers.push_back (std::move (key));
-
- auto bounds
- = index.find_name_components_bounds (lookup_name_without_params,
- lang_e, per_objfile);
-
- /* Now for each symbol name in range, check to see if we have a name
- match, and if so, call the MATCH_CALLBACK callback. */
-
- for (; bounds.first != bounds.second; ++bounds.first)
+ else if (strstr (name, "__") != nullptr)
{
- const char *qualified
- = index.symbol_name_at (bounds.first->idx, per_objfile);
-
- if (!name_matcher (qualified, lookup_name_without_params, NULL)
- || (symbol_matcher != NULL && !symbol_matcher (qualified)))
- continue;
-
- matches.push_back (bounds.first->idx);
+ /* The Ada case is handled during finalization, because gdb
+ does not write the synthesized package names into the
+ index. */
+ components.emplace_back (name);
+ lang = language_ada;
}
- }
-
- std::sort (matches.begin (), matches.end ());
-
- /* Finally call the callback, once per match. */
- ULONGEST prev = -1;
- bool result = true;
- for (offset_type idx : matches)
- {
- if (prev != idx)
+ else
{
- if (!match_callback (idx))
- {
- result = false;
- break;
- }
- prev = idx;
+ components = split_name (name, split_style::DOT_STYLE);
+ /* Mark ordinary names as having an unknown language. This
+ is a hack to avoid problems with some Ada names. */
+ lang = (components.size () == 1) ? language_unknown : language_go;
}
- }
-
- /* Above we use a type wider than idx's for 'prev', since 0 and
- (offset_type)-1 are both possible values. */
- static_assert (sizeof (prev) > sizeof (offset_type), "");
-
- return result;
-}
-
-#if GDB_SELF_TEST
-
-namespace selftests { namespace dw2_expand_symtabs_matching {
-
-/* A mock .gdb_index/.debug_names-like name index table, enough to
- exercise dw2_expand_symtabs_matching_symbol, which works with the
- mapped_index_base interface. Builds an index from the symbol list
- passed as parameter to the constructor. */
-class mock_mapped_index : public mapped_gdb_index
-{
-public:
- mock_mapped_index (gdb::array_view<const char *> symbols)
- : m_symbol_table (symbols)
- {}
-
- DISABLE_COPY_AND_ASSIGN (mock_mapped_index);
-
- bool symbol_name_slot_invalid (offset_type idx) const override
- { return false; }
-
- /* Return the number of names in the symbol table. */
- size_t symbol_name_count () const override
- {
- return m_symbol_table.size ();
- }
-
- /* Get the name of the symbol at IDX in the symbol table. */
- const char *symbol_name_at
- (offset_type idx, dwarf2_per_objfile *per_objfile) const override
- {
- return m_symbol_table[idx];
- }
-
- quick_symbol_functions_up make_quick_functions () const override
- {
- return nullptr;
- }
-
-private:
- gdb::array_view<const char *> m_symbol_table;
-};
-
-/* Convenience function that converts a NULL pointer to a "<null>"
- string, to pass to print routines. */
-
-static const char *
-string_or_null (const char *str)
-{
- return str != NULL ? str : "<null>";
-}
-
-/* Check if a lookup_name_info built from
- NAME/MATCH_TYPE/COMPLETION_MODE matches the symbols in the mock
- index. EXPECTED_LIST is the list of expected matches, in expected
- matching order. If no match expected, then an empty list is
- specified. Returns true on success. On failure prints a warning
- indicating the file:line that failed, and returns false. */
-
-static bool
-check_match (const char *file, int line,
- mock_mapped_index &mock_index,
- const char *name, symbol_name_match_type match_type,
- bool completion_mode,
- std::initializer_list<const char *> expected_list,
- dwarf2_per_objfile *per_objfile)
-{
- lookup_name_info lookup_name (name, match_type, completion_mode);
-
- bool matched = true;
-
- auto mismatch = [&] (const char *expected_str,
- const char *got)
- {
- warning (_("%s:%d: match_type=%s, looking-for=\"%s\", "
- "expected=\"%s\", got=\"%s\"\n"),
- file, line,
- (match_type == symbol_name_match_type::FULL
- ? "FULL" : "WILD"),
- name, string_or_null (expected_str), string_or_null (got));
- matched = false;
- };
-
- auto expected_it = expected_list.begin ();
- auto expected_end = expected_list.end ();
-
- dw2_expand_symtabs_matching_symbol (mock_index, lookup_name,
- nullptr,
- [&] (offset_type idx)
- {
- const char *matched_name = mock_index.symbol_name_at (idx, per_objfile);
- const char *expected_str
- = expected_it == expected_end ? NULL : *expected_it++;
-
- if (expected_str == NULL || strcmp (expected_str, matched_name) != 0)
- mismatch (expected_str, matched_name);
- return true;
- }, per_objfile, nullptr);
-
- const char *expected_str
- = expected_it == expected_end ? NULL : *expected_it++;
- if (expected_str != NULL)
- mismatch (expected_str, NULL);
-
- return matched;
-}
-
-/* The symbols added to the mock mapped_index for testing (in
- canonical form). */
-static const char *test_symbols[] = {
- "function",
- "std::bar",
- "std::zfunction",
- "std::zfunction2",
- "w1::w2",
- "ns::foo<char*>",
- "ns::foo<int>",
- "ns::foo<long>",
- "ns2::tmpl<int>::foo2",
- "(anonymous namespace)::A::B::C",
-
- /* These are used to check that the increment-last-char in the
- matching algorithm for completion doesn't match "t1_fund" when
- completing "t1_func". */
- "t1_func",
- "t1_func1",
- "t1_fund",
- "t1_fund1",
-
- /* A UTF-8 name with multi-byte sequences to make sure that
- cp-name-parser understands this as a single identifier ("função"
- is "function" in PT). */
- (const char *)u8"u8função",
-
- /* Test a symbol name that ends with a 0xff character, which is a
- valid character in non-UTF-8 source character sets (e.g. Latin1
- 'ÿ'), and we can't rule out compilers allowing it in identifiers.
- We test this because the completion algorithm finds the upper
- bound of symbols by looking for the insertion point of
- "func"-with-last-character-incremented, i.e. "fund", and adding 1
- to 0xff should wraparound and carry to the previous character.
- See comments in make_sort_after_prefix_name. */
- "yfunc\377",
-
- /* Some more symbols with \377 (0xff). See above. */
- "\377",
- "\377\377123",
-
- /* A name with all sorts of complications. Starts with "z" to make
- it easier for the completion tests below. */
-#define Z_SYM_NAME \
- "z::std::tuple<(anonymous namespace)::ui*, std::bar<(anonymous namespace)::ui> >" \
- "::tuple<(anonymous namespace)::ui*, " \
- "std::default_delete<(anonymous namespace)::ui>, void>"
-
- Z_SYM_NAME
-};
-
-/* Returns true if the mapped_index_base::find_name_component_bounds
- method finds EXPECTED_SYMS in INDEX when looking for SEARCH_NAME,
- in completion mode. */
-static bool
-check_find_bounds_finds (mapped_gdb_index &index,
- const char *search_name,
- gdb::array_view<const char *> expected_syms,
- dwarf2_per_objfile *per_objfile)
-{
- lookup_name_info lookup_name (search_name,
- symbol_name_match_type::FULL, true);
-
- auto bounds = index.find_name_components_bounds (lookup_name,
- language_cplus,
- per_objfile);
-
- size_t distance = std::distance (bounds.first, bounds.second);
- if (distance != expected_syms.size ())
- return false;
-
- for (size_t exp_elem = 0; exp_elem < distance; exp_elem++)
- {
- auto nc_elem = bounds.first + exp_elem;
- const char *qualified = index.symbol_name_at (nc_elem->idx, per_objfile);
- if (strcmp (qualified, expected_syms[exp_elem]) != 0)
- return false;
- }
-
- return true;
-}
-
-/* Test the lower-level mapped_index::find_name_component_bounds
- method. */
-
-static void
-test_mapped_index_find_name_component_bounds ()
-{
- mock_mapped_index mock_index (test_symbols);
-
- mock_index.build_name_components (NULL /* per_objfile */);
-
- /* Test the lower-level mapped_index::find_name_component_bounds
- method in completion mode. */
- {
- static const char *expected_syms[] = {
- "t1_func",
- "t1_func1",
- };
-
- SELF_CHECK (check_find_bounds_finds
- (mock_index, "t1_func", expected_syms,
- NULL /* per_objfile */));
- }
-
- /* Check that the increment-last-char in the name matching algorithm
- for completion doesn't get confused with Ansi1 'ÿ' / 0xff. See
- make_sort_after_prefix_name. */
- {
- static const char *expected_syms1[] = {
- "\377",
- "\377\377123",
- };
- SELF_CHECK (check_find_bounds_finds
- (mock_index, "\377", expected_syms1, NULL /* per_objfile */));
-
- static const char *expected_syms2[] = {
- "\377\377123",
- };
- SELF_CHECK (check_find_bounds_finds
- (mock_index, "\377\377", expected_syms2,
- NULL /* per_objfile */));
- }
-}
-
-/* Test dw2_expand_symtabs_matching_symbol. */
-
-static void
-test_dw2_expand_symtabs_matching_symbol ()
-{
- mock_mapped_index mock_index (test_symbols);
-
- /* We let all tests run until the end even if some fails, for debug
- convenience. */
- bool any_mismatch = false;
-
- /* Create the expected symbols list (an initializer_list). Needed
- because lists have commas, and we need to pass them to CHECK,
- which is a macro. */
-#define EXPECT(...) { __VA_ARGS__ }
-
- /* Wrapper for check_match that passes down the current
- __FILE__/__LINE__. */
-#define CHECK_MATCH(NAME, MATCH_TYPE, COMPLETION_MODE, EXPECTED_LIST) \
- any_mismatch |= !check_match (__FILE__, __LINE__, \
- mock_index, \
- NAME, MATCH_TYPE, COMPLETION_MODE, \
- EXPECTED_LIST, NULL)
-
- /* Identity checks. */
- for (const char *sym : test_symbols)
- {
- /* Should be able to match all existing symbols. */
- CHECK_MATCH (sym, symbol_name_match_type::FULL, false,
- EXPECT (sym));
-
- /* Should be able to match all existing symbols with
- parameters. */
- std::string with_params = std::string (sym) + "(int)";
- CHECK_MATCH (with_params.c_str (), symbol_name_match_type::FULL, false,
- EXPECT (sym));
-
- /* Should be able to match all existing symbols with
- parameters and qualifiers. */
- with_params = std::string (sym) + " ( int ) const";
- CHECK_MATCH (with_params.c_str (), symbol_name_match_type::FULL, false,
- EXPECT (sym));
-
- /* This should really find sym, but cp-name-parser.y doesn't
- know about lvalue/rvalue qualifiers yet. */
- with_params = std::string (sym) + " ( int ) &&";
- CHECK_MATCH (with_params.c_str (), symbol_name_match_type::FULL, false,
- {});
- }
-
- /* Check that the name matching algorithm for completion doesn't get
- confused with Latin1 'ÿ' / 0xff. See
- make_sort_after_prefix_name. */
- {
- static const char str[] = "\377";
- CHECK_MATCH (str, symbol_name_match_type::FULL, true,
- EXPECT ("\377", "\377\377123"));
- }
-
- /* Check that the increment-last-char in the matching algorithm for
- completion doesn't match "t1_fund" when completing "t1_func". */
- {
- static const char str[] = "t1_func";
- CHECK_MATCH (str, symbol_name_match_type::FULL, true,
- EXPECT ("t1_func", "t1_func1"));
- }
-
- /* Check that completion mode works at each prefix of the expected
- symbol name. */
- {
- static const char str[] = "function(int)";
- size_t len = strlen (str);
- std::string lookup;
-
- for (size_t i = 1; i < len; i++)
- {
- lookup.assign (str, i);
- CHECK_MATCH (lookup.c_str (), symbol_name_match_type::FULL, true,
- EXPECT ("function"));
- }
- }
-
- /* While "w" is a prefix of both components, the match function
- should still only be called once. */
- {
- CHECK_MATCH ("w", symbol_name_match_type::FULL, true,
- EXPECT ("w1::w2"));
- CHECK_MATCH ("w", symbol_name_match_type::WILD, true,
- EXPECT ("w1::w2"));
- }
-
- /* Same, with a "complicated" symbol. */
- {
- static const char str[] = Z_SYM_NAME;
- size_t len = strlen (str);
- std::string lookup;
-
- for (size_t i = 1; i < len; i++)
- {
- lookup.assign (str, i);
- CHECK_MATCH (lookup.c_str (), symbol_name_match_type::FULL, true,
- EXPECT (Z_SYM_NAME));
- }
- }
-
- /* In FULL mode, an incomplete symbol doesn't match. */
- {
- CHECK_MATCH ("std::zfunction(int", symbol_name_match_type::FULL, false,
- {});
- }
-
- /* A complete symbol with parameters matches any overload, since the
- index has no overload info. */
- {
- CHECK_MATCH ("std::zfunction(int)", symbol_name_match_type::FULL, true,
- EXPECT ("std::zfunction", "std::zfunction2"));
- CHECK_MATCH ("zfunction(int)", symbol_name_match_type::WILD, true,
- EXPECT ("std::zfunction", "std::zfunction2"));
- CHECK_MATCH ("zfunc", symbol_name_match_type::WILD, true,
- EXPECT ("std::zfunction", "std::zfunction2"));
- }
-
- /* Check that whitespace is ignored appropriately. A symbol with a
- template argument list. */
- {
- static const char expected[] = "ns::foo<int>";
- CHECK_MATCH ("ns :: foo < int > ", symbol_name_match_type::FULL, false,
- EXPECT (expected));
- CHECK_MATCH ("foo < int > ", symbol_name_match_type::WILD, false,
- EXPECT (expected));
- }
-
- /* Check that whitespace is ignored appropriately. A symbol with a
- template argument list that includes a pointer. */
- {
- static const char expected[] = "ns::foo<char*>";
- /* Try both completion and non-completion modes. */
- static const bool completion_mode[2] = {false, true};
- for (size_t i = 0; i < 2; i++)
- {
- CHECK_MATCH ("ns :: foo < char * >", symbol_name_match_type::FULL,
- completion_mode[i], EXPECT (expected));
- CHECK_MATCH ("foo < char * >", symbol_name_match_type::WILD,
- completion_mode[i], EXPECT (expected));
-
- CHECK_MATCH ("ns :: foo < char * > (int)", symbol_name_match_type::FULL,
- completion_mode[i], EXPECT (expected));
- CHECK_MATCH ("foo < char * > (int)", symbol_name_match_type::WILD,
- completion_mode[i], EXPECT (expected));
- }
- }
-
- {
- /* Check method qualifiers are ignored. */
- static const char expected[] = "ns::foo<char*>";
- CHECK_MATCH ("ns :: foo < char * > ( int ) const",
- symbol_name_match_type::FULL, true, EXPECT (expected));
- CHECK_MATCH ("ns :: foo < char * > ( int ) &&",
- symbol_name_match_type::FULL, true, EXPECT (expected));
- CHECK_MATCH ("foo < char * > ( int ) const",
- symbol_name_match_type::WILD, true, EXPECT (expected));
- CHECK_MATCH ("foo < char * > ( int ) &&",
- symbol_name_match_type::WILD, true, EXPECT (expected));
- }
-
- /* Test lookup names that don't match anything. */
- {
- CHECK_MATCH ("bar2", symbol_name_match_type::WILD, false,
- {});
-
- CHECK_MATCH ("doesntexist", symbol_name_match_type::FULL, false,
- {});
- }
-
- /* Some wild matching tests, exercising "(anonymous namespace)",
- which should not be confused with a parameter list. */
- {
- static const char *syms[] = {
- "A::B::C",
- "B::C",
- "C",
- "A :: B :: C ( int )",
- "B :: C ( int )",
- "C ( int )",
- };
-
- for (const char *s : syms)
- {
- CHECK_MATCH (s, symbol_name_match_type::WILD, false,
- EXPECT ("(anonymous namespace)::A::B::C"));
- }
- }
-
- {
- static const char expected[] = "ns2::tmpl<int>::foo2";
- CHECK_MATCH ("tmp", symbol_name_match_type::WILD, true,
- EXPECT (expected));
- CHECK_MATCH ("tmpl<", symbol_name_match_type::WILD, true,
- EXPECT (expected));
- }
-
- SELF_CHECK (!any_mismatch);
-
-#undef EXPECT
-#undef CHECK_MATCH
-}
-
-static void
-run_test ()
-{
- test_mapped_index_find_name_component_bounds ();
- test_dw2_expand_symtabs_matching_symbol ();
-}
-
-}} /* namespace selftests::dw2_expand_symtabs_matching */
-
-#endif /* GDB_SELF_TEST */
-
-struct dwarf2_gdb_index : public dwarf2_base_index_functions
-{
- /* This dumps minimal information about the index.
- It is called via "mt print objfiles".
- One use is to verify .gdb_index has been loaded by the
- gdb.dwarf2/gdb-index.exp testcase. */
- void dump (struct objfile *objfile) override;
-
- bool expand_symtabs_matching
- (struct objfile *objfile,
- expand_symtabs_file_matcher file_matcher,
- const lookup_name_info *lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
- block_search_flags search_flags,
- domain_search_flags domain,
- expand_symtabs_lang_matcher lang_matcher) override;
-};
-
-/* This dumps minimal information about the index.
- It is called via "mt print objfiles".
- One use is to verify .gdb_index has been loaded by the
- gdb.dwarf2/gdb-index.exp testcase. */
-
-void
-dwarf2_gdb_index::dump (struct objfile *objfile)
-{
- dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
- mapped_gdb_index *index = (gdb::checked_static_cast<mapped_gdb_index *>
- (per_objfile->per_bfd->index_table.get ()));
- gdb_printf (".gdb_index: version %d\n", index->version);
- gdb_printf ("\n");
-}
-
-/* Helper for dw2_expand_matching symtabs. Called on each symbol
- matched, to expand corresponding CUs that were marked. IDX is the
- index of the symbol name that matched. */
-
-static bool
-dw2_expand_marked_cus (dwarf2_per_objfile *per_objfile, offset_type idx,
- expand_symtabs_file_matcher file_matcher,
- expand_symtabs_expansion_listener expansion_notify,
- block_search_flags search_flags,
- domain_search_flags kind,
- expand_symtabs_lang_matcher lang_matcher)
-{
- offset_type vec_len, vec_idx;
- bool global_seen = false;
- mapped_gdb_index &index
- = *(gdb::checked_static_cast<mapped_gdb_index *>
- (per_objfile->per_bfd->index_table.get ()));
-
- offset_view vec (index.constant_pool.slice (index.symbol_vec_index (idx)));
- vec_len = vec[0];
- for (vec_idx = 0; vec_idx < vec_len; ++vec_idx)
- {
- offset_type cu_index_and_attrs = vec[vec_idx + 1];
- /* This value is only valid for index versions >= 7. */
- int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
- gdb_index_symbol_kind symbol_kind =
- GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
- int cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
- /* Only check the symbol attributes if they're present.
- Indices prior to version 7 don't record them,
- and indices >= 7 may elide them for certain symbols
- (gold does this). */
- int attrs_valid =
- (index.version >= 7
- && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
-
- /* Work around gold/15646. */
- if (attrs_valid
- && !is_static
- && symbol_kind == GDB_INDEX_SYMBOL_KIND_TYPE)
+ std::vector<cooked_index_entry *> these_entries;
+ offset_view vec (constant_pool.slice (symbol_vec_index (idx)));
+ offset_type vec_len = vec[0];
+ bool global_seen = false;
+ for (offset_type vec_idx = 0; vec_idx < vec_len; ++vec_idx)
{
- if (global_seen)
+ offset_type cu_index_and_attrs = vec[vec_idx + 1];
+ gdb_index_symbol_kind symbol_kind
+ = GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
+ /* Only use a symbol if the attributes are present. Indices
+ prior to version 7 don't record them, and indices >= 7
+ may elide them for certain symbols (gold does this). */
+ if (symbol_kind == GDB_INDEX_SYMBOL_KIND_NONE)
continue;
- global_seen = true;
- }
+ int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
- /* Only check the symbol's kind if it has one. */
- if (attrs_valid)
- {
- if (is_static)
- {
- if ((search_flags & SEARCH_STATIC_BLOCK) == 0)
- continue;
- }
- else
+ int cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
+ /* Don't crash on bad data. */
+ if (cu_index >= units.size ())
{
- if ((search_flags & SEARCH_GLOBAL_BLOCK) == 0)
- continue;
+ complaint (_(".gdb_index entry has bad CU index"
+ " [in module %s]"),
+ objfile_name (per_objfile->objfile));
+ continue;
}
+ dwarf2_per_cu *per_cu = units[cu_index];
- domain_search_flags mask = 0;
+ enum language this_lang = lang;
+ dwarf_tag tag;
switch (symbol_kind)
{
case GDB_INDEX_SYMBOL_KIND_VARIABLE:
- mask = SEARCH_VAR_DOMAIN;
+ tag = DW_TAG_variable;
break;
case GDB_INDEX_SYMBOL_KIND_FUNCTION:
- mask = SEARCH_FUNCTION_DOMAIN;
+ tag = DW_TAG_subprogram;
break;
case GDB_INDEX_SYMBOL_KIND_TYPE:
- mask = SEARCH_TYPE_DOMAIN | SEARCH_STRUCT_DOMAIN;
+ if (is_static)
+ tag = (dwarf_tag) DW_TAG_GDB_INDEX_TYPE;
+ else
+ {
+ /* Work around gold/15646. */
+ if (global_seen)
+ continue;
+ global_seen = true;
+
+ tag = DW_TAG_structure_type;
+ this_lang = language_cplus;
+ }
break;
+ /* The "default" should not happen, but we mention it to
+ avoid an uninitialized warning. */
+ default:
case GDB_INDEX_SYMBOL_KIND_OTHER:
- mask = SEARCH_MODULE_DOMAIN;
+ tag = (dwarf_tag) DW_TAG_GDB_INDEX_OTHER;
break;
}
- if ((kind & mask) == 0)
- continue;
- }
- /* Don't crash on bad data. */
- if (cu_index >= per_objfile->per_bfd->all_units.size ())
- {
- complaint (_(".gdb_index entry has bad CU index"
- " [in module %s]"), objfile_name (per_objfile->objfile));
- continue;
+ cooked_index_flag flags = 0;
+ if (is_static)
+ flags |= IS_STATIC;
+ if (main_name != nullptr
+ && tag == DW_TAG_subprogram
+ && strcmp (name, main_name) == 0)
+ {
+ flags |= IS_MAIN;
+ this_lang = main_lang;
+ /* Don't bother looking for another. */
+ main_name = nullptr;
+ }
+
+ /* Note that this assumes the final component ends in \0. */
+ cooked_index_entry *entry = result.add (per_cu->sect_off, tag,
+ flags, this_lang,
+ components.back ().data (),
+ nullptr, per_cu);
+ /* Don't bother pushing if we do not need a parent. */
+ if (components.size () > 1)
+ these_entries.push_back (entry);
+
+ /* We don't care exactly which entry ends up in this
+ map. */
+ by_name[std::string_view (name)] = entry;
}
- dwarf2_per_cu *per_cu = per_objfile->per_bfd->get_cu (cu_index);
+ if (components.size () > 1)
+ {
+ std::string_view penultimate = components[components.size () - 2];
+ std::string_view prefix (name, &penultimate.back () + 1 - name);
- if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
- expansion_notify, lang_matcher))
- return false;
+ need_parents.emplace_back (prefix, std::move (these_entries));
+ }
}
- return true;
+ for (const auto &[prefix, entries] : need_parents)
+ {
+ auto iter = by_name.find (prefix);
+ /* If we can't find the parent entry, just lose. It should
+ always be there. We could synthesize it from the components,
+ if we kept those, but that seems like overkill. */
+ if (iter != by_name.end ())
+ {
+ for (cooked_index_entry *entry : entries)
+ entry->set_parent (iter->second);
+ }
+ }
}
-bool
-dwarf2_gdb_index::expand_symtabs_matching
- (objfile *objfile,
- expand_symtabs_file_matcher file_matcher,
- const lookup_name_info *lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
- block_search_flags search_flags,
- domain_search_flags domain,
- expand_symtabs_lang_matcher lang_matcher)
+/* The worker that reads a mapped index and fills in a
+ cooked_index_worker_result. */
+
+class gdb_index_worker : public cooked_index_worker
{
- dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+public:
- dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
+ gdb_index_worker (dwarf2_per_objfile *per_objfile,
+ std::unique_ptr<mapped_gdb_index> map)
+ : cooked_index_worker (per_objfile),
+ map (std::move (map))
+ { }
- /* This invariant is documented in quick-functions.h. */
- gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
- if (lookup_name == nullptr)
- {
- for (dwarf2_per_cu *per_cu : all_units_range (per_objfile->per_bfd))
- {
- QUIT;
+ void do_reading () override;
- if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
- file_matcher,
- expansion_notify,
- lang_matcher))
- return false;
- }
- return true;
- }
+ /* The map we're reading. */
+ std::unique_ptr<mapped_gdb_index> map;
+};
- mapped_gdb_index &index
- = *(gdb::checked_static_cast<mapped_gdb_index *>
- (per_objfile->per_bfd->index_table.get ()));
+void
+gdb_index_worker::do_reading ()
+{
+ complaint_interceptor complaint_handler;
+ map->build_name_components (m_per_objfile);
- bool result
- = dw2_expand_symtabs_matching_symbol (index, *lookup_name,
- symbol_matcher,
- [&] (offset_type idx)
- {
- if (!dw2_expand_marked_cus (per_objfile, idx, file_matcher,
- expansion_notify, search_flags, domain,
- lang_matcher))
- return false;
- return true;
- }, per_objfile, lang_matcher);
+ m_results.push_back (std::move (map->result));
+ m_results[0].done_reading (complaint_handler.release ());
- return result;
-}
+ /* No longer needed. */
+ map.reset ();
-quick_symbol_functions_up
-mapped_gdb_index::make_quick_functions () const
-{
- return quick_symbol_functions_up (new dwarf2_gdb_index);
+ done_reading ();
+
+ bfd_thread_cleanup ();
}
/* A helper function that reads the .gdb_index from BUFFER and fills
@@ -1206,11 +431,9 @@ read_gdb_index_from_buffer (const char *filename,
/* Version check. */
offset_type version = metadata[0];
- /* Versions earlier than 3 emitted every copy of a psymbol. This
- causes the index to behave very poorly for certain requests. Version 3
- contained incomplete addrmap. So, it seems better to just ignore such
- indices. */
- if (version < 4)
+ /* GDB now requires the symbol attributes, which were added in
+ version 7. */
+ if (version < 7)
{
static int warning_printed = 0;
if (!warning_printed)
@@ -1221,30 +444,6 @@ read_gdb_index_from_buffer (const char *filename,
}
return 0;
}
- /* Index version 4 uses a different hash function than index version
- 5 and later.
-
- Versions earlier than 6 did not emit psymbols for inlined
- functions. Using these files will cause GDB not to be able to
- set breakpoints on inlined functions by name, so we ignore these
- indices unless the user has done
- "set use-deprecated-index-sections on". */
- if (version < 6 && !deprecated_ok)
- {
- static int warning_printed = 0;
- if (!warning_printed)
- {
- warning (_("\
-Skipping deprecated .gdb_index section in %s.\n\
-Do \"%ps\" before the file is read\n\
-to use the section anyway."),
- filename,
- styled_string (command_style.style (),
- "set use-deprecated-index-sections on"));
- warning_printed = 1;
- }
- return 0;
- }
/* Version 7 indices generated by gold refer to the CU for a symbol instead
of the TU (for symbols coming from TUs),
http://sourceware.org/bugzilla/show_bug.cgi?id=15021.
@@ -1313,7 +512,7 @@ static void
create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd,
const gdb_byte *cu_list, offset_type n_elements,
struct dwarf2_section_info *section,
- int is_dwz)
+ int is_dwz, std::vector<dwarf2_per_cu *> &units)
{
for (offset_type i = 0; i < n_elements; i += 2)
{
@@ -1324,10 +523,10 @@ create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd,
ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE);
cu_list += 2 * 8;
- per_bfd->all_units.emplace_back (per_bfd->allocate_per_cu (section,
- sect_off,
- length,
- is_dwz));
+ dwarf2_per_cu_up per_cu = per_bfd->allocate_per_cu (section, sect_off,
+ length, is_dwz);
+ units.emplace_back (per_cu.get ());
+ per_bfd->all_units.emplace_back (std::move (per_cu));
}
}
@@ -1337,20 +536,21 @@ create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd,
static void
create_cus_from_gdb_index (dwarf2_per_bfd *per_bfd,
const gdb_byte *cu_list, offset_type cu_list_elements,
+ std::vector<dwarf2_per_cu *> &units,
const gdb_byte *dwz_list, offset_type dwz_elements)
{
gdb_assert (per_bfd->all_units.empty ());
per_bfd->all_units.reserve ((cu_list_elements + dwz_elements) / 2);
create_cus_from_gdb_index_list (per_bfd, cu_list, cu_list_elements,
- &per_bfd->infos[0], 0);
+ &per_bfd->infos[0], 0, units);
if (dwz_elements == 0)
return;
dwz_file *dwz = per_bfd->get_dwz_file ();
create_cus_from_gdb_index_list (per_bfd, dwz_list, dwz_elements,
- &dwz->info, 1);
+ &dwz->info, 1, units);
}
/* Create the signatured type hash table from the index. */
@@ -1358,7 +558,8 @@ create_cus_from_gdb_index (dwarf2_per_bfd *per_bfd,
static void
create_signatured_type_table_from_gdb_index
(dwarf2_per_bfd *per_bfd, struct dwarf2_section_info *section,
- const gdb_byte *bytes, offset_type elements)
+ const gdb_byte *bytes, offset_type elements,
+ std::vector<dwarf2_per_cu *> &units)
{
signatured_type_set sig_types_hash;
@@ -1382,19 +583,20 @@ create_signatured_type_table_from_gdb_index
sig_type->type_offset_in_tu = type_offset_in_tu;
sig_types_hash.emplace (sig_type.get ());
+ units.emplace_back (sig_type.get ());
per_bfd->all_units.emplace_back (sig_type.release ());
}
per_bfd->signatured_types = std::move (sig_types_hash);
}
-/* Read the address map data from the mapped GDB index. */
+/* Read the address map data from the mapped GDB index. Return true if no
+ errors were found, otherwise return false. */
-static void
+static bool
create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile,
mapped_gdb_index *index)
{
- dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
const gdb_byte *iter, *end;
addrmap_mutable mutable_map;
@@ -1412,40 +614,48 @@ create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile,
cu_index = extract_unsigned_integer (iter, 4, BFD_ENDIAN_LITTLE);
iter += 4;
- if (lo > hi)
+ if (lo >= hi)
{
- complaint (_(".gdb_index address table has invalid range (%s - %s)"),
- hex_string (lo), hex_string (hi));
- continue;
+ warning (_(".gdb_index address table has invalid range (%s - %s),"
+ " ignoring .gdb_index"),
+ hex_string (lo), hex_string (hi));
+ return false;
}
- if (cu_index >= per_bfd->all_units.size ())
+ if (cu_index >= index->units.size ())
{
- complaint (_(".gdb_index address table has invalid CU number %u"),
- (unsigned) cu_index);
- continue;
+ warning (_(".gdb_index address table has invalid CU number %u,"
+ " ignoring .gdb_index"),
+ (unsigned) cu_index);
+ return false;
}
- mutable_map.set_empty (lo, hi - 1, per_bfd->get_cu (cu_index));
+ bool full_range_p
+ = mutable_map.set_empty (lo, hi - 1, index->units[cu_index]);
+ if (!full_range_p)
+ {
+ warning (_(".gdb_index address table has a range (%s - %s) that"
+ " overlaps with an earlier range, ignoring .gdb_index"),
+ hex_string (lo), hex_string (hi));
+ return false;
+ }
}
- index->index_addrmap
- = new (&per_bfd->obstack) addrmap_fixed (&per_bfd->obstack, &mutable_map);
-}
+ index->result.set_addrmap (std::move (mutable_map));
-/* Sets the name and language of the main function from the shortcut table. */
+ return true;
+}
-static void
-set_main_name_from_gdb_index (dwarf2_per_objfile *per_objfile,
- mapped_gdb_index *index)
+void
+mapped_gdb_index::set_main_name (dwarf2_per_objfile *per_objfile)
{
const auto expected_size = 2 * sizeof (offset_type);
- if (index->shortcut_table.size () < expected_size)
+ if (this->shortcut_table.size () < expected_size)
/* The data in the section is not present, is corrupted or is in a version
we don't know about. Regardless, we can't make use of it. */
return;
- auto ptr = index->shortcut_table.data ();
+ auto ptr = this->shortcut_table.data ();
const auto dw_lang = extract_unsigned_integer (ptr, 4, BFD_ENDIAN_LITTLE);
if (dw_lang >= DW_LANG_hi_user)
{
@@ -1461,13 +671,11 @@ set_main_name_from_gdb_index (dwarf2_per_objfile *per_objfile,
}
ptr += 4;
- const auto lang = dwarf_lang_to_enum_language (dw_lang);
+ main_lang = dwarf_lang_to_enum_language (dw_lang);
const auto name_offset = extract_unsigned_integer (ptr,
sizeof (offset_type),
BFD_ENDIAN_LITTLE);
- const auto name = (const char *) (index->constant_pool.data () + name_offset);
-
- set_objfile_main_name (per_objfile->objfile, name, (enum language) lang);
+ main_name = (const char *) (this->constant_pool.data () + name_offset);
}
/* See read-gdb-index.h. */
@@ -1482,6 +690,7 @@ dwarf2_read_gdb_index
offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0;
struct objfile *objfile = per_objfile->objfile;
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+ scoped_remove_all_units remove_all_units (*per_bfd);
gdb::array_view<const gdb_byte> main_index_contents
= get_gdb_index_contents (objfile, per_bfd);
@@ -1528,8 +737,8 @@ dwarf2_read_gdb_index
}
}
- create_cus_from_gdb_index (per_bfd, cu_list, cu_list_elements, dwz_list,
- dwz_list_elements);
+ create_cus_from_gdb_index (per_bfd, cu_list, cu_list_elements, map->units,
+ dwz_list, dwz_list_elements);
if (types_list_elements)
{
@@ -1537,10 +746,7 @@ dwarf2_read_gdb_index
an index. */
if (per_bfd->infos.size () > 1
|| per_bfd->types.size () > 1)
- {
- per_bfd->all_units.clear ();
- return false;
- }
+ return false;
dwarf2_section_info *section
= (per_bfd->types.size () == 1
@@ -1548,24 +754,30 @@ dwarf2_read_gdb_index
: &per_bfd->infos[0]);
create_signatured_type_table_from_gdb_index (per_bfd, section, types_list,
- types_list_elements);
+ types_list_elements,
+ map->units);
}
finalize_all_units (per_bfd);
- create_addrmap_from_gdb_index (per_objfile, map.get ());
+ if (!create_addrmap_from_gdb_index (per_objfile, map.get ()))
+ return false;
+
+ map->set_main_name (per_objfile);
- set_main_name_from_gdb_index (per_objfile, map.get ());
+ int version = map->version;
+ auto worker = std::make_unique<gdb_index_worker> (per_objfile,
+ std::move (map));
+ auto idx = std::make_unique<cooked_gdb_index> (std::move (worker),
+ version);
- per_bfd->index_table = std::move (map);
+ per_bfd->start_reading (std::move (idx));
+ remove_all_units.disable ();
return true;
}
-void _initialize_read_gdb_index ();
-
-void
-_initialize_read_gdb_index ()
+INIT_GDB_FILE (read_gdb_index)
{
add_setshow_boolean_cmd ("use-deprecated-index-sections",
no_class, &use_deprecated_index_sections, _("\
@@ -1578,9 +790,4 @@ Warning: This option must be enabled before gdb reads the file."),
NULL,
NULL,
&setlist, &showlist);
-
-#if GDB_SELF_TEST
- selftests::register_test ("dw2_expand_symtabs_matching",
- selftests::dw2_expand_symtabs_matching::run_test);
-#endif
}
diff --git a/gdb/dwarf2/read-gdb-index.h b/gdb/dwarf2/read-gdb-index.h
index 5107d63..c8f1fd0 100644
--- a/gdb/dwarf2/read-gdb-index.h
+++ b/gdb/dwarf2/read-gdb-index.h
@@ -27,6 +27,20 @@ struct dwarf2_per_objfile;
struct dwz_file;
struct objfile;
+/* .gdb_index doesn't distinguish between the various "other" symbols
+ -- but the symbol search machinery really wants to. For example,
+ an imported decl is "other" but is really a namespace and thus in
+ TYPE_DOMAIN; whereas a Fortran module is also "other" but is in the
+ MODULE_DOMAIN. We use this value internally to represent the
+ "other" case so that matching can work. The exact value does not
+ matter, all that matters here is that it won't overlap with any
+ symbol that gdb might create. */
+#define DW_TAG_GDB_INDEX_OTHER 0xffff
+
+/* Similarly, .gdb_index can't distinguish between the type and struct
+ domains. This is a special tag that inhabits both. */
+#define DW_TAG_GDB_INDEX_TYPE 0xfffe
+
/* Callback types for dwarf2_read_gdb_index. */
typedef gdb::function_view
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 0eb248f..7cf89d8f 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -38,6 +38,7 @@
#include "dwarf2/index-cache.h"
#include "dwarf2/leb.h"
#include "dwarf2/line-header.h"
+#include "dwarf2/line-program.h"
#include "dwarf2/dwz.h"
#include "dwarf2/macro.h"
#include "dwarf2/die.h"
@@ -147,7 +148,7 @@ static const registry<bfd>::key<dwarf2_per_bfd> dwarf2_per_bfd_bfd_data_key;
static const registry<objfile>::key<dwarf2_per_bfd>
dwarf2_per_bfd_objfile_data_key;
-/* The "aclass" indices for various kinds of computed DWARF symbols. */
+/* The "loc_class" indices for various kinds of computed DWARF symbols. */
static int dwarf2_locexpr_index;
static int dwarf2_loclist_index;
@@ -289,24 +290,29 @@ struct dwo_sections
struct dwo_unit
{
/* Backlink to the containing struct dwo_file. */
- struct dwo_file *dwo_file;
+ struct dwo_file *dwo_file = nullptr;
/* The "id" that distinguishes this CU/TU.
.debug_info calls this "dwo_id", .debug_types calls this "signature".
Since signatures came first, we stick with it for consistency. */
- ULONGEST signature;
+ ULONGEST signature = 0;
/* The section this CU/TU lives in, in the DWO file. */
- struct dwarf2_section_info *section;
+ dwarf2_section_info *section = nullptr;
+
+ /* This is set if SECTION is owned by this dwo_unit. */
+ dwarf2_section_info_up section_holder;
/* Same as dwarf2_per_cu::{sect_off,length} but in the DWO section. */
- sect_offset sect_off;
- unsigned int length;
+ sect_offset sect_off {};
+ unsigned int length = 0;
/* For types, offset in the type's DIE of the type defined by this TU. */
cu_offset type_offset_in_tu;
};
+using dwo_unit_up = std::unique_ptr<dwo_unit>;
+
/* Hash function for dwo_unit objects, based on the signature. */
struct dwo_unit_hash
@@ -316,7 +322,7 @@ struct dwo_unit_hash
std::size_t operator() (ULONGEST signature) const noexcept
{ return signature; }
- std::size_t operator() (const dwo_unit *unit) const noexcept
+ std::size_t operator() (const dwo_unit_up &unit) const noexcept
{ return (*this) (unit->signature); }
};
@@ -330,16 +336,16 @@ struct dwo_unit_eq
{
using is_transparent = void;
- bool operator() (ULONGEST sig, const dwo_unit *unit) const noexcept
+ bool operator() (ULONGEST sig, const dwo_unit_up &unit) const noexcept
{ return sig == unit->signature; }
- bool operator() (const dwo_unit *a, const dwo_unit *b) const noexcept
+ bool operator() (const dwo_unit_up &a, const dwo_unit_up &b) const noexcept
{ return (*this) (a->signature, b); }
};
/* Set of dwo_unit object, using their signature as identity. */
-using dwo_unit_set = gdb::unordered_set<dwo_unit *, dwo_unit_hash, dwo_unit_eq>;
+using dwo_unit_set = gdb::unordered_set<dwo_unit_up, dwo_unit_hash, dwo_unit_eq>;
/* include/dwarf2.h defines the DWP section codes.
It defines a max value but it doesn't define a min value, which we
@@ -599,6 +605,11 @@ struct dwp_file
dwo_unit_set loaded_cus;
dwo_unit_set loaded_tus;
+#if CXX_STD_THREAD
+ /* Mutex to synchronize access to LOADED_CUS and LOADED_TUS. */
+ std::mutex loaded_cutus_lock;
+#endif
+
/* Table to map ELF section numbers to their sections.
This is only needed for the DWP V1 file format. */
unsigned int num_sections = 0;
@@ -777,13 +788,6 @@ static line_header_up dwarf_decode_line_header (sect_offset sect_off,
struct dwarf2_cu *cu,
const char *comp_dir);
-static void dwarf_decode_lines (struct line_header *,
- struct dwarf2_cu *,
- unrelocated_addr, int decode_mapping);
-
-static void dwarf2_start_subfile (dwarf2_cu *cu, const file_entry &fe,
- const line_header &lh);
-
static struct symbol *new_symbol (struct die_info *, struct type *,
struct dwarf2_cu *, struct symbol * = NULL);
@@ -847,6 +851,11 @@ static struct dwarf2_section_info *cu_debug_loc_section (struct dwarf2_cu *cu);
static struct dwarf2_section_info *cu_debug_rnglists_section
(struct dwarf2_cu *cu, dwarf_tag tag);
+static void dw_search_file_matcher
+ (dwarf2_per_objfile *per_objfile,
+ auto_bool_vector &cus_to_skip,
+ search_symtabs_file_matcher file_matcher);
+
static void get_scope_pc_bounds (struct die_info *,
unrelocated_addr *, unrelocated_addr *,
struct dwarf2_cu *);
@@ -977,9 +986,6 @@ static void queue_comp_unit (dwarf2_per_cu *per_cu,
static void process_queue (dwarf2_per_objfile *per_objfile);
-static bool is_ada_import_or_export (dwarf2_cu *cu, const char *name,
- const char *linkagename);
-
/* Class, the destructor of which frees all allocated queue entries. This
will only have work to do if an error was thrown while processing the
dwarf. If no error was thrown then the queue entries should have all
@@ -1033,12 +1039,6 @@ dwarf2_per_cu_deleter::operator() (dwarf2_per_cu *data)
delete data;
}
-static const char *compute_include_file_name
- (const struct line_header *lh,
- const file_entry &fe,
- const file_and_directory &cu_info,
- std::string &name_holder);
-
static struct dwo_unit *lookup_dwo_unit_in_dwp
(dwarf2_per_bfd *per_bfd, struct dwp_file *dwp_file,
const char *comp_dir, ULONGEST signature, int is_debug_types);
@@ -1053,19 +1053,6 @@ static void process_cu_includes (dwarf2_per_objfile *per_objfile);
/* Various complaints about symbol reading that don't abort the process. */
static void
-dwarf2_debug_line_missing_file_complaint (void)
-{
- complaint (_(".debug_line section has line data without a file"));
-}
-
-static void
-dwarf2_debug_line_missing_end_sequence_complaint (void)
-{
- complaint (_(".debug_line section has line "
- "program sequence without an end"));
-}
-
-static void
dwarf2_complex_location_expr_complaint (void)
{
complaint (_("location expression too complex"));
@@ -1322,7 +1309,7 @@ dwarf2_per_bfd::locate_sections (asection *sectp,
bfd_size_type size = sectp->size;
warning (_("Discarding section %s which has an invalid size (%s) "
"[in module %s]"),
- bfd_section_name (sectp), phex_nz (size, sizeof (size)),
+ bfd_section_name (sectp), phex_nz (size),
this->filename ());
}
else if (names.info.matches (sectp->name))
@@ -1543,16 +1530,37 @@ struct readnow_functions : public dwarf2_base_index_functions
{
}
- bool expand_symtabs_matching
- (struct objfile *objfile,
- expand_symtabs_file_matcher file_matcher,
- const lookup_name_info *lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
- block_search_flags search_flags,
- domain_search_flags domain,
- expand_symtabs_lang_matcher lang_matcher) override
+ bool search (struct objfile *objfile,
+ search_symtabs_file_matcher file_matcher,
+ const lookup_name_info *lookup_name,
+ search_symtabs_symbol_matcher symbol_matcher,
+ search_symtabs_expansion_listener listener,
+ block_search_flags search_flags,
+ domain_search_flags domain,
+ search_symtabs_lang_matcher lang_matcher) override
{
+ dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+ auto_bool_vector cus_to_skip;
+ dw_search_file_matcher (per_objfile, cus_to_skip, file_matcher);
+
+ for (const auto &per_cu : per_objfile->per_bfd->all_units)
+ {
+ QUIT;
+
+ /* Skip various types of unit that should not be searched
+ directly: partial units and dummy units. */
+ if (/* Note that we request the non-strict unit type here. If
+ there was an error while reading, like in
+ dw-form-strx-out-of-bounds.exp, then the unit type may
+ not be set. */
+ per_cu->unit_type (false) == DW_UT_partial
+ || per_cu->unit_type (false) == 0
+ || per_objfile->get_symtab (per_cu.get ()) == nullptr)
+ continue;
+ if (!dw2_search_one (per_cu.get (), per_objfile, cus_to_skip,
+ file_matcher, listener, lang_matcher))
+ return false;
+ }
return true;
}
};
@@ -1680,6 +1688,7 @@ dwarf2_per_bfd::allocate_per_cu (dwarf2_section_info *section,
dwarf2_per_cu_up result (new dwarf2_per_cu (this, section, sect_off,
length, is_dwz));
result->index = all_units.size ();
+ this->num_comp_units++;
return result;
}
@@ -1696,10 +1705,79 @@ dwarf2_per_bfd::allocate_signatured_type (dwarf2_section_info *section,
= std::make_unique<signatured_type> (this, section, sect_off, length,
is_dwz, signature);
result->index = all_units.size ();
- tu_stats.nr_tus++;
+ this->num_type_units++;
return result;
}
+/* Subroutine of dw2_get_file_names_reader to simplify it.
+ Return the file name for the given file_entry.
+ CU_INFO describes the CU's DW_AT_name and DW_AT_comp_dir.
+ If space for the result is malloc'd, *NAME_HOLDER will be set.
+ Returns NULL if FILE_INDEX should be ignored, i.e., it is
+ equivalent to CU_INFO. */
+
+static const char *
+compute_include_file_name (const struct line_header *lh, const file_entry &fe,
+ const file_and_directory &cu_info,
+ std::string &name_holder)
+{
+ const char *include_name = fe.name;
+ const char *include_name_to_compare = include_name;
+
+ const char *dir_name = fe.include_dir (lh);
+
+ std::string hold_compare;
+ if (!IS_ABSOLUTE_PATH (include_name)
+ && (dir_name != nullptr || cu_info.get_comp_dir () != nullptr))
+ {
+ /* Avoid creating a duplicate name for CU_INFO.
+ We do this by comparing INCLUDE_NAME and CU_INFO.
+ Before we do the comparison, however, we need to account
+ for DIR_NAME and COMP_DIR.
+ First prepend dir_name (if non-NULL). If we still don't
+ have an absolute path prepend comp_dir (if non-NULL).
+ However, the directory we record in the include-file's
+ psymtab does not contain COMP_DIR (to match the
+ corresponding symtab(s)).
+
+ Example:
+
+ bash$ cd /tmp
+ bash$ gcc -g ./hello.c
+ include_name = "hello.c"
+ dir_name = "."
+ DW_AT_comp_dir = comp_dir = "/tmp"
+ DW_AT_name = "./hello.c"
+
+ */
+
+ if (dir_name != NULL)
+ {
+ name_holder = path_join (dir_name, include_name);
+ include_name = name_holder.c_str ();
+ include_name_to_compare = include_name;
+ }
+ if (!IS_ABSOLUTE_PATH (include_name)
+ && cu_info.get_comp_dir () != nullptr)
+ {
+ hold_compare = path_join (cu_info.get_comp_dir (), include_name);
+ include_name_to_compare = hold_compare.c_str ();
+ }
+ }
+
+ std::string copied_name;
+ const char *cu_filename = cu_info.get_name ();
+ if (!IS_ABSOLUTE_PATH (cu_filename) && cu_info.get_comp_dir () != nullptr)
+ {
+ copied_name = path_join (cu_info.get_comp_dir (), cu_filename);
+ cu_filename = copied_name.c_str ();
+ }
+
+ if (FILENAME_CMP (include_name_to_compare, cu_filename) == 0)
+ return nullptr;
+ return include_name;
+}
+
/* die_reader_func for dw2_get_file_names. */
static void
@@ -1891,13 +1969,13 @@ dwarf2_base_index_functions::print_stats (struct objfile *objfile,
for (int i = 0; i < total; ++i)
{
- dwarf2_per_cu *per_cu = per_objfile->per_bfd->get_cu (i);
+ dwarf2_per_cu *per_cu = per_objfile->per_bfd->get_unit (i);
if (!per_objfile->symtab_set_p (per_cu))
++count;
}
- gdb_printf (_(" Number of read CUs: %d\n"), total - count);
- gdb_printf (_(" Number of unread CUs: %d\n"), count);
+ gdb_printf (_(" Number of read units: %d\n"), total - count);
+ gdb_printf (_(" Number of unread units: %d\n"), count);
}
void
@@ -1919,14 +1997,16 @@ dwarf2_base_index_functions::expand_all_symtabs (struct objfile *objfile)
/* See read.h. */
bool
-dw2_expand_symtabs_matching_one
+dw2_search_one
(dwarf2_per_cu *per_cu,
dwarf2_per_objfile *per_objfile,
- expand_symtabs_file_matcher file_matcher,
- expand_symtabs_expansion_listener expansion_notify,
- expand_symtabs_lang_matcher lang_matcher)
+ auto_bool_vector &cus_to_skip,
+ search_symtabs_file_matcher file_matcher,
+ search_symtabs_expansion_listener listener,
+ search_symtabs_lang_matcher lang_matcher)
{
- if (file_matcher != nullptr && !per_cu->mark)
+ /* Already visited, or intentionally skipped. */
+ if (cus_to_skip.is_set (per_cu->index))
return true;
if (lang_matcher != nullptr)
@@ -1938,22 +2018,27 @@ dw2_expand_symtabs_matching_one
return true;
}
- bool symtab_was_null = !per_objfile->symtab_set_p (per_cu);
compunit_symtab *symtab
= dw2_instantiate_symtab (per_cu, per_objfile, false);
gdb_assert (symtab != nullptr);
- if (expansion_notify != NULL && symtab_was_null)
- return expansion_notify (symtab);
+ if (listener != nullptr)
+ {
+ cus_to_skip.set (per_cu->index, true);
+ return listener (symtab);
+ }
return true;
}
-/* See read.h. */
+/* If FILE_MATCHER is non-NULL, update CUS_TO_SKIP as appropriate
+ based on FILE_MATCHER. */
-void
-dw_expand_symtabs_matching_file_matcher
- (dwarf2_per_objfile *per_objfile, expand_symtabs_file_matcher file_matcher)
+static void
+dw_search_file_matcher
+ (dwarf2_per_objfile *per_objfile,
+ auto_bool_vector &cus_to_skip,
+ search_symtabs_file_matcher file_matcher)
{
if (file_matcher == NULL)
return;
@@ -1969,54 +2054,50 @@ dw_expand_symtabs_matching_file_matcher
QUIT;
if (per_cu->is_debug_types)
- continue;
- per_cu->mark = 0;
-
- /* We only need to look at symtabs not already expanded. */
- if (per_objfile->symtab_set_p (per_cu.get ()))
- continue;
+ {
+ cus_to_skip.set (per_cu->index, true);
+ continue;
+ }
if (per_cu->fnd != nullptr)
{
file_and_directory *fnd = per_cu->fnd.get ();
if (file_matcher (fnd->get_name (), false))
- {
- per_cu->mark = 1;
- continue;
- }
+ continue;
/* Before we invoke realpath, which can get expensive when many
files are involved, do a quick comparison of the basenames. */
if ((basenames_may_differ
|| file_matcher (lbasename (fnd->get_name ()), true))
&& file_matcher (fnd->get_fullname (), false))
- {
- per_cu->mark = 1;
- continue;
- }
+ continue;
}
quick_file_names *file_data = dw2_get_file_names (per_cu.get (),
per_objfile);
if (file_data == NULL)
- continue;
+ {
+ cus_to_skip.set (per_cu->index, true);
+ continue;
+ }
if (visited_not_found.contains (file_data))
- continue;
- else if (visited_found.contains (file_data))
{
- per_cu->mark = 1;
+ cus_to_skip.set (per_cu->index, true);
continue;
}
+ else if (visited_found.contains (file_data))
+ continue;
+ bool matched = false;
for (int j = 0; j < file_data->num_file_names; ++j)
{
const char *this_real_name;
if (file_matcher (file_data->file_names[j], false))
{
- per_cu->mark = 1;
+ matched = true;
break;
}
@@ -2030,15 +2111,18 @@ dw_expand_symtabs_matching_file_matcher
this_real_name = dw2_get_real_path (per_objfile, file_data, j);
if (file_matcher (this_real_name, false))
{
- per_cu->mark = 1;
+ matched = true;
break;
}
}
- if (per_cu->mark)
+ if (matched)
visited_found.insert (file_data);
else
- visited_not_found.insert (file_data);
+ {
+ cus_to_skip.set (per_cu->index, true);
+ visited_not_found.insert (file_data);
+ }
}
}
@@ -2360,6 +2444,24 @@ get_abbrev_section_for_cu (dwarf2_per_cu *this_cu)
return abbrev;
}
+/* "less than" function used to both sort and bisect units in the
+ `dwarf2_per_bfd::all_units` vector. Return true if the LHS CU comes before
+ (is "less" than) the section and offset in RHS.
+
+ For simplicity, sort sections by their pointer. This is not ideal, because
+ it can cause the behavior to change across runs, making some bugs harder to
+ investigate. An improvement would be for sections to be sorted by their
+ properties. */
+
+static bool
+all_units_less_than (const dwarf2_per_cu &lhs, const section_and_offset &rhs)
+{
+ if (lhs.section != rhs.section)
+ return lhs.section < rhs.section;
+
+ return lhs.sect_off < rhs.offset;
+}
+
/* Fetch the abbreviation table offset from a comp or type unit header. */
static sect_offset
@@ -2403,7 +2505,17 @@ add_type_unit (dwarf2_per_bfd *per_bfd, dwarf2_section_info *section,
false /* is_dwz */, sig);
signatured_type *sig_type = sig_type_holder.get ();
- per_bfd->all_units.emplace_back (sig_type_holder.release ());
+ /* Preserve the ordering of per_bfd->all_units. */
+ auto insert_it
+ = std::lower_bound (per_bfd->all_units.begin (), per_bfd->all_units.end (),
+ sig_type,
+ [] (const dwarf2_per_cu_up &lhs,
+ const signatured_type *rhs) {
+ return all_units_less_than (*lhs, { rhs->section,
+ rhs->sect_off });
+ });
+
+ per_bfd->all_units.emplace (insert_it, sig_type_holder.release ());
auto emplace_ret = per_bfd->signatured_types.emplace (sig_type);
/* Assert that an insertion took place - that there wasn't a type unit with
@@ -2487,7 +2599,7 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
if (it == dwo_file->tus.end ())
return nullptr;
- dwo_unit *dwo_entry = *it;
+ dwo_unit *dwo_entry = it->get ();
/* If the global table doesn't have an entry for this TU, add one. */
if (sig_type_it == per_bfd->signatured_types.end ())
@@ -2777,13 +2889,6 @@ dwo_unit *
cutu_reader::lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die,
const char *dwo_name)
{
-#if CXX_STD_THREAD
- /* We need a lock here to handle the DWO hash table. */
- static std::mutex dwo_lock;
-
- std::lock_guard<std::mutex> guard (dwo_lock);
-#endif
-
dwarf2_per_cu *per_cu = cu->per_cu;
struct dwo_unit *dwo_unit;
const char *comp_dir;
@@ -3209,10 +3314,11 @@ private:
void print_tu_stats (dwarf2_per_objfile *per_objfile)
{
- struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+ tu_stats *tu_stats = &per_bfd->tu_stats;
dwarf_read_debug_printf ("Type unit statistics:");
- dwarf_read_debug_printf (" %d TUs", tu_stats->nr_tus);
+ dwarf_read_debug_printf (" %d TUs", per_bfd->num_type_units);
dwarf_read_debug_printf (" %d uniq abbrev tables",
tu_stats->nr_uniq_abbrev_tables);
dwarf_read_debug_printf (" %d symtabs from stmt_list entries",
@@ -3362,7 +3468,7 @@ cooked_index_worker_debug_info::process_type_units
abbrev_table_up abbrev_table;
sect_offset abbrev_offset;
- if (per_objfile->per_bfd->all_type_units.size () == 0)
+ if (per_objfile->per_bfd->num_type_units == 0)
return;
/* TUs typically share abbrev tables, and there can be way more TUs than
@@ -3389,7 +3495,7 @@ cooked_index_worker_debug_info::process_type_units
/* Sort in a separate table to maintain the order of all_units
for .gdb_index: TU indices directly index all_type_units. */
std::vector<tu_abbrev_offset> sorted_by_abbrev;
- sorted_by_abbrev.reserve (per_objfile->per_bfd->all_type_units.size ());
+ sorted_by_abbrev.reserve (per_objfile->per_bfd->num_type_units);
for (const auto &cu : per_objfile->per_bfd->all_units)
if (cu->is_debug_types)
@@ -3422,7 +3528,10 @@ cooked_index_worker_debug_info::process_type_units
abbrev_table.get (), nullptr, false,
language_minimal);
if (!reader.is_dummy ())
- process_type_unit (&reader, storage);
+ storage->catch_error ([&] ()
+ {
+ process_type_unit (&reader, storage);
+ });
}
}
@@ -3458,13 +3567,16 @@ void
cooked_index_worker_debug_info::process_skeletonless_type_units
(dwarf2_per_objfile *per_objfile, cooked_index_worker_result *storage)
{
- scoped_time_it time_it ("DWARF skeletonless type units");
+ scoped_time_it time_it ("DWARF skeletonless type units", m_per_command_time);
/* Skeletonless TUs in DWP files without .gdb_index is not supported yet. */
if (per_objfile->per_bfd->dwp_file == nullptr)
for (const dwo_file_up &file : per_objfile->per_bfd->dwo_files)
- for (dwo_unit *unit : file->tus)
- process_skeletonless_type_unit (unit, per_objfile, storage);
+ for (const dwo_unit_up &unit : file->tus)
+ storage->catch_error ([&] ()
+ {
+ process_skeletonless_type_unit (unit.get (), per_objfile, storage);
+ });
}
void
@@ -3483,14 +3595,10 @@ cooked_index_worker_debug_info::process_units (size_t task_number,
{
dwarf2_per_cu *per_cu = inner->get ();
- try
+ thread_storage.catch_error ([&] ()
{
process_unit (per_cu, m_per_objfile, &thread_storage);
- }
- catch (gdb_exception &except)
- {
- thread_storage.note_error (std::move (except));
- }
+ });
}
thread_storage.done_reading (complaint_handler.release ());
@@ -3568,7 +3676,7 @@ cooked_index_worker_debug_info::do_reading ()
gdb_assert (iter != last);
workers.add_task ([this, task_count, iter, last] ()
{
- scoped_time_it time_it ("DWARF indexing worker");
+ scoped_time_it time_it ("DWARF indexing worker", m_per_command_time);
process_units (task_count, iter, last);
});
@@ -3639,16 +3747,22 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
}
}
-/* Initialize the views on all_units. */
+/* See read.h. */
void
finalize_all_units (dwarf2_per_bfd *per_bfd)
{
- size_t nr_tus = per_bfd->tu_stats.nr_tus;
- size_t nr_cus = per_bfd->all_units.size () - nr_tus;
- gdb::array_view<dwarf2_per_cu_up> tmp = per_bfd->all_units;
- per_bfd->all_comp_units = tmp.slice (0, nr_cus);
- per_bfd->all_type_units = tmp.slice (nr_cus, nr_tus);
+ /* Sanity check. */
+ gdb_assert (per_bfd->all_units.size ()
+ == per_bfd->num_comp_units + per_bfd->num_type_units);
+
+ /* Ensure that the all_units vector is in the expected order for
+ dwarf2_find_containing_unit to be able to perform a binary search. */
+ std::sort (per_bfd->all_units.begin (), per_bfd->all_units.end (),
+ [] (const dwarf2_per_cu_up &a, const dwarf2_per_cu_up &b)
+ {
+ return all_units_less_than (*a, { b->section, b->sect_off });
+ });
}
/* See read.h. */
@@ -3657,6 +3771,7 @@ void
create_all_units (dwarf2_per_objfile *per_objfile)
{
gdb_assert (per_objfile->per_bfd->all_units.empty ());
+ scoped_remove_all_units remove_all_units (*per_objfile->per_bfd);
signatured_type_set sig_types;
@@ -3677,8 +3792,6 @@ create_all_units (dwarf2_per_objfile *per_objfile)
if (!dwz->types.empty ())
{
- per_objfile->per_bfd->all_units.clear ();
-
/* See enhancement PR symtab/30838. */
error (_(DWARF_ERROR_PREFIX
".debug_types section not supported in dwz file"));
@@ -3688,6 +3801,7 @@ create_all_units (dwarf2_per_objfile *per_objfile)
per_objfile->per_bfd->signatured_types = std::move (sig_types);
finalize_all_units (per_objfile->per_bfd);
+ remove_all_units.disable ();
}
/* Return the initial uleb128 in the die at INFO_PTR. */
@@ -4220,7 +4334,7 @@ fixup_go_packaging (struct dwarf2_cu *cu)
struct symbol *sym = list->symbol[i];
if (sym->language () == language_go
- && sym->aclass () == LOC_BLOCK)
+ && sym->loc_class () == LOC_BLOCK)
{
gdb::unique_xmalloc_ptr<char> this_package_name
= go_symbol_package_name (sym);
@@ -4257,7 +4371,7 @@ fixup_go_packaging (struct dwarf2_cu *cu)
sym->set_language (language_go, &objfile->objfile_obstack);
sym->compute_and_set_names (saved_package_name, false, objfile->per_bfd);
sym->set_domain (TYPE_DOMAIN);
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_type (type);
add_symbol_to_list (sym, cu->get_builder ()->get_global_symbols ());
@@ -4467,9 +4581,9 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
else
{
struct type *disr_type = nullptr;
- for (int i = 0; i < type->num_fields (); ++i)
+ for (const auto &field : type->fields ())
{
- disr_type = type->field (i).type ();
+ disr_type = field.type ();
if (disr_type->code () != TYPE_CODE_STRUCT)
{
@@ -4508,7 +4622,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
field *new_fields
= (struct field *) TYPE_ZALLOC (type, ((type->num_fields () + 1)
* sizeof (struct field)));
- memcpy (new_fields + 1, type->fields (),
+ memcpy (new_fields + 1, type->fields ().data (),
type->num_fields () * sizeof (struct field));
type->set_fields (new_fields);
type->set_num_fields (type->num_fields () + 1);
@@ -4522,13 +4636,12 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
variant name. For convenience we build a map here. */
struct type *enum_type = disr_field->type ();
gdb::unordered_map<std::string_view, ULONGEST> discriminant_map;
- for (int i = 0; i < enum_type->num_fields (); ++i)
+ for (const auto &field : enum_type->fields ())
{
- if (enum_type->field (i).loc_kind () == FIELD_LOC_KIND_ENUMVAL)
+ if (field.loc_kind () == FIELD_LOC_KIND_ENUMVAL)
{
- const char *name
- = rust_last_path_segment (enum_type->field (i).name ());
- discriminant_map[name] = enum_type->field (i).loc_enumval ();
+ const char *name = rust_last_path_segment (field.name ());
+ discriminant_map[name] = field.loc_enumval ();
}
}
@@ -4564,7 +4677,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
if (sub_type->num_fields () > 0)
{
sub_type->set_num_fields (sub_type->num_fields () - 1);
- sub_type->set_fields (sub_type->fields () + 1);
+ sub_type->set_fields (sub_type->fields ().data () + 1);
}
type->field (i).set_name (variant_name);
sub_type->set_name
@@ -4904,6 +5017,21 @@ process_full_type_unit (dwarf2_cu *cu)
cu->reset_builder ();
}
+/* See read.h. */
+
+const dwarf2_section_info &
+get_section_for_ref (const attribute &attr, dwarf2_cu *cu)
+{
+ gdb_assert (attr.form_is_ref ());
+
+ if (attr.form_is_alt ())
+ return cu->per_cu->per_bfd->get_dwz_file (true)->info;
+
+ /* If the source is already in the supplementary (dwz) file, then CU->SECTION
+ already represents the section in the supplementary file. */
+ return cu->section ();
+}
+
/* Process an imported unit DIE. */
static void
@@ -4923,12 +5051,11 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
attr = dwarf2_attr (die, DW_AT_import, cu);
if (attr != NULL)
{
+ const dwarf2_section_info &section = get_section_for_ref (*attr, cu);
sect_offset sect_off = attr->get_ref_die_offset ();
- bool is_dwz = attr->form_is_alt () || cu->per_cu->is_dwz;
dwarf2_per_objfile *per_objfile = cu->per_objfile;
dwarf2_per_cu *per_cu
- = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
- per_objfile->per_bfd);
+ = dwarf2_find_containing_unit ({ &section, sect_off }, per_objfile);
/* We're importing a C++ compilation unit with tag DW_TAG_compile_unit
into another compilation unit, at root level. Regard this as a hint,
@@ -5630,7 +5757,7 @@ read_alias (struct die_info *die, struct dwarf2_cu *cu)
type = die_type (d, imported_cu);
struct symbol *sym = new_symbol (die, type, cu);
attr = dwarf2_attr (d, DW_AT_location, imported_cu);
- sym->set_aclass_index (LOC_UNRESOLVED);
+ sym->set_loc_class_index (LOC_UNRESOLVED);
if (attr != nullptr)
var_decode_location (attr, sym, cu);
return true;
@@ -5853,7 +5980,7 @@ find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu)
&& res.get_name () != nullptr
&& IS_ABSOLUTE_PATH (res.get_name ()))
{
- res.set_comp_dir (ldirname (res.get_name ()));
+ res.set_comp_dir (gdb_ldirname (res.get_name ()));
res.set_name (make_unique_xstrdup (lbasename (res.get_name ())));
}
@@ -6049,6 +6176,20 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
}
}
+/* See cu.h.
+
+ This function is defined in this file (instead of cu.c) because it needs
+ to see the definition of struct dwo_unit. */
+
+const dwarf2_section_info &
+dwarf2_cu::section () const
+{
+ if (this->dwo_unit != nullptr)
+ return *this->dwo_unit->section;
+ else
+ return *this->per_cu->section;
+}
+
void
dwarf2_cu::setup_type_unit_groups (struct die_info *die)
{
@@ -6200,11 +6341,33 @@ static dwo_file *
lookup_dwo_file (dwarf2_per_bfd *per_bfd, const char *dwo_name,
const char *comp_dir)
{
+#if CXX_STD_THREAD
+ std::lock_guard<std::mutex> guard (per_bfd->dwo_files_lock);
+#endif
+
auto it = per_bfd->dwo_files.find (dwo_file_search {dwo_name, comp_dir});
return it != per_bfd->dwo_files.end () ? it->get() : nullptr;
}
+/* Add DWO_FILE to the per-BFD DWO file hash table.
+
+ Return the dwo_file actually kept in the hash table.
+
+ If another thread raced with this one, opening the exact same DWO file and
+ inserting it first in the hash table, then keep that other thread's copy
+ and DWO_FILE gets freed. */
+
+static dwo_file *
+add_dwo_file (dwarf2_per_bfd *per_bfd, dwo_file_up dwo_file)
+{
+#if CXX_STD_THREAD
+ std::lock_guard<std::mutex> lock (per_bfd->dwo_files_lock);
+#endif
+
+ return per_bfd->dwo_files.emplace (std::move (dwo_file)).first->get ();
+}
+
void
cutu_reader::create_dwo_unit_hash_tables (dwo_file &dwo_file,
dwarf2_cu &skeleton_cu,
@@ -6283,7 +6446,7 @@ cutu_reader::create_dwo_unit_hash_tables (dwo_file &dwo_file,
else
signature = header.signature;
- dwo_unit *dwo_unit = OBSTACK_ZALLOC (&per_bfd.obstack, struct dwo_unit);
+ auto dwo_unit = std::make_unique<struct dwo_unit> ();
/* Set the fields common to compile and type units. */
dwo_unit->dwo_file = &dwo_file;
@@ -6301,7 +6464,7 @@ cutu_reader::create_dwo_unit_hash_tables (dwo_file &dwo_file,
sect_offset_str (sect_off),
hex_string (dwo_unit->signature));
- auto [it, inserted] = dwo_file.cus.emplace (dwo_unit);
+ auto [it, inserted] = dwo_file.cus.emplace (std::move (dwo_unit));
if (!inserted)
complaint (_("debug cu entry at offset %s is duplicate to"
" the entry at offset %s, signature %s"),
@@ -6320,7 +6483,7 @@ cutu_reader::create_dwo_unit_hash_tables (dwo_file &dwo_file,
sect_offset_str (sect_off),
hex_string (dwo_unit->signature));
- auto [it, inserted] = dwo_file.tus.emplace (dwo_unit);
+ auto [it, inserted] = dwo_file.tus.emplace (std::move (dwo_unit));
if (!inserted)
complaint (_("debug type entry at offset %s is duplicate to"
" the entry at offset %s, signature %s"),
@@ -6801,7 +6964,7 @@ locate_v1_virtual_dwo_sections (asection *sectp,
COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU.
This is for DWP version 1 files. */
-static struct dwo_unit *
+static dwo_unit_up
create_dwo_unit_in_dwp_v1 (dwarf2_per_bfd *per_bfd,
struct dwp_file *dwp_file,
uint32_t unit_index,
@@ -6924,19 +7087,17 @@ create_dwo_unit_in_dwp_v1 (dwarf2_per_bfd *per_bfd,
types we'll grow the vector and eventually have to reallocate space
for it, invalidating all copies of pointers into the previous
contents. */
- auto [it, inserted]
- = per_bfd->dwo_files.emplace (std::move (new_dwo_file));
- gdb_assert (inserted);
- dwo_file = it->get ();
+ dwo_file = add_dwo_file (per_bfd, std::move (new_dwo_file));
}
else
dwarf_read_debug_printf ("Using existing virtual DWO: %s",
virtual_dwo_name.c_str ());
- dwo_unit *dwo_unit = OBSTACK_ZALLOC (&per_bfd->obstack, struct dwo_unit);
+ auto dwo_unit = std::make_unique<struct dwo_unit> ();
dwo_unit->dwo_file = dwo_file;
dwo_unit->signature = signature;
- dwo_unit->section = XOBNEW (&per_bfd->obstack, struct dwarf2_section_info);
+ dwo_unit->section_holder = std::make_unique<dwarf2_section_info> ();
+ dwo_unit->section = dwo_unit->section_holder.get ();
*dwo_unit->section = sections.info_or_types;
/* dwo_unit->{offset,length,type_offset_in_tu} are set later. */
@@ -6994,7 +7155,7 @@ create_dwp_v2_or_v5_section (dwarf2_per_bfd *per_bfd,
COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU.
This is for DWP version 2 files. */
-static struct dwo_unit *
+static dwo_unit_up
create_dwo_unit_in_dwp_v2 (dwarf2_per_bfd *per_bfd,
struct dwp_file *dwp_file,
uint32_t unit_index,
@@ -7129,19 +7290,17 @@ create_dwo_unit_in_dwp_v2 (dwarf2_per_bfd *per_bfd,
types we'll grow the vector and eventually have to reallocate space
for it, invalidating all copies of pointers into the previous
contents. */
- auto [it, inserted]
- = per_bfd->dwo_files.emplace (std::move (new_dwo_file));
- gdb_assert (inserted);
- dwo_file = it->get ();
+ dwo_file = add_dwo_file (per_bfd, std::move (new_dwo_file));
}
else
dwarf_read_debug_printf ("Using existing virtual DWO: %s",
virtual_dwo_name.c_str ());
- dwo_unit *dwo_unit = OBSTACK_ZALLOC (&per_bfd->obstack, struct dwo_unit);
+ auto dwo_unit = std::make_unique<struct dwo_unit> ();
dwo_unit->dwo_file = dwo_file;
dwo_unit->signature = signature;
- dwo_unit->section = XOBNEW (&per_bfd->obstack, struct dwarf2_section_info);
+ dwo_unit->section_holder = std::make_unique<dwarf2_section_info> ();
+ dwo_unit->section = dwo_unit->section_holder.get ();
*dwo_unit->section = create_dwp_v2_or_v5_section
(per_bfd,
is_debug_types
@@ -7159,7 +7318,7 @@ create_dwo_unit_in_dwp_v2 (dwarf2_per_bfd *per_bfd,
COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU.
This is for DWP version 5 files. */
-static struct dwo_unit *
+static dwo_unit_up
create_dwo_unit_in_dwp_v5 (dwarf2_per_bfd *per_bfd,
struct dwp_file *dwp_file,
uint32_t unit_index,
@@ -7299,16 +7458,13 @@ create_dwo_unit_in_dwp_v5 (dwarf2_per_bfd *per_bfd,
types we'll grow the vector and eventually have to reallocate space
for it, invalidating all copies of pointers into the previous
contents. */
- auto [it, inserted]
- = per_bfd->dwo_files.emplace (std::move (new_dwo_file));
- gdb_assert (inserted);
- dwo_file = it->get ();
+ dwo_file = add_dwo_file (per_bfd, std::move (new_dwo_file));
}
else
dwarf_read_debug_printf ("Using existing virtual DWO: %s",
virtual_dwo_name.c_str ());
- dwo_unit *dwo_unit = OBSTACK_ZALLOC (&per_bfd->obstack, struct dwo_unit);
+ auto dwo_unit = std::make_unique<struct dwo_unit> ();
dwo_unit->dwo_file = dwo_file;
dwo_unit->signature = signature;
dwo_unit->section
@@ -7339,9 +7495,15 @@ lookup_dwo_unit_in_dwp (dwarf2_per_bfd *per_bfd,
auto &dwo_unit_set
= is_debug_types ? dwp_file->loaded_tus : dwp_file->loaded_cus;
- if (auto it = dwo_unit_set.find (signature);
- it != dwo_unit_set.end ())
- return *it;
+ {
+#if CXX_STD_THREAD
+ std::lock_guard<std::mutex> guard (dwp_file->loaded_cutus_lock);
+#endif
+
+ if (auto it = dwo_unit_set.find (signature);
+ it != dwo_unit_set.end ())
+ return it->get ();
+ }
/* Use a for loop so that we don't loop forever on bad debug info. */
for (unsigned int i = 0; i < dwp_htab->nr_slots; ++i)
@@ -7355,7 +7517,7 @@ lookup_dwo_unit_in_dwp (dwarf2_per_bfd *per_bfd,
uint32_t unit_index =
read_4_bytes (dbfd,
dwp_htab->unit_table + hash * sizeof (uint32_t));
- dwo_unit *dwo_unit;
+ dwo_unit_up dwo_unit;
if (dwp_file->version == 1)
dwo_unit
@@ -7370,9 +7532,14 @@ lookup_dwo_unit_in_dwp (dwarf2_per_bfd *per_bfd,
= create_dwo_unit_in_dwp_v5 (per_bfd, dwp_file, unit_index,
comp_dir, signature, is_debug_types);
- auto [it, inserted] = dwo_unit_set.emplace (dwo_unit);
- gdb_assert (inserted);
- return *it;
+ /* If another thread raced with this one, opening the exact same
+ DWO unit, then we'll keep that other thread's copy. */
+#if CXX_STD_THREAD
+ std::lock_guard<std::mutex> guard (dwp_file->loaded_cutus_lock);
+#endif
+
+ auto it = dwo_unit_set.emplace (std::move (dwo_unit)).first;
+ return it->get ();
}
if (signature_in_table == 0)
@@ -7428,7 +7595,7 @@ try_open_dwop_file (dwarf2_per_bfd *per_bfd, const char *file_name, int is_dwp,
search_path = per_bfd->captured_debug_dir.c_str ();
/* Add the path for the executable binary to the list of search paths. */
- std::string objfile_dir = ldirname (per_bfd->filename ());
+ std::string objfile_dir = gdb_ldirname (per_bfd->filename ());
search_path_holder.reset (concat (objfile_dir.c_str (),
dirname_separator_string,
search_path, nullptr));
@@ -7449,14 +7616,23 @@ try_open_dwop_file (dwarf2_per_bfd *per_bfd, const char *file_name, int is_dwp,
if (sym_bfd == NULL)
return NULL;
- if (!bfd_check_format (sym_bfd.get (), bfd_object))
- return NULL;
+ {
+#if CXX_STD_THREAD
+ /* The operations below are not thread-safe, use a lock to synchronize
+ concurrent accesses. */
+ static std::mutex mutex;
+ std::lock_guard<std::mutex> lock (mutex);
+#endif
+
+ if (!bfd_check_format (sym_bfd.get (), bfd_object))
+ return NULL;
- /* Success. Record the bfd as having been included by the objfile's bfd.
+ /* Success. Record the bfd as having been included by the objfile's bfd.
This is important because things like demangled_names_hash lives in the
objfile's per_bfd space and may have references to things like symbol
names that live in the DWO/DWP file's per_bfd space. PR 16426. */
- gdb_bfd_record_inclusion (per_bfd->obfd, sym_bfd.get ());
+ gdb_bfd_record_inclusion (per_bfd->obfd, sym_bfd.get ());
+ }
return sym_bfd;
}
@@ -7506,45 +7682,66 @@ cutu_reader::open_dwo_file (dwarf2_per_bfd *per_bfd, const char *file_name,
size of each of the DWO debugging sections we are interested in. */
void
-cutu_reader::locate_dwo_sections (struct objfile *objfile, bfd *abfd,
- asection *sectp, dwo_sections *dwo_sections)
+cutu_reader::locate_dwo_sections (objfile *objfile, dwo_file &dwo_file)
{
const struct dwop_section_names *names = &dwop_section_names;
+ dwo_sections &dwo_sections = dwo_file.sections;
+ bool complained_about_macro_already = false;
+
+ for (asection *sec : gdb_bfd_sections (dwo_file.dbfd))
+ {
+ struct dwarf2_section_info *dw_sect = nullptr;
+
+ if (names->abbrev_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.abbrev;
+ else if (names->info_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.infos.emplace_back (dwarf2_section_info {});
+ else if (names->line_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.line;
+ else if (names->loc_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.loc;
+ else if (names->loclists_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.loclists;
+ else if (names->macinfo_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.macinfo;
+ else if (names->macro_dwo.matches (sec->name))
+ {
+ /* gcc versions <= 13 generate multiple .debug_macro.dwo sections with
+ some unresolved links between them. It's not usable, so do as if
+ there were not there. */
+ if (!complained_about_macro_already)
+ {
+ if (dwo_sections.macro.s.section == nullptr)
+ dw_sect = &dwo_sections.macro;
+ else
+ {
+ warning (_("Multiple .debug_macro.dwo sections found in "
+ "%s, ignoring them."), dwo_file.dbfd->filename);
- struct dwarf2_section_info *dw_sect = nullptr;
-
- if (names->abbrev_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->abbrev;
- else if (names->info_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->infos.emplace_back (dwarf2_section_info {});
- else if (names->line_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->line;
- else if (names->loc_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->loc;
- else if (names->loclists_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->loclists;
- else if (names->macinfo_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->macinfo;
- else if (names->macro_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->macro;
- else if (names->rnglists_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->rnglists;
- else if (names->str_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->str;
- else if (names->str_offsets_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->str_offsets;
- else if (names->types_dwo.matches (sectp->name))
- dw_sect = &dwo_sections->types.emplace_back (dwarf2_section_info {});
-
- if (dw_sect != nullptr)
- {
- /* Make sure we don't overwrite a section info that has been filled in
+ dwo_sections.macro = dwarf2_section_info {};
+ complained_about_macro_already = true;
+ }
+ }
+ }
+ else if (names->rnglists_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.rnglists;
+ else if (names->str_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.str;
+ else if (names->str_offsets_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.str_offsets;
+ else if (names->types_dwo.matches (sec->name))
+ dw_sect = &dwo_sections.types.emplace_back (dwarf2_section_info {});
+
+ if (dw_sect != nullptr)
+ {
+ /* Make sure we don't overwrite a section info that has been filled in
already. */
- gdb_assert (!dw_sect->readin);
+ gdb_assert (!dw_sect->readin);
- dw_sect->s.section = sectp;
- dw_sect->size = bfd_section_size (sectp);
- dw_sect->read (objfile);
+ dw_sect->s.section = sec;
+ dw_sect->size = bfd_section_size (sec);
+ dw_sect->read (objfile);
+ }
}
}
@@ -7572,15 +7769,8 @@ cutu_reader::open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name,
dwo_file->comp_dir = comp_dir;
dwo_file->dbfd = std::move (dbfd);
- for (asection *sec : gdb_bfd_sections (dwo_file->dbfd))
- this->locate_dwo_sections (per_objfile->objfile, dwo_file->dbfd.get (), sec,
- &dwo_file->sections);
+ this->locate_dwo_sections (per_objfile->objfile, *dwo_file);
- /* There is normally just one .debug_info.dwo section in a DWO file. But when
- building with -fdebug-types-section, gcc produces multiple .debug_info.dwo
- sections. One for each produced type unit and one for the compile unit.
- This is not expected, but we can easily enough deal with what gcc
- produces. This behavior has been observed with gcc 14.2.1. */
for (dwarf2_section_info &section : dwo_file->sections.infos)
create_dwo_unit_hash_tables (*dwo_file, *cu, section, ruh_kind::COMPILE);
@@ -7782,7 +7972,7 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile)
struct objfile *backlink = objfile->separate_debug_objfile_backlink;
const char *backlink_basename = lbasename (backlink->original_name);
- dwp_name = ldirname (objfile->original_name) + SLASH_STRING + backlink_basename;
+ dwp_name = gdb_ldirname (objfile->original_name) + SLASH_STRING + backlink_basename;
}
else
dwp_name = objfile->original_name;
@@ -7932,12 +8122,7 @@ cutu_reader::lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name,
= open_and_init_dwo_file (cu, dwo_name, comp_dir);
if (new_dwo_file != nullptr)
- {
- auto [it, inserted]
- = per_bfd->dwo_files.emplace (std::move (new_dwo_file));
- gdb_assert (inserted);
- dwo_file = (*it).get ();
- }
+ dwo_file = add_dwo_file (per_bfd, std::move (new_dwo_file));
}
if (dwo_file != NULL)
@@ -7948,13 +8133,13 @@ cutu_reader::lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name,
{
if (auto it = dwo_file->tus.find (signature);
it != dwo_file->tus.end ())
- dwo_cutu = *it;
+ dwo_cutu = it->get ();
}
else if (!is_debug_types && !dwo_file->cus.empty ())
{
if (auto it = dwo_file->cus.find (signature);
it != dwo_file->cus.end ())
- dwo_cutu = *it;
+ dwo_cutu = it->get ();
}
if (dwo_cutu != NULL)
@@ -8061,8 +8246,8 @@ queue_and_load_all_dwo_tus (dwarf2_cu *cu)
dwo_file = dwo_unit->dwo_file;
- for (struct dwo_unit *unit : dwo_file->tus)
- queue_and_load_dwo_tu (unit, cu);
+ for (const dwo_unit_up &unit : dwo_file->tus)
+ queue_and_load_dwo_tu (unit.get (), cu);
}
/* Read in various DIEs. */
@@ -8738,7 +8923,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
struct dwarf2_locexpr_baton *dlbaton;
struct dwarf_block *block = attr->as_block ();
- dlbaton = XOBNEW (&objfile->objfile_obstack, struct dwarf2_locexpr_baton);
+ dlbaton = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_locexpr_baton);
dlbaton->data = block->data;
dlbaton->size = block->size;
dlbaton->per_objfile = per_objfile;
@@ -9861,69 +10047,44 @@ dwarf2_access_attribute (struct die_info *die, struct dwarf2_cu *cu)
}
}
-/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset. Set
- *OFFSET to the byte offset. If the attribute was not found return
- 0, otherwise return 1. If it was found but could not properly be
- handled, set *OFFSET to 0. */
+/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset and
+ store the results in FIELD. */
-static int
+static void
handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
- LONGEST *offset)
+ struct field *field)
{
- struct attribute *attr;
+ const auto data_member_location_attr
+ = dwarf2_attr (die, DW_AT_data_member_location, cu);
- attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
- if (attr != NULL)
+ if (data_member_location_attr != nullptr)
{
- *offset = 0;
- CORE_ADDR temp;
+ bool has_bit_offset = false;
+ LONGEST bit_offset = 0;
+ LONGEST anonymous_size = 0;
+ const auto bit_offset_attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
- /* Note that we do not check for a section offset first here.
- This is because DW_AT_data_member_location is new in DWARF 4,
- so if we see it, we can assume that a constant form is really
- a constant and not a section offset. */
- if (attr->form_is_constant ())
- *offset = attr->unsigned_constant ().value_or (0);
- else if (attr->form_is_section_offset ())
- dwarf2_complex_location_expr_complaint ();
- else if (attr->form_is_block ()
- && decode_locdesc (attr->as_block (), cu, &temp))
+ if (bit_offset_attr != nullptr && bit_offset_attr->form_is_constant ())
{
- *offset = temp;
- }
- else
- dwarf2_complex_location_expr_complaint ();
+ has_bit_offset = true;
+ bit_offset = bit_offset_attr->confused_constant ().value_or (0);
- return 1;
- }
- else
- {
- attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
- if (attr != nullptr)
- {
- *offset = attr->unsigned_constant ().value_or (0);
- return 1;
- }
- }
+ const auto byte_size_attr = dwarf2_attr (die, DW_AT_byte_size, cu);
- return 0;
-}
-
-/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset and
- store the results in FIELD. */
-
-static void
-handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
- struct field *field)
-{
- struct attribute *attr;
+ if (byte_size_attr != nullptr && byte_size_attr->form_is_constant ())
+ {
+ /* The size of the anonymous object containing
+ the bit field is explicit, so use the
+ indicated size (in bytes). */
+ anonymous_size
+ = byte_size_attr->unsigned_constant ().value_or (0);
+ }
+ }
- attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
- if (attr != NULL)
- {
- if (attr->form_is_constant ())
+ if (data_member_location_attr->form_is_constant ())
{
- LONGEST offset = attr->unsigned_constant ().value_or (0);
+ LONGEST offset
+ = data_member_location_attr->confused_constant ().value_or (0);
/* Work around this GCC 11 bug, where it would erroneously use -1
data member locations, instead of 0:
@@ -9938,23 +10099,40 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
}
field->set_loc_bitpos (offset * bits_per_byte);
+ if (has_bit_offset)
+ apply_bit_offset_to_field (*field, bit_offset, anonymous_size);
}
- else if (attr->form_is_section_offset ())
- dwarf2_complex_location_expr_complaint ();
- else if (attr->form_is_block ())
+ else if (data_member_location_attr->form_is_block ())
{
CORE_ADDR offset;
- if (decode_locdesc (attr->as_block (), cu, &offset))
- field->set_loc_bitpos (offset * bits_per_byte);
+ if (decode_locdesc (data_member_location_attr->as_block (), cu,
+ &offset))
+ {
+ field->set_loc_bitpos (offset * bits_per_byte);
+
+ if (has_bit_offset)
+ apply_bit_offset_to_field (*field, bit_offset, anonymous_size);
+ }
else
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
struct objfile *objfile = per_objfile->objfile;
- struct dwarf2_locexpr_baton *dlbaton
- = XOBNEW (&objfile->objfile_obstack,
- struct dwarf2_locexpr_baton);
- dlbaton->data = attr->as_block ()->data;
- dlbaton->size = attr->as_block ()->size;
+ struct dwarf2_locexpr_baton *dlbaton;
+ if (has_bit_offset)
+ {
+ dwarf2_field_location_baton *flbaton
+ = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ dwarf2_field_location_baton);
+ flbaton->is_field_location = true;
+ flbaton->bit_offset = bit_offset;
+ flbaton->explicit_byte_size = anonymous_size;
+ dlbaton = flbaton;
+ }
+ else
+ dlbaton = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_locexpr_baton);
+ dlbaton->data = data_member_location_attr->as_block ()->data;
+ dlbaton->size = data_member_location_attr->as_block ()->size;
/* When using this baton, we want to compute the address
of the field, not the value. This is why
is_reference is set to false here. */
@@ -9962,28 +10140,74 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
dlbaton->per_objfile = per_objfile;
dlbaton->per_cu = cu->per_cu;
- field->set_loc_dwarf_block (dlbaton);
+ field->set_loc_dwarf_block_addr (dlbaton);
}
}
else
- dwarf2_complex_location_expr_complaint ();
+ complaint (_("Unsupported form %s for DW_AT_data_member_location"),
+ dwarf_form_name (data_member_location_attr->form));
}
else
{
- attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
- if (attr != nullptr)
- field->set_loc_bitpos (attr->unsigned_constant ().value_or (0));
+ const auto data_bit_offset_attr
+ = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
+
+ if (data_bit_offset_attr != nullptr)
+ {
+ if (data_bit_offset_attr->form_is_constant ())
+ field->set_loc_bitpos (data_bit_offset_attr->unsigned_constant ()
+ .value_or (0));
+ else if (data_bit_offset_attr->form_is_block ())
+ {
+ /* This is a DWARF extension. See
+ https://dwarfstd.org/issues/250501.1.html. */
+ dwarf2_per_objfile *per_objfile = cu->per_objfile;
+ dwarf2_locexpr_baton *dlbaton
+ = OBSTACK_ZALLOC (&per_objfile->objfile->objfile_obstack,
+ dwarf2_locexpr_baton);
+ dlbaton->data = data_bit_offset_attr->as_block ()->data;
+ dlbaton->size = data_bit_offset_attr->as_block ()->size;
+ dlbaton->per_objfile = per_objfile;
+ dlbaton->per_cu = cu->per_cu;
+
+ field->set_loc_dwarf_block_bitpos (dlbaton);
+ }
+ else
+ complaint (_("Unsupported form %s for DW_AT_data_bit_offset"),
+ dwarf_form_name (data_bit_offset_attr->form));
+ }
}
}
+/* A helper that computes the location of a field. The CU and the
+ DW_TAG_member DIE are passed in. The results are stored in
+ *FP. */
+
+static void
+compute_field_location (dwarf2_cu *cu, die_info *die, field *fp)
+{
+ /* Get type of field. */
+ fp->set_type (die_type (die, cu));
+
+ fp->set_loc_bitpos (0);
+
+ /* Get bit size of field (zero if none). */
+ attribute *attr = dwarf2_attr (die, DW_AT_bit_size, cu);
+ if (attr != nullptr)
+ fp->set_bitsize (attr->unsigned_constant ().value_or (0));
+ else
+ fp->set_bitsize (0);
+
+ /* Get bit offset of field. */
+ handle_member_location (die, cu, fp);
+}
+
/* Add an aggregate field to the field list. */
static void
dwarf2_add_field (struct field_info *fip, struct die_info *die,
struct dwarf2_cu *cu)
{
- struct objfile *objfile = cu->per_objfile->objfile;
- struct gdbarch *gdbarch = objfile->arch ();
struct nextfield *new_field;
struct attribute *attr;
struct field *fp;
@@ -10033,64 +10257,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
}
/* Data member other than a C++ static data member. */
- /* Get type of field. */
- fp->set_type (die_type (die, cu));
-
- fp->set_loc_bitpos (0);
-
- /* Get bit size of field (zero if none). */
- attr = dwarf2_attr (die, DW_AT_bit_size, cu);
- if (attr != nullptr)
- fp->set_bitsize (attr->unsigned_constant ().value_or (0));
- else
- fp->set_bitsize (0);
-
- /* Get bit offset of field. */
- handle_member_location (die, cu, fp);
- attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
- if (attr != nullptr && attr->form_is_constant ())
- {
- ULONGEST bit_offset = attr->unsigned_constant ().value_or (0);
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- {
- /* For big endian bits, the DW_AT_bit_offset gives the
- additional bit offset from the MSB of the containing
- anonymous object to the MSB of the field. We don't
- have to do anything special since we don't need to
- know the size of the anonymous object. */
- fp->set_loc_bitpos (fp->loc_bitpos () + bit_offset);
- }
- else
- {
- /* For little endian bits, compute the bit offset to the
- MSB of the anonymous object, subtract off the number of
- bits from the MSB of the field to the MSB of the
- object, and then subtract off the number of bits of
- the field itself. The result is the bit offset of
- the LSB of the field. */
- int anonymous_size;
-
- attr = dwarf2_attr (die, DW_AT_byte_size, cu);
- if (attr != nullptr && attr->form_is_constant ())
- {
- /* The size of the anonymous object containing
- the bit field is explicit, so use the
- indicated size (in bytes). */
- anonymous_size = attr->unsigned_constant ().value_or (0);
- }
- else
- {
- /* The size of the anonymous object containing
- the bit field must be inferred from the type
- attribute of the data member containing the
- bit field. */
- anonymous_size = fp->type ()->length ();
- }
- fp->set_loc_bitpos (fp->loc_bitpos ()
- + anonymous_size * bits_per_byte
- - bit_offset - fp->bitsize ());
- }
- }
+ compute_field_location (cu, die, fp);
/* Get name of field. */
fieldname = dwarf2_name (die, cu);
@@ -10538,7 +10705,6 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
smash_to_method_type (fnp->type, type,
this_type->target_type (),
this_type->fields (),
- this_type->num_fields (),
this_type->has_varargs ());
/* Handle static member functions.
@@ -10760,8 +10926,7 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
self_type = pfn_type->field (0).type ()->target_type ();
new_type = type_allocator (type).new_type ();
smash_to_method_type (new_type, self_type, pfn_type->target_type (),
- pfn_type->fields (), pfn_type->num_fields (),
- pfn_type->has_varargs ());
+ pfn_type->fields (), pfn_type->has_varargs ());
smash_to_methodptr_type (type, new_type);
}
@@ -11269,6 +11434,21 @@ handle_struct_member_die (struct die_info *child_die, struct type *type,
handle_variant (child_die, type, fi, template_args, cu);
}
+/* Create a property baton for a field. DIE is the field's DIE. The
+ baton's "field" member is filled in, but the other members of the
+ baton are not. The new property baton is returned. */
+
+static dwarf2_property_baton *
+find_field_create_baton (dwarf2_cu *cu, die_info *die)
+{
+ dwarf2_property_baton *result
+ = XOBNEW (&cu->per_objfile->objfile->objfile_obstack,
+ struct dwarf2_property_baton);
+ memset (&result->field, 0, sizeof (result->field));
+ compute_field_location (cu, die, &result->field);
+ return result;
+}
+
/* Finish creating a structure or union type, including filling in its
members and creating a symbol for it. This function also handles Fortran
namelist variables, their items or members and creating a symbol for
@@ -12262,7 +12442,8 @@ mark_common_block_symbol_computed (struct symbol *sym,
gdb_assert (member_loc->form_is_block ()
|| member_loc->form_is_constant ());
- baton = XOBNEW (&objfile->objfile_obstack, struct dwarf2_locexpr_baton);
+ baton = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_locexpr_baton);
baton->per_objfile = per_objfile;
baton->per_cu = cu->per_cu;
gdb_assert (baton->per_cu);
@@ -12304,7 +12485,7 @@ mark_common_block_symbol_computed (struct symbol *sym,
gdb_assert (ptr - baton->data == baton->size);
SYMBOL_LOCATION_BATON (sym) = baton;
- sym->set_aclass_index (dwarf2_locexpr_index);
+ sym->set_loc_class_index (dwarf2_locexpr_index);
}
/* Create appropriate locally-scoped variables for all the
@@ -12666,8 +12847,7 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
= type_allocator (cu->per_objfile->objfile, cu->lang ()).new_type ();
smash_to_method_type (new_type, domain, to_type->target_type (),
- to_type->fields (), to_type->num_fields (),
- to_type->has_varargs ());
+ to_type->fields (), to_type->has_varargs ());
type = lookup_methodptr_type (new_type);
}
else
@@ -13165,7 +13345,7 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
a given gmp_mpz given an attribute. */
static void
-get_mpz (struct dwarf2_cu *cu, gdb_mpz *value, struct attribute *attr)
+get_mpz_for_rational (dwarf2_cu *cu, gdb_mpz *value, attribute *attr)
{
/* GCC will sometimes emit a 16-byte constant value as a DWARF
location expression that pushes an implicit value. */
@@ -13199,10 +13379,11 @@ get_mpz (struct dwarf2_cu *cu, gdb_mpz *value, struct attribute *attr)
? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE,
true);
}
- else if (attr->form_is_strictly_unsigned ())
- *value = gdb_mpz (attr->as_unsigned ());
else
- *value = gdb_mpz (attr->signed_constant ().value_or (1));
+ {
+ /* Rational constants for Ada are always unsigned. */
+ *value = gdb_mpz (attr->unsigned_constant ().value_or (1));
+ }
}
/* Assuming DIE is a rational DW_TAG_constant, read the DIE's
@@ -13231,8 +13412,8 @@ get_dwarf2_rational_constant (struct die_info *die, struct dwarf2_cu *cu,
if (num_attr == nullptr || denom_attr == nullptr)
return;
- get_mpz (cu, numerator, num_attr);
- get_mpz (cu, denominator, denom_attr);
+ get_mpz_for_rational (cu, numerator, num_attr);
+ get_mpz_for_rational (cu, denominator, denom_attr);
}
/* Same as get_dwarf2_rational_constant, but extracting an unsigned
@@ -13288,7 +13469,7 @@ ada_get_gnat_encoded_number (const char *encoding, int &k, gdb_mpz *result)
{
/* The next character should be an underscore ('_') followed
by a digit. */
- if (encoding[k] != '_' || !isdigit (encoding[k + 1]))
+ if (encoding[k] != '_' || !c_isdigit (encoding[k + 1]))
return false;
/* Skip the underscore. */
@@ -13296,7 +13477,7 @@ ada_get_gnat_encoded_number (const char *encoding, int &k, gdb_mpz *result)
int start = k;
/* Determine the number of digits for our number. */
- while (isdigit (encoding[k]))
+ while (c_isdigit (encoding[k]))
k++;
if (k == start)
return false;
@@ -13924,17 +14105,13 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
case DW_AT_data_member_location:
case DW_AT_data_bit_offset:
{
- LONGEST offset;
-
- if (!handle_member_location (target_die, target_cu, &offset))
+ baton = find_field_create_baton (cu, target_die);
+ if (baton == nullptr)
return 0;
- baton = XOBNEW (obstack, struct dwarf2_property_baton);
baton->property_type = read_type_die (target_die->parent,
- target_cu);
- baton->offset_info.offset = offset;
- baton->offset_info.type = die_type (target_die, target_cu);
- prop->set_addr_offset (baton);
+ target_cu);
+ prop->set_field (baton);
break;
}
}
@@ -14416,21 +14593,22 @@ cooked_index_functions::find_compunit_symtab_by_address
}
bool
-cooked_index_functions::expand_symtabs_matching
+cooked_index_functions::search
(objfile *objfile,
- expand_symtabs_file_matcher file_matcher,
+ search_symtabs_file_matcher file_matcher,
const lookup_name_info *lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
+ search_symtabs_symbol_matcher symbol_matcher,
+ search_symtabs_expansion_listener listener,
block_search_flags search_flags,
domain_search_flags domain,
- expand_symtabs_lang_matcher lang_matcher)
+ search_symtabs_lang_matcher lang_matcher)
{
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
cooked_index *table = wait (objfile, true);
- dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
+ auto_bool_vector cus_to_skip;
+ dw_search_file_matcher (per_objfile, cus_to_skip, file_matcher);
/* This invariant is documented in quick-functions.h. */
gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
@@ -14440,10 +14618,8 @@ cooked_index_functions::expand_symtabs_matching
{
QUIT;
- if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
- file_matcher,
- expansion_notify,
- lang_matcher))
+ if (!dw2_search_one (per_cu, per_objfile, cus_to_skip, file_matcher,
+ listener, lang_matcher))
return false;
}
return true;
@@ -14518,13 +14694,8 @@ cooked_index_functions::expand_symtabs_matching
{
QUIT;
- /* No need to consider symbols from expanded CUs. */
- if (per_objfile->symtab_set_p (entry->per_cu))
- continue;
-
- /* If file-matching was done, we don't need to consider
- symbols from unmarked CUs. */
- if (file_matcher != nullptr && !entry->per_cu->mark)
+ /* We don't need to consider symbols from some CUs. */
+ if (cus_to_skip.is_set (entry->per_cu->index))
continue;
/* See if the symbol matches the type filter. */
@@ -14541,13 +14712,26 @@ cooked_index_functions::expand_symtabs_matching
continue;
}
+ /* This is a bit of a hack to support .gdb_index. Since
+ .gdb_index does not record languages, and since we want
+ to know the language to avoid excessive CU expansion due
+ to false matches, if we see a symbol with an unknown
+ language we find the CU's language. Only the .gdb_index
+ reader creates such symbols. */
+ enum language entry_lang = entry->lang;
+ if (entry_lang == language_unknown)
+ {
+ entry->per_cu->ensure_lang (per_objfile);
+ entry_lang = entry->per_cu->lang ();
+ }
+
/* We've found the base name of the symbol; now walk its
parentage chain, ensuring that each component
matches. */
bool found = true;
const cooked_index_entry *parent = entry->get_parent ();
- const language_defn *lang_def = language_def (entry->lang);
+ const language_defn *lang_def = language_def (entry_lang);
for (int i = name_vec.size () - 1; i > 0; --i)
{
/* If we ran out of entries, or if this segment doesn't
@@ -14557,17 +14741,15 @@ cooked_index_functions::expand_symtabs_matching
found = false;
break;
}
- if (parent->lang != language_unknown)
+
+ symbol_name_matcher_ftype *name_matcher
+ = (lang_def->get_symbol_name_matcher
+ (segment_lookup_names[i-1]));
+ if (!name_matcher (parent->canonical,
+ segment_lookup_names[i-1], nullptr))
{
- symbol_name_matcher_ftype *name_matcher
- = lang_def->get_symbol_name_matcher
- (segment_lookup_names[i-1]);
- if (!name_matcher (parent->canonical,
- segment_lookup_names[i-1], nullptr))
- {
- found = false;
- break;
- }
+ found = false;
+ break;
}
parent = parent->get_parent ();
@@ -14590,27 +14772,23 @@ cooked_index_functions::expand_symtabs_matching
seems like the loop above could just examine every
element of the name, avoiding the need to check here; but
this is hard. See PR symtab/32733. */
- if (symbol_matcher != nullptr || entry->lang != language_unknown)
+ auto_obstack temp_storage;
+ const char *full_name = entry->full_name (&temp_storage,
+ FOR_ADA_LINKAGE_NAME);
+ if (symbol_matcher == nullptr)
{
- auto_obstack temp_storage;
- const char *full_name = entry->full_name (&temp_storage,
- FOR_ADA_LINKAGE_NAME);
- if (symbol_matcher == nullptr)
- {
- symbol_name_matcher_ftype *name_matcher
- = (lang_def->get_symbol_name_matcher
- (lookup_name_without_params));
- if (!name_matcher (full_name, lookup_name_without_params,
- nullptr))
- continue;
- }
- else if (!symbol_matcher (full_name))
+ symbol_name_matcher_ftype *name_matcher
+ = (lang_def->get_symbol_name_matcher
+ (lookup_name_without_params));
+ if (!name_matcher (full_name, lookup_name_without_params,
+ nullptr))
continue;
}
+ else if (!symbol_matcher (full_name))
+ continue;
- if (!dw2_expand_symtabs_matching_one (entry->per_cu, per_objfile,
- file_matcher,
- expansion_notify, nullptr))
+ if (!dw2_search_one (entry->per_cu, per_objfile, cus_to_skip,
+ file_matcher, listener, nullptr))
return false;
}
}
@@ -15333,9 +15511,16 @@ read_str_index (struct dwarf2_cu *cu,
" in CU at offset %s [in module %s]"),
form_name, str_section->get_name (),
sect_offset_str (cu->header.sect_off), objf_name);
- info_ptr = (str_offsets_section->buffer
- + str_offsets_base
- + str_index * offset_size);
+
+ ULONGEST str_offsets_offset = str_offsets_base + str_index * offset_size;
+ if (str_offsets_offset >= str_offsets_section->size)
+ error (_(DWARF_ERROR_PREFIX
+ "Offset from %s pointing outside of %s section in CU at offset %s"
+ " [in module %s]"),
+ form_name, str_offsets_section->get_name (),
+ sect_offset_str (cu->header.sect_off), objf_name);
+ info_ptr = str_offsets_section->buffer + str_offsets_offset;
+
if (offset_size == 4)
str_offset = bfd_get_32 (abfd, info_ptr);
else
@@ -15648,9 +15833,9 @@ die_specification (struct die_info *die, struct dwarf2_cu **spec_cu)
return follow_die_ref (die, spec_attr, spec_cu);
}
-/* A convenience function to find the proper .debug_line section for a CU. */
+/* See dwarf2/read.h. */
-static struct dwarf2_section_info *
+struct dwarf2_section_info *
get_debug_line_section (struct dwarf2_cu *cu)
{
struct dwarf2_section_info *section;
@@ -15701,808 +15886,9 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu,
comp_dir);
}
-/* Subroutine of dwarf_decode_lines to simplify it.
- Return the file name for the given file_entry.
- CU_INFO describes the CU's DW_AT_name and DW_AT_comp_dir.
- If space for the result is malloc'd, *NAME_HOLDER will be set.
- Returns NULL if FILE_INDEX should be ignored, i.e., it is
- equivalent to CU_INFO. */
-
-static const char *
-compute_include_file_name (const struct line_header *lh, const file_entry &fe,
- const file_and_directory &cu_info,
- std::string &name_holder)
-{
- const char *include_name = fe.name;
- const char *include_name_to_compare = include_name;
-
- const char *dir_name = fe.include_dir (lh);
-
- std::string hold_compare;
- if (!IS_ABSOLUTE_PATH (include_name)
- && (dir_name != nullptr || cu_info.get_comp_dir () != nullptr))
- {
- /* Avoid creating a duplicate name for CU_INFO.
- We do this by comparing INCLUDE_NAME and CU_INFO.
- Before we do the comparison, however, we need to account
- for DIR_NAME and COMP_DIR.
- First prepend dir_name (if non-NULL). If we still don't
- have an absolute path prepend comp_dir (if non-NULL).
- However, the directory we record in the include-file's
- psymtab does not contain COMP_DIR (to match the
- corresponding symtab(s)).
-
- Example:
-
- bash$ cd /tmp
- bash$ gcc -g ./hello.c
- include_name = "hello.c"
- dir_name = "."
- DW_AT_comp_dir = comp_dir = "/tmp"
- DW_AT_name = "./hello.c"
-
- */
-
- if (dir_name != NULL)
- {
- name_holder = path_join (dir_name, include_name);
- include_name = name_holder.c_str ();
- include_name_to_compare = include_name;
- }
- if (!IS_ABSOLUTE_PATH (include_name)
- && cu_info.get_comp_dir () != nullptr)
- {
- hold_compare = path_join (cu_info.get_comp_dir (), include_name);
- include_name_to_compare = hold_compare.c_str ();
- }
- }
-
- std::string copied_name;
- const char *cu_filename = cu_info.get_name ();
- if (!IS_ABSOLUTE_PATH (cu_filename) && cu_info.get_comp_dir () != nullptr)
- {
- copied_name = path_join (cu_info.get_comp_dir (), cu_filename);
- cu_filename = copied_name.c_str ();
- }
-
- if (FILENAME_CMP (include_name_to_compare, cu_filename) == 0)
- return nullptr;
- return include_name;
-}
-
-/* State machine to track the state of the line number program. */
-
-class lnp_state_machine
-{
-public:
- /* Initialize a machine state for the start of a line number
- program. */
- lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, line_header *lh);
-
- file_entry *current_file ()
- {
- /* lh->file_names is 0-based, but the file name numbers in the
- statement program are 1-based. */
- return m_line_header->file_name_at (m_file);
- }
-
- /* Record the line in the state machine. END_SEQUENCE is true if
- we're processing the end of a sequence. */
- void record_line (bool end_sequence);
-
- /* Check ADDRESS is -1, -2, or zero and less than UNRELOCATED_LOWPC, and if
- true nop-out rest of the lines in this sequence. */
- void check_line_address (struct dwarf2_cu *cu,
- const gdb_byte *line_ptr,
- unrelocated_addr unrelocated_lowpc,
- unrelocated_addr address);
-
- void handle_set_discriminator (unsigned int discriminator)
- {
- m_discriminator = discriminator;
- m_line_has_non_zero_discriminator |= discriminator != 0;
- }
-
- /* Handle DW_LNE_set_address. */
- void handle_set_address (unrelocated_addr address)
- {
- m_op_index = 0;
- m_address
- = (unrelocated_addr) gdbarch_adjust_dwarf2_line (m_gdbarch,
- (CORE_ADDR) address,
- false);
- }
-
- /* Handle DW_LNS_advance_pc. */
- void handle_advance_pc (CORE_ADDR adjust);
-
- /* Handle a special opcode. */
- void handle_special_opcode (unsigned char op_code);
-
- /* Handle DW_LNS_advance_line. */
- void handle_advance_line (int line_delta)
- {
- advance_line (line_delta);
- }
-
- /* Handle DW_LNS_set_file. */
- void handle_set_file (file_name_index file);
-
- /* Handle DW_LNS_negate_stmt. */
- void handle_negate_stmt ()
- {
- m_flags ^= LEF_IS_STMT;
- }
-
- /* Handle DW_LNS_const_add_pc. */
- void handle_const_add_pc ();
-
- /* Handle DW_LNS_fixed_advance_pc. */
- void handle_fixed_advance_pc (CORE_ADDR addr_adj)
- {
- addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
- m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
- m_op_index = 0;
- }
-
- /* Handle DW_LNS_copy. */
- void handle_copy ()
- {
- record_line (false);
- m_discriminator = 0;
- m_flags &= ~LEF_PROLOGUE_END;
- m_flags &= ~LEF_EPILOGUE_BEGIN;
- }
-
- /* Handle DW_LNE_end_sequence. */
- void handle_end_sequence ()
- {
- m_currently_recording_lines = true;
- }
-
- /* Handle DW_LNS_set_prologue_end. */
- void handle_set_prologue_end ()
- {
- m_flags |= LEF_PROLOGUE_END;
- }
-
- void handle_set_epilogue_begin ()
- {
- m_flags |= LEF_EPILOGUE_BEGIN;
- }
-
-private:
- /* Advance the line by LINE_DELTA. */
- void advance_line (int line_delta)
- {
- m_line += line_delta;
-
- if (line_delta != 0)
- m_line_has_non_zero_discriminator = m_discriminator != 0;
- }
-
- struct dwarf2_cu *m_cu;
-
- gdbarch *m_gdbarch;
-
- /* The line number header. */
- line_header *m_line_header;
-
- /* These are part of the standard DWARF line number state machine,
- and initialized according to the DWARF spec. */
-
- unsigned char m_op_index = 0;
- /* The line table index of the current file. */
- file_name_index m_file = 1;
- unsigned int m_line = 1;
-
- /* These are initialized in the constructor. */
-
- unrelocated_addr m_address;
- linetable_entry_flags m_flags;
- unsigned int m_discriminator = 0;
-
- /* Additional bits of state we need to track. */
-
- /* The last file a line number was recorded for. */
- struct subfile *m_last_subfile = NULL;
-
- /* The address of the last line entry. */
- unrelocated_addr m_last_address;
-
- /* Set to true when a previous line at the same address (using
- m_last_address) had LEF_IS_STMT set in m_flags. This is reset to false
- when a line entry at a new address (m_address different to
- m_last_address) is processed. */
- bool m_stmt_at_address = false;
-
- /* When true, record the lines we decode. */
- bool m_currently_recording_lines = true;
-
- /* The last line number that was recorded, used to coalesce
- consecutive entries for the same line. This can happen, for
- example, when discriminators are present. PR 17276. */
- unsigned int m_last_line = 0;
- bool m_line_has_non_zero_discriminator = false;
-};
-
-void
-lnp_state_machine::handle_advance_pc (CORE_ADDR adjust)
-{
- CORE_ADDR addr_adj = (((m_op_index + adjust)
- / m_line_header->maximum_ops_per_instruction)
- * m_line_header->minimum_instruction_length);
- addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
- m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
- m_op_index = ((m_op_index + adjust)
- % m_line_header->maximum_ops_per_instruction);
-}
-
-void
-lnp_state_machine::handle_special_opcode (unsigned char op_code)
-{
- unsigned char adj_opcode = op_code - m_line_header->opcode_base;
- unsigned char adj_opcode_d = adj_opcode / m_line_header->line_range;
- unsigned char adj_opcode_r = adj_opcode % m_line_header->line_range;
- CORE_ADDR addr_adj = (((m_op_index + adj_opcode_d)
- / m_line_header->maximum_ops_per_instruction)
- * m_line_header->minimum_instruction_length);
- addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
- m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
- m_op_index = ((m_op_index + adj_opcode_d)
- % m_line_header->maximum_ops_per_instruction);
-
- int line_delta = m_line_header->line_base + adj_opcode_r;
- advance_line (line_delta);
- record_line (false);
- m_discriminator = 0;
- m_flags &= ~LEF_PROLOGUE_END;
- m_flags &= ~LEF_EPILOGUE_BEGIN;
-}
-
-void
-lnp_state_machine::handle_set_file (file_name_index file)
-{
- m_file = file;
-
- const file_entry *fe = current_file ();
- if (fe == NULL)
- dwarf2_debug_line_missing_file_complaint ();
- else
- {
- m_line_has_non_zero_discriminator = m_discriminator != 0;
- dwarf2_start_subfile (m_cu, *fe, *m_line_header);
- }
-}
-
-void
-lnp_state_machine::handle_const_add_pc ()
-{
- CORE_ADDR adjust
- = (255 - m_line_header->opcode_base) / m_line_header->line_range;
-
- CORE_ADDR addr_adj
- = (((m_op_index + adjust)
- / m_line_header->maximum_ops_per_instruction)
- * m_line_header->minimum_instruction_length);
-
- addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
- m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
- m_op_index = ((m_op_index + adjust)
- % m_line_header->maximum_ops_per_instruction);
-}
-
-/* Return non-zero if we should add LINE to the line number table.
- LINE is the line to add, LAST_LINE is the last line that was added,
- LAST_SUBFILE is the subfile for LAST_LINE.
- LINE_HAS_NON_ZERO_DISCRIMINATOR is non-zero if LINE has ever
- had a non-zero discriminator.
-
- We have to be careful in the presence of discriminators.
- E.g., for this line:
-
- for (i = 0; i < 100000; i++);
-
- clang can emit four line number entries for that one line,
- each with a different discriminator.
- See gdb.dwarf2/dw2-single-line-discriminators.exp for an example.
-
- However, we want gdb to coalesce all four entries into one.
- Otherwise the user could stepi into the middle of the line and
- gdb would get confused about whether the pc really was in the
- middle of the line.
-
- Things are further complicated by the fact that two consecutive
- line number entries for the same line is a heuristic used by gcc
- to denote the end of the prologue. So we can't just discard duplicate
- entries, we have to be selective about it. The heuristic we use is
- that we only collapse consecutive entries for the same line if at least
- one of those entries has a non-zero discriminator. PR 17276.
-
- Note: Addresses in the line number state machine can never go backwards
- within one sequence, thus this coalescing is ok. */
-
-static int
-dwarf_record_line_p (struct dwarf2_cu *cu,
- unsigned int line, unsigned int last_line,
- int line_has_non_zero_discriminator,
- struct subfile *last_subfile)
-{
- if (cu->get_builder ()->get_current_subfile () != last_subfile)
- return 1;
- if (line != last_line)
- return 1;
- /* Same line for the same file that we've seen already.
- As a last check, for pr 17276, only record the line if the line
- has never had a non-zero discriminator. */
- if (!line_has_non_zero_discriminator)
- return 1;
- return 0;
-}
-
-/* Use the CU's builder to record line number LINE beginning at
- address ADDRESS in the line table of subfile SUBFILE. */
-
-static void
-dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
- unsigned int line, unrelocated_addr address,
- linetable_entry_flags flags,
- struct dwarf2_cu *cu)
-{
- unrelocated_addr addr
- = unrelocated_addr (gdbarch_addr_bits_remove (gdbarch,
- (CORE_ADDR) address));
-
- if (cu != nullptr)
- {
- if (dwarf_line_debug)
- gdb_printf (gdb_stdlog, "Recording line %u, file %s, address %s\n",
- line, lbasename (subfile->name.c_str ()),
- paddress (gdbarch, (CORE_ADDR) address));
-
- cu->get_builder ()->record_line (subfile, line, addr, flags);
- }
-}
-
-/* Subroutine of dwarf_decode_lines_1 to simplify it.
- Mark the end of a set of line number records.
- The arguments are the same as for dwarf_record_line_1.
- If SUBFILE is NULL the request is ignored. */
-
-static void
-dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
- unrelocated_addr address, struct dwarf2_cu *cu)
-{
- if (subfile == NULL)
- return;
-
- if (dwarf_line_debug)
- {
- gdb_printf (gdb_stdlog,
- "Finishing current line, file %s, address %s\n",
- lbasename (subfile->name.c_str ()),
- paddress (gdbarch, (CORE_ADDR) address));
- }
-
- dwarf_record_line_1 (gdbarch, subfile, 0, address, LEF_IS_STMT, cu);
-}
-
-void
-lnp_state_machine::record_line (bool end_sequence)
-{
- if (dwarf_line_debug)
- {
- gdb_printf (gdb_stdlog,
- "Processing actual line %u: file %u,"
- " address %s, is_stmt %u, prologue_end %u,"
- " epilogue_begin %u, discrim %u%s\n",
- m_line, m_file,
- paddress (m_gdbarch, (CORE_ADDR) m_address),
- (m_flags & LEF_IS_STMT) != 0,
- (m_flags & LEF_PROLOGUE_END) != 0,
- (m_flags & LEF_EPILOGUE_BEGIN) != 0,
- m_discriminator,
- (end_sequence ? "\t(end sequence)" : ""));
- }
-
- file_entry *fe = current_file ();
-
- if (fe == NULL)
- dwarf2_debug_line_missing_file_complaint ();
- /* For now we ignore lines not starting on an instruction boundary.
- But not when processing end_sequence for compatibility with the
- previous version of the code. */
- else if (m_op_index == 0 || end_sequence)
- {
- /* When we switch files we insert an end maker in the first file,
- switch to the second file and add a new line entry. The
- problem is that the end marker inserted in the first file will
- discard any previous line entries at the same address. If the
- line entries in the first file are marked as is-stmt, while
- the new line in the second file is non-stmt, then this means
- the end marker will discard is-stmt lines so we can have a
- non-stmt line. This means that there are less addresses at
- which the user can insert a breakpoint.
-
- To improve this we track the last address in m_last_address,
- and whether we have seen an is-stmt at this address. Then
- when switching files, if we have seen a stmt at the current
- address, and we are switching to create a non-stmt line, then
- discard the new line. */
- bool file_changed
- = m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
- bool ignore_this_line
- = ((file_changed && !end_sequence && m_last_address == m_address
- && ((m_flags & LEF_IS_STMT) == 0)
- && m_stmt_at_address)
- || (!end_sequence && m_line == 0));
-
- if ((file_changed && !ignore_this_line) || end_sequence)
- {
- dwarf_finish_line (m_gdbarch, m_last_subfile, m_address,
- m_currently_recording_lines ? m_cu : nullptr);
- }
-
- if (!end_sequence && !ignore_this_line)
- {
- linetable_entry_flags lte_flags = m_flags;
- if (m_cu->producer_is_codewarrior ())
- lte_flags |= LEF_IS_STMT;
-
- if (dwarf_record_line_p (m_cu, m_line, m_last_line,
- m_line_has_non_zero_discriminator,
- m_last_subfile))
- {
- buildsym_compunit *builder = m_cu->get_builder ();
- dwarf_record_line_1 (m_gdbarch,
- builder->get_current_subfile (),
- m_line, m_address, lte_flags,
- m_currently_recording_lines ? m_cu : nullptr);
-
- m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
- m_last_line = m_line;
- }
- }
- }
-
- /* Track whether we have seen any IS_STMT true at m_address in case we
- have multiple line table entries all at m_address. */
- if (m_last_address != m_address)
- {
- m_stmt_at_address = false;
- m_last_address = m_address;
- }
- m_stmt_at_address |= (m_flags & LEF_IS_STMT) != 0;
-}
-
-lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
- line_header *lh)
- : m_cu (cu),
- m_gdbarch (arch),
- m_line_header (lh),
- /* Call `gdbarch_adjust_dwarf2_line' on the initial 0 address as
- if there was a line entry for it so that the backend has a
- chance to adjust it and also record it in case it needs it.
- This is currently used by MIPS code,
- cf. `mips_adjust_dwarf2_line'. */
- m_address ((unrelocated_addr) gdbarch_adjust_dwarf2_line (arch, 0, 0)),
- m_flags (lh->default_is_stmt ? LEF_IS_STMT : (linetable_entry_flags) 0),
- m_last_address (m_address)
-{
-}
+/* See dwarf2/read.h. */
void
-lnp_state_machine::check_line_address (struct dwarf2_cu *cu,
- const gdb_byte *line_ptr,
- unrelocated_addr unrelocated_lowpc,
- unrelocated_addr address)
-{
- /* Linkers resolve a symbolic relocation referencing a GC'd function to 0,
- -1 or -2 (-2 is used by certain lld versions, see
- https://github.com/llvm/llvm-project/commit/e618ccbf431f6730edb6d1467a127c3a52fd57f7).
- If ADDRESS is 0, ignoring the opcode will err if the text section is
- located at 0x0. In this case, additionally check that if
- ADDRESS < UNRELOCATED_LOWPC. */
-
- if ((address == (unrelocated_addr) 0 && address < unrelocated_lowpc)
- || address == (unrelocated_addr) -1
- || address == (unrelocated_addr) -2)
- {
- /* This line table is for a function which has been
- GCd by the linker. Ignore it. PR gdb/12528 */
-
- struct objfile *objfile = cu->per_objfile->objfile;
- long line_offset = line_ptr - get_debug_line_section (cu)->buffer;
-
- complaint (_(".debug_line address at offset 0x%lx is 0 [in module %s]"),
- line_offset, objfile_name (objfile));
- m_currently_recording_lines = false;
- /* Note: m_currently_recording_lines is left as false until we see
- DW_LNE_end_sequence. */
- }
-}
-
-/* Subroutine of dwarf_decode_lines to simplify it.
- Process the line number information in LH. */
-
-static void
-dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
- unrelocated_addr lowpc)
-{
- const gdb_byte *line_ptr, *extended_end;
- const gdb_byte *line_end;
- unsigned int bytes_read, extended_len;
- unsigned char op_code, extended_op;
- struct objfile *objfile = cu->per_objfile->objfile;
- bfd *abfd = objfile->obfd.get ();
- struct gdbarch *gdbarch = objfile->arch ();
-
- line_ptr = lh->statement_program_start;
- line_end = lh->statement_program_end;
-
- /* Read the statement sequences until there's nothing left. */
- while (line_ptr < line_end)
- {
- /* The DWARF line number program state machine. Reset the state
- machine at the start of each sequence. */
- lnp_state_machine state_machine (cu, gdbarch, lh);
- bool end_sequence = false;
-
- /* Start a subfile for the current file of the state
- machine. */
- const file_entry *fe = state_machine.current_file ();
-
- if (fe != NULL)
- dwarf2_start_subfile (cu, *fe, *lh);
-
- /* Decode the table. */
- while (line_ptr < line_end && !end_sequence)
- {
- op_code = read_1_byte (abfd, line_ptr);
- line_ptr += 1;
-
- if (op_code >= lh->opcode_base)
- {
- /* Special opcode. */
- state_machine.handle_special_opcode (op_code);
- }
- else switch (op_code)
- {
- case DW_LNS_extended_op:
- extended_len = read_unsigned_leb128 (abfd, line_ptr,
- &bytes_read);
- line_ptr += bytes_read;
- extended_end = line_ptr + extended_len;
- extended_op = read_1_byte (abfd, line_ptr);
- line_ptr += 1;
- if (DW_LNE_lo_user <= extended_op
- && extended_op <= DW_LNE_hi_user)
- {
- /* Vendor extension, ignore. */
- line_ptr = extended_end;
- break;
- }
- switch (extended_op)
- {
- case DW_LNE_end_sequence:
- state_machine.handle_end_sequence ();
- end_sequence = true;
- break;
- case DW_LNE_set_address:
- {
- unrelocated_addr address
- = cu->header.read_address (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
-
- state_machine.check_line_address (cu, line_ptr, lowpc,
- address);
- state_machine.handle_set_address (address);
- }
- break;
- case DW_LNE_define_file:
- {
- const char *cur_file;
- unsigned int mod_time, length;
- dir_index dindex;
-
- cur_file = read_direct_string (abfd, line_ptr,
- &bytes_read);
- line_ptr += bytes_read;
- dindex = (dir_index)
- read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- mod_time =
- read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- length =
- read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- lh->add_file_name (cur_file, dindex, mod_time, length);
- }
- break;
- case DW_LNE_set_discriminator:
- {
- /* The discriminator is not interesting to the
- debugger; just ignore it. We still need to
- check its value though:
- if there are consecutive entries for the same
- (non-prologue) line we want to coalesce them.
- PR 17276. */
- unsigned int discr
- = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
-
- state_machine.handle_set_discriminator (discr);
- }
- break;
- default:
- complaint (_("mangled .debug_line section"));
- return;
- }
- /* Make sure that we parsed the extended op correctly. If e.g.
- we expected a different address size than the producer used,
- we may have read the wrong number of bytes. */
- if (line_ptr != extended_end)
- {
- complaint (_("mangled .debug_line section"));
- return;
- }
- break;
- case DW_LNS_copy:
- state_machine.handle_copy ();
- break;
- case DW_LNS_advance_pc:
- {
- CORE_ADDR adjust
- = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
-
- state_machine.handle_advance_pc (adjust);
- }
- break;
- case DW_LNS_advance_line:
- {
- int line_delta
- = read_signed_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
-
- state_machine.handle_advance_line (line_delta);
- }
- break;
- case DW_LNS_set_file:
- {
- file_name_index file
- = (file_name_index) read_unsigned_leb128 (abfd, line_ptr,
- &bytes_read);
- line_ptr += bytes_read;
-
- state_machine.handle_set_file (file);
- }
- break;
- case DW_LNS_set_column:
- (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- break;
- case DW_LNS_negate_stmt:
- state_machine.handle_negate_stmt ();
- break;
- case DW_LNS_set_basic_block:
- break;
- /* Add to the address register of the state machine the
- address increment value corresponding to special opcode
- 255. I.e., this value is scaled by the minimum
- instruction length since special opcode 255 would have
- scaled the increment. */
- case DW_LNS_const_add_pc:
- state_machine.handle_const_add_pc ();
- break;
- case DW_LNS_fixed_advance_pc:
- {
- CORE_ADDR addr_adj = read_2_bytes (abfd, line_ptr);
- line_ptr += 2;
-
- state_machine.handle_fixed_advance_pc (addr_adj);
- }
- break;
- case DW_LNS_set_prologue_end:
- state_machine.handle_set_prologue_end ();
- break;
- case DW_LNS_set_epilogue_begin:
- state_machine.handle_set_epilogue_begin ();
- break;
- default:
- {
- /* Unknown standard opcode, ignore it. */
- int i;
-
- for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++)
- {
- (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- }
- }
- }
- }
-
- if (!end_sequence)
- dwarf2_debug_line_missing_end_sequence_complaint ();
-
- /* We got a DW_LNE_end_sequence (or we ran off the end of the buffer,
- in which case we still finish recording the last line). */
- state_machine.record_line (true);
- }
-}
-
-/* Decode the Line Number Program (LNP) for the given line_header
- structure and CU. The actual information extracted and the type
- of structures created from the LNP depends on the value of PST.
-
- FND holds the CU file name and directory, if known.
- It is used for relative paths in the line table.
-
- NOTE: It is important that psymtabs have the same file name (via
- strcmp) as the corresponding symtab. Since the directory is not
- used in the name of the symtab we don't use it in the name of the
- psymtabs we create. E.g. expand_line_sal requires this when
- finding psymtabs to expand. A good testcase for this is
- mb-inline.exp.
-
- LOWPC is the lowest address in CU (or 0 if not known).
-
- Boolean DECODE_MAPPING specifies we need to fully decode .debug_line
- for its PC<->lines mapping information. Otherwise only the filename
- table is read in. */
-
-static void
-dwarf_decode_lines (struct line_header *lh, struct dwarf2_cu *cu,
- unrelocated_addr lowpc, int decode_mapping)
-{
- if (decode_mapping)
- dwarf_decode_lines_1 (lh, cu, lowpc);
-
- /* Make sure a symtab is created for every file, even files
- which contain only variables (i.e. no code with associated
- line numbers). */
- buildsym_compunit *builder = cu->get_builder ();
- struct compunit_symtab *cust = builder->get_compunit_symtab ();
-
- for (auto &fe : lh->file_names ())
- {
- dwarf2_start_subfile (cu, fe, *lh);
- subfile *sf = builder->get_current_subfile ();
-
- if (sf->symtab == nullptr)
- sf->symtab = allocate_symtab (cust, sf->name.c_str (),
- sf->name_for_id.c_str ());
-
- fe.symtab = sf->symtab;
- }
-}
-
-/* Start a subfile for DWARF. FILENAME is the name of the file and
- DIRNAME the name of the source directory which contains FILENAME
- or NULL if not known.
- This routine tries to keep line numbers from identical absolute and
- relative file names in a common subfile.
-
- Using the `list' example from the GDB testsuite, which resides in
- /srcdir and compiling it with Irix6.2 cc in /compdir using a filename
- of /srcdir/list0.c yields the following debugging information for list0.c:
-
- DW_AT_name: /srcdir/list0.c
- DW_AT_comp_dir: /compdir
- files.files[0].name: list0.h
- files.files[0].dir: /srcdir
- files.files[1].name: list0.c
- files.files[1].dir: /srcdir
-
- The line number information for list0.c has to end up in a single
- subfile, so that `break /srcdir/list0.c:1' works as expected.
- start_subfile will ensure that this happens provided that we pass the
- concatenation of files.files[1].dir and files.files[1].name as the
- subfile's name. */
-
-static void
dwarf2_start_subfile (dwarf2_cu *cu, const file_entry &fe,
const line_header &lh)
{
@@ -16548,7 +15934,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
variable has been optimized away. */
if (attr->form_is_block () && attr->as_block ()->size == 0)
{
- sym->set_aclass_index (LOC_OPTIMIZED_OUT);
+ sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
return;
}
@@ -16578,7 +15964,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
else
tem = read_addr_index_from_leb128 (cu, block->data + 1, &dummy);
sym->set_value_address ((CORE_ADDR) tem);
- sym->set_aclass_index (LOC_STATIC);
+ sym->set_loc_class_index (LOC_STATIC);
fixup_symbol_section (sym, objfile);
sym->set_value_address
(sym->value_address ()
@@ -16615,20 +16001,20 @@ add_ada_export_symbol (struct symbol *orig, const char *new_name,
= new (&cu->per_objfile->objfile->objfile_obstack) symbol (*orig);
copy->set_linkage_name (new_name);
SYMBOL_LOCATION_BATON (copy) = (void *) orig_name;
- copy->set_aclass_index (copy->aclass () == LOC_BLOCK
+ copy->set_loc_class_index (copy->loc_class () == LOC_BLOCK
? ada_block_index
: ada_imported_index);
add_symbol_to_list (copy, list_to_add);
}
-/* A helper function that decides if a given symbol is an Ada Pragma
- Import or Pragma Export. */
+/* See read.h. */
-static bool
+bool
is_ada_import_or_export (dwarf2_cu *cu, const char *name,
const char *linkagename)
{
return (cu->lang () == language_ada
+ && name != nullptr
&& linkagename != nullptr
&& !streq (name, linkagename)
/* The following exclusions are necessary because symbols
@@ -16715,7 +16101,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
/* Default assumptions.
Use the passed type or decode it from the die. */
sym->set_domain (UNDEF_DOMAIN);
- sym->set_aclass_index (LOC_OPTIMIZED_OUT);
+ sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
if (type != NULL)
sym->set_type (type);
else
@@ -16765,10 +16151,10 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
CORE_ADDR addr = per_objfile->relocate (attr->as_address ());
sym->set_section_index (SECT_OFF_TEXT (objfile));
sym->set_value_address (addr);
- sym->set_aclass_index (LOC_LABEL);
+ sym->set_loc_class_index (LOC_LABEL);
}
else
- sym->set_aclass_index (LOC_OPTIMIZED_OUT);
+ sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
sym->set_type (builtin_type (objfile)->builtin_core_addr);
sym->set_domain (LABEL_DOMAIN);
list_to_add = cu->list_in_scope;
@@ -16777,7 +16163,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
/* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
finish_block. */
sym->set_domain (FUNCTION_DOMAIN);
- sym->set_aclass_index (LOC_BLOCK);
+ sym->set_loc_class_index (LOC_BLOCK);
/* DW_TAG_entry_point provides an additional entry_point to an
existing sub_program. Therefore, we inherit the "external"
attribute from the sub_program to which the entry_point
@@ -16792,7 +16178,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
/* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
finish_block. */
sym->set_domain (FUNCTION_DOMAIN);
- sym->set_aclass_index (LOC_BLOCK);
+ sym->set_loc_class_index (LOC_BLOCK);
attr2 = dwarf2_attr (die, DW_AT_external, cu);
if ((attr2 != nullptr && attr2->as_boolean ())
|| cu->lang () == language_ada
@@ -16821,7 +16207,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
/* For Import, create a symbol using the source
name, and have it refer to the linkage name. */
SYMBOL_LOCATION_BATON (sym) = (void *) linkagename;
- sym->set_aclass_index (ada_block_index);
+ sym->set_loc_class_index (ada_block_index);
}
else
{
@@ -16837,7 +16223,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
/* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
finish_block. */
sym->set_domain (FUNCTION_DOMAIN);
- sym->set_aclass_index (LOC_BLOCK);
+ sym->set_loc_class_index (LOC_BLOCK);
sym->set_is_inlined (1);
list_to_add = cu->list_in_scope;
break;
@@ -16889,7 +16275,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
&& die->parent->tag == DW_TAG_common_block)
attr2 = NULL;
- if (sym->aclass () == LOC_STATIC
+ if (sym->loc_class () == LOC_STATIC
&& sym->value_address () == 0
&& !per_objfile->per_bfd->has_section_at_zero)
{
@@ -16900,7 +16286,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
}
else if (attr2 != nullptr && attr2->as_boolean ())
{
- if (sym->aclass () == LOC_STATIC
+ if (sym->loc_class () == LOC_STATIC
&& (objfile->flags & OBJF_MAINLINE) == 0
&& per_objfile->per_bfd->can_copy)
{
@@ -16969,7 +16355,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
? cu->get_builder ()->get_global_symbols ()
: cu->list_in_scope);
SYMBOL_LOCATION_BATON (sym) = (void *) linkagename;
- sym->set_aclass_index (ada_imported_index);
+ sym->set_loc_class_index (ada_imported_index);
}
else if (attr2 != nullptr && attr2->as_boolean ()
&& dwarf2_attr (die, DW_AT_type, cu) != NULL)
@@ -16982,12 +16368,12 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
? cu->get_builder ()->get_global_symbols ()
: cu->list_in_scope);
- sym->set_aclass_index (LOC_UNRESOLVED);
+ sym->set_loc_class_index (LOC_UNRESOLVED);
}
else if (!die_is_declaration (die, cu))
{
/* Use the default LOC_OPTIMIZED_OUT class. */
- gdb_assert (sym->aclass () == LOC_OPTIMIZED_OUT);
+ gdb_assert (sym->loc_class () == LOC_OPTIMIZED_OUT);
if (!suppress_add)
list_to_add = cu->list_in_scope;
}
@@ -17043,13 +16429,13 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
there's a special hack for C++ in the matching code,
so we don't need to enter a separate typedef for the
tag. */
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_domain (STRUCT_DOMAIN);
}
else
{
/* Other languages don't have a tag namespace. */
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_domain (TYPE_DOMAIN);
}
@@ -17094,7 +16480,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
case DW_TAG_base_type:
case DW_TAG_subrange_type:
case DW_TAG_generic_subrange:
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_domain (TYPE_DOMAIN);
list_to_add = cu->list_in_scope;
break;
@@ -17118,21 +16504,21 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
case DW_TAG_imported_declaration:
case DW_TAG_namespace:
sym->set_domain (TYPE_DOMAIN);
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
list_to_add = cu->get_builder ()->get_global_symbols ();
break;
case DW_TAG_module:
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_domain (MODULE_DOMAIN);
list_to_add = cu->get_builder ()->get_global_symbols ();
break;
case DW_TAG_common_block:
- sym->set_aclass_index (LOC_COMMON_BLOCK);
+ sym->set_loc_class_index (LOC_COMMON_BLOCK);
sym->set_domain (COMMON_BLOCK_DOMAIN);
list_to_add = cu->list_in_scope;
break;
case DW_TAG_namelist:
- sym->set_aclass_index (LOC_STATIC);
+ sym->set_loc_class_index (LOC_STATIC);
sym->set_domain (VAR_DOMAIN);
list_to_add = cu->list_in_scope;
break;
@@ -17165,29 +16551,6 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
return (sym);
}
-/* Given an attr with a DW_FORM_dataN value in host byte order,
- zero-extend it as appropriate for the symbol's type. The DWARF
- standard (v4) is not entirely clear about the meaning of using
- DW_FORM_dataN for a constant with a signed type, where the type is
- wider than the data. The conclusion of a discussion on the DWARF
- list was that this is unspecified. We choose to always zero-extend
- because that is the interpretation long in use by GCC. */
-
-static void
-dwarf2_const_value_data (const struct attribute *attr, LONGEST *value,
- int bits)
-{
- LONGEST l = attr->constant_value (0);
-
- if (bits < sizeof (*value) * 8)
- {
- l &= ((LONGEST) 1 << bits) - 1;
- *value = l;
- }
- else
- *value = l;
-}
-
/* Read a constant value from an attribute. Either set *VALUE, or if
the value does not fit in *VALUE, set *BYTES - either already
allocated on the objfile obstack, or newly allocated on OBSTACK,
@@ -17227,7 +16590,7 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type,
/* Symbols of this form are reasonably rare, so we just
piggyback on the existing location code rather than writing
a new implementation of symbol_computed_ops. */
- *baton = XOBNEW (obstack, struct dwarf2_locexpr_baton);
+ *baton = OBSTACK_ZALLOC (obstack, struct dwarf2_locexpr_baton);
(*baton)->per_objfile = per_objfile;
(*baton)->per_cu = cu->per_cu;
gdb_assert ((*baton)->per_cu);
@@ -17271,25 +16634,13 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type,
converted to host endianness, so we just need to sign- or
zero-extend it as appropriate. */
case DW_FORM_data1:
- dwarf2_const_value_data (attr, value, 8);
- break;
case DW_FORM_data2:
- dwarf2_const_value_data (attr, value, 16);
- break;
case DW_FORM_data4:
- dwarf2_const_value_data (attr, value, 32);
- break;
case DW_FORM_data8:
- dwarf2_const_value_data (attr, value, 64);
- break;
-
case DW_FORM_sdata:
case DW_FORM_implicit_const:
- *value = attr->as_signed ();
- break;
-
case DW_FORM_udata:
- *value = attr->as_unsigned ();
+ *value = attr->confused_constant ().value_or (0);
break;
default:
@@ -17320,17 +16671,17 @@ dwarf2_const_value (const struct attribute *attr, struct symbol *sym,
if (baton != NULL)
{
SYMBOL_LOCATION_BATON (sym) = baton;
- sym->set_aclass_index (dwarf2_locexpr_index);
+ sym->set_loc_class_index (dwarf2_locexpr_index);
}
else if (bytes != NULL)
{
sym->set_value_bytes (bytes);
- sym->set_aclass_index (LOC_CONST_BYTES);
+ sym->set_loc_class_index (LOC_CONST_BYTES);
}
else
{
sym->set_value_longest (value);
- sym->set_aclass_index (LOC_CONST);
+ sym->set_loc_class_index (LOC_CONST);
}
}
@@ -17456,9 +16807,10 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
if (attr->form_is_alt ())
{
+ const auto &section = get_section_for_ref (*attr, cu);
sect_offset sect_off = attr->get_ref_die_offset ();
dwarf2_per_cu *per_cu
- = dwarf2_find_containing_comp_unit (sect_off, 1, per_objfile->per_bfd);
+ = dwarf2_find_containing_unit ({ &section, sect_off }, per_objfile);
this_type = get_die_type_at_offset (sect_off, per_cu, per_objfile);
}
@@ -18159,14 +17511,13 @@ follow_die_ref_or_sig (struct die_info *src_die, const struct attribute *attr,
return die;
}
-/* Follow reference OFFSET.
- On entry *REF_CU is the CU of the source die referencing OFFSET.
+/* Follow reference TARGET.
+ On entry *REF_CU is the CU of the source die referencing TARGET.
On exit *REF_CU is the CU of the result.
- Returns NULL if OFFSET is invalid. */
+ Returns nullptr if TARGET is invalid. */
-static struct die_info *
-follow_die_offset (sect_offset sect_off, int offset_in_dwz,
- struct dwarf2_cu **ref_cu)
+static die_info *
+follow_die_offset (const section_and_offset &target, dwarf2_cu **ref_cu)
{
dwarf2_cu *source_cu = *ref_cu;
dwarf2_cu *target_cu = source_cu;
@@ -18178,23 +17529,23 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
dwarf_read_debug_printf_v ("source CU offset: %s, target offset: %s, "
"source CU contains target offset: %d",
sect_offset_str (source_cu->per_cu->sect_off),
- sect_offset_str (sect_off),
- source_cu->header.offset_in_unit_p (sect_off));
+ sect_offset_str (target.offset),
+ (target.section == &source_cu->section ()
+ && source_cu->header.offset_in_unit_p (target.offset)));
if (source_cu->per_cu->is_debug_types)
{
/* .debug_types CUs cannot reference anything outside their CU.
If they need to, they have to reference a signatured type via
DW_FORM_ref_sig8. */
- if (!source_cu->header.offset_in_unit_p (sect_off))
+ if (!source_cu->header.offset_in_unit_p (target.offset))
return NULL;
}
- else if (offset_in_dwz != source_cu->per_cu->is_dwz
- || !source_cu->header.offset_in_unit_p (sect_off))
+ else if (target.section != &source_cu->section ()
+ || !source_cu->header.offset_in_unit_p (target.offset))
{
dwarf2_per_cu *target_per_cu
- = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
- per_objfile->per_bfd);
+ = dwarf2_find_containing_unit (target, per_objfile);
dwarf_read_debug_printf_v ("target CU offset: %s, "
"target CU DIEs loaded: %d",
@@ -18216,13 +17567,13 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
error (_(DWARF_ERROR_PREFIX
"cannot follow reference to DIE at %s"
" [in module %s]"),
- sect_offset_str (sect_off),
+ sect_offset_str (target.offset),
objfile_name (per_objfile->objfile));
}
*ref_cu = target_cu;
- return target_cu->find_die (sect_off);
+ return target_cu->find_die (target.offset);
}
/* Follow reference attribute ATTR of SRC_DIE.
@@ -18234,8 +17585,7 @@ follow_die_ref (struct die_info *src_die, const struct attribute *attr,
struct dwarf2_cu **ref_cu)
{
sect_offset sect_off = attr->get_ref_die_offset ();
- struct dwarf2_cu *cu = *ref_cu;
- struct die_info *die;
+ struct dwarf2_cu *src_cu = *ref_cu;
if (!attr->form_is_alt () && src_die->sect_off == sect_off)
{
@@ -18243,14 +17593,13 @@ follow_die_ref (struct die_info *src_die, const struct attribute *attr,
return src_die;
}
- die = follow_die_offset (sect_off,
- attr->form_is_alt () || cu->per_cu->is_dwz,
- ref_cu);
- if (!die)
+ const dwarf2_section_info &section = get_section_for_ref (*attr, src_cu);
+ die_info *die = follow_die_offset ({ &section, sect_off }, ref_cu);
+ if (die == nullptr)
error (_(DWARF_ERROR_PREFIX
"Cannot find DIE at %s referenced from DIE at %s [in module %s]"),
sect_offset_str (sect_off), sect_offset_str (src_die->sect_off),
- objfile_name (cu->per_objfile->objfile));
+ objfile_name (src_cu->per_objfile->objfile));
return die;
}
@@ -18263,7 +17612,6 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
gdb::function_view<CORE_ADDR ()> get_frame_pc,
bool resolve_abstract_p)
{
- struct die_info *die;
struct attribute *attr;
struct dwarf2_locexpr_baton retval;
struct objfile *objfile = per_objfile->objfile;
@@ -18281,8 +17629,8 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
sect_offset_str (sect_off), objfile_name (objfile));
}
- die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
- if (!die)
+ die_info *die = follow_die_offset ({ &cu->section (), sect_off }, &cu);
+ if (die == nullptr)
error (_(DWARF_ERROR_PREFIX
"Cannot find DIE at %s referenced [in module %s]"),
sect_offset_str (sect_off), objfile_name (objfile));
@@ -18298,8 +17646,8 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
: per_objfile->per_bfd->abstract_to_concrete[die->sect_off])
{
struct dwarf2_cu *cand_cu = cu;
- struct die_info *cand
- = follow_die_offset (cand_off, per_cu->is_dwz, &cand_cu);
+ die_info *cand
+ = follow_die_offset ({ &cu->section (), cand_off }, &cand_cu);
if (!cand
|| !cand->parent
|| cand->parent->tag != DW_TAG_subprogram)
@@ -18401,7 +17749,6 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
obstack *obstack,
LONGEST *len)
{
- struct die_info *die;
struct attribute *attr;
const gdb_byte *result = NULL;
struct type *type;
@@ -18422,7 +17769,7 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
sect_offset_str (sect_off), objfile_name (objfile));
}
- die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
+ die_info *die = follow_die_offset ({ &cu->section (), sect_off }, &cu);
if (!die)
error (_(DWARF_ERROR_PREFIX
"Cannot find DIE at %s referenced [in module %s]"),
@@ -18481,39 +17828,19 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
symbol's value "represented as it would be on the target
architecture." By the time we get here, it's already been
converted to host endianness, so we just need to sign- or
- zero-extend it as appropriate. */
+ zero-extend it as appropriate.
+
+ Both GCC and LLVM agree that these are always signed, though. */
case DW_FORM_data1:
- type = die_type (die, cu);
- dwarf2_const_value_data (attr, &value, 8);
- result = write_constant_as_bytes (obstack, byte_order, type, value, len);
- break;
case DW_FORM_data2:
- type = die_type (die, cu);
- dwarf2_const_value_data (attr, &value, 16);
- result = write_constant_as_bytes (obstack, byte_order, type, value, len);
- break;
case DW_FORM_data4:
- type = die_type (die, cu);
- dwarf2_const_value_data (attr, &value, 32);
- result = write_constant_as_bytes (obstack, byte_order, type, value, len);
- break;
case DW_FORM_data8:
- type = die_type (die, cu);
- dwarf2_const_value_data (attr, &value, 64);
- result = write_constant_as_bytes (obstack, byte_order, type, value, len);
- break;
-
case DW_FORM_sdata:
case DW_FORM_implicit_const:
- type = die_type (die, cu);
- result = write_constant_as_bytes (obstack, byte_order,
- type, attr->as_signed (), len);
- break;
-
case DW_FORM_udata:
type = die_type (die, cu);
- result = write_constant_as_bytes (obstack, byte_order,
- type, attr->as_unsigned (), len);
+ value = attr->confused_constant ().value_or (0);
+ result = write_constant_as_bytes (obstack, byte_order, type, value, len);
break;
default:
@@ -18532,8 +17859,6 @@ dwarf2_fetch_die_type_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
dwarf2_per_objfile *per_objfile,
const char **var_name)
{
- struct die_info *die;
-
dwarf2_cu *cu = per_objfile->get_cu (per_cu);
if (cu == nullptr)
cu = load_cu (per_cu, per_objfile, false);
@@ -18541,7 +17866,7 @@ dwarf2_fetch_die_type_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
if (cu == nullptr)
return nullptr;
- die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
+ die_info *die = follow_die_offset ({ &cu->section (), sect_off }, &cu);
if (!die)
return NULL;
@@ -18927,7 +18252,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu,
case DW_OP_deref:
/* If we're not the last op, then we definitely can't encode
- this using GDB's address_class enum. This is valid for partial
+ this using GDB's location_class enum. This is valid for partial
global symbols, although the variable's address will be bogus
in the psymtab. */
if (i < size)
@@ -19169,7 +18494,7 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
complaint (_("Location list used without "
"specifying the CU base address."));
- sym->set_aclass_index ((is_block
+ sym->set_loc_class_index ((is_block
? dwarf2_loclist_block_index
: dwarf2_loclist_index));
SYMBOL_LOCATION_BATON (sym) = baton;
@@ -19178,7 +18503,8 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
{
struct dwarf2_locexpr_baton *baton;
- baton = XOBNEW (&objfile->objfile_obstack, struct dwarf2_locexpr_baton);
+ baton = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_locexpr_baton);
baton->per_objfile = per_objfile;
baton->per_cu = cu->per_cu;
gdb_assert (baton->per_cu);
@@ -19201,7 +18527,7 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
baton->size = 0;
}
- sym->set_aclass_index ((is_block
+ sym->set_loc_class_index ((is_block
? dwarf2_locexpr_block_index
: dwarf2_locexpr_index));
SYMBOL_LOCATION_BATON (sym) = baton;
@@ -19290,69 +18616,115 @@ dwarf2_per_cu::ensure_lang (dwarf2_per_objfile *per_objfile)
true, language_minimal, nullptr);
}
-/* A helper function for dwarf2_find_containing_comp_unit that returns
- the index of the result, and that searches a vector. It will
- return a result even if the offset in question does not actually
- occur in any CU. This is separate so that it can be unit
- tested. */
+/* Return the unit from ALL_UNITS that potentially contains TARGET.
-static int
-dwarf2_find_containing_comp_unit
- (sect_offset sect_off,
- unsigned int offset_in_dwz,
- const std::vector<dwarf2_per_cu_up> &all_units)
+ Since the unit lengths may not be known yet, this function doesn't check that
+ TARGET.OFFSET actually falls within the range of the returned unit. The
+ caller is responsible for this.
+
+ If no units possibly match TARGET, return nullptr. */
+
+static dwarf2_per_cu *
+dwarf2_find_containing_unit (const section_and_offset &target,
+ const std::vector<dwarf2_per_cu_up> &all_units)
{
- int low, high;
+ auto it = std::lower_bound (all_units.begin (), all_units.end (), target,
+ [] (const dwarf2_per_cu_up &per_cu,
+ const section_and_offset &key)
+ {
+ return all_units_less_than (*per_cu, key);
+ });
- low = 0;
- high = all_units.size () - 1;
- while (high > low)
+ if (it == all_units.begin ())
{
- int mid = low + (high - low) / 2;
- dwarf2_per_cu *mid_cu = all_units[mid].get ();
-
- if (mid_cu->is_dwz > offset_in_dwz
- || (mid_cu->is_dwz == offset_in_dwz
- && mid_cu->sect_off + mid_cu->length () > sect_off))
- high = mid;
+ /* TARGET falls before the first unit of the first section, or is an
+ exact match with the first. */
+ if ((*it)->section == target.section && (*it)->sect_off == target.offset)
+ return it->get ();
else
- low = mid + 1;
+ return nullptr;
+ }
+
+ if (it != all_units.end ()
+ && (*it)->section == target.section
+ && (*it)->sect_off == target.offset)
+ {
+ /* TARGET is an exact match with the start of *IT, so *IT is what we're
+ looking for. */
+ return it->get ();
}
- gdb_assert (low == high);
- return low;
+
+ /* Otherwise, the match is the one just before, as long as it matches the
+ section we're looking for. */
+ --it;
+
+ if ((*it)->section == target.section)
+ return it->get ();
+
+ return nullptr;
}
/* See read.h. */
dwarf2_per_cu *
-dwarf2_find_containing_comp_unit (sect_offset sect_off,
- unsigned int offset_in_dwz,
- dwarf2_per_bfd *per_bfd)
+dwarf2_find_containing_unit (const section_and_offset &target,
+ dwarf2_per_objfile *per_objfile)
{
- int low = dwarf2_find_containing_comp_unit
- (sect_off, offset_in_dwz, per_bfd->all_units);
- dwarf2_per_cu *this_cu = per_bfd->all_units[low].get ();
-
- if (this_cu->is_dwz != offset_in_dwz || this_cu->sect_off > sect_off)
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+ dwarf2_per_cu *per_cu
+ = dwarf2_find_containing_unit (target, per_bfd->all_units);
+ auto error_out = [&target, per_bfd] ()
{
- if (low == 0 || this_cu->is_dwz != offset_in_dwz)
- error (_(DWARF_ERROR_PREFIX
- "could not find CU containing offset %s [in module %s]"),
- sect_offset_str (sect_off),
- per_bfd->filename ());
+ error (_(DWARF_ERROR_PREFIX
+ "could not find unit containing offset %s [in module %s]"),
+ sect_offset_str (target.offset), per_bfd->filename ());
+ };
- gdb_assert (per_bfd->all_units[low-1]->sect_off
- <= sect_off);
- return per_bfd->all_units[low - 1].get ();
- }
- else
- {
- if (low == per_bfd->all_units.size () - 1
- && sect_off >= this_cu->sect_off + this_cu->length ())
- error (_("invalid dwarf2 offset %s"), sect_offset_str (sect_off));
- gdb_assert (sect_off < this_cu->sect_off + this_cu->length ());
- return this_cu;
- }
+ if (per_cu == nullptr)
+ error_out ();
+
+ gdb_assert (per_cu->section == target.section);
+
+ /* Some producers of dwarf2_per_cu objects (thinking of the .gdb_index reader)
+ do not set the length ahead of time. The length is needed to check if
+ the target is truly within PER_CU's range, so compute it now. Constructing
+ the cutu_reader object has the side-effect of setting PER_CU's length.
+ Even though it should happen too often, it could be replaced with
+ something more lightweight that has the same effect. */
+ if (!per_cu->length_is_set ())
+ cutu_reader (*per_cu, *per_objfile, nullptr, nullptr, false,
+ language_minimal);
+
+ /* Now we can check if the target section offset is within PER_CU's range. */
+ if (target.offset < per_cu->sect_off
+ || target.offset >= per_cu->sect_off + per_cu->length ())
+ error_out ();
+
+ return per_cu;
+}
+
+/* See read.h. */
+
+dwarf2_per_cu *
+dwarf2_find_unit (const section_and_offset &start, dwarf2_per_bfd *per_bfd)
+{
+ auto it = std::lower_bound (per_bfd->all_units.begin (),
+ per_bfd->all_units.end (), start,
+ [] (const dwarf2_per_cu_up &per_cu,
+ const section_and_offset &key)
+ {
+ return all_units_less_than (*per_cu, key);
+ });
+
+ if (it == per_bfd->all_units.end ())
+ return nullptr;
+
+ dwarf2_per_cu *per_cu = it->get ();
+
+ if (per_cu->section != start.section || per_cu->sect_off != start.offset)
+ return nullptr;
+
+ return per_cu;
}
#if GDB_SELF_TEST
@@ -19363,59 +18735,55 @@ namespace find_containing_comp_unit {
static void
run_test ()
{
- char dummy_per_bfd;
- char dummy_section;
-
- const auto create_dummy_per_cu = [&] (sect_offset sect_off,
- unsigned int length,
- bool is_dwz)
- {
- auto per_bfd = reinterpret_cast<dwarf2_per_bfd *> (&dummy_per_bfd);
- auto section = reinterpret_cast<dwarf2_section_info *> (&dummy_section);
+ auto dummy_per_bfd = reinterpret_cast<dwarf2_per_bfd *> (0x3000);
+ auto &main_section = *reinterpret_cast<dwarf2_section_info *> (0x4000);
+ auto &dwz_section = *reinterpret_cast<dwarf2_section_info *> (0x5000);
+ std::vector<dwarf2_per_cu_up> units;
- return dwarf2_per_cu_up (new dwarf2_per_cu (per_bfd, section, sect_off,
- length, is_dwz));
+ /* Create one dummy unit, append it to UNITS, return a non-owning
+ reference. */
+ auto create_dummy_per_unit = [&] (dwarf2_section_info &section,
+ unsigned int sect_off, bool is_dwz)
+ -> dwarf2_per_cu &
+ {
+ /* Omit the length, because dwarf2_find_containing_unit does not consider
+ it. */
+ return *units.emplace_back (new dwarf2_per_cu (dummy_per_bfd, &section,
+ sect_offset (sect_off),
+ 0, is_dwz));
};
- /* Units in the main file. */
- dwarf2_per_cu_up one = create_dummy_per_cu (sect_offset (0), 5, false);
- dwarf2_per_cu *one_ptr = one.get ();
- dwarf2_per_cu_up two
- = create_dummy_per_cu (sect_offset (one->length ()), 7, false);
- dwarf2_per_cu *two_ptr = two.get ();
-
- /* Units in the supplementary (dwz) file. */
- dwarf2_per_cu_up three = create_dummy_per_cu (sect_offset (0), 5, true);
- dwarf2_per_cu *three_ptr = three.get ();
- dwarf2_per_cu_up four
- = create_dummy_per_cu (sect_offset (three->length ()), 7, true);
- dwarf2_per_cu *four_ptr = four.get ();
-
- std::vector<dwarf2_per_cu_up> units;
- units.push_back (std::move (one));
- units.push_back (std::move (two));
- units.push_back (std::move (three));
- units.push_back (std::move (four));
-
- int result;
+ /* Create 2 units in the main file and 2 units in the supplementary (dwz)
+ file. */
+ auto &main1 = create_dummy_per_unit (main_section, 10, false);
+ auto &main2 = create_dummy_per_unit (main_section, 20, false);
+ auto &dwz1 = create_dummy_per_unit (dwz_section, 10, false);
+ auto &dwz2 = create_dummy_per_unit (dwz_section, 20, false);
+
+ /* Check that looking up a unit at all offsets in the range [START,END[ in
+ section SECTION finds EXPECTED. */
+ auto check_range = [&units] (dwarf2_section_info &section, unsigned int start,
+ unsigned int end, dwarf2_per_cu *expected)
+ {
+ for (unsigned int sect_off = start; sect_off < end; ++sect_off)
+ {
+ section_and_offset target { &section, sect_offset (sect_off) };
+ dwarf2_per_cu *result = dwarf2_find_containing_unit (target, units);
- result = dwarf2_find_containing_comp_unit (sect_offset (0), 0, units);
- SELF_CHECK (units[result].get () == one_ptr);
- result = dwarf2_find_containing_comp_unit (sect_offset (3), 0, units);
- SELF_CHECK (units[result].get () == one_ptr);
- result = dwarf2_find_containing_comp_unit (sect_offset (5), 0, units);
- SELF_CHECK (units[result].get () == two_ptr);
+ SELF_CHECK (result == expected);
+ }
+ };
- result = dwarf2_find_containing_comp_unit (sect_offset (0), 1, units);
- SELF_CHECK (units[result].get () == three_ptr);
- result = dwarf2_find_containing_comp_unit (sect_offset (3), 1, units);
- SELF_CHECK (units[result].get () == three_ptr);
- result = dwarf2_find_containing_comp_unit (sect_offset (5), 1, units);
- SELF_CHECK (units[result].get () == four_ptr);
-}
+ check_range (main_section, 0, 10, nullptr);
+ check_range (main_section, 10, 20, &main1);
+ check_range (main_section, 20, 30, &main2);
+ check_range (dwz_section, 0, 10, nullptr);
+ check_range (dwz_section, 10, 20, &dwz1);
+ check_range (dwz_section, 20, 30, &dwz2);
}
-}
+} /* namespace find_containing_comp_unit */
+} /* namespace selftests */
#endif /* GDB_SELF_TEST */
@@ -19710,9 +19078,7 @@ show_check_physname (struct ui_file *file, int from_tty,
value);
}
-void _initialize_dwarf2_read ();
-void
-_initialize_dwarf2_read ()
+INIT_GDB_FILE (dwarf2_read)
{
add_setshow_prefix_cmd ("dwarf", class_maintenance,
_("\
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index 5b4c8f6..2f9ad05 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -20,6 +20,9 @@
#ifndef GDB_DWARF2_READ_H
#define GDB_DWARF2_READ_H
+#if CXX_STD_THREAD
+#include <mutex>
+#endif
#include <queue>
#include "dwarf2/abbrev.h"
#include "dwarf2/unit-head.h"
@@ -44,7 +47,6 @@ struct tu_stats
int nr_symtab_sharers = 0;
int nr_stmt_less_type_units = 0;
int nr_all_type_units_reallocs = 0;
- int nr_tus = 0;
};
struct abbrev_table_cache;
@@ -52,6 +54,7 @@ struct dwarf2_cu;
struct dwarf2_debug_sections;
struct dwarf2_per_bfd;
struct dwarf2_per_cu;
+struct file_entry;
struct mapped_index;
struct mapped_debug_names;
struct signatured_type;
@@ -125,7 +128,6 @@ struct dwarf2_per_cu
lto_artificial (false),
queued (false),
m_header_read_in (false),
- mark (false),
files_read (false),
scanned (false),
section (section),
@@ -193,10 +195,6 @@ public:
it private at the moment. */
mutable packed<bool, 1> m_header_read_in;
- /* A temporary mark bit used when iterating over all CUs in
- expand_symtabs_matching. */
- packed<unsigned int, 1> mark;
-
/* True if we've tried to read the file table. There will be no
point in trying to read it again next time. */
packed<bool, 1> files_read;
@@ -293,6 +291,10 @@ public:
return m_length;
}
+ /* Return true if the length of this CU has been set. */
+ bool length_is_set () const
+ { return m_length != 0; }
+
void set_length (unsigned int length, bool strict_p = true)
{
if (m_length == 0)
@@ -512,26 +514,12 @@ struct dwarf2_per_bfd
const char *filename () const
{ return bfd_get_filename (this->obfd); }
- /* Return the CU given its index. */
- dwarf2_per_cu *get_cu (int index) const
+ /* Return the unit given its index. */
+ dwarf2_per_cu *get_unit (int index) const
{
return this->all_units[index].get ();
}
- /* Return the CU given its index in the CU table in the index. */
- dwarf2_per_cu *get_index_cu (int index) const
- {
- if (this->all_comp_units_index_cus.empty ())
- return get_cu (index);
-
- return this->all_comp_units_index_cus[index];
- }
-
- dwarf2_per_cu *get_index_tu (int index) const
- {
- return this->all_comp_units_index_tus[index];
- }
-
/* Return the separate '.dwz' debug file. If there is no
.gnu_debugaltlink or .debug_sup section in the file, then the
result depends on REQUIRE: if REQUIRE is true, error out; if
@@ -616,13 +604,9 @@ public:
the target compilation unit of a particular reference. */
std::vector<dwarf2_per_cu_up> all_units;
- /* The all_units vector contains both CUs and TUs. Provide views on the
- vector that are limited to either the CU part or the TU part. */
- gdb::array_view<dwarf2_per_cu_up> all_comp_units;
- gdb::array_view<dwarf2_per_cu_up> all_type_units;
-
- std::vector<dwarf2_per_cu *> all_comp_units_index_cus;
- std::vector<dwarf2_per_cu *> all_comp_units_index_tus;
+ /* Number of compilation and type units in the ALL_UNITS vector. */
+ unsigned int num_comp_units = 0;
+ unsigned int num_type_units = 0;
/* Set of signatured_types, used to look up by signature. */
signatured_type_set signatured_types;
@@ -634,6 +618,11 @@ public:
/* Set of dwo_file objects. */
dwo_file_up_set dwo_files;
+#if CXX_STD_THREAD
+ /* Mutex to synchronize access to DWO_FILES. */
+ std::mutex dwo_files_lock;
+#endif
+
/* The DWP file if there is one, or NULL. */
dwp_file_up dwp_file;
@@ -680,6 +669,36 @@ public:
std::string captured_debug_dir;
};
+/* Scoped object to remove all units from PER_BFD and clear other associated
+ fields in case of failure. */
+
+struct scoped_remove_all_units
+{
+ explicit scoped_remove_all_units (dwarf2_per_bfd &per_bfd)
+ : m_per_bfd (&per_bfd)
+ {}
+
+ DISABLE_COPY_AND_ASSIGN (scoped_remove_all_units);
+
+ ~scoped_remove_all_units ()
+ {
+ if (m_per_bfd == nullptr)
+ return;
+
+ m_per_bfd->all_units.clear ();
+ m_per_bfd->num_comp_units = 0;
+ m_per_bfd->num_type_units = 0;
+ }
+
+ /* Disable this object. Call this to keep the units of M_PER_BFD on the
+ success path. */
+ void disable () { m_per_bfd = nullptr; }
+
+private:
+ /* This is nullptr if the object is disabled. */
+ dwarf2_per_bfd *m_per_bfd;
+};
+
/* An iterator for all_units that is based on index. This
approach makes it possible to iterate over all_units safely,
when some caller in the loop may add new units. */
@@ -702,7 +721,7 @@ public:
dwarf2_per_cu *operator* () const
{
- return m_per_bfd->get_cu (m_index);
+ return m_per_bfd->get_unit (m_index);
}
bool operator== (const all_units_iterator &other) const
@@ -1029,8 +1048,7 @@ private:
dwo_file_up open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name,
const char *comp_dir);
- void locate_dwo_sections (struct objfile *objfile, bfd *abfd, asection *sectp,
- struct dwo_sections *dwo_sections);
+ void locate_dwo_sections (objfile *objfile, dwo_file &dwo_file);
void create_dwo_unit_hash_tables (dwo_file &dwo_file, dwarf2_cu &skeleton_cu,
dwarf2_section_info &section,
@@ -1200,32 +1218,51 @@ struct dwarf2_base_index_functions : public quick_symbol_functions
bool need_fullname) override;
};
-/* If FILE_MATCHER is NULL or if PER_CU has
- dwarf2_per_cu_quick_data::MARK set (see
- dw_expand_symtabs_matching_file_matcher), expand the CU and call
- EXPANSION_NOTIFY on it. */
+/* This is used to track whether a CU has already been visited during
+ symbol expansion. It is an auto-resizing bool vector. */
+class auto_bool_vector
+{
+public:
+
+ auto_bool_vector () = default;
+
+ /* Return true if element I is set. */
+ bool is_set (size_t i) const
+ {
+ if (i < m_vec.size ())
+ return m_vec[i];
+ return false;
+ }
+
+ /* Set a value in this vector, growing it automatically. */
+ void set (size_t i, bool value)
+ {
+ if (m_vec.size () < i + 1)
+ m_vec.resize (i + 1);
+ m_vec[i] = value;
+ }
+
+private:
+ std::vector<bool> m_vec;
+};
+
+/* If FILE_MATCHER is NULL and if CUS_TO_SKIP does not include the
+ CU's index, expand the CU and call LISTENER on it. */
-extern bool dw2_expand_symtabs_matching_one
+extern bool dw2_search_one
(dwarf2_per_cu *per_cu,
dwarf2_per_objfile *per_objfile,
- expand_symtabs_file_matcher file_matcher,
- expand_symtabs_expansion_listener expansion_notify,
- expand_symtabs_lang_matcher lang_matcher);
-
-/* If FILE_MATCHER is non-NULL, set all the
- dwarf2_per_cu_quick_data::MARK of the current DWARF2_PER_OBJFILE
- that match FILE_MATCHER. */
-
-extern void dw_expand_symtabs_matching_file_matcher
- (dwarf2_per_objfile *per_objfile,
- expand_symtabs_file_matcher file_matcher);
+ auto_bool_vector &cus_to_skip,
+ search_symtabs_file_matcher file_matcher,
+ search_symtabs_expansion_listener listener,
+ search_symtabs_lang_matcher lang_matcher);
/* Return pointer to string at .debug_str offset STR_OFFSET. */
extern const char *read_indirect_string_at_offset
(dwarf2_per_objfile *per_objfile, LONGEST str_offset);
-/* Initialize the views on all_units. */
+/* Finalize the all_units vector. */
extern void finalize_all_units (dwarf2_per_bfd *per_bfd);
@@ -1270,14 +1307,17 @@ extern pc_bounds_kind dwarf2_get_pc_bounds (die_info *die,
dwarf2_cu *cu, addrmap_mutable *map,
void *datum);
-/* Locate the .debug_info compilation unit from CU's objfile which contains
- the DIE at OFFSET. Raises an error on failure. */
+/* Locate the unit in PER_OBJFILE which contains the DIE at TARGET. Raises an
+ error on failure. */
-extern dwarf2_per_cu *dwarf2_find_containing_comp_unit (sect_offset sect_off,
- unsigned int
- offset_in_dwz,
- dwarf2_per_bfd
- *per_bfd);
+extern dwarf2_per_cu *dwarf2_find_containing_unit
+ (const section_and_offset &target, dwarf2_per_objfile *per_objfile);
+
+/* Locate the unit starting at START in PER_BFD. Return nullptr if not
+ found. */
+
+extern dwarf2_per_cu *dwarf2_find_unit (const section_and_offset &start,
+ dwarf2_per_bfd *per_bfd);
/* Decode simple location descriptions.
@@ -1320,4 +1360,46 @@ extern int dwarf2_ranges_read (unsigned offset, unrelocated_addr *low_return,
extern file_and_directory &find_file_and_directory (die_info *die,
dwarf2_cu *cu);
+
+/* Return the section that ATTR, an attribute with ref form, references. */
+
+extern const dwarf2_section_info &get_section_for_ref
+ (const attribute &attr, dwarf2_cu *cu);
+
+/* A convenience function to find the proper .debug_line section for a CU. */
+
+extern struct dwarf2_section_info *get_debug_line_section
+ (struct dwarf2_cu *cu);
+
+/* Start a subfile for DWARF. FILENAME is the name of the file and
+ DIRNAME the name of the source directory which contains FILENAME
+ or NULL if not known.
+ This routine tries to keep line numbers from identical absolute and
+ relative file names in a common subfile.
+
+ Using the `list' example from the GDB testsuite, which resides in
+ /srcdir and compiling it with Irix6.2 cc in /compdir using a filename
+ of /srcdir/list0.c yields the following debugging information for list0.c:
+
+ DW_AT_name: /srcdir/list0.c
+ DW_AT_comp_dir: /compdir
+ files.files[0].name: list0.h
+ files.files[0].dir: /srcdir
+ files.files[1].name: list0.c
+ files.files[1].dir: /srcdir
+
+ The line number information for list0.c has to end up in a single
+ subfile, so that `break /srcdir/list0.c:1' works as expected.
+ start_subfile will ensure that this happens provided that we pass the
+ concatenation of files.files[1].dir and files.files[1].name as the
+ subfile's name. */
+extern void dwarf2_start_subfile (dwarf2_cu *cu, const file_entry &fe,
+ const line_header &lh);
+
+/* A helper function that decides if a given symbol is an Ada Pragma
+ Import or Pragma Export. */
+
+extern bool is_ada_import_or_export (dwarf2_cu *cu, const char *name,
+ const char *linkagename);
+
#endif /* GDB_DWARF2_READ_H */
diff --git a/gdb/dwarf2/section.h b/gdb/dwarf2/section.h
index b9d3c31..fbdb025 100644
--- a/gdb/dwarf2/section.h
+++ b/gdb/dwarf2/section.h
@@ -43,6 +43,8 @@
the real section this "virtual" section is contained in, and BUFFER,SIZE
describe the virtual section. */
+#include "dwarf2/types.h"
+
struct dwarf2_section_info
{
/* Return the name of this section. */
@@ -112,4 +114,14 @@ struct dwarf2_section_info
bool is_virtual;
};
+using dwarf2_section_info_up = std::unique_ptr<dwarf2_section_info>;
+
+/* A pair-like structure to represent an offset into a section. */
+
+struct section_and_offset
+{
+ const dwarf2_section_info *section;
+ sect_offset offset;
+};
+
#endif /* GDB_DWARF2_SECTION_H */
diff --git a/gdb/dwarf2/stringify.c b/gdb/dwarf2/stringify.c
index c9625e8..bdb5125 100644
--- a/gdb/dwarf2/stringify.c
+++ b/gdb/dwarf2/stringify.c
@@ -25,6 +25,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "dwarf2.h"
+#include "dwarf2/read-gdb-index.h"
#include "dwarf2/stringify.h"
/* A convenience function that returns an "unknown" DWARF name,
@@ -44,6 +45,11 @@ dwarf_unknown (const char *str, unsigned v)
const char *
dwarf_tag_name (unsigned tag)
{
+ if (tag == DW_TAG_GDB_INDEX_OTHER)
+ return "DW_TAG_GDB_INDEX_OTHER";
+ else if (tag == DW_TAG_GDB_INDEX_TYPE)
+ return "DW_TAG_GDB_INDEX_TYPE";
+
const char *name = get_DW_TAG_name (tag);
if (name == NULL)
diff --git a/gdb/dwarf2/tag.h b/gdb/dwarf2/tag.h
index ed730c0..9b5c775 100644
--- a/gdb/dwarf2/tag.h
+++ b/gdb/dwarf2/tag.h
@@ -22,6 +22,7 @@
#include "dwarf2.h"
#include "symtab.h"
+#include "read-gdb-index.h"
/* Return true if TAG represents a type, false otherwise. */
@@ -102,6 +103,10 @@ tag_matches_domain (dwarf_tag tag, domain_search_flags search, language lang)
}
break;
+ case DW_TAG_imported_declaration:
+ /* DW_TAG_imported_declaration isn't necessarily a type, but the
+ scanner doesn't track the referent, and the full reader
+ also currently puts it in TYPE_DOMAIN. */
case DW_TAG_padding:
case DW_TAG_array_type:
case DW_TAG_pointer_type:
@@ -140,6 +145,13 @@ tag_matches_domain (dwarf_tag tag, domain_search_flags search, language lang)
else
flags = SEARCH_MODULE_DOMAIN;
break;
+
+ case DW_TAG_GDB_INDEX_OTHER:
+ flags = SEARCH_MODULE_DOMAIN | SEARCH_TYPE_DOMAIN;
+ break;
+ case DW_TAG_GDB_INDEX_TYPE:
+ flags = SEARCH_STRUCT_DOMAIN | SEARCH_TYPE_DOMAIN;
+ break;
}
return (flags & search) != 0;
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 7dd8fc7..c8e976a 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -776,9 +776,8 @@ elf_gnu_ifunc_resolve_by_cache (const char *name, CORE_ADDR *addr_p)
To search other namespaces, we would need to provide context, e.g. in
form of an objfile in that namespace. */
- gdbarch_iterate_over_objfiles_in_search_order
- (current_inferior ()->arch (),
- [name, &addr_p, &found] (struct objfile *objfile)
+ current_program_space->iterate_over_objfiles_in_search_order
+ ([name, &addr_p, &found] (struct objfile *objfile)
{
htab_t htab;
elf_gnu_ifunc_cache *entry_p;
@@ -830,9 +829,8 @@ elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p)
To search other namespaces, we would need to provide context, e.g. in
form of an objfile in that namespace. */
- gdbarch_iterate_over_objfiles_in_search_order
- (current_inferior ()->arch (),
- [name, name_got_plt, &addr_p, &found] (struct objfile *objfile)
+ current_program_space->iterate_over_objfiles_in_search_order
+ ([name, name_got_plt, &addr_p, &found] (struct objfile *objfile)
{
bfd *obfd = objfile->obfd.get ();
struct gdbarch *gdbarch = objfile->arch ();
@@ -1513,9 +1511,7 @@ static const struct gnu_ifunc_fns elf_gnu_ifunc_fns =
elf_gnu_ifunc_resolver_return_stop
};
-void _initialize_elfread ();
-void
-_initialize_elfread ()
+INIT_GDB_FILE (elfread)
{
add_symtab_fns (bfd_target_elf_flavour, &elf_sym_fns);
diff --git a/gdb/eval.c b/gdb/eval.c
index 19770ad..cefc857 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -38,7 +38,6 @@
#include "gdbsupport/gdb_obstack.h"
#include "objfiles.h"
#include "typeprint.h"
-#include <ctype.h>
#include "expop.h"
#include "c-exp.h"
#include "inferior.h"
@@ -492,7 +491,7 @@ fake_method::fake_method (type_instance_flags flags,
fake_method::~fake_method ()
{
- xfree (m_type.fields ());
+ xfree (m_type.fields ().data ());
}
namespace expr
@@ -1181,8 +1180,8 @@ ternop_slice_operation::evaluate (struct type *expect_type,
struct value *upper
= std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
- int lowbound = value_as_long (low);
- int upperbound = value_as_long (upper);
+ LONGEST lowbound = value_as_long (low);
+ LONGEST upperbound = value_as_long (upper);
return value_slice (array, lowbound, upperbound - lowbound + 1);
}
@@ -2558,27 +2557,26 @@ unop_extract_operation::evaluate (struct type *expect_type,
}
-
/* Helper for evaluate_subexp_for_address. */
static value *
-evaluate_subexp_for_address_base (struct expression *exp, enum noside noside,
- value *x)
+evaluate_subexp_for_address_base (enum noside noside, value *x)
{
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
struct type *type = check_typedef (x->type ());
+ enum type_code typecode = type->code ();
if (TYPE_IS_REFERENCE (type))
return value::zero (lookup_pointer_type (type->target_type ()),
- not_lval);
- else if (x->lval () == lval_memory || value_must_coerce_to_target (x))
- return value::zero (lookup_pointer_type (x->type ()),
- not_lval);
+ not_lval);
+ else if (x->lval () == lval_memory || value_must_coerce_to_target (x)
+ || typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)
+ return value::zero (lookup_pointer_type (x->type ()), not_lval);
else
- error (_("Attempt to take address of "
- "value not located in memory."));
+ error (_("Attempt to take address of value not located in memory."));
}
+
return value_addr (x);
}
@@ -2598,7 +2596,7 @@ value *
operation::evaluate_for_address (struct expression *exp, enum noside noside)
{
value *val = evaluate (nullptr, exp, noside);
- return evaluate_subexp_for_address_base (exp, noside, val);
+ return evaluate_subexp_for_address_base (noside, val);
}
value *
@@ -2625,7 +2623,7 @@ unop_ind_base_operation::evaluate_for_address (struct expression *exp,
if (unop_user_defined_p (UNOP_IND, x))
{
x = value_x_unop (x, UNOP_IND, noside);
- return evaluate_subexp_for_address_base (exp, noside, x);
+ return evaluate_subexp_for_address_base (noside, x);
}
return coerce_array (x);
@@ -2679,11 +2677,11 @@ var_value_operation::evaluate_for_address (struct expression *exp,
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
struct type *type = lookup_pointer_type (var->type ());
- enum address_class sym_class = var->aclass ();
+ location_class loc_class = var->loc_class ();
- if (sym_class == LOC_CONST
- || sym_class == LOC_CONST_BYTES
- || sym_class == LOC_REGISTER)
+ if (loc_class == LOC_CONST
+ || loc_class == LOC_CONST_BYTES
+ || loc_class == LOC_REGISTER)
error (_("Attempt to take address of register or constant."));
return value::zero (type, not_lval);
diff --git a/gdb/event-top.c b/gdb/event-top.c
index 968117c..3138e8c 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -1180,6 +1180,9 @@ quit (void)
throw_forced_quit ("SIGTERM");
}
+ /* Pressing ^C cancels i-search. Tell readline that a ^C happened. */
+ rl_callback_sigcleanup ();
+
#ifdef __MSDOS__
/* No steenking SIGINT will ever be coming our way when the
program is resumed. Don't lie. */
@@ -1650,9 +1653,7 @@ show_debug_event_loop_command (struct ui_file *file, int from_tty,
gdb_printf (file, _("Event loop debugging is %s.\n"), value);
}
-void _initialize_event_top ();
-void
-_initialize_event_top ()
+INIT_GDB_FILE (event_top)
{
add_setshow_enum_cmd ("event-loop", class_maintenance,
debug_event_loop_enum,
diff --git a/gdb/exceptions.c b/gdb/exceptions.c
index 6af3a7e..35400f3 100644
--- a/gdb/exceptions.c
+++ b/gdb/exceptions.c
@@ -25,6 +25,7 @@
#include "serial.h"
#include "ui.h"
#include <optional>
+#include "cli/cli-style.h"
static void
print_flush (void)
@@ -105,6 +106,7 @@ exception_print (struct ui_file *file, const struct gdb_exception &e)
if (e.reason < 0 && e.message != NULL)
{
print_flush ();
+ print_error_prefix (file);
print_exception (file, e);
}
}
@@ -118,6 +120,7 @@ exception_fprintf (struct ui_file *file, const struct gdb_exception &e,
va_list args;
print_flush ();
+ print_error_prefix (file);
/* Print the prefix. */
va_start (args, prefix);
diff --git a/gdb/exec.c b/gdb/exec.c
index c7979a2..a904f5c 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -42,9 +42,8 @@
#include "readline/tilde.h"
#include "gdbcore.h"
-#include <ctype.h>
#include <sys/stat.h>
-#include "solist.h"
+#include "solib.h"
#include <algorithm>
#include "gdbsupport/pathstuff.h"
#include "cli/cli-style.h"
@@ -218,28 +217,32 @@ validate_exec_file (int from_tty)
if (exec_file_mismatch_mode == exec_file_mismatch_off)
return;
+ /* If there's no current executable, then there's nothing to
+ validate against, so we're done. */
const char *current_exec_file = current_program_space->exec_filename ();
- struct inferior *inf = current_inferior ();
- /* Try to determine a filename from the process itself. */
- const char *pid_exec_file = target_pid_to_exec_file (inf->pid);
- bool build_id_mismatch = false;
-
- /* If we cannot validate the exec file, return. */
- if (current_exec_file == NULL || pid_exec_file == NULL)
+ if (current_exec_file == nullptr)
return;
- /* Try validating via build-id, if available. This is the most
- reliable check. */
+ /* Try to determine a filename from the process itself. If we
+ cannot get an executable from the process, then no validation is
+ possible. */
+ const char *pid_exec_file
+ = target_pid_to_exec_file (current_inferior ()->pid);
+ if (pid_exec_file == nullptr)
+ return;
- /* In case current_exec_file was changed, reopen_exec_file ensures
- an up to date build_id (will do nothing if the file timestamp
- did not change). If exec file changed, reopen_exec_file has
- allocated another file name, so get_exec_file again. */
+ /* In case current_exec_file was changed, reopen_exec_file ensures an up
+ to date build_id (will do nothing if the file timestamp did not
+ change). If exec file changed, reopen_exec_file has allocated another
+ file name, so get_exec_file again. */
reopen_exec_file ();
current_exec_file = current_program_space->exec_filename ();
+ /* Try validating via build-id, if available. This is the most reliable
+ check. */
const bfd_build_id *exec_file_build_id
= build_id_bfd_get (current_program_space->exec_bfd ());
+ bool build_id_mismatch = false;
if (exec_file_build_id != nullptr)
{
/* Prepend the target prefix, to force gdb_bfd_open to open the
@@ -334,6 +337,14 @@ exec_file_locate_attach (int pid, int defer_bp_reset, int from_tty)
gdb::unique_xmalloc_ptr<char> exec_file_host
= exec_file_find (exec_file_target, NULL);
+ if (exec_file_host == nullptr)
+ {
+ warning (_("No executable has been specified, and target executable "
+ "%ps could not be found. Try using the \"%ps\" command."),
+ styled_string (file_name_style.style (), exec_file_target),
+ styled_string (command_style.style (), "file"));
+ return;
+ }
if (defer_bp_reset)
add_flags |= SYMFILE_DEFER_BP_RESET;
@@ -641,13 +652,13 @@ program_space::add_target_sections (struct objfile *objfile)
gdb_assert (objfile != nullptr);
/* Compute the number of sections to add. */
- for (obj_section *osect : objfile->sections ())
+ for (obj_section &osect : objfile->sections ())
{
- if (bfd_section_size (osect->the_bfd_section) == 0)
+ if (bfd_section_size (osect.the_bfd_section) == 0)
continue;
- m_target_sections.emplace_back (osect->addr (), osect->endaddr (),
- osect->the_bfd_section, objfile);
+ m_target_sections.emplace_back (osect.addr (), osect.endaddr (),
+ osect.the_bfd_section, objfile);
}
}
@@ -1003,7 +1014,7 @@ set_section_command (const char *args, int from_tty)
error (_("Must specify section name and its virtual address"));
/* Parse out section name. */
- for (secname = args; !isspace (*args); args++);
+ for (secname = args; !c_isspace (*args); args++);
unsigned seclen = args - secname;
/* Parse out new virtual address. */
@@ -1065,9 +1076,7 @@ exec_target::find_memory_regions (find_memory_region_ftype func, void *data)
return objfile_find_memory_regions (this, func, data);
}
-void _initialize_exec ();
-void
-_initialize_exec ()
+INIT_GDB_FILE (exec)
{
struct cmd_list_element *c;
diff --git a/gdb/expop.h b/gdb/expop.h
index a3541d4..6f509da 100644
--- a/gdb/expop.h
+++ b/gdb/expop.h
@@ -476,11 +476,11 @@ check_constant (const gdb_mpz &cst)
static inline bool
check_constant (struct symbol *sym)
{
- enum address_class sc = sym->aclass ();
- return (sc == LOC_BLOCK
- || sc == LOC_CONST
- || sc == LOC_CONST_BYTES
- || sc == LOC_LABEL);
+ location_class lc = sym->loc_class ();
+ return (lc == LOC_BLOCK
+ || lc == LOC_CONST
+ || lc == LOC_CONST_BYTES
+ || lc == LOC_LABEL);
}
static inline bool
diff --git a/gdb/expprint.c b/gdb/expprint.c
index c87be74..a32b7ac 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -33,7 +33,6 @@
#include "expop.h"
#include "ada-exp.h"
-#include <ctype.h>
/* Meant to be used in debug sessions, so don't export it in a header file. */
extern void ATTRIBUTE_USED debug_exp (struct expression *exp);
diff --git a/gdb/extension.c b/gdb/extension.c
index 6d14a20..1e967c5 100644
--- a/gdb/extension.c
+++ b/gdb/extension.c
@@ -34,6 +34,8 @@
#include <array>
#include "inferior.h"
#include "gdbsupport/scoped_signal_handler.h"
+#include "gdbsupport/scoped_ignore_signal.h"
+#include "run-on-main-thread.h"
static script_sourcer_func source_gdb_script;
static objfile_script_sourcer_func source_gdb_objfile_script;
@@ -638,7 +640,7 @@ breakpoint_ext_lang_cond_says_stop (struct breakpoint *b)
This requires cooperation with the extension languages so the support
is defined here. */
-#if CXX_STD_THREAD
+#if CXX_STD_THREAD && defined __MINGW32__
#include <mutex>
@@ -648,10 +650,19 @@ breakpoint_ext_lang_cond_says_stop (struct breakpoint *b)
available, DAP will not start.
This lock is held for accesses to quit_flag, active_ext_lang, and
- cooperative_sigint_handling_disabled. */
+ cooperative_sigint_handling_disabled.
+
+ This lock is only required for targets that don't support kill(), and,
+ it is assumed, handle SIGINT not as a signal, but as a new thread. For
+ these targets this mutex prevents multiple threads adjusting the above
+ state at the same time.
+
+ For targets that support kill() gdb.interrupt is implemented by just
+ sending SIGINT to the process, which is then handled in the "normal"
+ way. */
static std::recursive_mutex ext_lang_mutex;
-#endif /* CXX_STD_THREAD */
+#endif /* CXX_STD_THREAD && defined (__MINGW32__)*/
/* This flag tracks quit requests when we haven't called out to an
extension language. it also holds quit requests when we transition to
@@ -700,6 +711,44 @@ void (*hook_set_active_ext_lang) () = nullptr;
}
#endif
+namespace gdb
+{
+/* Wrapper that acquires the global EXT_LANG_MUTEX, but only for hosts
+ that might call quit related functions from a separate thread.
+ Specifically, this is hosts that don't support Unix like signals
+ (currently only Mingw).
+
+ For hosts with signal support, we don't try to use a mutex as a signal
+ might interrupt the lock acquisition, in which case deadlock will
+ occur. However, for these hosts, all the quit related functions are
+ called on the main thread (there's an assert for this), so the lack of
+ locking shouldn't be an issue.
+
+ For Mingw, without signals, the implementation of the Python
+ gdb.interrupt function can call set_quit_flag() from a second thread,
+ and additionally, the emulation of SIGINT involves the creation of a
+ temporary thread which calls the sigint handler. So for Mingw, we do
+ need the mutex, but that's OK, as no signal can interrupt the lock
+ acquisition. */
+struct ext_lang_guard
+{
+ ext_lang_guard ()
+ {
+#if CXX_STD_THREAD && !defined __MINGW32__
+ gdb_assert (is_main_thread ());
+#endif /* CXX_STD_THREAD && ! defined __MINGW32__ */
+ }
+
+ ~ext_lang_guard () { /* Nothing. */ }
+
+private:
+#if CXX_STD_THREAD && defined __MINGW32__
+ std::lock_guard<typeof (ext_lang_mutex)> m_guard { ext_lang_mutex };
+#endif
+};
+
+}
+
/* True if cooperative SIGINT handling is disabled. This is needed so
that calls to set_active_ext_lang do not re-enable cooperative
handling, which if enabled would make set_quit_flag store the
@@ -708,9 +757,7 @@ static bool cooperative_sigint_handling_disabled = false;
scoped_disable_cooperative_sigint_handling::scoped_disable_cooperative_sigint_handling ()
{
-#if CXX_STD_THREAD
- std::lock_guard guard (ext_lang_mutex);
-#endif /* CXX_STD_THREAD */
+ gdb::ext_lang_guard guard;
/* Force the active extension language to the GDB scripting
language. This ensures that a previously saved SIGINT is moved
@@ -729,9 +776,7 @@ scoped_disable_cooperative_sigint_handling::scoped_disable_cooperative_sigint_ha
scoped_disable_cooperative_sigint_handling::~scoped_disable_cooperative_sigint_handling ()
{
-#if CXX_STD_THREAD
- std::lock_guard guard (ext_lang_mutex);
-#endif /* CXX_STD_THREAD */
+ gdb::ext_lang_guard guard;
cooperative_sigint_handling_disabled = m_prev_cooperative_sigint_handling_disabled;
restore_active_ext_lang (m_prev_active_ext_lang_state);
@@ -771,9 +816,7 @@ scoped_disable_cooperative_sigint_handling::~scoped_disable_cooperative_sigint_h
struct active_ext_lang_state *
set_active_ext_lang (const struct extension_language_defn *now_active)
{
-#if CXX_STD_THREAD
- std::lock_guard guard (ext_lang_mutex);
-#endif /* CXX_STD_THREAD */
+ gdb::ext_lang_guard guard;
#if GDB_SELF_TEST
if (selftests::hook_set_active_ext_lang)
@@ -827,9 +870,7 @@ set_active_ext_lang (const struct extension_language_defn *now_active)
void
restore_active_ext_lang (struct active_ext_lang_state *previous)
{
-#if CXX_STD_THREAD
- std::lock_guard guard (ext_lang_mutex);
-#endif /* CXX_STD_THREAD */
+ gdb::ext_lang_guard guard;
if (cooperative_sigint_handling_disabled)
{
@@ -861,9 +902,7 @@ restore_active_ext_lang (struct active_ext_lang_state *previous)
void
set_quit_flag ()
{
-#if CXX_STD_THREAD
- std::lock_guard guard (ext_lang_mutex);
-#endif /* CXX_STD_THREAD */
+ gdb::ext_lang_guard guard;
if (active_ext_lang->ops != NULL
&& active_ext_lang->ops->set_quit_flag != NULL)
@@ -886,9 +925,7 @@ set_quit_flag ()
bool
check_quit_flag ()
{
-#if CXX_STD_THREAD
- std::lock_guard guard (ext_lang_mutex);
-#endif /* CXX_STD_THREAD */
+ gdb::ext_lang_guard guard;
bool result = false;
@@ -1102,9 +1139,7 @@ ext_lang_before_prompt (const char *current_gdb_prompt)
}
}
-void _initialize_extension ();
-void
-_initialize_extension ()
+INIT_GDB_FILE (extension)
{
gdb::observers::before_prompt.attach (ext_lang_before_prompt, "extension");
}
diff --git a/gdb/extract-store-integer.c b/gdb/extract-store-integer.c
index 4f20092..d73040b 100644
--- a/gdb/extract-store-integer.c
+++ b/gdb/extract-store-integer.c
@@ -337,9 +337,7 @@ extract_integer_test ()
#endif
-void _initialize_extract_store_integer ();
-void
-_initialize_extract_store_integer ()
+INIT_GDB_FILE (extract_store_integer)
{
#if GDB_SELF_TEST
selftests::register_test ("copy_integer_to_size",
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
index 44ea11b..a8ee9a3 100644
--- a/gdb/f-exp.y
+++ b/gdb/f-exp.y
@@ -48,7 +48,6 @@
#include "language.h"
#include "f-lang.h"
#include "block.h"
-#include <ctype.h>
#include <algorithm>
#include "type-stack.h"
#include "f-exp.h"
@@ -1061,8 +1060,8 @@ parse_number (struct parser_state *par_state,
while (len-- > 0)
{
c = *p++;
- if (isupper (c))
- c = tolower (c);
+ if (c_isupper (c))
+ c = c_tolower (c);
if (len == 0 && c == 'l')
long_p = 1;
else if (len == 0 && c == 'u')
@@ -1160,8 +1159,7 @@ push_kind_type (LONGEST val, struct type *type)
ival = static_cast <int> (val);
}
- type_stack->push (ival);
- type_stack->push (tp_kind);
+ type_stack->push (tp_kind, ival);
}
/* Helper function for convert_to_kind_type. */
@@ -1663,7 +1661,7 @@ yylex (void)
{
result = lookup_symbol (tmp.c_str (), pstate->expression_context_block,
domain, NULL);
- if (result.symbol && result.symbol->aclass () == LOC_TYPEDEF)
+ if (result.symbol && result.symbol->loc_class () == LOC_TYPEDEF)
{
yylval.tsym.type = result.symbol->type ();
return TYPENAME;
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 3e31dce..1aa9fc4 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -1836,9 +1836,7 @@ builtin_f_type (struct gdbarch *gdbarch)
static struct cmd_list_element *set_fortran_list;
static struct cmd_list_element *show_fortran_list;
-void _initialize_f_language ();
-void
-_initialize_f_language ()
+INIT_GDB_FILE (f_language)
{
add_setshow_prefix_cmd
("fortran", no_class,
diff --git a/gdb/f-typeprint.c b/gdb/f-typeprint.c
index 7d0cdc0..e96d27c 100644
--- a/gdb/f-typeprint.c
+++ b/gdb/f-typeprint.c
@@ -299,8 +299,6 @@ void
f_language::f_type_print_base (struct type *type, struct ui_file *stream,
int show, int level) const
{
- int index;
-
QUIT;
stream->wrap_here (4);
@@ -423,14 +421,13 @@ f_language::f_type_print_base (struct type *type, struct ui_file *stream,
if (show > 0)
{
gdb_puts ("\n", stream);
- for (index = 0; index < type->num_fields (); index++)
+ for (const auto &field : type->fields ())
{
- f_type_print_base (type->field (index).type (), stream,
- show - 1, level + 4);
+ f_type_print_base (field.type (), stream, show - 1, level + 4);
gdb_puts (" :: ", stream);
- fputs_styled (type->field (index).name (),
+ fputs_styled (field.name (),
variable_name_style.style (), stream);
- f_type_print_varspec_suffix (type->field (index).type (),
+ f_type_print_varspec_suffix (field.type (),
stream, show - 1, 0, 0, 0, false);
gdb_puts ("\n", stream);
}
diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c
index 0f3b2a6..935bf02 100644
--- a/gdb/f-valprint.c
+++ b/gdb/f-valprint.c
@@ -631,7 +631,7 @@ info_common_command_for_block (const struct block *block, const char *comname,
const struct common_block *common = sym->value_common_block ();
size_t index;
- gdb_assert (sym->aclass () == LOC_COMMON_BLOCK);
+ gdb_assert (sym->loc_class () == LOC_COMMON_BLOCK);
if (comname && (!sym->linkage_name ()
|| strcmp (comname, sym->linkage_name ()) != 0))
@@ -719,9 +719,7 @@ info_common_command (const char *comname, int from_tty)
}
}
-void _initialize_f_valprint ();
-void
-_initialize_f_valprint ()
+INIT_GDB_FILE (f_valprint)
{
add_info ("common", info_common_command,
_("Print out the values contained in a Fortran COMMON block."));
diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c
index 71a8386..81bd6d9 100644
--- a/gdb/fbsd-nat.c
+++ b/gdb/fbsd-nat.c
@@ -304,7 +304,7 @@ fbsd_nat_target::info_proc (const char *args, enum info_proc_what what)
if (pid == 0)
error (_("No current process: you must name one."));
}
- else if (built_argv.count () == 1 && isdigit (built_argv[0][0]))
+ else if (built_argv.count () == 1 && c_isdigit (built_argv[0][0]))
pid = strtol (built_argv[0], NULL, 10);
else
error (_("Invalid arguments."));
@@ -2465,14 +2465,12 @@ fbsd_nat_get_siginfo (ptid_t ptid, siginfo_t *siginfo)
if (ptrace (PT_LWPINFO, pid, (caddr_t) &pl, sizeof pl) == -1)
return false;
if (!(pl.pl_flags & PL_FLAG_SI))
- return false;;
+ return false;
*siginfo = pl.pl_siginfo;
return (true);
}
-void _initialize_fbsd_nat ();
-void
-_initialize_fbsd_nat ()
+INIT_GDB_FILE (fbsd_nat)
{
add_setshow_boolean_cmd ("fbsd-lwp", class_maintenance,
&debug_fbsd_lwp, _("\
diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c
index 39e1e86..32571b8 100644
--- a/gdb/fbsd-tdep.c
+++ b/gdb/fbsd-tdep.c
@@ -548,7 +548,8 @@ fbsd_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid)
string in a static buffer. */
static const char *
-fbsd_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr)
+fbsd_core_thread_name (struct gdbarch *gdbarch, bfd &cbfd,
+ struct thread_info *thr)
{
static char buf[80];
struct bfd_section *section;
@@ -564,16 +565,15 @@ fbsd_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr)
extract the null-terminated name from the start of the
note. */
thread_section_name section_name (".thrmisc", thr->ptid);
- bfd *cbfd = current_program_space->core_bfd ();
- section = bfd_get_section_by_name (cbfd, section_name.c_str ());
+ section = bfd_get_section_by_name (&cbfd, section_name.c_str ());
if (section != NULL && bfd_section_size (section) > 0)
{
/* Truncate the name if it is longer than "buf". */
size = bfd_section_size (section);
if (size > sizeof buf - 1)
size = sizeof buf - 1;
- if (bfd_get_section_contents (cbfd, section, buf, (file_ptr) 0, size)
+ if (bfd_get_section_contents (&cbfd, section, buf, (file_ptr) 0, size)
&& buf[0] != '\0')
{
buf[size] = '\0';
@@ -582,7 +582,7 @@ fbsd_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr)
as its thread name instead of an empty name if a name
has not been set explicitly. Return a NULL name in
that case. */
- if (strcmp (buf, elf_tdata (cbfd)->core->program) != 0)
+ if (strcmp (buf, elf_tdata (&cbfd)->core->program) != 0)
return buf;
}
}
@@ -594,8 +594,8 @@ fbsd_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr)
/* Implement the "core_xfer_siginfo" gdbarch method. */
static LONGEST
-fbsd_core_xfer_siginfo (struct gdbarch *gdbarch, gdb_byte *readbuf,
- ULONGEST offset, ULONGEST len)
+fbsd_core_xfer_siginfo (struct gdbarch *gdbarch, struct bfd &cbfd,
+ gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
{
size_t siginfo_size;
@@ -607,13 +607,12 @@ fbsd_core_xfer_siginfo (struct gdbarch *gdbarch, gdb_byte *readbuf,
return -1;
thread_section_name section_name (".note.freebsdcore.lwpinfo", inferior_ptid);
- bfd *cbfd = current_program_space->core_bfd ();
- asection *section = bfd_get_section_by_name (cbfd, section_name.c_str ());
+ asection *section = bfd_get_section_by_name (&cbfd, section_name.c_str ());
if (section == NULL)
return -1;
gdb_byte buf[4];
- if (!bfd_get_section_contents (cbfd, section, buf,
+ if (!bfd_get_section_contents (&cbfd, section, buf,
LWPINFO_OFFSET + LWPINFO_PL_FLAGS, 4))
return -1;
@@ -630,7 +629,7 @@ fbsd_core_xfer_siginfo (struct gdbarch *gdbarch, gdb_byte *readbuf,
else
siginfo_offset = LWPINFO_OFFSET + LWPINFO64_PL_SIGINFO;
- if (!bfd_get_section_contents (cbfd, section, readbuf,
+ if (!bfd_get_section_contents (&cbfd, section, readbuf,
siginfo_offset + offset, len))
return -1;
@@ -1015,12 +1014,11 @@ fbsd_info_proc_files_entry (int kf_type, int kf_fd, int kf_flags,
gdb_printf ("\n");
}
-/* Implement "info proc files" for a corefile. */
+/* Implement "info proc files" for corefile CBFD. */
static void
-fbsd_core_info_proc_files (struct gdbarch *gdbarch)
+fbsd_core_info_proc_files (struct gdbarch *gdbarch, bfd *cbfd)
{
- bfd *cbfd = current_program_space->core_bfd ();
asection *section = bfd_get_section_by_name (cbfd, ".note.freebsdcore.files");
if (section == NULL)
{
@@ -1143,15 +1141,14 @@ fbsd_info_proc_mappings_entry (int addr_bit, ULONGEST kve_start,
}
}
-/* Implement "info proc mappings" for a corefile. */
+/* Implement "info proc mappings" for corefile CBFD. */
static void
-fbsd_core_info_proc_mappings (struct gdbarch *gdbarch)
+fbsd_core_info_proc_mappings (struct gdbarch *gdbarch, bfd *cbfd)
{
asection *section;
unsigned char *descdata, *descend;
size_t note_size;
- bfd *cbfd = current_program_space->core_bfd ();
section = bfd_get_section_by_name (cbfd, ".note.freebsdcore.vmmap");
if (section == NULL)
@@ -1194,15 +1191,14 @@ fbsd_core_info_proc_mappings (struct gdbarch *gdbarch)
}
/* Fetch the pathname of a vnode for a single file descriptor from the
- file table core note. */
+ file table core note in CBFD. */
static gdb::unique_xmalloc_ptr<char>
-fbsd_core_vnode_path (struct gdbarch *gdbarch, int fd)
+fbsd_core_vnode_path (struct gdbarch *gdbarch, bfd *cbfd, int fd)
{
asection *section;
unsigned char *descdata, *descend;
size_t note_size;
- bfd *cbfd = current_program_space->core_bfd ();
section = bfd_get_section_by_name (cbfd, ".note.freebsdcore.files");
if (section == NULL)
@@ -1242,14 +1238,12 @@ fbsd_core_vnode_path (struct gdbarch *gdbarch, int fd)
return nullptr;
}
-/* Helper function to read a struct timeval. */
+/* Helper function to read a struct timeval from core file CBFD. */
static void
-fbsd_core_fetch_timeval (struct gdbarch *gdbarch, unsigned char *data,
- LONGEST &sec, ULONGEST &usec)
+fbsd_core_fetch_timeval (struct gdbarch *gdbarch, bfd *cbfd,
+ unsigned char *data, LONGEST &sec, ULONGEST &usec)
{
- bfd *cbfd = current_program_space->core_bfd ();
-
if (gdbarch_addr_bit (gdbarch) == 64)
{
sec = bfd_get_signed_64 (cbfd, data);
@@ -1267,12 +1261,11 @@ fbsd_core_fetch_timeval (struct gdbarch *gdbarch, unsigned char *data,
}
}
-/* Print out the contents of a signal set. */
+/* Print out the contents of a signal set SIGSET in core file CBFD. */
static void
-fbsd_print_sigset (const char *descr, unsigned char *sigset)
+fbsd_print_sigset (bfd *cbfd, const char *descr, unsigned char *sigset)
{
- bfd *cbfd = current_program_space->core_bfd ();
gdb_printf ("%s: ", descr);
for (int i = 0; i < SIG_WORDS; i++)
gdb_printf ("%08x ",
@@ -1280,10 +1273,10 @@ fbsd_print_sigset (const char *descr, unsigned char *sigset)
gdb_printf ("\n");
}
-/* Implement "info proc status" for a corefile. */
+/* Implement "info proc status" for corefile CBFD. */
static void
-fbsd_core_info_proc_status (struct gdbarch *gdbarch)
+fbsd_core_info_proc_status (struct gdbarch *gdbarch, bfd *cbfd)
{
const struct kinfo_proc_layout *kp;
asection *section;
@@ -1292,7 +1285,6 @@ fbsd_core_info_proc_status (struct gdbarch *gdbarch)
size_t note_size;
ULONGEST value;
LONGEST sec;
- bfd *cbfd = current_program_space->core_bfd ();
section = bfd_get_section_by_name (cbfd, ".note.freebsdcore.proc");
if (section == NULL)
@@ -1387,25 +1379,25 @@ fbsd_core_info_proc_status (struct gdbarch *gdbarch)
value = bfd_get (long_bit, cbfd,
descdata + kp->ki_rusage_ch + kp->ru_majflt);
gdb_printf ("Major faults, children: %s\n", pulongest (value));
- fbsd_core_fetch_timeval (gdbarch,
+ fbsd_core_fetch_timeval (gdbarch, cbfd,
descdata + kp->ki_rusage + kp->ru_utime,
sec, value);
gdb_printf ("utime: %s.%06d\n", plongest (sec), (int) value);
- fbsd_core_fetch_timeval (gdbarch,
+ fbsd_core_fetch_timeval (gdbarch, cbfd,
descdata + kp->ki_rusage + kp->ru_stime,
sec, value);
gdb_printf ("stime: %s.%06d\n", plongest (sec), (int) value);
- fbsd_core_fetch_timeval (gdbarch,
+ fbsd_core_fetch_timeval (gdbarch, cbfd,
descdata + kp->ki_rusage_ch + kp->ru_utime,
sec, value);
gdb_printf ("utime, children: %s.%06d\n", plongest (sec), (int) value);
- fbsd_core_fetch_timeval (gdbarch,
+ fbsd_core_fetch_timeval (gdbarch, cbfd,
descdata + kp->ki_rusage_ch + kp->ru_stime,
sec, value);
gdb_printf ("stime, children: %s.%06d\n", plongest (sec), (int) value);
gdb_printf ("'nice' value: %d\n",
(int) bfd_get_signed_8 (core_bfd, descdata + kp->ki_nice));
- fbsd_core_fetch_timeval (gdbarch, descdata + kp->ki_start, sec, value);
+ fbsd_core_fetch_timeval (gdbarch, cbfd, descdata + kp->ki_start, sec, value);
gdb_printf ("Start time: %s.%06d\n", plongest (sec), (int) value);
gdb_printf ("Virtual memory size: %s kB\n",
pulongest (bfd_get (addr_bit, cbfd,
@@ -1426,15 +1418,15 @@ fbsd_core_info_proc_status (struct gdbarch *gdbarch)
pulongest (bfd_get (long_bit, cbfd,
descdata + kp->ki_rusage
+ kp->ru_maxrss)));
- fbsd_print_sigset ("Ignored Signals", descdata + kp->ki_sigignore);
- fbsd_print_sigset ("Caught Signals", descdata + kp->ki_sigcatch);
+ fbsd_print_sigset (cbfd, "Ignored Signals", descdata + kp->ki_sigignore);
+ fbsd_print_sigset (cbfd, "Caught Signals", descdata + kp->ki_sigcatch);
}
/* Implement the "core_info_proc" gdbarch method. */
static void
-fbsd_core_info_proc (struct gdbarch *gdbarch, const char *args,
- enum info_proc_what what)
+fbsd_core_info_proc (struct gdbarch *gdbarch, struct bfd *cbfd,
+ const char *args, enum info_proc_what what)
{
bool do_cmdline = false;
bool do_cwd = false;
@@ -1482,7 +1474,6 @@ fbsd_core_info_proc (struct gdbarch *gdbarch, const char *args,
return;
}
- bfd *cbfd = current_program_space->core_bfd ();
pid = bfd_core_file_pid (cbfd);
if (pid != 0)
gdb_printf (_("process %d\n"), pid);
@@ -1500,7 +1491,7 @@ fbsd_core_info_proc (struct gdbarch *gdbarch, const char *args,
if (do_cwd)
{
gdb::unique_xmalloc_ptr<char> cwd =
- fbsd_core_vnode_path (gdbarch, KINFO_FILE_FD_TYPE_CWD);
+ fbsd_core_vnode_path (gdbarch, cbfd, KINFO_FILE_FD_TYPE_CWD);
if (cwd)
gdb_printf ("cwd = '%s'\n", cwd.get ());
else
@@ -1509,18 +1500,18 @@ fbsd_core_info_proc (struct gdbarch *gdbarch, const char *args,
if (do_exe)
{
gdb::unique_xmalloc_ptr<char> exe =
- fbsd_core_vnode_path (gdbarch, KINFO_FILE_FD_TYPE_TEXT);
+ fbsd_core_vnode_path (gdbarch, cbfd, KINFO_FILE_FD_TYPE_TEXT);
if (exe)
gdb_printf ("exe = '%s'\n", exe.get ());
else
warning (_("unable to read executable path name"));
}
if (do_files)
- fbsd_core_info_proc_files (gdbarch);
+ fbsd_core_info_proc_files (gdbarch, cbfd);
if (do_mappings)
- fbsd_core_info_proc_mappings (gdbarch);
+ fbsd_core_info_proc_mappings (gdbarch, cbfd);
if (do_status)
- fbsd_core_info_proc_status (gdbarch);
+ fbsd_core_info_proc_status (gdbarch, cbfd);
}
/* Print descriptions of FreeBSD-specific AUXV entries to FILE. */
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index 7a8c799..d17c349 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -100,6 +100,7 @@ OUTPUTS = $(patsubst %,$(outdir)/%.dat,$(WHICH))
# --enable-targets=all GDB. You can override this by passing XMLTOC
# to make on the command line.
XMLTOC = \
+ alpha.xml \
microblaze-with-stack-protect.xml \
microblaze.xml \
mips-dsp-linux.xml \
@@ -203,6 +204,8 @@ FEATURE_XMLFILES = aarch64-core.xml \
aarch64-fpu.xml \
aarch64-pauth.xml \
aarch64-mte.xml \
+ aarch64-gcs.xml \
+ aarch64-gcs-linux.xml \
arc/v1-core.xml \
arc/v1-aux.xml \
arc/v2-core.xml \
@@ -225,6 +228,7 @@ FEATURE_XMLFILES = aarch64-core.xml \
i386/32bit-avx.xml \
i386/32bit-avx512.xml \
i386/32bit-segments.xml \
+ i386/32bit-ssp.xml \
i386/64bit-avx512.xml \
i386/64bit-core.xml \
i386/64bit-segments.xml \
@@ -232,6 +236,7 @@ FEATURE_XMLFILES = aarch64-core.xml \
i386/64bit-linux.xml \
i386/64bit-sse.xml \
i386/pkeys.xml \
+ i386/64bit-ssp.xml \
i386/x32-core.xml \
loongarch/base32.xml \
loongarch/base64.xml \
diff --git a/gdb/features/aarch64-gcs-linux.c b/gdb/features/aarch64-gcs-linux.c
new file mode 100644
index 0000000..6b0d25b
--- /dev/null
+++ b/gdb/features/aarch64-gcs-linux.c
@@ -0,0 +1,21 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: aarch64-gcs-linux.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_aarch64_gcs_linux (struct target_desc *result, long regnum)
+{
+ struct tdesc_feature *feature;
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.gcs.linux");
+ tdesc_type_with_fields *type_with_fields;
+ type_with_fields = tdesc_create_flags (feature, "features_flags", 8);
+ tdesc_add_flag (type_with_fields, 0, "PR_SHADOW_STACK_ENABLE");
+ tdesc_add_flag (type_with_fields, 1, "PR_SHADOW_STACK_WRITE");
+ tdesc_add_flag (type_with_fields, 2, "PR_SHADOW_STACK_PUSH");
+
+ tdesc_create_reg (feature, "gcs_features_enabled", regnum++, 1, "system", 64, "features_flags");
+ tdesc_create_reg (feature, "gcs_features_locked", regnum++, 1, "system", 64, "features_flags");
+ return regnum;
+}
diff --git a/gdb/features/aarch64-gcs-linux.xml b/gdb/features/aarch64-gcs-linux.xml
new file mode 100644
index 0000000..8d9d2ce
--- /dev/null
+++ b/gdb/features/aarch64-gcs-linux.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2025 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.aarch64.gcs.linux">
+ <flags id="features_flags" size="8">
+ <field name="PR_SHADOW_STACK_ENABLE" start="0" end="0"/>
+ <field name="PR_SHADOW_STACK_WRITE" start="1" end="1"/>
+ <field name="PR_SHADOW_STACK_PUSH" start="2" end="2"/>
+ </flags>
+
+ <reg name="gcs_features_enabled" bitsize="64" type="features_flags" group="system"/>
+ <reg name="gcs_features_locked" bitsize="64" type="features_flags" group="system"/>
+</feature>
diff --git a/gdb/features/aarch64-gcs.c b/gdb/features/aarch64-gcs.c
new file mode 100644
index 0000000..2b2caf2
--- /dev/null
+++ b/gdb/features/aarch64-gcs.c
@@ -0,0 +1,14 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: aarch64-gcs.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_aarch64_gcs (struct target_desc *result, long regnum)
+{
+ struct tdesc_feature *feature;
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.gcs");
+ tdesc_create_reg (feature, "gcspr", regnum++, 1, "system", 64, "data_ptr");
+ return regnum;
+}
diff --git a/gdb/features/aarch64-gcs.xml b/gdb/features/aarch64-gcs.xml
new file mode 100644
index 0000000..bbee5e0
--- /dev/null
+++ b/gdb/features/aarch64-gcs.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2025 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.aarch64.gcs">
+ <reg name="gcspr" bitsize="64" type="data_ptr" group="system"/>
+</feature>
diff --git a/gdb/features/alpha-core.xml b/gdb/features/alpha-core.xml
new file mode 100644
index 0000000..c9e12f4
--- /dev/null
+++ b/gdb/features/alpha-core.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2025 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.alpha.core">
+ <!-- IEEE rounding mode values -->
+ <enum id="dyn_rm_enum" size="8">
+ <!-- Chopped rounding mode -->
+ <evalue name="chop" value="0"/>
+ <!-- Minus infinity -->
+ <evalue name="-inf" value="1"/>
+ <!-- Normal rounding -->
+ <evalue name="norm" value="2"/>
+ <!-- Plus infinity -->
+ <evalue name="+inf" value="3"/>
+ </enum>
+
+ <!-- Floating-Point Control Register Flags -->
+ <flags id="fpcr_flags" size="8">
+ <!-- Denormal Operand Exception Disable -->
+ <field name="DNOD" start="47" end="47"/>
+ <!-- Denormal Operands to Zero -->
+ <field name="DNZ" start="48" end="48"/>
+ <!-- Invalid Operation Disable -->
+ <field name="INVD" start="49" end="49"/>
+ <!-- Division by Zero Disable -->
+ <field name="DZED" start="50" end="50"/>
+ <!-- Overflow Disable -->
+ <field name="OVFD" start="51" end="51"/>
+ <!-- Invalid Operation -->
+ <field name="INV" start="52" end="52"/>
+ <!-- Division by Zero -->
+ <field name="DZE" start="53" end="53"/>
+ <!-- Overflow -->
+ <field name="OVF" start="54" end="54"/>
+ <!-- Underflow -->
+ <field name="UNF" start="55" end="55"/>
+ <!-- Inexact Result -->
+ <field name="INE" start="56" end="56"/>
+ <!-- Integer Overflow -->
+ <field name="IOV" start="57" end="57"/>
+ <!-- Dynamic Rounding Mode -->
+ <field name="DYN_RM" start="58" end="59" type="dyn_rm_enum"/>
+ <!-- Underflow to Zero -->
+ <field name="UNDZ" start="60" end="60"/>
+ <!-- Underflow Disable -->
+ <field name="UNFD" start="61" end="61"/>
+ <!-- Inexact Disable -->
+ <field name="INED" start="62" end="62"/>
+ <!-- Summary Bit -->
+ <field name="SUM" start="63" end="63"/>
+ </flags>
+
+ <!-- Integer Registers -->
+ <reg name="v0" bitsize="64" type="int64"/>
+ <reg name="t0" bitsize="64" type="int64"/>
+ <reg name="t1" bitsize="64" type="int64"/>
+ <reg name="t2" bitsize="64" type="int64"/>
+ <reg name="t3" bitsize="64" type="int64"/>
+ <reg name="t4" bitsize="64" type="int64"/>
+ <reg name="t5" bitsize="64" type="int64"/>
+ <reg name="t6" bitsize="64" type="int64"/>
+ <reg name="t7" bitsize="64" type="int64"/>
+ <reg name="s0" bitsize="64" type="int64"/>
+ <reg name="s1" bitsize="64" type="int64"/>
+ <reg name="s2" bitsize="64" type="int64"/>
+ <reg name="s3" bitsize="64" type="int64"/>
+ <reg name="s4" bitsize="64" type="int64"/>
+ <reg name="s5" bitsize="64" type="int64"/>
+ <reg name="fp" bitsize="64" type="int64"/>
+ <reg name="a0" bitsize="64" type="int64"/>
+ <reg name="a1" bitsize="64" type="int64"/>
+ <reg name="a2" bitsize="64" type="int64"/>
+ <reg name="a3" bitsize="64" type="int64"/>
+ <reg name="a4" bitsize="64" type="int64"/>
+ <reg name="a5" bitsize="64" type="int64"/>
+ <reg name="t8" bitsize="64" type="int64"/>
+ <reg name="t9" bitsize="64" type="int64"/>
+ <reg name="t10" bitsize="64" type="int64"/>
+ <reg name="t11" bitsize="64" type="int64"/>
+ <reg name="ra" bitsize="64" type="int64"/>
+ <reg name="t12" bitsize="64" type="int64"/>
+ <reg name="at" bitsize="64" type="int64"/>
+ <reg name="gp" bitsize="64" type="data_ptr"/>
+ <reg name="sp" bitsize="64" type="data_ptr"/>
+ <reg name="zero" bitsize="64" type="int64" save-restore="no"/>
+
+ <!-- Floating-Point Registers -->
+ <reg name="f0" bitsize="64" type="float" group="float"/>
+ <reg name="f1" bitsize="64" type="float" group="float"/>
+ <reg name="f2" bitsize="64" type="float" group="float"/>
+ <reg name="f3" bitsize="64" type="float" group="float"/>
+ <reg name="f4" bitsize="64" type="float" group="float"/>
+ <reg name="f5" bitsize="64" type="float" group="float"/>
+ <reg name="f6" bitsize="64" type="float" group="float"/>
+ <reg name="f7" bitsize="64" type="float" group="float"/>
+ <reg name="f8" bitsize="64" type="float" group="float"/>
+ <reg name="f9" bitsize="64" type="float" group="float"/>
+ <reg name="f10" bitsize="64" type="float" group="float"/>
+ <reg name="f11" bitsize="64" type="float" group="float"/>
+ <reg name="f12" bitsize="64" type="float" group="float"/>
+ <reg name="f13" bitsize="64" type="float" group="float"/>
+ <reg name="f14" bitsize="64" type="float" group="float"/>
+ <reg name="f15" bitsize="64" type="float" group="float"/>
+ <reg name="f16" bitsize="64" type="float" group="float"/>
+ <reg name="f17" bitsize="64" type="float" group="float"/>
+ <reg name="f18" bitsize="64" type="float" group="float"/>
+ <reg name="f19" bitsize="64" type="float" group="float"/>
+ <reg name="f20" bitsize="64" type="float" group="float"/>
+ <reg name="f21" bitsize="64" type="float" group="float"/>
+ <reg name="f22" bitsize="64" type="float" group="float"/>
+ <reg name="f23" bitsize="64" type="float" group="float"/>
+ <reg name="f24" bitsize="64" type="float" group="float"/>
+ <reg name="f25" bitsize="64" type="float" group="float"/>
+ <reg name="f26" bitsize="64" type="float" group="float"/>
+ <reg name="f27" bitsize="64" type="float" group="float"/>
+ <reg name="f28" bitsize="64" type="float" group="float"/>
+ <reg name="f29" bitsize="64" type="float" group="float"/>
+ <reg name="f30" bitsize="64" type="float" group="float"/>
+
+ <!-- Floating-Point Control Register -->
+ <reg name="fpcr" bitsize="64" type="fpcr_flags" group="float"/>
+
+ <!-- Program Counter -->
+ <reg name="pc" bitsize="64" type="code_ptr"/>
+
+ <!-- Reserved Index for Former Virtual Register -->
+ <reg name="" bitsize="64" type="int64" save-restore="no"/>
+
+ <!-- PALcode Memory Slot -->
+ <reg name="unique" bitsize="64" type="int64" group="system"/>
+</feature>
diff --git a/gdb/features/alpha.c b/gdb/features/alpha.c
new file mode 100644
index 0000000..35f12fc
--- /dev/null
+++ b/gdb/features/alpha.c
@@ -0,0 +1,111 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: alpha.xml */
+
+#include "osabi.h"
+#include "target-descriptions.h"
+
+const struct target_desc *tdesc_alpha;
+static void
+initialize_tdesc_alpha (void)
+{
+ target_desc_up result = allocate_target_description ();
+ struct tdesc_feature *feature;
+
+ feature = tdesc_create_feature (result.get (), "org.gnu.gdb.alpha.core");
+ tdesc_type_with_fields *type_with_fields;
+ type_with_fields = tdesc_create_enum (feature, "dyn_rm_enum", 8);
+ tdesc_add_enum_value (type_with_fields, 0, "chop");
+ tdesc_add_enum_value (type_with_fields, 1, "-inf");
+ tdesc_add_enum_value (type_with_fields, 2, "norm");
+ tdesc_add_enum_value (type_with_fields, 3, "+inf");
+
+ type_with_fields = tdesc_create_flags (feature, "fpcr_flags", 8);
+ tdesc_add_flag (type_with_fields, 47, "DNOD");
+ tdesc_add_flag (type_with_fields, 48, "DNZ");
+ tdesc_add_flag (type_with_fields, 49, "INVD");
+ tdesc_add_flag (type_with_fields, 50, "DZED");
+ tdesc_add_flag (type_with_fields, 51, "OVFD");
+ tdesc_add_flag (type_with_fields, 52, "INV");
+ tdesc_add_flag (type_with_fields, 53, "DZE");
+ tdesc_add_flag (type_with_fields, 54, "OVF");
+ tdesc_add_flag (type_with_fields, 55, "UNF");
+ tdesc_add_flag (type_with_fields, 56, "INE");
+ tdesc_add_flag (type_with_fields, 57, "IOV");
+ tdesc_type *field_type;
+ field_type = tdesc_named_type (feature, "dyn_rm_enum");
+ tdesc_add_typed_bitfield (type_with_fields, "DYN_RM", 58, 59, field_type);
+ tdesc_add_flag (type_with_fields, 60, "UNDZ");
+ tdesc_add_flag (type_with_fields, 61, "UNFD");
+ tdesc_add_flag (type_with_fields, 62, "INED");
+ tdesc_add_flag (type_with_fields, 63, "SUM");
+
+ tdesc_create_reg (feature, "v0", 0, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "t0", 1, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "t1", 2, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "t2", 3, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "t3", 4, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "t4", 5, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "t5", 6, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "t6", 7, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "t7", 8, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "s0", 9, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "s1", 10, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "s2", 11, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "s3", 12, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "s4", 13, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "s5", 14, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "fp", 15, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "a0", 16, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "a1", 17, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "a2", 18, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "a3", 19, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "a4", 20, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "a5", 21, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "t8", 22, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "t9", 23, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "t10", 24, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "t11", 25, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "ra", 26, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "t12", 27, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "at", 28, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "gp", 29, 1, NULL, 64, "data_ptr");
+ tdesc_create_reg (feature, "sp", 30, 1, NULL, 64, "data_ptr");
+ tdesc_create_reg (feature, "zero", 31, 0, NULL, 64, "int64");
+ tdesc_create_reg (feature, "f0", 32, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f1", 33, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f2", 34, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f3", 35, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f4", 36, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f5", 37, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f6", 38, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f7", 39, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f8", 40, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f9", 41, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f10", 42, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f11", 43, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f12", 44, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f13", 45, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f14", 46, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f15", 47, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f16", 48, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f17", 49, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f18", 50, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f19", 51, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f20", 52, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f21", 53, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f22", 54, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f23", 55, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f24", 56, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f25", 57, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f26", 58, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f27", 59, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f28", 60, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f29", 61, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "f30", 62, 1, "float", 64, "float");
+ tdesc_create_reg (feature, "fpcr", 63, 1, "float", 64, "fpcr_flags");
+ tdesc_create_reg (feature, "pc", 64, 1, NULL, 64, "code_ptr");
+ tdesc_create_reg (feature, "", 65, 0, NULL, 64, "int64");
+ tdesc_create_reg (feature, "unique", 66, 1, "system", 64, "int64");
+
+ tdesc_alpha = result.release ();
+}
diff --git a/gdb/features/alpha.xml b/gdb/features/alpha.xml
new file mode 100644
index 0000000..3ae0ab8
--- /dev/null
+++ b/gdb/features/alpha.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2025 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<target version="1.0">
+ <xi:include href="alpha-core.xml"/>
+</target>
diff --git a/gdb/features/i386/32bit-ssp.c b/gdb/features/i386/32bit-ssp.c
new file mode 100644
index 0000000..991bae3
--- /dev/null
+++ b/gdb/features/i386/32bit-ssp.c
@@ -0,0 +1,14 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: 32bit-ssp.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_i386_32bit_ssp (struct target_desc *result, long regnum)
+{
+ struct tdesc_feature *feature;
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.i386.pl3_ssp");
+ tdesc_create_reg (feature, "pl3_ssp", regnum++, 1, NULL, 32, "data_ptr");
+ return regnum;
+}
diff --git a/gdb/features/i386/32bit-ssp.xml b/gdb/features/i386/32bit-ssp.xml
new file mode 100644
index 0000000..d17e700
--- /dev/null
+++ b/gdb/features/i386/32bit-ssp.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2022-2024 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.i386.pl3_ssp">
+ <reg name="pl3_ssp" bitsize="32" type="data_ptr"/>
+</feature>
diff --git a/gdb/features/i386/64bit-ssp.c b/gdb/features/i386/64bit-ssp.c
new file mode 100644
index 0000000..5468099
--- /dev/null
+++ b/gdb/features/i386/64bit-ssp.c
@@ -0,0 +1,14 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: 64bit-ssp.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_i386_64bit_ssp (struct target_desc *result, long regnum)
+{
+ struct tdesc_feature *feature;
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.i386.pl3_ssp");
+ tdesc_create_reg (feature, "pl3_ssp", regnum++, 1, NULL, 64, "data_ptr");
+ return regnum;
+}
diff --git a/gdb/features/i386/64bit-ssp.xml b/gdb/features/i386/64bit-ssp.xml
new file mode 100644
index 0000000..a0688d0
--- /dev/null
+++ b/gdb/features/i386/64bit-ssp.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2022-2024 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.i386.pl3_ssp">
+ <reg name="pl3_ssp" bitsize="64" type="data_ptr"/>
+</feature>
diff --git a/gdb/filesystem.c b/gdb/filesystem.c
index 51e1c3f..a272c13 100644
--- a/gdb/filesystem.c
+++ b/gdb/filesystem.c
@@ -76,9 +76,7 @@ is \"%s\".\n"),
value);
}
-void _initialize_filesystem ();
-void
-_initialize_filesystem ()
+INIT_GDB_FILE (filesystem)
{
add_setshow_enum_cmd ("target-file-system-kind",
class_files,
diff --git a/gdb/findcmd.c b/gdb/findcmd.c
index 993c487..03c3fcc 100644
--- a/gdb/findcmd.c
+++ b/gdb/findcmd.c
@@ -18,7 +18,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "arch-utils.h"
-#include <ctype.h>
#include "cli/cli-cmds.h"
#include "value.h"
#include "target.h"
@@ -76,12 +75,12 @@ parse_find_args (const char *args, ULONGEST *max_countp,
{
++s;
- while (*s != '\0' && *s != '/' && !isspace (*s))
+ while (*s != '\0' && *s != '/' && !c_isspace (*s))
{
- if (isdigit (*s))
+ if (c_isdigit (*s))
{
max_count = atoi (s);
- while (isdigit (*s))
+ while (c_isdigit (*s))
++s;
continue;
}
@@ -279,9 +278,7 @@ find_command (const char *args, int from_tty)
found_count > 1 ? "s" : "");
}
-void _initialize_mem_search ();
-void
-_initialize_mem_search ()
+INIT_GDB_FILE (mem_search)
{
add_cmd ("find", class_vars, find_command, _("\
Search memory for a sequence of bytes.\n\
diff --git a/gdb/findvar.c b/gdb/findvar.c
index 9da5c48..41efc8d 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -65,14 +65,15 @@ value_of_register (int regnum, const frame_info_ptr &next_frame)
/* See value.h. */
value *
-value_of_register_lazy (const frame_info_ptr &next_frame, int regnum)
+value_of_register_lazy (const frame_info_ptr &next_frame, int regnum,
+ struct type *type)
{
gdbarch *gdbarch = frame_unwind_arch (next_frame);
gdb_assert (regnum < gdbarch_num_cooked_regs (gdbarch));
gdb_assert (next_frame != nullptr);
- return value::allocate_register_lazy (next_frame, regnum);
+ return value::allocate_register_lazy (next_frame, regnum, type);
}
/* Given a pointer of type TYPE in target form in BUF, return the
@@ -124,7 +125,7 @@ symbol_read_needs (struct symbol *sym)
computed_ops != nullptr)
return computed_ops->get_symbol_read_needs (sym);
- switch (sym->aclass ())
+ switch (sym->loc_class ())
{
/* All cases listed explicitly so that gcc -Wall will detect it if
we failed to consider one. */
@@ -306,7 +307,7 @@ language_defn::read_var_value (struct symbol *var,
if (const symbol_computed_ops *computed_ops = var->computed_ops ())
return computed_ops->read_variable (var, frame);
- switch (var->aclass ())
+ switch (var->loc_class ())
{
case LOC_CONST:
if (is_dynamic_type (type))
@@ -429,7 +430,7 @@ language_defn::read_var_value (struct symbol *var,
const symbol_register_ops *reg_ops = var->register_ops ();
int regno = reg_ops->register_number (var, get_frame_arch (frame));
- if (var->aclass () == LOC_REGPARM_ADDR)
+ if (var->loc_class () == LOC_REGPARM_ADDR)
addr = value_as_address
(value_from_register (lookup_pointer_type (type), regno, frame));
else
@@ -445,9 +446,8 @@ language_defn::read_var_value (struct symbol *var,
struct obj_section *obj_section;
bound_minimal_symbol bmsym;
- gdbarch_iterate_over_objfiles_in_search_order
- (var->arch (),
- [var, &bmsym] (objfile *objfile)
+ current_program_space->iterate_over_objfiles_in_search_order
+ ([var, &bmsym] (objfile *objfile)
{
bmsym = lookup_minimal_symbol (current_program_space,
var->linkage_name (), objfile);
diff --git a/gdb/fork-child.c b/gdb/fork-child.c
index 8abfbda..fd7f1e0 100644
--- a/gdb/fork-child.c
+++ b/gdb/fork-child.c
@@ -153,9 +153,7 @@ show_startup_with_shell (struct ui_file *file, int from_tty,
value);
}
-void _initialize_fork_child ();
-void
-_initialize_fork_child ()
+INIT_GDB_FILE (fork_child)
{
add_setshow_filename_cmd ("exec-wrapper", class_run, &exec_wrapper, _("\
Set a wrapper for running programs.\n\
diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
index 9ed2dee..3709215 100644
--- a/gdb/frame-unwind.c
+++ b/gdb/frame-unwind.c
@@ -49,6 +49,7 @@ static constexpr std::initializer_list<const frame_unwind *>
standard_unwinders =
{
&dummy_frame_unwind,
+#if defined(DWARF_FORMAT_AVAILABLE)
/* The DWARF tailcall sniffer must come before the inline sniffer.
Otherwise, we can end up in a situation where a DWARF frame finds
tailcall information, but then the inline sniffer claims a frame
@@ -57,6 +58,7 @@ static constexpr std::initializer_list<const frame_unwind *>
activated if the newer frame was created using the DWARF
unwinder, and it also found tailcall information. */
&dwarf2_tailcall_frame_unwind,
+#endif
&inline_frame_unwind,
};
@@ -295,8 +297,16 @@ struct value *
frame_unwind_got_register (const frame_info_ptr &frame,
int regnum, int new_regnum)
{
+ struct gdbarch *gdbarch = frame_unwind_arch (frame);
+ struct type *regnum_type = register_type (gdbarch, regnum);
+ struct type *new_regnum_type = register_type (gdbarch, new_regnum);
+
+ /* REGNUM has been copied into NEW_REGNUM, therefore, the former
+ must be smaller or equal in size to the latter. */
+ gdb_assert (regnum_type->length () <= new_regnum_type->length ());
+
return value_of_register_lazy (get_next_frame_sentinel_okay (frame),
- new_regnum);
+ new_regnum, regnum_type);
}
/* Return a value which indicates that FRAME saved REGNUM in memory at
@@ -612,9 +622,7 @@ maintenance_enable_frame_unwinders (const char *args, int from_tty)
enable_disable_frame_unwinders (args, from_tty, true);
}
-void _initialize_frame_unwind ();
-void
-_initialize_frame_unwind ()
+INIT_GDB_FILE (frame_unwind)
{
/* Add "maint info frame-unwinders". */
add_cmd ("frame-unwinders",
diff --git a/gdb/frame.c b/gdb/frame.c
index fe5336f..5c41dcd 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2617,7 +2617,7 @@ inside_main_func (const frame_info_ptr &this_frame)
SEARCH_FUNCTION_DOMAIN, nullptr);
/* This lookup should always yield a block-valued symbol. */
- if (bs.symbol != nullptr && bs.symbol->aclass () == LOC_BLOCK)
+ if (bs.symbol != nullptr && bs.symbol->loc_class () == LOC_BLOCK)
{
const struct block *block = bs.symbol->value_block ();
gdb_assert (block != nullptr);
@@ -2663,15 +2663,14 @@ get_prev_frame (const frame_info_ptr &this_frame)
{
FRAME_SCOPED_DEBUG_ENTER_EXIT;
- CORE_ADDR frame_pc;
- int frame_pc_p;
+ std::optional<CORE_ADDR> frame_pc;
/* There is always a frame. If this assertion fails, suspect that
something should be calling get_selected_frame() or
get_current_frame(). */
gdb_assert (this_frame != NULL);
- frame_pc_p = get_frame_pc_if_available (this_frame, &frame_pc);
+ frame_pc = get_frame_pc_if_available (this_frame);
/* tausq/2004-12-07: Dummy frames are skipped because it doesn't make much
sense to stop unwinding at a dummy frame. One place where a dummy
@@ -2686,7 +2685,7 @@ get_prev_frame (const frame_info_ptr &this_frame)
if (this_frame->level >= 0
&& get_frame_type (this_frame) == NORMAL_FRAME
&& !user_set_backtrace_options.backtrace_past_main
- && frame_pc_p
+ && frame_pc.has_value ()
&& inside_main_func (this_frame))
/* Don't unwind past main(). Note, this is done _before_ the
frame has been marked as previously unwound. That way if the
@@ -2733,7 +2732,7 @@ get_prev_frame (const frame_info_ptr &this_frame)
if (this_frame->level >= 0
&& get_frame_type (this_frame) == NORMAL_FRAME
&& !user_set_backtrace_options.backtrace_past_entry
- && frame_pc_p
+ && frame_pc.has_value ()
&& inside_entry_func (this_frame))
{
frame_debug_got_null_frame (this_frame, "inside entry func");
@@ -2747,7 +2746,7 @@ get_prev_frame (const frame_info_ptr &this_frame)
&& (get_frame_type (this_frame) == NORMAL_FRAME
|| get_frame_type (this_frame) == INLINE_FRAME)
&& get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME
- && frame_pc_p && frame_pc == 0)
+ && frame_pc.has_value () && *frame_pc == 0)
{
frame_debug_got_null_frame (this_frame, "zero PC");
return NULL;
@@ -2763,25 +2762,24 @@ get_frame_pc (const frame_info_ptr &frame)
return frame_unwind_pc (frame_info_ptr (frame->next));
}
-bool
-get_frame_pc_if_available (const frame_info_ptr &frame, CORE_ADDR *pc)
+std::optional<CORE_ADDR>
+get_frame_pc_if_available (const frame_info_ptr &frame)
{
+ std::optional<CORE_ADDR> pc;
gdb_assert (frame->next != NULL);
try
{
- *pc = frame_unwind_pc (frame_info_ptr (frame->next));
+ pc = frame_unwind_pc (frame_info_ptr (frame->next));
}
catch (const gdb_exception_error &ex)
{
- if (ex.error == NOT_AVAILABLE_ERROR)
- return false;
- else
+ if (ex.error != NOT_AVAILABLE_ERROR)
throw;
}
- return true;
+ return pc;
}
/* Return an address that falls within THIS_FRAME's code block. */
@@ -2870,7 +2868,7 @@ find_frame_sal (const frame_info_ptr &frame)
{
frame_info_ptr next_frame;
int notcurrent;
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
if (frame_inlined_callees (frame) > 0)
{
@@ -2914,11 +2912,11 @@ find_frame_sal (const frame_info_ptr &frame)
PC and such a PC indicates the current (rather than next)
instruction/line, consequently, for such cases, want to get the
line containing fi->pc. */
- if (!get_frame_pc_if_available (frame, &pc))
+ if (!(pc = get_frame_pc_if_available (frame)))
return {};
- notcurrent = (pc != get_frame_address_in_block (frame));
- return find_pc_line (pc, notcurrent);
+ notcurrent = (*pc != get_frame_address_in_block (frame));
+ return find_pc_line (*pc, notcurrent);
}
/* Per "frame.h", return the ``address'' of the frame. Code should
@@ -3424,9 +3422,7 @@ frame_info_ptr::reinflate () const
return m_ptr;
}
-void _initialize_frame ();
-void
-_initialize_frame ()
+INIT_GDB_FILE (frame)
{
obstack_init (&frame_cache_obstack);
diff --git a/gdb/frame.h b/gdb/frame.h
index b240662..99a7983 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -504,7 +504,8 @@ extern CORE_ADDR get_frame_pc (const frame_info_ptr &);
/* Same as get_frame_pc, but return a boolean indication of whether
the PC is actually available, instead of throwing an error. */
-extern bool get_frame_pc_if_available (const frame_info_ptr &frame, CORE_ADDR *pc);
+extern std::optional<CORE_ADDR> get_frame_pc_if_available
+ (const frame_info_ptr &frame);
/* An address (not necessarily aligned to an instruction boundary)
that falls within THIS frame's code block.
diff --git a/gdb/frv-linux-tdep.c b/gdb/frv-linux-tdep.c
index 067b983..2a0fe1b 100644
--- a/gdb/frv-linux-tdep.c
+++ b/gdb/frv-linux-tdep.c
@@ -482,9 +482,7 @@ frv_linux_elf_osabi_sniffer (bfd *abfd)
return GDB_OSABI_UNKNOWN;
}
-void _initialize_frv_linux_tdep ();
-void
-_initialize_frv_linux_tdep ()
+INIT_GDB_FILE (frv_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_frv, 0, GDB_OSABI_LINUX,
frv_linux_init_abi);
diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c
index 3608872..b2d6e1a 100644
--- a/gdb/frv-tdep.c
+++ b/gdb/frv-tdep.c
@@ -25,6 +25,7 @@
#include "frame.h"
#include "frame-unwind.h"
#include "frame-base.h"
+#include "solib-frv.h"
#include "trad-frame.h"
#include "dis-asm.h"
#include "sim-regno.h"
@@ -1554,7 +1555,7 @@ frv_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_convert_from_func_ptr_addr (gdbarch,
frv_convert_from_func_ptr_addr);
- set_gdbarch_so_ops (gdbarch, &frv_so_ops);
+ set_gdbarch_make_solib_ops (gdbarch, make_frv_solib_ops);
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);
@@ -1569,9 +1570,7 @@ frv_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_frv_tdep ();
-void
-_initialize_frv_tdep ()
+INIT_GDB_FILE (frv_tdep)
{
gdbarch_register (bfd_arch_frv, frv_gdbarch_init);
}
diff --git a/gdb/frv-tdep.h b/gdb/frv-tdep.h
index 07982b4..7b51b42 100644
--- a/gdb/frv-tdep.h
+++ b/gdb/frv-tdep.h
@@ -118,7 +118,4 @@ CORE_ADDR frv_fdpic_find_canonical_descriptor (CORE_ADDR entry_point);
needed for TLS support. */
CORE_ADDR frv_fetch_objfile_link_map (struct objfile *objfile);
-struct solib_ops;
-extern const solib_ops frv_so_ops;
-
#endif /* GDB_FRV_TDEP_H */
diff --git a/gdb/ft32-tdep.c b/gdb/ft32-tdep.c
index f84e225..3384929 100644
--- a/gdb/ft32-tdep.c
+++ b/gdb/ft32-tdep.c
@@ -621,9 +621,7 @@ ft32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Register this machine's init routine. */
-void _initialize_ft32_tdep ();
-void
-_initialize_ft32_tdep ()
+INIT_GDB_FILE (ft32_tdep)
{
gdbarch_register (bfd_arch_ft32, ft32_gdbarch_init);
}
diff --git a/gdb/gcore-1.in b/gdb/gcore-1.in
index 1220f4a..2f6eb02 100644
--- a/gdb/gcore-1.in
+++ b/gdb/gcore-1.in
@@ -34,11 +34,11 @@ data_directory_opt=()
function print_usage() {
prefix="Usage: $0"
- paddin=$(printf '%*s' ${#prefix})
+ padding=$(printf '%*s' ${#prefix})
echo "$prefix [-h|--help] [-v|--version]"
- echo "$paddin [-a] [-o prefix] [-d data-directory]"
- echo "$paddin pid1 [pid2...pidN]"
+ echo "$padding [-a] [-o prefix] [-d data-directory]"
+ echo "$padding pid1 [pid2...pidN]"
}
function print_try_help() {
diff --git a/gdb/gcore.c b/gdb/gcore.c
index fa15d06..ce5f570 100644
--- a/gdb/gcore.c
+++ b/gdb/gcore.c
@@ -425,13 +425,13 @@ gcore_create_callback (CORE_ADDR vaddr, unsigned long size, int read,
If so, we can avoid copying its contents by clearing SEC_LOAD. */
for (objfile *objfile : current_program_space->objfiles ())
- for (obj_section *objsec : objfile->sections ())
+ for (obj_section &objsec : objfile->sections ())
{
bfd *abfd = objfile->obfd.get ();
- asection *asec = objsec->the_bfd_section;
+ asection *asec = objsec.the_bfd_section;
bfd_vma align = (bfd_vma) 1 << bfd_section_alignment (asec);
- bfd_vma start = objsec->addr () & -align;
- bfd_vma end = (objsec->endaddr () + align - 1) & -align;
+ bfd_vma start = objsec.addr () & -align;
+ bfd_vma end = (objsec.endaddr () + align - 1) & -align;
/* Match if either the entire memory region lies inside the
section (i.e. a mapping covering some pages of a large
@@ -533,9 +533,9 @@ objfile_find_memory_regions (struct target_ops *self,
/* Call callback function for each objfile section. */
for (objfile *objfile : current_program_space->objfiles ())
- for (obj_section *objsec : objfile->sections ())
+ for (obj_section &objsec : objfile->sections ())
{
- asection *isec = objsec->the_bfd_section;
+ asection *isec = objsec.the_bfd_section;
flagword flags = bfd_section_flags (isec);
/* Separate debug info files are irrelevant for gcore. */
@@ -547,7 +547,7 @@ objfile_find_memory_regions (struct target_ops *self,
int size = bfd_section_size (isec);
int ret;
- ret = (*func) (objsec->addr (), size,
+ ret = (*func) (objsec.addr (), size,
1, /* All sections will be readable. */
(flags & SEC_READONLY) == 0, /* Writable. */
(flags & SEC_CODE) != 0, /* Executable. */
@@ -861,9 +861,7 @@ gcore_find_signalled_thread ()
return nullptr;
}
-void _initialize_gcore ();
-void
-_initialize_gcore ()
+INIT_GDB_FILE (gcore)
{
cmd_list_element *generate_core_file_cmd
= add_com ("generate-core-file", class_files, gcore_command, _("\
diff --git a/gdb/gdb-demangle.c b/gdb/gdb-demangle.c
index 239306a..c285788 100644
--- a/gdb/gdb-demangle.c
+++ b/gdb/gdb-demangle.c
@@ -208,9 +208,7 @@ demangle_command (const char *args, int from_tty)
error (_("Can't demangle \"%s\""), name);
}
-void _initialize_gdb_demangle ();
-void
-_initialize_gdb_demangle ()
+INIT_GDB_FILE (gdb_demangle)
{
int i, ndems;
diff --git a/gdb/gdb-gdb.gdb.in b/gdb/gdb-gdb.gdb.in
index d5d533a..34ce5f0 100644
--- a/gdb/gdb-gdb.gdb.in
+++ b/gdb/gdb-gdb.gdb.in
@@ -37,3 +37,6 @@ document pdie
Pretty print a DWARF DIE.
Syntax: pdie die [depth]
end
+
+# Trivial and uninteresting functions to skip.
+skip -rfu "^gdb::ref_ptr<.*>::get"
diff --git a/gdb/gdb-gdb.py.in b/gdb/gdb-gdb.py.in
index 4d96235..7388c6f 100644
--- a/gdb/gdb-gdb.py.in
+++ b/gdb/gdb-gdb.py.in
@@ -122,7 +122,7 @@ class StructTypePrettyPrinter:
class StructMainTypePrettyPrinter:
- """Pretty-print an objet of type main_type"""
+ """Pretty-print an object of type main_type"""
def __init__(self, val):
self.val = val
@@ -164,8 +164,10 @@ class StructMainTypePrettyPrinter:
return "physaddr = 0x%x" % loc_val["physaddr"]
elif loc_kind == "FIELD_LOC_KIND_PHYSNAME":
return "physname = %s" % loc_val["physname"]
- elif loc_kind == "FIELD_LOC_KIND_DWARF_BLOCK":
- return "dwarf_block = %s" % loc_val["dwarf_block"]
+ elif loc_kind == "FIELD_LOC_KIND_DWARF_BLOCK_ADDR":
+ return "dwarf_block_addr = %s" % loc_val["dwarf_block"]
+ elif loc_kind == "FIELD_LOC_KIND_DWARF_BLOCK_BITPOS":
+ return "dwarf_block_bitpos = %s" % loc_val["dwarf_block"]
else:
return "m_loc = ??? (unsupported m_loc_kind value)"
diff --git a/gdb/gdb-stabs.h b/gdb/gdb-stabs.h
index 2f3a0a5..9909129 100644
--- a/gdb/gdb-stabs.h
+++ b/gdb/gdb-stabs.h
@@ -20,9 +20,9 @@
#ifndef GDB_GDB_STABS_H
#define GDB_GDB_STABS_H
-/* During initial symbol readin, we need to have a structure to keep
+/* During initial symbol reading, we need to have a structure to keep
track of which psymtabs have which bincls in them. This structure
- is used during readin to setup the list of dependencies within each
+ is used during reading to setup the list of dependencies within each
partial symbol table. */
struct legacy_psymtab;
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 06d6f5c..2e477eb 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -1346,9 +1346,7 @@ gdb_bfd_init ()
error (_("fatal error: libbfd ABI mismatch"));
}
-void _initialize_gdb_bfd ();
-void
-_initialize_gdb_bfd ()
+INIT_GDB_FILE (gdb_bfd)
{
add_cmd ("bfds", class_maintenance, maintenance_info_bfds, _("\
List the BFDs that are currently open."),
diff --git a/gdb/gdb_buildall.sh b/gdb/gdb_buildall.sh
index 430aae4..2053333 100644
--- a/gdb/gdb_buildall.sh
+++ b/gdb/gdb_buildall.sh
@@ -261,7 +261,7 @@ echo "done."
# Clean up build directory if necessary.
if ${clean}
then
- echo "cleanning up $dir"
+ echo "cleaning up $dir"
rm -rf ${dir}
fi
diff --git a/gdb/gdb_wchar.h b/gdb/gdb_wchar.h
index 417d5ba..9db0d5e 100644
--- a/gdb/gdb_wchar.h
+++ b/gdb/gdb_wchar.h
@@ -113,8 +113,8 @@ typedef char gdb_wchar_t;
typedef int gdb_wint_t;
#define gdb_wcslen strlen
-#define gdb_iswprint isprint
-#define gdb_iswxdigit isxdigit
+#define gdb_iswprint c_isprint
+#define gdb_iswxdigit c_isxdigit
#define gdb_btowc /* empty */
#define gdb_WEOF EOF
diff --git a/gdb/gdbarch-gen.c b/gdb/gdbarch-gen.c
index 32d1659..7887b13 100644
--- a/gdb/gdbarch-gen.c
+++ b/gdb/gdbarch-gen.c
@@ -153,11 +153,11 @@ struct gdbarch
gdbarch_set_memtags_ftype *set_memtags = default_set_memtags;
gdbarch_get_memtag_ftype *get_memtag = default_get_memtag;
CORE_ADDR memtag_granule_size = 0;
- gdbarch_software_single_step_ftype *software_single_step = nullptr;
+ gdbarch_get_next_pcs_ftype *get_next_pcs = nullptr;
gdbarch_single_step_through_delay_ftype *single_step_through_delay = nullptr;
gdbarch_print_insn_ftype *print_insn = default_print_insn;
gdbarch_skip_trampoline_code_ftype *skip_trampoline_code = generic_skip_trampoline_code;
- const solib_ops * so_ops = &solib_target_so_ops;
+ gdbarch_make_solib_ops_ftype *make_solib_ops = make_target_solib_ops;
gdbarch_skip_solib_resolver_ftype *skip_solib_resolver = generic_skip_solib_resolver;
gdbarch_in_solib_return_trampoline_ftype *in_solib_return_trampoline = generic_in_solib_return_trampoline;
gdbarch_in_indirect_branch_thunk_ftype *in_indirect_branch_thunk = default_in_indirect_branch_thunk;
@@ -240,7 +240,6 @@ struct gdbarch
gdbarch_gen_return_address_ftype *gen_return_address = default_gen_return_address;
gdbarch_info_proc_ftype *info_proc = nullptr;
gdbarch_core_info_proc_ftype *core_info_proc = nullptr;
- gdbarch_iterate_over_objfiles_in_search_order_ftype *iterate_over_objfiles_in_search_order = default_iterate_over_objfiles_in_search_order;
struct ravenscar_arch_ops * ravenscar_ops = NULL;
gdbarch_insn_is_call_ftype *insn_is_call = default_insn_is_call;
gdbarch_insn_is_ret_ftype *insn_is_ret = default_insn_is_ret;
@@ -262,6 +261,8 @@ struct gdbarch
gdbarch_read_core_file_mappings_ftype *read_core_file_mappings = default_read_core_file_mappings;
gdbarch_use_target_description_from_corefile_notes_ftype *use_target_description_from_corefile_notes = default_use_target_description_from_corefile_notes;
gdbarch_core_parse_exec_context_ftype *core_parse_exec_context = default_core_parse_exec_context;
+ gdbarch_shadow_stack_push_ftype *shadow_stack_push = nullptr;
+ gdbarch_get_shadow_stack_pointer_ftype *get_shadow_stack_pointer = default_get_shadow_stack_pointer;
};
/* Create a new ``struct gdbarch'' based on information provided by
@@ -421,11 +422,11 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of set_memtags, invalid_p == 0. */
/* Skip verify of get_memtag, invalid_p == 0. */
/* Skip verify of memtag_granule_size, invalid_p == 0. */
- /* Skip verify of software_single_step, has predicate. */
+ /* Skip verify of get_next_pcs, has predicate. */
/* Skip verify of single_step_through_delay, has predicate. */
/* Skip verify of print_insn, invalid_p == 0. */
/* Skip verify of skip_trampoline_code, invalid_p == 0. */
- /* Skip verify of so_ops, invalid_p == 0. */
+ /* Skip verify of make_solib_ops, invalid_p == 0. */
/* Skip verify of skip_solib_resolver, invalid_p == 0. */
/* Skip verify of in_solib_return_trampoline, invalid_p == 0. */
/* Skip verify of in_indirect_branch_thunk, invalid_p == 0. */
@@ -513,7 +514,6 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of gen_return_address, invalid_p == 0. */
/* Skip verify of info_proc, has predicate. */
/* Skip verify of core_info_proc, has predicate. */
- /* Skip verify of iterate_over_objfiles_in_search_order, invalid_p == 0. */
/* Skip verify of ravenscar_ops, invalid_p == 0. */
/* Skip verify of insn_is_call, invalid_p == 0. */
/* Skip verify of insn_is_ret, invalid_p == 0. */
@@ -535,6 +535,8 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of read_core_file_mappings, invalid_p == 0. */
/* Skip verify of use_target_description_from_corefile_notes, invalid_p == 0. */
/* Skip verify of core_parse_exec_context, invalid_p == 0. */
+ /* Skip verify of shadow_stack_push, has predicate. */
+ /* Skip verify of get_shadow_stack_pointer, invalid_p == 0. */
if (!log.empty ())
internal_error (_("verify_gdbarch: the following are invalid ...%s"),
log.c_str ());
@@ -948,11 +950,11 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
"gdbarch_dump: memtag_granule_size = %s\n",
core_addr_to_string_nz (gdbarch->memtag_granule_size));
gdb_printf (file,
- "gdbarch_dump: gdbarch_software_single_step_p() = %d\n",
- gdbarch_software_single_step_p (gdbarch));
+ "gdbarch_dump: gdbarch_get_next_pcs_p() = %d\n",
+ gdbarch_get_next_pcs_p (gdbarch));
gdb_printf (file,
- "gdbarch_dump: software_single_step = <%s>\n",
- host_address_to_string (gdbarch->software_single_step));
+ "gdbarch_dump: get_next_pcs = <%s>\n",
+ host_address_to_string (gdbarch->get_next_pcs));
gdb_printf (file,
"gdbarch_dump: gdbarch_single_step_through_delay_p() = %d\n",
gdbarch_single_step_through_delay_p (gdbarch));
@@ -966,8 +968,8 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
"gdbarch_dump: skip_trampoline_code = <%s>\n",
host_address_to_string (gdbarch->skip_trampoline_code));
gdb_printf (file,
- "gdbarch_dump: so_ops = %s\n",
- host_address_to_string (gdbarch->so_ops));
+ "gdbarch_dump: make_solib_ops = <%s>\n",
+ host_address_to_string (gdbarch->make_solib_ops));
gdb_printf (file,
"gdbarch_dump: skip_solib_resolver = <%s>\n",
host_address_to_string (gdbarch->skip_solib_resolver));
@@ -1338,9 +1340,6 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
"gdbarch_dump: core_info_proc = <%s>\n",
host_address_to_string (gdbarch->core_info_proc));
gdb_printf (file,
- "gdbarch_dump: iterate_over_objfiles_in_search_order = <%s>\n",
- host_address_to_string (gdbarch->iterate_over_objfiles_in_search_order));
- gdb_printf (file,
"gdbarch_dump: ravenscar_ops = %s\n",
host_address_to_string (gdbarch->ravenscar_ops));
gdb_printf (file,
@@ -1406,6 +1405,15 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
gdb_printf (file,
"gdbarch_dump: core_parse_exec_context = <%s>\n",
host_address_to_string (gdbarch->core_parse_exec_context));
+ gdb_printf (file,
+ "gdbarch_dump: gdbarch_shadow_stack_push_p() = %d\n",
+ gdbarch_shadow_stack_push_p (gdbarch));
+ gdb_printf (file,
+ "gdbarch_dump: shadow_stack_push = <%s>\n",
+ host_address_to_string (gdbarch->shadow_stack_push));
+ gdb_printf (file,
+ "gdbarch_dump: get_shadow_stack_pointer = <%s>\n",
+ host_address_to_string (gdbarch->get_shadow_stack_pointer));
if (gdbarch->dump_tdep != NULL)
gdbarch->dump_tdep (gdbarch, file);
}
@@ -3388,27 +3396,27 @@ set_gdbarch_memtag_granule_size (struct gdbarch *gdbarch,
}
bool
-gdbarch_software_single_step_p (struct gdbarch *gdbarch)
+gdbarch_get_next_pcs_p (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- return gdbarch->software_single_step != NULL;
+ return gdbarch->get_next_pcs != NULL;
}
std::vector<CORE_ADDR>
-gdbarch_software_single_step (struct gdbarch *gdbarch, struct regcache *regcache)
+gdbarch_get_next_pcs (struct gdbarch *gdbarch, struct regcache *regcache)
{
gdb_assert (gdbarch != NULL);
- gdb_assert (gdbarch->software_single_step != NULL);
+ gdb_assert (gdbarch->get_next_pcs != NULL);
if (gdbarch_debug >= 2)
- gdb_printf (gdb_stdlog, "gdbarch_software_single_step called\n");
- return gdbarch->software_single_step (regcache);
+ gdb_printf (gdb_stdlog, "gdbarch_get_next_pcs called\n");
+ return gdbarch->get_next_pcs (regcache);
}
void
-set_gdbarch_software_single_step (struct gdbarch *gdbarch,
- gdbarch_software_single_step_ftype software_single_step)
+set_gdbarch_get_next_pcs (struct gdbarch *gdbarch,
+ gdbarch_get_next_pcs_ftype get_next_pcs)
{
- gdbarch->software_single_step = software_single_step;
+ gdbarch->get_next_pcs = get_next_pcs;
}
bool
@@ -3469,21 +3477,21 @@ set_gdbarch_skip_trampoline_code (struct gdbarch *gdbarch,
gdbarch->skip_trampoline_code = skip_trampoline_code;
}
-const solib_ops *
-gdbarch_so_ops (struct gdbarch *gdbarch)
+solib_ops_up
+gdbarch_make_solib_ops (struct gdbarch *gdbarch, program_space *pspace)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of so_ops, invalid_p == 0. */
+ gdb_assert (gdbarch->make_solib_ops != NULL);
if (gdbarch_debug >= 2)
- gdb_printf (gdb_stdlog, "gdbarch_so_ops called\n");
- return gdbarch->so_ops;
+ gdb_printf (gdb_stdlog, "gdbarch_make_solib_ops called\n");
+ return gdbarch->make_solib_ops (pspace);
}
void
-set_gdbarch_so_ops (struct gdbarch *gdbarch,
- const solib_ops * so_ops)
+set_gdbarch_make_solib_ops (struct gdbarch *gdbarch,
+ gdbarch_make_solib_ops_ftype make_solib_ops)
{
- gdbarch->so_ops = so_ops;
+ gdbarch->make_solib_ops = make_solib_ops;
}
CORE_ADDR
@@ -3962,13 +3970,13 @@ gdbarch_core_xfer_shared_libraries_p (struct gdbarch *gdbarch)
}
ULONGEST
-gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
+gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, struct bfd &cbfd, gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->core_xfer_shared_libraries != NULL);
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_core_xfer_shared_libraries called\n");
- return gdbarch->core_xfer_shared_libraries (gdbarch, readbuf, offset, len);
+ return gdbarch->core_xfer_shared_libraries (gdbarch, cbfd, readbuf, offset, len);
}
void
@@ -3986,13 +3994,13 @@ gdbarch_core_xfer_shared_libraries_aix_p (struct gdbarch *gdbarch)
}
ULONGEST
-gdbarch_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
+gdbarch_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch, struct bfd &cbfd, gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->core_xfer_shared_libraries_aix != NULL);
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_core_xfer_shared_libraries_aix called\n");
- return gdbarch->core_xfer_shared_libraries_aix (gdbarch, readbuf, offset, len);
+ return gdbarch->core_xfer_shared_libraries_aix (gdbarch, cbfd, readbuf, offset, len);
}
void
@@ -4034,13 +4042,13 @@ gdbarch_core_thread_name_p (struct gdbarch *gdbarch)
}
const char *
-gdbarch_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr)
+gdbarch_core_thread_name (struct gdbarch *gdbarch, struct bfd &cbfd, struct thread_info *thr)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->core_thread_name != NULL);
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_core_thread_name called\n");
- return gdbarch->core_thread_name (gdbarch, thr);
+ return gdbarch->core_thread_name (gdbarch, cbfd, thr);
}
void
@@ -4058,13 +4066,13 @@ gdbarch_core_xfer_siginfo_p (struct gdbarch *gdbarch)
}
LONGEST
-gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
+gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch, struct bfd &cbfd, gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->core_xfer_siginfo != NULL);
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_core_xfer_siginfo called\n");
- return gdbarch->core_xfer_siginfo (gdbarch, readbuf, offset, len);
+ return gdbarch->core_xfer_siginfo (gdbarch, cbfd, readbuf, offset, len);
}
void
@@ -4082,13 +4090,13 @@ gdbarch_core_read_x86_xsave_layout_p (struct gdbarch *gdbarch)
}
bool
-gdbarch_core_read_x86_xsave_layout (struct gdbarch *gdbarch, x86_xsave_layout &xsave_layout)
+gdbarch_core_read_x86_xsave_layout (struct gdbarch *gdbarch, struct bfd &cbfd, x86_xsave_layout &xsave_layout)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->core_read_x86_xsave_layout != NULL);
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_core_read_x86_xsave_layout called\n");
- return gdbarch->core_read_x86_xsave_layout (gdbarch, xsave_layout);
+ return gdbarch->core_read_x86_xsave_layout (gdbarch, cbfd, xsave_layout);
}
void
@@ -5155,13 +5163,13 @@ gdbarch_core_info_proc_p (struct gdbarch *gdbarch)
}
void
-gdbarch_core_info_proc (struct gdbarch *gdbarch, const char *args, enum info_proc_what what)
+gdbarch_core_info_proc (struct gdbarch *gdbarch, struct bfd *cbfd, const char *args, enum info_proc_what what)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->core_info_proc != NULL);
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_core_info_proc called\n");
- gdbarch->core_info_proc (gdbarch, args, what);
+ gdbarch->core_info_proc (gdbarch, cbfd, args, what);
}
void
@@ -5171,23 +5179,6 @@ set_gdbarch_core_info_proc (struct gdbarch *gdbarch,
gdbarch->core_info_proc = core_info_proc;
}
-void
-gdbarch_iterate_over_objfiles_in_search_order (struct gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb, struct objfile *current_objfile)
-{
- gdb_assert (gdbarch != NULL);
- gdb_assert (gdbarch->iterate_over_objfiles_in_search_order != NULL);
- if (gdbarch_debug >= 2)
- gdb_printf (gdb_stdlog, "gdbarch_iterate_over_objfiles_in_search_order called\n");
- gdbarch->iterate_over_objfiles_in_search_order (gdbarch, cb, current_objfile);
-}
-
-void
-set_gdbarch_iterate_over_objfiles_in_search_order (struct gdbarch *gdbarch,
- gdbarch_iterate_over_objfiles_in_search_order_ftype iterate_over_objfiles_in_search_order)
-{
- gdbarch->iterate_over_objfiles_in_search_order = iterate_over_objfiles_in_search_order;
-}
-
struct ravenscar_arch_ops *
gdbarch_ravenscar_ops (struct gdbarch *gdbarch)
{
@@ -5551,3 +5542,44 @@ set_gdbarch_core_parse_exec_context (struct gdbarch *gdbarch,
{
gdbarch->core_parse_exec_context = core_parse_exec_context;
}
+
+bool
+gdbarch_shadow_stack_push_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->shadow_stack_push != NULL;
+}
+
+void
+gdbarch_shadow_stack_push (struct gdbarch *gdbarch, CORE_ADDR new_addr, regcache *regcache)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->shadow_stack_push != NULL);
+ if (gdbarch_debug >= 2)
+ gdb_printf (gdb_stdlog, "gdbarch_shadow_stack_push called\n");
+ gdbarch->shadow_stack_push (gdbarch, new_addr, regcache);
+}
+
+void
+set_gdbarch_shadow_stack_push (struct gdbarch *gdbarch,
+ gdbarch_shadow_stack_push_ftype shadow_stack_push)
+{
+ gdbarch->shadow_stack_push = shadow_stack_push;
+}
+
+std::optional<CORE_ADDR>
+gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->get_shadow_stack_pointer != NULL);
+ if (gdbarch_debug >= 2)
+ gdb_printf (gdb_stdlog, "gdbarch_get_shadow_stack_pointer called\n");
+ return gdbarch->get_shadow_stack_pointer (gdbarch, regcache, shadow_stack_enabled);
+}
+
+void
+set_gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch,
+ gdbarch_get_shadow_stack_pointer_ftype get_shadow_stack_pointer)
+{
+ gdbarch->get_shadow_stack_pointer = get_shadow_stack_pointer;
+}
diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h
index 313a8f1..24fa8ba 100644
--- a/gdb/gdbarch-gen.h
+++ b/gdb/gdbarch-gen.h
@@ -792,11 +792,11 @@ extern void set_gdbarch_memtag_granule_size (struct gdbarch *gdbarch, CORE_ADDR
the condition is true, so that we ensure forward progress when stepping
past a conditional branch to self. */
-extern bool gdbarch_software_single_step_p (struct gdbarch *gdbarch);
+extern bool gdbarch_get_next_pcs_p (struct gdbarch *gdbarch);
-typedef std::vector<CORE_ADDR> (gdbarch_software_single_step_ftype) (struct regcache *regcache);
-extern std::vector<CORE_ADDR> gdbarch_software_single_step (struct gdbarch *gdbarch, struct regcache *regcache);
-extern void set_gdbarch_software_single_step (struct gdbarch *gdbarch, gdbarch_software_single_step_ftype *software_single_step);
+typedef std::vector<CORE_ADDR> (gdbarch_get_next_pcs_ftype) (struct regcache *regcache);
+extern std::vector<CORE_ADDR> gdbarch_get_next_pcs (struct gdbarch *gdbarch, struct regcache *regcache);
+extern void set_gdbarch_get_next_pcs (struct gdbarch *gdbarch, gdbarch_get_next_pcs_ftype *get_next_pcs);
/* Return non-zero if the processor is executing a delay slot and a
further single-step is needed before the instruction finishes. */
@@ -818,10 +818,11 @@ typedef CORE_ADDR (gdbarch_skip_trampoline_code_ftype) (const frame_info_ptr &fr
extern CORE_ADDR gdbarch_skip_trampoline_code (struct gdbarch *gdbarch, const frame_info_ptr &frame, CORE_ADDR pc);
extern void set_gdbarch_skip_trampoline_code (struct gdbarch *gdbarch, gdbarch_skip_trampoline_code_ftype *skip_trampoline_code);
-/* Vtable of solib operations functions. */
+/* Return a newly-allocated solib_ops object capable of providing the solibs for this architecture. */
-extern const solib_ops * gdbarch_so_ops (struct gdbarch *gdbarch);
-extern void set_gdbarch_so_ops (struct gdbarch *gdbarch, const solib_ops * so_ops);
+typedef solib_ops_up (gdbarch_make_solib_ops_ftype) (program_space *pspace);
+extern solib_ops_up gdbarch_make_solib_ops (struct gdbarch *gdbarch, program_space *pspace);
+extern void set_gdbarch_make_solib_ops (struct gdbarch *gdbarch, gdbarch_make_solib_ops_ftype *make_solib_ops);
/* If in_solib_dynsym_resolve_code() returns true, and SKIP_SOLIB_RESOLVER
evaluates non-zero, this is the address where the debugger will place
@@ -1028,8 +1029,8 @@ extern void set_gdbarch_decode_memtag_section (struct gdbarch *gdbarch, gdbarch_
extern bool gdbarch_core_xfer_shared_libraries_p (struct gdbarch *gdbarch);
-typedef ULONGEST (gdbarch_core_xfer_shared_libraries_ftype) (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
-extern ULONGEST gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
+typedef ULONGEST (gdbarch_core_xfer_shared_libraries_ftype) (struct gdbarch *gdbarch, struct bfd &cbfd, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
+extern ULONGEST gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, struct bfd &cbfd, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
extern void set_gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries);
/* Read offset OFFSET of TARGET_OBJECT_LIBRARIES_AIX formatted shared
@@ -1038,8 +1039,8 @@ extern void set_gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdb
extern bool gdbarch_core_xfer_shared_libraries_aix_p (struct gdbarch *gdbarch);
-typedef ULONGEST (gdbarch_core_xfer_shared_libraries_aix_ftype) (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
-extern ULONGEST gdbarch_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
+typedef ULONGEST (gdbarch_core_xfer_shared_libraries_aix_ftype) (struct gdbarch *gdbarch, struct bfd &cbfd, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
+extern ULONGEST gdbarch_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch, struct bfd &cbfd, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
extern void set_gdbarch_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch, gdbarch_core_xfer_shared_libraries_aix_ftype *core_xfer_shared_libraries_aix);
/* How the core target converts a PTID from a core file to a string. */
@@ -1050,31 +1051,31 @@ typedef std::string (gdbarch_core_pid_to_str_ftype) (struct gdbarch *gdbarch, pt
extern std::string gdbarch_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid);
extern void set_gdbarch_core_pid_to_str (struct gdbarch *gdbarch, gdbarch_core_pid_to_str_ftype *core_pid_to_str);
-/* How the core target extracts the name of a thread from a core file. */
+/* How the core target extracts the name of a thread from core file CBFD. */
extern bool gdbarch_core_thread_name_p (struct gdbarch *gdbarch);
-typedef const char * (gdbarch_core_thread_name_ftype) (struct gdbarch *gdbarch, struct thread_info *thr);
-extern const char * gdbarch_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr);
+typedef const char * (gdbarch_core_thread_name_ftype) (struct gdbarch *gdbarch, struct bfd &cbfd, struct thread_info *thr);
+extern const char * gdbarch_core_thread_name (struct gdbarch *gdbarch, struct bfd &cbfd, struct thread_info *thr);
extern void set_gdbarch_core_thread_name (struct gdbarch *gdbarch, gdbarch_core_thread_name_ftype *core_thread_name);
/* Read offset OFFSET of TARGET_OBJECT_SIGNAL_INFO signal information
- from core file into buffer READBUF with length LEN. Return the number
+ from core file CBFD into buffer READBUF with length LEN. Return the number
of bytes read (zero indicates EOF, a negative value indicates failure). */
extern bool gdbarch_core_xfer_siginfo_p (struct gdbarch *gdbarch);
-typedef LONGEST (gdbarch_core_xfer_siginfo_ftype) (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
-extern LONGEST gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
+typedef LONGEST (gdbarch_core_xfer_siginfo_ftype) (struct gdbarch *gdbarch, struct bfd &cbfd, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
+extern LONGEST gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch, struct bfd &cbfd, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
extern void set_gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch, gdbarch_core_xfer_siginfo_ftype *core_xfer_siginfo);
-/* Read x86 XSAVE layout information from core file into XSAVE_LAYOUT.
+/* Read x86 XSAVE layout information from core file CBFD into XSAVE_LAYOUT.
Returns true if the layout was read successfully. */
extern bool gdbarch_core_read_x86_xsave_layout_p (struct gdbarch *gdbarch);
-typedef bool (gdbarch_core_read_x86_xsave_layout_ftype) (struct gdbarch *gdbarch, x86_xsave_layout &xsave_layout);
-extern bool gdbarch_core_read_x86_xsave_layout (struct gdbarch *gdbarch, x86_xsave_layout &xsave_layout);
+typedef bool (gdbarch_core_read_x86_xsave_layout_ftype) (struct gdbarch *gdbarch, struct bfd &cbfd, x86_xsave_layout &xsave_layout);
+extern bool gdbarch_core_read_x86_xsave_layout (struct gdbarch *gdbarch, struct bfd &cbfd, x86_xsave_layout &xsave_layout);
extern void set_gdbarch_core_read_x86_xsave_layout (struct gdbarch *gdbarch, gdbarch_core_read_x86_xsave_layout_ftype *core_read_x86_xsave_layout);
/* BFD target to use when generating a core file. */
@@ -1147,7 +1148,7 @@ extern void set_gdbarch_displaced_step_copy_insn (struct gdbarch *gdbarch, gdbar
the displaced instruction buffer).
The default implementation returns false on all targets that provide a
- gdbarch_software_single_step routine, and true otherwise. */
+ gdbarch_get_next_pcs routine, and true otherwise. */
typedef bool (gdbarch_displaced_step_hw_singlestep_ftype) (struct gdbarch *gdbarch);
extern bool gdbarch_displaced_step_hw_singlestep (struct gdbarch *gdbarch);
@@ -1625,27 +1626,14 @@ extern void set_gdbarch_info_proc (struct gdbarch *gdbarch, gdbarch_info_proc_ft
/* Implement the "info proc" command for core files. Note that there
are two "info_proc"-like methods on gdbarch -- one for core files,
- one for live targets. */
+ one for live targets. CBFD is the core file being read from. */
extern bool gdbarch_core_info_proc_p (struct gdbarch *gdbarch);
-typedef void (gdbarch_core_info_proc_ftype) (struct gdbarch *gdbarch, const char *args, enum info_proc_what what);
-extern void gdbarch_core_info_proc (struct gdbarch *gdbarch, const char *args, enum info_proc_what what);
+typedef void (gdbarch_core_info_proc_ftype) (struct gdbarch *gdbarch, struct bfd *cbfd, const char *args, enum info_proc_what what);
+extern void gdbarch_core_info_proc (struct gdbarch *gdbarch, struct bfd *cbfd, const char *args, enum info_proc_what what);
extern void set_gdbarch_core_info_proc (struct gdbarch *gdbarch, gdbarch_core_info_proc_ftype *core_info_proc);
-/* Iterate over all objfiles in the order that makes the most sense
- for the architecture to make global symbol searches.
-
- CB is a callback function passed an objfile to be searched. The iteration stops
- if this function returns nonzero.
-
- If not NULL, CURRENT_OBJFILE corresponds to the objfile being
- inspected when the symbol search was requested. */
-
-typedef void (gdbarch_iterate_over_objfiles_in_search_order_ftype) (struct gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb, struct objfile *current_objfile);
-extern void gdbarch_iterate_over_objfiles_in_search_order (struct gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb, struct objfile *current_objfile);
-extern void set_gdbarch_iterate_over_objfiles_in_search_order (struct gdbarch *gdbarch, gdbarch_iterate_over_objfiles_in_search_order_ftype *iterate_over_objfiles_in_search_order);
-
/* Ravenscar arch-dependent ops. */
extern struct ravenscar_arch_ops * gdbarch_ravenscar_ops (struct gdbarch *gdbarch);
@@ -1801,3 +1789,31 @@ extern void set_gdbarch_use_target_description_from_corefile_notes (struct gdbar
typedef core_file_exec_context (gdbarch_core_parse_exec_context_ftype) (struct gdbarch *gdbarch, bfd *cbfd);
extern core_file_exec_context gdbarch_core_parse_exec_context (struct gdbarch *gdbarch, bfd *cbfd);
extern void set_gdbarch_core_parse_exec_context (struct gdbarch *gdbarch, gdbarch_core_parse_exec_context_ftype *core_parse_exec_context);
+
+/* Some targets support special hardware-assisted control-flow protection
+ technologies. For example, the Intel Control-Flow Enforcement Technology
+ (Intel CET) on x86 provides a shadow stack and indirect branch tracking.
+ To enable shadow stack support for inferior calls the shadow_stack_push
+ gdbarch hook has to be provided. The get_shadow_stack_pointer gdbarch
+ hook has to be provided to enable displaced stepping.
+
+ Push NEW_ADDR to the shadow stack and update the shadow stack pointer. */
+
+extern bool gdbarch_shadow_stack_push_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_shadow_stack_push_ftype) (struct gdbarch *gdbarch, CORE_ADDR new_addr, regcache *regcache);
+extern void gdbarch_shadow_stack_push (struct gdbarch *gdbarch, CORE_ADDR new_addr, regcache *regcache);
+extern void set_gdbarch_shadow_stack_push (struct gdbarch *gdbarch, gdbarch_shadow_stack_push_ftype *shadow_stack_push);
+
+/* If possible, return the shadow stack pointer. If the shadow stack
+ feature is enabled then set SHADOW_STACK_ENABLED to true, otherwise
+ set SHADOW_STACK_ENABLED to false. This hook has to be provided to enable
+ displaced stepping for shadow stack enabled programs.
+ On some architectures, the shadow stack pointer is available even if the
+ feature is disabled. So dependent on the target, an implementation of
+ this function may return a valid shadow stack pointer, but set
+ SHADOW_STACK_ENABLED to false. */
+
+typedef std::optional<CORE_ADDR> (gdbarch_get_shadow_stack_pointer_ftype) (struct gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled);
+extern std::optional<CORE_ADDR> gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled);
+extern void set_gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch, gdbarch_get_shadow_stack_pointer_ftype *get_shadow_stack_pointer);
diff --git a/gdb/gdbarch-selftests.c b/gdb/gdbarch-selftests.c
index c370204..5c94f60 100644
--- a/gdb/gdbarch-selftests.c
+++ b/gdb/gdbarch-selftests.c
@@ -183,9 +183,7 @@ check_stack_growth (struct gdbarch *gdbarch)
} /* namespace selftests */
-void _initialize_gdbarch_selftests ();
-void
-_initialize_gdbarch_selftests ()
+INIT_GDB_FILE (gdbarch_selftests)
{
selftests::register_test_foreach_arch ("register_to_value",
selftests::register_to_value_test);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 9feb2cc..2049761 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -30,6 +30,7 @@
#include "displaced-stepping.h"
#include "gdbsupport/gdb-checked-static-cast.h"
#include "registry.h"
+#include "solib.h"
struct floatformat;
struct ui_file;
@@ -74,12 +75,6 @@ struct gdbarch_tdep_base
using gdbarch_tdep_up = std::unique_ptr<gdbarch_tdep_base>;
-/* Callback type for the 'iterate_over_objfiles_in_search_order'
- gdbarch method. */
-
-using iterate_over_objfiles_in_search_order_cb_ftype
- = gdb::function_view<bool(objfile *)>;
-
/* Callback type for regset section iterators. The callback usually
invokes the REGSET's supply or collect method, to which it must
pass a buffer - for collects this buffer will need to be created using
diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py
index ec09d95..3820ae3 100644
--- a/gdb/gdbarch_components.py
+++ b/gdb/gdbarch_components.py
@@ -1395,7 +1395,7 @@ the condition is true, so that we ensure forward progress when stepping
past a conditional branch to self.
""",
type="std::vector<CORE_ADDR>",
- name="software_single_step",
+ name="get_next_pcs",
params=[("struct regcache *", "regcache")],
predicate=True,
)
@@ -1431,12 +1431,12 @@ Function(
invalid=False,
)
-Value(
- comment="Vtable of solib operations functions.",
- type="const solib_ops *",
- name="so_ops",
- predefault="&solib_target_so_ops",
- printer="host_address_to_string (gdbarch->so_ops)",
+Function(
+ comment="Return a newly-allocated solib_ops object capable of providing the solibs for this architecture.",
+ type="solib_ops_up",
+ name="make_solib_ops",
+ params=[("program_space *", "pspace")],
+ predefault="make_target_solib_ops",
invalid=False,
)
@@ -1738,7 +1738,12 @@ failed, otherwise, return the red length of READBUF.
""",
type="ULONGEST",
name="core_xfer_shared_libraries",
- params=[("gdb_byte *", "readbuf"), ("ULONGEST", "offset"), ("ULONGEST", "len")],
+ params=[
+ ("struct bfd &", "cbfd"),
+ ("gdb_byte *", "readbuf"),
+ ("ULONGEST", "offset"),
+ ("ULONGEST", "len"),
+ ],
predicate=True,
)
@@ -1750,7 +1755,12 @@ Return the number of bytes read (zero indicates failure).
""",
type="ULONGEST",
name="core_xfer_shared_libraries_aix",
- params=[("gdb_byte *", "readbuf"), ("ULONGEST", "offset"), ("ULONGEST", "len")],
+ params=[
+ ("struct bfd &", "cbfd"),
+ ("gdb_byte *", "readbuf"),
+ ("ULONGEST", "offset"),
+ ("ULONGEST", "len"),
+ ],
predicate=True,
)
@@ -1766,34 +1776,39 @@ How the core target converts a PTID from a core file to a string.
Method(
comment="""
-How the core target extracts the name of a thread from a core file.
+How the core target extracts the name of a thread from core file CBFD.
""",
type="const char *",
name="core_thread_name",
- params=[("struct thread_info *", "thr")],
+ params=[("struct bfd &", "cbfd"), ("struct thread_info *", "thr")],
predicate=True,
)
Method(
comment="""
Read offset OFFSET of TARGET_OBJECT_SIGNAL_INFO signal information
-from core file into buffer READBUF with length LEN. Return the number
+from core file CBFD into buffer READBUF with length LEN. Return the number
of bytes read (zero indicates EOF, a negative value indicates failure).
""",
type="LONGEST",
name="core_xfer_siginfo",
- params=[("gdb_byte *", "readbuf"), ("ULONGEST", "offset"), ("ULONGEST", "len")],
+ params=[
+ ("struct bfd &", "cbfd"),
+ ("gdb_byte *", "readbuf"),
+ ("ULONGEST", "offset"),
+ ("ULONGEST", "len"),
+ ],
predicate=True,
)
Method(
comment="""
-Read x86 XSAVE layout information from core file into XSAVE_LAYOUT.
+Read x86 XSAVE layout information from core file CBFD into XSAVE_LAYOUT.
Returns true if the layout was read successfully.
""",
type="bool",
name="core_read_x86_xsave_layout",
- params=[("x86_xsave_layout &", "xsave_layout")],
+ params=[("struct bfd &", "cbfd"), ("x86_xsave_layout &", "xsave_layout")],
predicate=True,
)
@@ -1891,7 +1906,7 @@ receive control again (e.g. by placing a software breakpoint instruction into
the displaced instruction buffer).
The default implementation returns false on all targets that provide a
-gdbarch_software_single_step routine, and true otherwise.
+gdbarch_get_next_pcs routine, and true otherwise.
""",
type="bool",
name="displaced_step_hw_singlestep",
@@ -2554,33 +2569,16 @@ Method(
comment="""
Implement the "info proc" command for core files. Note that there
are two "info_proc"-like methods on gdbarch -- one for core files,
-one for live targets.
+one for live targets. CBFD is the core file being read from.
""",
type="void",
name="core_info_proc",
- params=[("const char *", "args"), ("enum info_proc_what", "what")],
- predicate=True,
-)
-
-Method(
- comment="""
-Iterate over all objfiles in the order that makes the most sense
-for the architecture to make global symbol searches.
-
-CB is a callback function passed an objfile to be searched. The iteration stops
-if this function returns nonzero.
-
-If not NULL, CURRENT_OBJFILE corresponds to the objfile being
-inspected when the symbol search was requested.
-""",
- type="void",
- name="iterate_over_objfiles_in_search_order",
params=[
- ("iterate_over_objfiles_in_search_order_cb_ftype", "cb"),
- ("struct objfile *", "current_objfile"),
+ ("struct bfd *", "cbfd"),
+ ("const char *", "args"),
+ ("enum info_proc_what", "what"),
],
- predefault="default_iterate_over_objfiles_in_search_order",
- invalid=False,
+ predicate=True,
)
Value(
@@ -2848,3 +2846,38 @@ which all assume current_inferior() is the one to read from.
predefault="default_core_parse_exec_context",
invalid=False,
)
+
+Method(
+ comment="""
+Some targets support special hardware-assisted control-flow protection
+technologies. For example, the Intel Control-Flow Enforcement Technology
+(Intel CET) on x86 provides a shadow stack and indirect branch tracking.
+To enable shadow stack support for inferior calls the shadow_stack_push
+gdbarch hook has to be provided. The get_shadow_stack_pointer gdbarch
+hook has to be provided to enable displaced stepping.
+
+Push NEW_ADDR to the shadow stack and update the shadow stack pointer.
+""",
+ type="void",
+ name="shadow_stack_push",
+ params=[("CORE_ADDR", "new_addr"), ("regcache *", "regcache")],
+ predicate=True,
+)
+
+Method(
+ comment="""
+If possible, return the shadow stack pointer. If the shadow stack
+feature is enabled then set SHADOW_STACK_ENABLED to true, otherwise
+set SHADOW_STACK_ENABLED to false. This hook has to be provided to enable
+displaced stepping for shadow stack enabled programs.
+On some architectures, the shadow stack pointer is available even if the
+feature is disabled. So dependent on the target, an implementation of
+this function may return a valid shadow stack pointer, but set
+SHADOW_STACK_ENABLED to false.
+""",
+ type="std::optional<CORE_ADDR>",
+ name="get_shadow_stack_pointer",
+ params=[("regcache *", "regcache"), ("bool &", "shadow_stack_enabled")],
+ predefault="default_get_shadow_stack_pointer",
+ invalid=False,
+)
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 5713eac..24e6d0b 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -902,7 +902,7 @@ operator== (const dynamic_prop &l, const dynamic_prop &r)
return true;
case PROP_CONST:
return l.const_val () == r.const_val ();
- case PROP_ADDR_OFFSET:
+ case PROP_FIELD:
case PROP_LOCEXPR:
case PROP_LOCLIST:
return l.baton () == r.baton ();
@@ -1080,10 +1080,10 @@ get_discrete_low_bound (struct type *type)
entries. */
LONGEST low = type->field (0).loc_enumval ();
- for (int i = 0; i < type->num_fields (); i++)
+ for (const auto &field : type->fields ())
{
- if (type->field (i).loc_enumval () < low)
- low = type->field (i).loc_enumval ();
+ if (field.loc_enumval () < low)
+ low = field.loc_enumval ();
}
return low;
@@ -1147,10 +1147,10 @@ get_discrete_high_bound (struct type *type)
entries. */
LONGEST high = type->field (0).loc_enumval ();
- for (int i = 0; i < type->num_fields (); i++)
+ for (const auto &field : type->fields ())
{
- if (type->field (i).loc_enumval () > high)
- high = type->field (i).loc_enumval ();
+ if (field.loc_enumval () > high)
+ high = field.loc_enumval ();
}
return high;
@@ -1602,15 +1602,15 @@ smash_to_methodptr_type (struct type *type, struct type *to_type)
void
smash_to_method_type (struct type *type, struct type *self_type,
- struct type *to_type, struct field *args,
- int nargs, int varargs)
+ struct type *to_type, gdb::array_view<struct field> args,
+ int varargs)
{
smash_type (type);
type->set_code (TYPE_CODE_METHOD);
type->set_target_type (to_type);
set_type_self_type (type, self_type);
- type->set_fields (args);
- type->set_num_fields (nargs);
+ type->set_fields (args.data ());
+ type->set_num_fields (args.size ());
if (varargs)
type->set_has_varargs (true);
@@ -2121,7 +2121,7 @@ is_dynamic_type_internal (struct type *type, bool top_level)
return true;
/* If the field is at a fixed offset, then it is not
dynamic. */
- if (type->field (i).loc_kind () != FIELD_LOC_KIND_DWARF_BLOCK)
+ if (!type->field (i).loc_is_dwarf_block ())
continue;
/* Do not consider C++ virtual base types to be dynamic
due to the field's offset being dynamic; these are
@@ -2146,7 +2146,7 @@ is_dynamic_type (struct type *type)
}
static struct type *resolve_dynamic_type_internal
- (struct type *type, struct property_addr_info *addr_stack,
+ (struct type *type, const property_addr_info *addr_stack,
const frame_info_ptr &frame, bool top_level);
/* Given a dynamic range type (dyn_range_type) and a stack of
@@ -2167,7 +2167,7 @@ static struct type *resolve_dynamic_type_internal
static struct type *
resolve_dynamic_range (struct type *dyn_range_type,
- struct property_addr_info *addr_stack,
+ const property_addr_info *addr_stack,
const frame_info_ptr &frame,
int rank, bool resolve_p = true)
{
@@ -2269,7 +2269,7 @@ resolve_dynamic_range (struct type *dyn_range_type,
static struct type *
resolve_dynamic_array_or_string_1 (struct type *type,
- struct property_addr_info *addr_stack,
+ const property_addr_info *addr_stack,
const frame_info_ptr &frame,
int rank, bool resolve_p)
{
@@ -2397,7 +2397,7 @@ resolve_dynamic_array_or_string_1 (struct type *type,
static struct type *
resolve_dynamic_array_or_string (struct type *type,
- struct property_addr_info *addr_stack,
+ const property_addr_info *addr_stack,
const frame_info_ptr &frame)
{
CORE_ADDR value;
@@ -2490,27 +2490,26 @@ resolve_dynamic_array_or_string (struct type *type,
static struct type *
resolve_dynamic_union (struct type *type,
- struct property_addr_info *addr_stack,
+ const property_addr_info *addr_stack,
const frame_info_ptr &frame)
{
struct type *resolved_type;
- int i;
unsigned int max_len = 0;
gdb_assert (type->code () == TYPE_CODE_UNION);
resolved_type = copy_type (type);
resolved_type->copy_fields (type);
- for (i = 0; i < resolved_type->num_fields (); ++i)
+ for (auto &field : resolved_type->fields ())
{
struct type *t;
- if (type->field (i).is_static ())
+ if (field.is_static ())
continue;
- t = resolve_dynamic_type_internal (resolved_type->field (i).type (),
- addr_stack, frame, false);
- resolved_type->field (i).set_type (t);
+ t = resolve_dynamic_type_internal (field.type (), addr_stack,
+ frame, false);
+ field.set_type (t);
struct type *real_type = check_typedef (t);
if (real_type->length () > max_len)
@@ -2534,7 +2533,7 @@ variant::matches (ULONGEST value, bool is_unsigned) const
static void
compute_variant_fields_inner (struct type *type,
- struct property_addr_info *addr_stack,
+ const property_addr_info *addr_stack,
const variant_part &part,
std::vector<bool> &flags);
@@ -2549,7 +2548,7 @@ compute_variant_fields_inner (struct type *type,
static void
compute_variant_fields_recurse (struct type *type,
- struct property_addr_info *addr_stack,
+ const property_addr_info *addr_stack,
const variant &variant,
std::vector<bool> &flags,
bool enabled)
@@ -2581,7 +2580,7 @@ compute_variant_fields_recurse (struct type *type,
static void
compute_variant_fields_inner (struct type *type,
- struct property_addr_info *addr_stack,
+ const property_addr_info *addr_stack,
const variant_part &part,
std::vector<bool> &flags)
{
@@ -2650,7 +2649,7 @@ compute_variant_fields_inner (struct type *type,
static void
compute_variant_fields (struct type *type,
struct type *resolved_type,
- struct property_addr_info *addr_stack,
+ const property_addr_info *addr_stack,
const gdb::array_view<variant_part> &parts)
{
/* Assume all fields are included by default. */
@@ -2676,17 +2675,121 @@ compute_variant_fields (struct type *type,
}
}
+/* See gdbtypes.h. */
+
+void
+apply_bit_offset_to_field (struct field &field, LONGEST bit_offset,
+ LONGEST explicit_byte_size)
+{
+ struct type *field_type = field.type ();
+ struct gdbarch *gdbarch = field_type->arch ();
+ LONGEST current_bitpos = field.loc_bitpos ();
+
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ {
+ /* For big endian bits, the DW_AT_bit_offset gives the
+ additional bit offset from the MSB of the containing
+ anonymous object to the MSB of the field. We don't
+ have to do anything special since we don't need to
+ know the size of the anonymous object. */
+ field.set_loc_bitpos (current_bitpos + bit_offset);
+ }
+ else
+ {
+ /* For little endian bits, compute the bit offset to the
+ MSB of the anonymous object, subtract off the number of
+ bits from the MSB of the field to the MSB of the
+ object, and then subtract off the number of bits of
+ the field itself. The result is the bit offset of
+ the LSB of the field. */
+ LONGEST object_size = explicit_byte_size;
+ if (object_size == 0)
+ object_size = field_type->length ();
+
+ field.set_loc_bitpos (current_bitpos
+ + 8 * object_size
+ - bit_offset
+ - field.bitsize ());
+ }
+}
+
+/* See gdbtypes.h. */
+
+void
+resolve_dynamic_field (struct field &field,
+ const property_addr_info *addr_stack,
+ const frame_info_ptr &frame)
+{
+ gdb_assert (!field.is_static ());
+
+ if (field.loc_is_dwarf_block ())
+ {
+ dwarf2_locexpr_baton *field_loc
+ = field.loc_dwarf_block ();
+
+ struct dwarf2_property_baton baton;
+ baton.property_type = lookup_pointer_type (field.type ());
+ baton.locexpr = *field_loc;
+
+ struct dynamic_prop prop;
+ prop.set_locexpr (&baton);
+
+ CORE_ADDR vals[1] = {addr_stack->addr};
+ CORE_ADDR addr_or_bitpos;
+ if (dwarf2_evaluate_property (&prop, frame, addr_stack,
+ &addr_or_bitpos, vals))
+ {
+ if (field.loc_kind () == FIELD_LOC_KIND_DWARF_BLOCK_ADDR)
+ field.set_loc_bitpos (TARGET_CHAR_BIT
+ * (addr_or_bitpos - addr_stack->addr));
+ else
+ field.set_loc_bitpos (addr_or_bitpos);
+
+ if (field_loc->is_field_location)
+ {
+ dwarf2_field_location_baton *fl_baton
+ = static_cast<dwarf2_field_location_baton *> (field_loc);
+ apply_bit_offset_to_field (field, fl_baton->bit_offset,
+ fl_baton->explicit_byte_size);
+ }
+ }
+ }
+
+ /* As we know this field is not a static field, the field's
+ field_loc_kind should be FIELD_LOC_KIND_BITPOS. Verify
+ this is the case, but only trigger a simple error rather
+ than an internal error if that fails. While failing
+ that verification indicates a bug in our code, the error
+ is not severe enough to suggest to the user he stops
+ his debugging session because of it. */
+ if (field.loc_kind () != FIELD_LOC_KIND_BITPOS)
+ error (_("Cannot determine struct field location"
+ " (invalid location kind)"));
+
+ struct property_addr_info pinfo;
+ pinfo.type = check_typedef (field.type ());
+ size_t offset = field.loc_bitpos () / TARGET_CHAR_BIT;
+ pinfo.valaddr = addr_stack->valaddr;
+ if (!pinfo.valaddr.empty ())
+ pinfo.valaddr = pinfo.valaddr.slice (offset);
+ pinfo.addr = addr_stack->addr + offset;
+ pinfo.next = addr_stack;
+
+ field.set_type (resolve_dynamic_type_internal (field.type (),
+ &pinfo, frame, false));
+ gdb_assert (field.loc_kind () == FIELD_LOC_KIND_BITPOS);
+}
+
/* Resolve dynamic bounds of members of the struct TYPE to static
bounds. ADDR_STACK is a stack of struct property_addr_info to
be used if needed during the dynamic resolution. */
static struct type *
resolve_dynamic_struct (struct type *type,
- struct property_addr_info *addr_stack,
+ const property_addr_info *addr_stack,
const frame_info_ptr &frame)
{
struct type *resolved_type;
- int i;
unsigned resolved_type_bit_length = 0;
gdb_assert (type->code () == TYPE_CODE_STRUCT);
@@ -2707,63 +2810,21 @@ resolve_dynamic_struct (struct type *type,
resolved_type->copy_fields (type);
}
- for (i = 0; i < resolved_type->num_fields (); ++i)
+ for (auto &field : resolved_type->fields ())
{
unsigned new_bit_length;
- struct property_addr_info pinfo;
- if (resolved_type->field (i).is_static ())
+ if (field.is_static ())
continue;
- if (resolved_type->field (i).loc_kind () == FIELD_LOC_KIND_DWARF_BLOCK)
- {
- struct dwarf2_property_baton baton;
- baton.property_type
- = lookup_pointer_type (resolved_type->field (i).type ());
- baton.locexpr = *resolved_type->field (i).loc_dwarf_block ();
-
- struct dynamic_prop prop;
- prop.set_locexpr (&baton);
-
- CORE_ADDR addr;
- if (dwarf2_evaluate_property (&prop, frame, addr_stack, &addr,
- {addr_stack->addr}))
- resolved_type->field (i).set_loc_bitpos
- (TARGET_CHAR_BIT * (addr - addr_stack->addr));
- }
-
- /* As we know this field is not a static field, the field's
- field_loc_kind should be FIELD_LOC_KIND_BITPOS. Verify
- this is the case, but only trigger a simple error rather
- than an internal error if that fails. While failing
- that verification indicates a bug in our code, the error
- is not severe enough to suggest to the user he stops
- his debugging session because of it. */
- if (resolved_type->field (i).loc_kind () != FIELD_LOC_KIND_BITPOS)
- error (_("Cannot determine struct field location"
- " (invalid location kind)"));
+ resolve_dynamic_field (field, addr_stack, frame);
- pinfo.type = check_typedef (resolved_type->field (i).type ());
- size_t offset = resolved_type->field (i).loc_bitpos () / TARGET_CHAR_BIT;
- pinfo.valaddr = addr_stack->valaddr;
- if (!pinfo.valaddr.empty ())
- pinfo.valaddr = pinfo.valaddr.slice (offset);
- pinfo.addr = addr_stack->addr + offset;
- pinfo.next = addr_stack;
-
- resolved_type->field (i).set_type
- (resolve_dynamic_type_internal (resolved_type->field (i).type (),
- &pinfo, frame, false));
- gdb_assert (resolved_type->field (i).loc_kind ()
- == FIELD_LOC_KIND_BITPOS);
-
- new_bit_length = resolved_type->field (i).loc_bitpos ();
- if (resolved_type->field (i).bitsize () != 0)
- new_bit_length += resolved_type->field (i).bitsize ();
+ new_bit_length = field.loc_bitpos ();
+ if (field.bitsize () != 0)
+ new_bit_length += field.bitsize ();
else
{
- struct type *real_type
- = check_typedef (resolved_type->field (i).type ());
+ struct type *real_type = check_typedef (field.type ());
new_bit_length += (real_type->length () * TARGET_CHAR_BIT);
}
@@ -2797,7 +2858,7 @@ resolve_dynamic_struct (struct type *type,
static struct type *
resolve_dynamic_type_internal (struct type *type,
- struct property_addr_info *addr_stack,
+ const property_addr_info *addr_stack,
const frame_info_ptr &frame,
bool top_level)
{
@@ -3330,7 +3391,8 @@ check_stub_method (struct type *type, int method_id, int signature_id)
/* MTYPE may currently be a function (TYPE_CODE_FUNC).
We want a method (TYPE_CODE_METHOD). */
smash_to_method_type (mtype, type, mtype->target_type (),
- argtypes, argcount, p[-2] == '.');
+ gdb::make_array_view (argtypes, argcount),
+ p[-2] == '.');
mtype->set_is_stub (false);
TYPE_FN_FIELD_STUB (f, signature_id) = 0;
}
@@ -3634,12 +3696,12 @@ type_align (struct type *type)
case TYPE_CODE_UNION:
{
int number_of_non_static_fields = 0;
- for (unsigned i = 0; i < type->num_fields (); ++i)
+ for (const auto &field : type->fields ())
{
- if (!type->field (i).is_static ())
+ if (!field.is_static ())
{
number_of_non_static_fields++;
- ULONGEST f_align = type_align (type->field (i).type ());
+ ULONGEST f_align = type_align (field.type ());
if (f_align == 0)
{
/* Don't pretend we know something we don't. */
@@ -4356,7 +4418,8 @@ check_types_equal (struct type *type1, struct type *type2,
field2->loc_physname ()))
return false;
break;
- case FIELD_LOC_KIND_DWARF_BLOCK:
+ case FIELD_LOC_KIND_DWARF_BLOCK_ADDR:
+ case FIELD_LOC_KIND_DWARF_BLOCK_BITPOS:
{
struct dwarf2_locexpr_baton *block1, *block2;
@@ -4973,19 +5036,14 @@ rank_one_type (struct type *parm, struct type *arg, struct value *value)
situation. */
static void
-print_args (struct field *args, int nargs, int spaces)
+print_args (gdb::array_view<struct field> args, int spaces)
{
- if (args != NULL)
+ for (int i = 0; i < args.size (); i++)
{
- int i;
-
- for (i = 0; i < nargs; i++)
- {
- gdb_printf
- ("%*s[%d] name '%s'\n", spaces, "", i,
- args[i].name () != NULL ? args[i].name () : "<NULL>");
- recursive_dump_type (args[i].type (), spaces + 2);
- }
+ gdb_printf
+ ("%*s[%d] name '%s'\n", spaces, "", i,
+ args[i].name () != NULL ? args[i].name () : "<NULL>");
+ recursive_dump_type (args[i].type (), spaces + 2);
}
}
@@ -5026,9 +5084,8 @@ dump_fn_fieldlists (struct type *type, int spaces)
gdb_printf
("%*sargs %s\n", spaces + 8, "",
- host_address_to_string (TYPE_FN_FIELD_ARGS (f, overload_idx)));
+ host_address_to_string (TYPE_FN_FIELD_ARGS (f, overload_idx).data ()));
print_args (TYPE_FN_FIELD_ARGS (f, overload_idx),
- TYPE_FN_FIELD_TYPE (f, overload_idx)->num_fields (),
spaces + 8 + 2);
gdb_printf
("%*sfcontext %s\n", spaces + 8, "",
@@ -5310,7 +5367,7 @@ recursive_dump_type (struct type *type, int spaces)
}
gdb_printf ("\n");
}
- gdb_printf ("%s\n", host_address_to_string (type->fields ()));
+ gdb_printf ("%s\n", host_address_to_string (type->fields ().data ()));
for (idx = 0; idx < type->num_fields (); idx++)
{
field &fld = type->field (idx);
@@ -5501,8 +5558,12 @@ copy_type_recursive (struct type *type, copied_types_hash_t &copied_types)
new_type->field (i).set_loc_physname
(xstrdup (type->field (i).loc_physname ()));
break;
- case FIELD_LOC_KIND_DWARF_BLOCK:
- new_type->field (i).set_loc_dwarf_block
+ case FIELD_LOC_KIND_DWARF_BLOCK_ADDR:
+ new_type->field (i).set_loc_dwarf_block_addr
+ (type->field (i).loc_dwarf_block ());
+ break;
+ case FIELD_LOC_KIND_DWARF_BLOCK_BITPOS:
+ new_type->field (i).set_loc_dwarf_block_bitpos
(type->field (i).loc_dwarf_block ());
break;
default:
@@ -5687,7 +5748,7 @@ append_composite_type_field_raw (struct type *t, const char *name,
struct field *f;
t->set_num_fields (t->num_fields () + 1);
- t->set_fields (XRESIZEVEC (struct field, t->fields (),
+ t->set_fields (XRESIZEVEC (struct field, t->fields ().data (),
t->num_fields ()));
f = &t->field (t->num_fields () - 1);
memset (f, 0, sizeof f[0]);
@@ -5838,7 +5899,7 @@ type::alloc_fields (unsigned int nfields, bool init)
return;
}
- size_t size = nfields * sizeof (*this->fields ());
+ size_t size = nfields * sizeof (struct field);
struct field *fields
= (struct field *) (init
? TYPE_ZALLOC (this, size)
@@ -5857,8 +5918,8 @@ type::copy_fields (struct type *src)
if (nfields == 0)
return;
- size_t size = nfields * sizeof (*this->fields ());
- memcpy (this->fields (), src->fields (), size);
+ size_t size = nfields * sizeof (struct field);
+ memcpy (this->fields ().data (), src->fields ().data (), size);
}
/* See gdbtypes.h. */
@@ -5871,8 +5932,8 @@ type::copy_fields (std::vector<struct field> &src)
if (nfields == 0)
return;
- size_t size = nfields * sizeof (*this->fields ());
- memcpy (this->fields (), src.data (), size);
+ size_t size = nfields * sizeof (struct field);
+ memcpy (this->fields ().data (), src.data (), size);
}
/* See gdbtypes.h. */
@@ -6115,17 +6176,25 @@ builtin_type (struct objfile *objfile)
return builtin_type (objfile->arch ());
}
-/* See gdbtypes.h. */
+/* See dwarf2/call-site.h. */
CORE_ADDR
call_site::pc () const
{
+ /* dwarf2_per_objfile is defined in dwarf/read.c, so if that is disabled
+ at configure time, we won't be able to use this relocate function.
+ This is dwarf-specific, and would ideally be in call-site.h, but
+ including dwarf2/read.h in dwarf2/call-site.h will lead to things being
+ included in the wrong order and many compilation errors will happen.
+ This is the next best thing. */
+#if defined(DWARF_FORMAT_AVAILABLE)
return per_objfile->relocate (m_unrelocated_pc);
+#else
+ gdb_assert_not_reached ("unexpected call_site object found");
+#endif
}
-void _initialize_gdbtypes ();
-void
-_initialize_gdbtypes ()
+INIT_GDB_FILE (gdbtypes)
{
add_setshow_zuinteger_cmd ("overload", no_class, &overload_debug,
_("Set debugging of C++ overloading."),
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 5ee9deb..75c77b3 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -259,7 +259,7 @@ enum dynamic_prop_kind
{
PROP_UNDEFINED, /* Not defined. */
PROP_CONST, /* Constant. */
- PROP_ADDR_OFFSET, /* Address offset. */
+ PROP_FIELD, /* Field of a type. */
PROP_LOCEXPR, /* Location expression. */
PROP_LOCLIST, /* Location list. */
PROP_VARIANT_PARTS, /* Variant parts. */
@@ -347,7 +347,7 @@ struct dynamic_prop
{
gdb_assert (m_kind == PROP_LOCEXPR
|| m_kind == PROP_LOCLIST
- || m_kind == PROP_ADDR_OFFSET);
+ || m_kind == PROP_FIELD);
return m_data.baton;
}
@@ -364,9 +364,9 @@ struct dynamic_prop
m_data.baton = baton;
}
- void set_addr_offset (const dwarf2_property_baton *baton)
+ void set_field (const dwarf2_property_baton *baton)
{
- m_kind = PROP_ADDR_OFFSET;
+ m_kind = PROP_FIELD;
m_data.baton = baton;
}
@@ -480,7 +480,10 @@ enum field_loc_kind
FIELD_LOC_KIND_ENUMVAL, /**< enumval */
FIELD_LOC_KIND_PHYSADDR, /**< physaddr */
FIELD_LOC_KIND_PHYSNAME, /**< physname */
- FIELD_LOC_KIND_DWARF_BLOCK /**< dwarf_block */
+ /* A DWARF block that computes the address of the field. */
+ FIELD_LOC_KIND_DWARF_BLOCK_ADDR, /**< dwarf_block */
+ /* A DWARF block that computes the bit offset of the field. */
+ FIELD_LOC_KIND_DWARF_BLOCK_BITPOS,
};
/* * A discriminant to determine which field in the
@@ -616,6 +619,13 @@ struct field
return m_loc_kind;
}
+ /* Return true if this location has either "DWARF block" kind. */
+ bool loc_is_dwarf_block () const
+ {
+ return (m_loc_kind == FIELD_LOC_KIND_DWARF_BLOCK_ADDR
+ || m_loc_kind == FIELD_LOC_KIND_DWARF_BLOCK_BITPOS);
+ }
+
LONGEST loc_bitpos () const
{
gdb_assert (m_loc_kind == FIELD_LOC_KIND_BITPOS);
@@ -666,13 +676,19 @@ struct field
dwarf2_locexpr_baton *loc_dwarf_block () const
{
- gdb_assert (m_loc_kind == FIELD_LOC_KIND_DWARF_BLOCK);
+ gdb_assert (loc_is_dwarf_block ());
return m_loc.dwarf_block;
}
- void set_loc_dwarf_block (dwarf2_locexpr_baton *dwarf_block)
+ void set_loc_dwarf_block_addr (dwarf2_locexpr_baton *dwarf_block)
{
- m_loc_kind = FIELD_LOC_KIND_DWARF_BLOCK;
+ m_loc_kind = FIELD_LOC_KIND_DWARF_BLOCK_ADDR;
+ m_loc.dwarf_block = dwarf_block;
+ }
+
+ void set_loc_dwarf_block_bitpos (dwarf2_locexpr_baton *dwarf_block)
+ {
+ m_loc_kind = FIELD_LOC_KIND_DWARF_BLOCK_BITPOS;
m_loc.dwarf_block = dwarf_block;
}
@@ -1064,12 +1080,6 @@ struct type
this->main_type->m_nfields = num_fields;
}
- /* Get the fields array of this type. */
- struct field *fields () const
- {
- return this->main_type->flds_bnds.fields;
- }
-
/* Get the field at index IDX. */
struct field &field (int idx) const
{
@@ -1077,6 +1087,13 @@ struct type
return this->fields ()[idx];
}
+ /* Return an array view of the fields. */
+ gdb::array_view<struct field> fields () const
+ {
+ return gdb::make_array_view (this->main_type->flds_bnds.fields,
+ num_fields ());
+ }
+
/* Set the fields array of this type. */
void set_fields (struct field *fields)
{
@@ -2454,8 +2471,9 @@ extern struct type *lookup_memberptr_type (struct type *, struct type *);
extern struct type *lookup_methodptr_type (struct type *);
extern void smash_to_method_type (struct type *type, struct type *self_type,
- struct type *to_type, struct field *args,
- int nargs, int varargs);
+ struct type *to_type,
+ gdb::array_view<struct field> args,
+ int varargs);
extern void smash_to_memberptr_type (struct type *, struct type *,
struct type *);
@@ -2629,6 +2647,41 @@ extern struct type *resolve_dynamic_type
"dynamic". */
extern bool is_dynamic_type (struct type *type);
+/* Resolve any dynamic components of FIELD. FIELD is updated.
+ ADDR_STACK and FRAME are used where necessary to supply information
+ for the resolution process; see resolve_dynamic_type.
+ Specifically, after calling this, the field's bit position will be
+ a constant, and the field's type will not have dynamic properties.
+
+ This function assumes that FIELD is not a static field. */
+
+extern void resolve_dynamic_field (struct field &field,
+ const struct property_addr_info *addr_stack,
+ const frame_info_ptr &frame);
+
+/* A helper function that handles the DWARF semantics for
+ DW_AT_bit_offset.
+
+ DWARF 3 specified DW_AT_bit_offset in a funny way, making it simple
+ to use on big-endian targets but somewhat difficult for
+ little-endian. This function handles the logic here.
+
+ While DW_AT_bit_offset was deprecated in DWARF 4 (and removed
+ entirely from DWARF 5), it is still useful because it is the only
+ way to describe a field that appears at a non-constant bit
+ offset.
+
+ FIELD is updated in-place. It is assumed that FIELD already has a
+ constant bit position. BIT_OFFSET is the value of the
+ DW_AT_bit_offset attribute, and EXPLICIT_BYTE_SIZE is either the
+ value of a DW_AT_byte_size from the field's DIE -- indicating an
+ explicit size of the enclosing anonymous object -- or it may be 0,
+ indicating that the field's type size should be used. */
+
+extern void apply_bit_offset_to_field (struct field &field,
+ LONGEST bit_offset,
+ LONGEST explicit_byte_size);
+
extern struct type *check_typedef (struct type *);
extern void check_stub_method_group (struct type *, int);
diff --git a/gdb/gmp-utils.c b/gdb/gmp-utils.c
index b48e97c..5c5423a 100644
--- a/gdb/gmp-utils.c
+++ b/gdb/gmp-utils.c
@@ -250,10 +250,7 @@ xfree_for_gmp (void *ptr, size_t size)
xfree (ptr);
}
-void _initialize_gmp_utils ();
-
-void
-_initialize_gmp_utils ()
+INIT_GDB_FILE (gmp_utils)
{
/* Tell GMP to use GDB's memory management routines. */
mp_set_memory_functions (xmalloc, xrealloc_for_gmp, xfree_for_gmp);
diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c
index ea07dd6..33391ba 100644
--- a/gdb/gnu-nat.c
+++ b/gdb/gnu-nat.c
@@ -50,7 +50,6 @@ extern "C"
}
-#include <ctype.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/ptrace.h>
@@ -2926,7 +2925,7 @@ set_sig_thread_cmd (const char *args, int from_tty)
{
struct inf *inf = cur_inf ();
- if (!args || (!isdigit (*args) && strcmp (args, "none") != 0))
+ if (!args || (!c_isdigit (*args) && strcmp (args, "none") != 0))
error (_("Illegal argument to \"set signal-thread\" command.\n"
"Should be a thread ID, or \"none\"."));
@@ -3434,9 +3433,7 @@ to the thread's initial suspend-count when gdb notices the threads."),
&thread_cmd_list);
}
-void _initialize_gnu_nat ();
-void
-_initialize_gnu_nat ()
+INIT_GDB_FILE (gnu_nat)
{
proc_server = getproc ();
diff --git a/gdb/gnu-v2-abi.c b/gdb/gnu-v2-abi.c
index ab9f53b..1fbc41d 100644
--- a/gdb/gnu-v2-abi.c
+++ b/gdb/gnu-v2-abi.c
@@ -26,7 +26,6 @@
#include "gdb-demangle.h"
#include "cp-abi.h"
#include "cp-support.h"
-#include <ctype.h>
static cp_abi_ops gnu_v2_abi_ops;
@@ -46,7 +45,7 @@ static enum ctor_kinds
gnuv2_is_constructor_name (const char *name)
{
if ((name[0] == '_' && name[1] == '_'
- && (isdigit (name[2]) || strchr ("Qt", name[2])))
+ && (c_isdigit (name[2]) || strchr ("Qt", name[2])))
|| startswith (name, "__ct__"))
return complete_object_ctor;
else
@@ -265,15 +264,9 @@ gnuv2_value_rtti_type (struct value *v, int *full, LONGEST *top, int *using_enc)
if (top && ((*top) >0))
{
if (rtti_type->length () > known_type->length ())
- {
- if (full)
- *full=0;
- }
+ *full = 0;
else
- {
- if (full)
- *full=1;
- }
+ *full = 1;
}
}
else
@@ -411,9 +404,7 @@ init_gnuv2_ops (void)
gnu_v2_abi_ops.baseclass_offset = gnuv2_baseclass_offset;
}
-void _initialize_gnu_v2_abi ();
-void
-_initialize_gnu_v2_abi ()
+INIT_GDB_FILE (gnu_v2_abi)
{
init_gnuv2_ops ();
register_cp_abi (&gnu_v2_abi_ops);
diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c
index 4f53e9f..e3818d9 100644
--- a/gdb/gnu-v3-abi.c
+++ b/gdb/gnu-v3-abi.c
@@ -476,7 +476,7 @@ gnuv3_baseclass_offset (struct type *type, int index,
return TYPE_BASECLASS_BITPOS (type, index) / 8;
/* If we have a DWARF expression for the offset, evaluate it. */
- if (type->field (index).loc_kind () == FIELD_LOC_KIND_DWARF_BLOCK)
+ if (type->field (index).loc_kind () == FIELD_LOC_KIND_DWARF_BLOCK_ADDR)
{
struct dwarf2_property_baton baton;
baton.property_type
@@ -1570,9 +1570,7 @@ init_gnuv3_ops (void)
gnu_v3_abi_ops.pass_by_reference = gnuv3_pass_by_reference;
}
-void _initialize_gnu_v3_abi ();
-void
-_initialize_gnu_v3_abi ()
+INIT_GDB_FILE (gnu_v3_abi)
{
init_gnuv3_ops ();
diff --git a/gdb/go-exp.y b/gdb/go-exp.y
index 8823503..5da8cef 100644
--- a/gdb/go-exp.y
+++ b/gdb/go-exp.y
@@ -51,7 +51,6 @@
%{
-#include <ctype.h>
#include "expression.h"
#include "value.h"
#include "parser-defs.h"
@@ -663,13 +662,13 @@ parse_number (struct parser_state *par_state,
/* Handle suffixes: 'f' for float32, 'l' for long double.
FIXME: This appears to be an extension -- do we want this? */
- if (len >= 1 && tolower (p[len - 1]) == 'f')
+ if (len >= 1 && c_tolower (p[len - 1]) == 'f')
{
putithere->typed_val_float.type
= builtin_go_types->builtin_float32;
len--;
}
- else if (len >= 1 && tolower (p[len - 1]) == 'l')
+ else if (len >= 1 && c_tolower (p[len - 1]) == 'l')
{
putithere->typed_val_float.type
= parse_type (par_state)->builtin_long_double;
@@ -1113,9 +1112,9 @@ lex_one_token (struct parser_state *par_state)
const char *p = &tokstart[1];
size_t len = strlen ("entry");
- while (isspace (*p))
+ while (c_isspace (*p))
p++;
- if (strncmp (p, "entry", len) == 0 && !isalnum (p[len])
+ if (strncmp (p, "entry", len) == 0 && !c_isalnum (p[len])
&& p[len] != '_')
{
par_state->lexptr = &p[len];
@@ -1290,7 +1289,7 @@ package_name_p (const char *name, const struct block *block)
&is_a_field_of_this).symbol;
if (sym
- && sym->aclass () == LOC_TYPEDEF
+ && sym->loc_class () == LOC_TYPEDEF
&& sym->type ()->code () == TYPE_CODE_MODULE)
return 1;
diff --git a/gdb/go-lang.c b/gdb/go-lang.c
index bad2ccf..23ffedb 100644
--- a/gdb/go-lang.c
+++ b/gdb/go-lang.c
@@ -41,7 +41,6 @@
#include "parser-defs.h"
#include "gdbarch.h"
-#include <ctype.h>
/* The main function in the main package. */
static const char GO_MAIN_MAIN[] = "main.main";
@@ -292,7 +291,7 @@ unpack_mangled_go_symbol (const char *mangled_name,
while (p > buf)
{
int current = *(const unsigned char *) --p;
- int current_is_digit = isdigit (current);
+ int current_is_digit = c_isdigit (current);
if (saw_digit)
{
diff --git a/gdb/go32-nat.c b/gdb/go32-nat.c
index 8dcb22d..ab13b57 100644
--- a/gdb/go32-nat.c
+++ b/gdb/go32-nat.c
@@ -103,7 +103,6 @@
#include "cli/cli-utils.h"
#include "inf-child.h"
-#include <ctype.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <io.h>
@@ -2057,9 +2056,7 @@ go32_pte_for_address (const char *arg, int from_tty)
static struct cmd_list_element *info_dos_cmdlist = NULL;
-void _initialize_go32_nat ();
-void
-_initialize_go32_nat ()
+INIT_GDB_FILE (go32_nat)
{
x86_dr_low.set_control = go32_set_dr7;
x86_dr_low.set_addr = go32_set_dr;
diff --git a/gdb/guile/guile-internal.h b/gdb/guile/guile-internal.h
index 3101882..60a8bf3 100644
--- a/gdb/guile/guile-internal.h
+++ b/gdb/guile/guile-internal.h
@@ -449,10 +449,11 @@ extern const struct block *bkscm_scm_to_block
/* scm-cmd.c */
-extern char *gdbscm_parse_command_name (const char *name,
- const char *func_name, int arg_pos,
- struct cmd_list_element ***base_list,
- struct cmd_list_element **start_list);
+extern char *gdbscm_parse_command_name
+ (const char *name, const char *func_name, int arg_pos,
+ struct cmd_list_element ***base_list,
+ struct cmd_list_element **start_list,
+ struct cmd_list_element **prefix_cmd = nullptr);
extern int gdbscm_valid_command_class_p (int command_class);
diff --git a/gdb/guile/guile.c b/gdb/guile/guile.c
index 1803df0..66a74b3 100644
--- a/gdb/guile/guile.c
+++ b/gdb/guile/guile.c
@@ -827,9 +827,7 @@ message == an error message without a stack will be printed."),
&set_guile_list, &show_guile_list);
}
-void _initialize_guile ();
-void
-_initialize_guile ()
+INIT_GDB_FILE (guile)
{
install_gdb_commands ();
}
diff --git a/gdb/guile/scm-cmd.c b/gdb/guile/scm-cmd.c
index 4757872..ef4c9d6 100644
--- a/gdb/guile/scm-cmd.c
+++ b/gdb/guile/scm-cmd.c
@@ -20,7 +20,6 @@
/* See README file in this directory for implementation notes, coding
conventions, et.al. */
-#include <ctype.h>
#include "charset.h"
#include "cli/cli-cmds.h"
#include "cli/cli-decode.h"
@@ -457,11 +456,13 @@ cmdscm_completer (struct cmd_list_element *command,
name of the new command. All earlier words must be existing prefix
commands.
- *BASE_LIST is set to the final prefix command's list of
- *sub-commands.
+ *BASE_LIST is set to the final prefix command's list of sub-commands.
START_LIST is the list in which the search starts.
+ When PREFIX_CMD is not NULL then *PREFIX_CMD is set to the prefix
+ command itself, or NULL, if there is no prefix command.
+
This function returns the xmalloc()d name of the new command.
On error a Scheme exception is thrown. */
@@ -469,13 +470,17 @@ char *
gdbscm_parse_command_name (const char *name,
const char *func_name, int arg_pos,
struct cmd_list_element ***base_list,
- struct cmd_list_element **start_list)
+ struct cmd_list_element **start_list,
+ struct cmd_list_element **prefix_cmd)
{
struct cmd_list_element *elt;
int len = strlen (name);
int i, lastchar;
char *msg;
+ if (prefix_cmd != nullptr)
+ *prefix_cmd = nullptr;
+
/* Skip trailing whitespace. */
for (i = len - 1; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i)
;
@@ -490,9 +495,9 @@ gdbscm_parse_command_name (const char *name,
/* Find first character of the final word. */
for (; i > 0 && valid_cmd_char_p (name[i - 1]); --i)
;
- gdb::unique_xmalloc_ptr<char> result ((char *) xmalloc (lastchar - i + 2));
- memcpy (result.get (), &name[i], lastchar - i + 1);
- result.get ()[lastchar - i + 1] = '\0';
+
+ gdb::unique_xmalloc_ptr<char> result
+ = make_unique_xstrndup (&name[i], lastchar - i + 1);
/* Skip whitespace again. */
for (--i; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i)
@@ -503,18 +508,21 @@ gdbscm_parse_command_name (const char *name,
return result.release ();
}
- gdb::unique_xmalloc_ptr<char> prefix_text ((char *) xmalloc (i + 2));
- memcpy (prefix_text.get (), name, i + 1);
- prefix_text.get ()[i + 1] = '\0';
+ gdb::unique_xmalloc_ptr<char> prefix_text
+ = make_unique_xstrndup (name, i + 1);
const char *prefix_text2 = prefix_text.get ();
elt = lookup_cmd_1 (&prefix_text2, *start_list, NULL, NULL, 1);
- if (elt == NULL || elt == CMD_LIST_AMBIGUOUS)
+ if (elt == nullptr || elt == CMD_LIST_AMBIGUOUS || *prefix_text2 != '\0')
{
msg = xstrprintf (_("could not find command prefix '%s'"),
prefix_text.get ()).release ();
scm_dynwind_begin ((scm_t_dynwind_flags) 0);
gdbscm_dynwind_xfree (msg);
+ /* Release memory now as the destructors will not be run when the
+ guile exception is thrown. */
+ result = nullptr;
+ prefix_text = nullptr;
gdbscm_out_of_range_error (func_name, arg_pos,
gdbscm_scm_from_c_string (name), msg);
}
@@ -522,6 +530,8 @@ gdbscm_parse_command_name (const char *name,
if (elt->is_prefix ())
{
*base_list = elt->subcommands;
+ if (prefix_cmd != nullptr)
+ *prefix_cmd = elt;
return result.release ();
}
@@ -529,6 +539,10 @@ gdbscm_parse_command_name (const char *name,
prefix_text.get ()).release ();
scm_dynwind_begin ((scm_t_dynwind_flags) 0);
gdbscm_dynwind_xfree (msg);
+ /* Release memory now as the destructors will not be run when the guile
+ exception is thrown. */
+ result = nullptr;
+ prefix_text = nullptr;
gdbscm_out_of_range_error (func_name, arg_pos,
gdbscm_scm_from_c_string (name), msg);
/* NOTREACHED */
@@ -743,8 +757,9 @@ gdbscm_register_command_x (SCM self)
if (cmdscm_is_valid (c_smob))
scm_misc_error (FUNC_NAME, _("command is already registered"), SCM_EOL);
+ struct cmd_list_element *prefix_cmd = nullptr;
cmd_name = gdbscm_parse_command_name (c_smob->name, FUNC_NAME, SCM_ARG1,
- &cmd_list, &cmdlist);
+ &cmd_list, &cmdlist, &prefix_cmd);
c_smob->cmd_name = gdbscm_gc_xstrdup (cmd_name);
xfree (cmd_name);
@@ -753,18 +768,50 @@ gdbscm_register_command_x (SCM self)
{
if (c_smob->is_prefix)
{
- /* If we have our own "invoke" method, then allow unknown
- sub-commands. */
- int allow_unknown = gdbscm_is_true (c_smob->invoke);
+ bool has_invoke = gdbscm_is_true (c_smob->invoke) == 1;
- cmd = add_prefix_cmd (c_smob->cmd_name, c_smob->cmd_class,
- NULL, c_smob->doc, &c_smob->sub_list,
- allow_unknown, cmd_list);
+ if (has_invoke)
+ {
+ cmd = add_prefix_cmd (c_smob->cmd_name, c_smob->cmd_class,
+ NULL, c_smob->doc, &c_smob->sub_list,
+ 1 /* allow_unknown */, cmd_list);
+ cmd->func = cmdscm_function;
+ }
+ else
+ {
+ /* If there is no 'invoke' method, then create the prefix
+ using the standard prefix callbacks. This means that for
+ 'set prefix' the user will get the help text listing all
+ of the sub-commands, and for 'show prefix', the user will
+ see all of the sub-command values. */
+ if (prefix_cmd != nullptr)
+ {
+ while (prefix_cmd->prefix != nullptr)
+ prefix_cmd = prefix_cmd->prefix;
+ }
+
+ bool is_show = (prefix_cmd != nullptr
+ && prefix_cmd->subcommands == &showlist);
+
+ if (is_show)
+ cmd = add_show_prefix_cmd (c_smob->cmd_name,
+ c_smob->cmd_class,
+ c_smob->doc,
+ &c_smob->sub_list,
+ 0 /* allow_unknown */, cmd_list);
+ else
+ cmd = add_basic_prefix_cmd (c_smob->cmd_name,
+ c_smob->cmd_class,
+ c_smob->doc,
+ &c_smob->sub_list,
+ 0 /* allow_unknown */, cmd_list);
+ }
}
else
{
cmd = add_cmd (c_smob->cmd_name, c_smob->cmd_class,
c_smob->doc, cmd_list);
+ cmd->func = cmdscm_function;
}
}
catch (const gdb_exception &except)
@@ -777,7 +824,6 @@ gdbscm_register_command_x (SCM self)
So no more errors after this point. */
/* There appears to be no API to set this. */
- cmd->func = cmdscm_function;
cmd->destroyer = cmdscm_destroyer;
c_smob->command = cmd;
diff --git a/gdb/guile/scm-color.c b/gdb/guile/scm-color.c
index 4850575..cde22e5 100644
--- a/gdb/guile/scm-color.c
+++ b/gdb/guile/scm-color.c
@@ -24,6 +24,7 @@
#include "language.h"
#include "arch-utils.h"
#include "guile-internal.h"
+#include "cli/cli-style.h"
/* A GDB color. */
@@ -354,8 +355,14 @@ gdbscm_color_escape_sequence (SCM self, SCM is_fg_scm)
const ui_file_style::color &color = coscm_get_color (self);
SCM_ASSERT_TYPE (gdbscm_is_bool (is_fg_scm), is_fg_scm, SCM_ARG2, FUNC_NAME,
_("boolean"));
- bool is_fg = gdbscm_is_true (is_fg_scm);
- std::string s = color.to_ansi (is_fg);
+
+ std::string s;
+ if (term_cli_styling ())
+ {
+ bool is_fg = gdbscm_is_true (is_fg_scm);
+ s = color.to_ansi (is_fg);
+ }
+
return gdbscm_scm_from_host_string (s.c_str (), s.size ());
}
diff --git a/gdb/guile/scm-param.c b/gdb/guile/scm-param.c
index 65226ec..5137847 100644
--- a/gdb/guile/scm-param.c
+++ b/gdb/guile/scm-param.c
@@ -308,13 +308,37 @@ pascm_is_valid (param_smob *p_smob)
return p_smob->commands.set != nullptr;
}
-/* A helper function which return the default documentation string for
- a parameter (which is to say that it's undocumented). */
+
+/* The different types of documentation string. */
+
+enum doc_string_type
+{
+ doc_string_set,
+ doc_string_show,
+ doc_string_description
+};
+
+/* A helper function which returns the default documentation string for
+ a parameter CMD_NAME. The DOC_TYPE indicates which type of
+ documentation string is needed. The returned string is dynamically
+ allocated. */
static char *
-get_doc_string (void)
+get_doc_string (doc_string_type doc_type, const char *cmd_name)
{
- return xstrdup (_("This command is not documented."));
+ if (doc_type == doc_string_description)
+ return xstrdup (_("This command is not documented."));
+ else
+ {
+ gdb_assert (cmd_name != nullptr);
+
+ if (doc_type == doc_string_show)
+ return xstrprintf (_("Show the current value of '%s'."),
+ cmd_name).release ();
+ else
+ return xstrprintf (_("Set the current value of '%s'."),
+ cmd_name).release ();
+ }
}
/* Subroutine of pascm_set_func, pascm_show_func to simplify them.
@@ -990,11 +1014,14 @@ gdbscm_make_parameter (SCM name_scm, SCM rest)
&show_doc_arg_pos, &show_doc,
&initial_value_arg_pos, &initial_value_scm);
- /* If doc is NULL, leave it NULL. See add_setshow_cmd_full. */
+ if (doc == nullptr)
+ doc = get_doc_string (doc_string_description, nullptr);
+ else if (*doc == '\0')
+ doc = nullptr;
if (set_doc == NULL)
- set_doc = get_doc_string ();
+ set_doc = get_doc_string (doc_string_set, name);
if (show_doc == NULL)
- show_doc = get_doc_string ();
+ show_doc = get_doc_string (doc_string_show, name);
s = name;
name = gdbscm_canonicalize_command_name (s, 0);
diff --git a/gdb/guile/scm-symbol.c b/gdb/guile/scm-symbol.c
index 8c2ae24..1d3fb29 100644
--- a/gdb/guile/scm-symbol.c
+++ b/gdb/guile/scm-symbol.c
@@ -405,7 +405,7 @@ gdbscm_symbol_addr_class (SCM self)
= syscm_get_valid_symbol_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
const struct symbol *symbol = s_smob->symbol;
- return scm_from_int (symbol->aclass ());
+ return scm_from_int (symbol->loc_class ());
}
/* (symbol-argument? <gdb:symbol>) -> boolean */
@@ -428,11 +428,9 @@ gdbscm_symbol_constant_p (SCM self)
symbol_smob *s_smob
= syscm_get_valid_symbol_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
const struct symbol *symbol = s_smob->symbol;
- enum address_class theclass;
+ location_class loc_class = symbol->loc_class ();
- theclass = symbol->aclass ();
-
- return scm_from_bool (theclass == LOC_CONST || theclass == LOC_CONST_BYTES);
+ return scm_from_bool (loc_class == LOC_CONST || loc_class == LOC_CONST_BYTES);
}
/* (symbol-function? <gdb:symbol>) -> boolean */
@@ -443,11 +441,9 @@ gdbscm_symbol_function_p (SCM self)
symbol_smob *s_smob
= syscm_get_valid_symbol_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
const struct symbol *symbol = s_smob->symbol;
- enum address_class theclass;
-
- theclass = symbol->aclass ();
+ location_class loc_class = symbol->loc_class ();
- return scm_from_bool (theclass == LOC_BLOCK);
+ return scm_from_bool (loc_class == LOC_BLOCK);
}
/* (symbol-variable? <gdb:symbol>) -> boolean */
@@ -458,14 +454,12 @@ gdbscm_symbol_variable_p (SCM self)
symbol_smob *s_smob
= syscm_get_valid_symbol_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
const struct symbol *symbol = s_smob->symbol;
- enum address_class theclass;
-
- theclass = symbol->aclass ();
+ location_class loc_class = symbol->loc_class ();
return scm_from_bool (!symbol->is_argument ()
- && (theclass == LOC_LOCAL || theclass == LOC_REGISTER
- || theclass == LOC_STATIC || theclass == LOC_COMPUTED
- || theclass == LOC_OPTIMIZED_OUT));
+ && (loc_class == LOC_LOCAL || loc_class == LOC_REGISTER
+ || loc_class == LOC_STATIC || loc_class == LOC_COMPUTED
+ || loc_class == LOC_OPTIMIZED_OUT));
}
/* (symbol-needs-frame? <gdb:symbol>) -> boolean
@@ -526,7 +520,7 @@ gdbscm_symbol_value (SCM self, SCM rest)
if (!gdbscm_is_false (frame_scm))
f_smob = frscm_get_frame_smob_arg_unsafe (frame_scm, frame_pos, FUNC_NAME);
- if (symbol->aclass () == LOC_TYPEDEF)
+ if (symbol->loc_class () == LOC_TYPEDEF)
{
gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, self,
_("cannot get the value of a typedef"));
diff --git a/gdb/guile/scm-type.c b/gdb/guile/scm-type.c
index 5114579..13676ce 100644
--- a/gdb/guile/scm-type.c
+++ b/gdb/guile/scm-type.c
@@ -510,7 +510,7 @@ tyscm_field_smob_to_field (field_smob *f_smob)
struct type *type = tyscm_field_smob_containing_type (f_smob);
/* This should be non-NULL by construction. */
- gdb_assert (type->fields () != NULL);
+ gdb_assert (type->fields ().data () != nullptr);
return &type->field (f_smob->field_num);
}
diff --git a/gdb/h8300-tdep.c b/gdb/h8300-tdep.c
index db54438..15b0002 100644
--- a/gdb/h8300-tdep.c
+++ b/gdb/h8300-tdep.c
@@ -1374,9 +1374,7 @@ h8300_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
}
-void _initialize_h8300_tdep ();
-void
-_initialize_h8300_tdep ()
+INIT_GDB_FILE (h8300_tdep)
{
gdbarch_register (bfd_arch_h8300, h8300_gdbarch_init);
}
diff --git a/gdb/hppa-bsd-tdep.c b/gdb/hppa-bsd-tdep.c
index db6c92f..b9cd61e 100644
--- a/gdb/hppa-bsd-tdep.c
+++ b/gdb/hppa-bsd-tdep.c
@@ -54,12 +54,12 @@ hppabsd_find_global_pointer (struct gdbarch *gdbarch, struct value *function)
faddr_sec = find_pc_section (faddr);
if (faddr_sec != NULL)
{
- for (struct obj_section *sec : faddr_sec->objfile->sections ())
+ for (struct obj_section &sec : faddr_sec->objfile->sections ())
{
- if (strcmp (sec->the_bfd_section->name, ".dynamic") == 0)
+ if (strcmp (sec.the_bfd_section->name, ".dynamic") == 0)
{
- CORE_ADDR addr = sec->addr ();
- CORE_ADDR endaddr = sec->endaddr ();
+ CORE_ADDR addr = sec.addr ();
+ CORE_ADDR endaddr = sec.endaddr ();
while (addr < endaddr)
{
@@ -81,7 +81,7 @@ hppabsd_find_global_pointer (struct gdbarch *gdbarch, struct value *function)
DT_PLTGOT, so we have to do it ourselves. */
pltgot = extract_unsigned_integer (buf, sizeof buf,
byte_order);
- pltgot += sec->objfile->text_section_offset ();
+ pltgot += sec.objfile->text_section_offset ();
return pltgot;
}
@@ -128,8 +128,7 @@ hppabsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_skip_trampoline_code (gdbarch, hppa_skip_trampoline_code);
/* OpenBSD and NetBSD use SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
/* Hook in the DWARF CFI frame unwinder. */
dwarf2_frame_set_init_reg (gdbarch, hppabsd_dwarf2_frame_init_reg);
diff --git a/gdb/hppa-linux-nat.c b/gdb/hppa-linux-nat.c
index 62b3294..5e63e7f 100644
--- a/gdb/hppa-linux-nat.c
+++ b/gdb/hppa-linux-nat.c
@@ -383,9 +383,7 @@ fill_fpregset (const struct regcache *regcache,
}
}
-void _initialize_hppa_linux_nat ();
-void
-_initialize_hppa_linux_nat ()
+INIT_GDB_FILE (hppa_linux_nat)
{
/* Register the target. */
linux_target = &the_hppa_linux_nat_target;
diff --git a/gdb/hppa-linux-tdep.c b/gdb/hppa-linux-tdep.c
index 16cdd45..d0bb562 100644
--- a/gdb/hppa-linux-tdep.c
+++ b/gdb/hppa-linux-tdep.c
@@ -32,6 +32,7 @@
#include "regcache.h"
#include "hppa-tdep.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "elf/common.h"
/* Map DWARF DBX register numbers to GDB register numbers. */
@@ -361,14 +362,14 @@ hppa_linux_find_global_pointer (struct gdbarch *gdbarch,
faddr_sect = find_pc_section (faddr);
if (faddr_sect != NULL)
{
- for (obj_section *osect : faddr_sect->objfile->sections ())
+ for (obj_section &osect : faddr_sect->objfile->sections ())
{
- if (strcmp (osect->the_bfd_section->name, ".dynamic") == 0)
+ if (strcmp (osect.the_bfd_section->name, ".dynamic") == 0)
{
CORE_ADDR addr, endaddr;
- addr = osect->addr ();
- endaddr = osect->endaddr ();
+ addr = osect.addr ();
+ endaddr = osect.endaddr ();
while (addr < endaddr)
{
@@ -499,8 +500,7 @@ hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
frame_unwind_append_unwinder (gdbarch, &hppa_linux_sigtramp_frame_unwind);
/* GNU/Linux uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
tdep->in_solib_call_trampoline = hppa_in_solib_call_trampoline;
set_gdbarch_skip_trampoline_code (gdbarch, hppa_skip_trampoline_code);
@@ -524,9 +524,7 @@ hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
svr4_fetch_objfile_link_map);
}
-void _initialize_hppa_linux_tdep ();
-void
-_initialize_hppa_linux_tdep ()
+INIT_GDB_FILE (hppa_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_LINUX,
hppa_linux_init_abi);
diff --git a/gdb/hppa-netbsd-nat.c b/gdb/hppa-netbsd-nat.c
index f57d650..1ebf205 100644
--- a/gdb/hppa-netbsd-nat.c
+++ b/gdb/hppa-netbsd-nat.c
@@ -229,9 +229,7 @@ hppa_nbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
}
}
-void _initialize_hppanbsd_nat ();
-void
-_initialize_hppanbsd_nat ()
+INIT_GDB_FILE (hppanbsd_nat)
{
add_inf_child_target (&the_hppa_nbsd_nat_target);
}
diff --git a/gdb/hppa-netbsd-tdep.c b/gdb/hppa-netbsd-tdep.c
index e52e181..90d8eb8 100644
--- a/gdb/hppa-netbsd-tdep.c
+++ b/gdb/hppa-netbsd-tdep.c
@@ -210,9 +210,7 @@ hppanbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tramp_frame_prepend_unwinder (gdbarch, &hppanbsd_sigtramp_si4);
}
-void _initialize_hppanbsd_tdep ();
-void
-_initialize_hppanbsd_tdep ()
+INIT_GDB_FILE (hppanbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_NETBSD,
hppanbsd_init_abi);
diff --git a/gdb/hppa-obsd-nat.c b/gdb/hppa-obsd-nat.c
index d879835..322b6f9 100644
--- a/gdb/hppa-obsd-nat.c
+++ b/gdb/hppa-obsd-nat.c
@@ -250,9 +250,7 @@ hppa_obsd_nat_target::store_registers (struct regcache *regcache, int regnum)
}
}
-void _initialize_hppaobsd_nat ();
-void
-_initialize_hppaobsd_nat ()
+INIT_GDB_FILE (hppaobsd_nat)
{
add_inf_child_target (&the_hppa_obsd_nat_target);
}
diff --git a/gdb/hppa-obsd-tdep.c b/gdb/hppa-obsd-tdep.c
index d2144f9..a511fa8 100644
--- a/gdb/hppa-obsd-tdep.c
+++ b/gdb/hppa-obsd-tdep.c
@@ -166,9 +166,7 @@ hppaobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
(gdbarch, hppaobsd_iterate_over_regset_sections);
}
-void _initialize_hppabsd_tdep ();
-void
-_initialize_hppabsd_tdep ()
+INIT_GDB_FILE (hppabsd_tdep)
{
gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_OPENBSD,
hppaobsd_init_abi);
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c
index 3c9dde2..6f0cebe 100644
--- a/gdb/hppa-tdep.c
+++ b/gdb/hppa-tdep.c
@@ -920,12 +920,12 @@ hppa64_convert_code_addr_to_fptr (struct gdbarch *gdbarch, CORE_ADDR code)
if (!(sec->the_bfd_section->flags & SEC_CODE))
return code;
- for (obj_section *opd : sec->objfile->sections ())
+ for (obj_section &opd : sec->objfile->sections ())
{
- if (strcmp (opd->the_bfd_section->name, ".opd") == 0)
+ if (strcmp (opd.the_bfd_section->name, ".opd") == 0)
{
- for (CORE_ADDR addr = opd->addr ();
- addr < opd->endaddr ();
+ for (CORE_ADDR addr = opd.addr ();
+ addr < opd.endaddr ();
addr += 2 * 8)
{
ULONGEST opdaddr;
@@ -3119,9 +3119,7 @@ hppa_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
gdb_printf (file, "elf = %s\n", tdep->is_elf ? "yes" : "no");
}
-void _initialize_hppa_tdep ();
-void
-_initialize_hppa_tdep ()
+INIT_GDB_FILE (hppa_tdep)
{
gdbarch_register (bfd_arch_hppa, hppa_gdbarch_init, hppa_dump_tdep);
diff --git a/gdb/i386-bsd-nat.c b/gdb/i386-bsd-nat.c
index ae9e090..c5eda86 100644
--- a/gdb/i386-bsd-nat.c
+++ b/gdb/i386-bsd-nat.c
@@ -237,9 +237,7 @@ i386bsd_store_inferior_registers (struct regcache *regcache, int regnum)
}
}
-void _initialize_i386bsd_nat ();
-void
-_initialize_i386bsd_nat ()
+INIT_GDB_FILE (i386bsd_nat)
{
/* To support the recognition of signal handlers, i386-bsd-tdep.c
hardcodes some constants. Inclusion of this file means that we
diff --git a/gdb/i386-darwin-nat.c b/gdb/i386-darwin-nat.c
index 08d3a71..09d6ba6 100644
--- a/gdb/i386-darwin-nat.c
+++ b/gdb/i386-darwin-nat.c
@@ -631,9 +631,7 @@ darwin_set_sstep (thread_t thread, int enable)
}
}
-void _initialize_i386_darwin_nat ();
-void
-_initialize_i386_darwin_nat ()
+INIT_GDB_FILE (i386_darwin_nat)
{
#ifdef BFD64
amd64_native_gregset64_reg_offset = amd64_darwin_thread_state_reg_offset;
diff --git a/gdb/i386-darwin-tdep.c b/gdb/i386-darwin-tdep.c
index 6180e02..a91afa2 100644
--- a/gdb/i386-darwin-tdep.c
+++ b/gdb/i386-darwin-tdep.c
@@ -271,7 +271,7 @@ i386_darwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
alignment. */
set_gdbarch_long_double_bit (gdbarch, 128);
- set_gdbarch_so_ops (gdbarch, &darwin_so_ops);
+ set_gdbarch_make_solib_ops (gdbarch, make_darwin_solib_ops);
}
static enum gdb_osabi
@@ -286,9 +286,7 @@ i386_mach_o_osabi_sniffer (bfd *abfd)
return GDB_OSABI_UNKNOWN;
}
-void _initialize_i386_darwin_tdep ();
-void
-_initialize_i386_darwin_tdep ()
+INIT_GDB_FILE (i386_darwin_tdep)
{
gdbarch_register_osabi_sniffer (bfd_arch_unknown, bfd_target_mach_o_flavour,
i386_mach_o_osabi_sniffer);
diff --git a/gdb/i386-dicos-tdep.c b/gdb/i386-dicos-tdep.c
index d3f19e2..50570c9 100644
--- a/gdb/i386-dicos-tdep.c
+++ b/gdb/i386-dicos-tdep.c
@@ -40,9 +40,7 @@ i386_dicos_osabi_sniffer (bfd *abfd)
return GDB_OSABI_UNKNOWN;
}
-void _initialize_i386_dicos_tdep ();
-void
-_initialize_i386_dicos_tdep ()
+INIT_GDB_FILE (i386_dicos_tdep)
{
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
i386_dicos_osabi_sniffer);
diff --git a/gdb/i386-fbsd-nat.c b/gdb/i386-fbsd-nat.c
index 77f0edd..f4088a3 100644
--- a/gdb/i386-fbsd-nat.c
+++ b/gdb/i386-fbsd-nat.c
@@ -330,9 +330,7 @@ i386_fbsd_nat_target::read_description ()
return i386_target_description (X86_XSTATE_X87_MASK, true);
}
-void _initialize_i386fbsd_nat ();
-void
-_initialize_i386fbsd_nat ()
+INIT_GDB_FILE (i386fbsd_nat)
{
add_inf_child_target (&the_i386_fbsd_nat_target);
diff --git a/gdb/i386-fbsd-tdep.c b/gdb/i386-fbsd-tdep.c
index 72237d8..a32880e 100644
--- a/gdb/i386-fbsd-tdep.c
+++ b/gdb/i386-fbsd-tdep.c
@@ -274,11 +274,10 @@ i386_fbsd_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
/* See i386-fbsd-tdep.h. */
bool
-i386_fbsd_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
+i386_fbsd_core_read_x86_xsave_layout (struct gdbarch *gdbarch, bfd &cbfd,
x86_xsave_layout &layout)
{
- return i386_fbsd_core_read_xsave_info (current_program_space->core_bfd (),
- layout) != 0;
+ return i386_fbsd_core_read_xsave_info (&cbfd, layout) != 0;
}
/* Implement the core_read_description gdbarch method. */
@@ -402,8 +401,7 @@ i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
i386fbsd_core_read_description);
/* FreeBSD uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
@@ -411,9 +409,7 @@ i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
i386fbsd_get_thread_local_address);
}
-void _initialize_i386fbsd_tdep ();
-void
-_initialize_i386fbsd_tdep ()
+INIT_GDB_FILE (i386fbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD,
i386fbsd_init_abi);
diff --git a/gdb/i386-fbsd-tdep.h b/gdb/i386-fbsd-tdep.h
index 70ad32f..acc5776 100644
--- a/gdb/i386-fbsd-tdep.h
+++ b/gdb/i386-fbsd-tdep.h
@@ -32,8 +32,9 @@
uint64_t i386_fbsd_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout);
/* Implement the core_read_x86_xsave_layout gdbarch method. */
-bool i386_fbsd_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
- x86_xsave_layout &layout);
+extern bool i386_fbsd_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
+ bfd &cbfd,
+ x86_xsave_layout &layout);
/* The format of the XSAVE extended area is determined by hardware.
Cores store the XSAVE extended area in a NT_X86_XSTATE note that
diff --git a/gdb/i386-gnu-tdep.c b/gdb/i386-gnu-tdep.c
index 97fbc69..f944fa5 100644
--- a/gdb/i386-gnu-tdep.c
+++ b/gdb/i386-gnu-tdep.c
@@ -180,8 +180,7 @@ i386gnu_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Hurd uses SVR4-style shared libraries. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
/* Hurd uses the dynamic linker included in the GNU C Library. */
set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
@@ -202,9 +201,7 @@ i386gnu_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->sc_num_regs = ARRAY_SIZE (i386_gnu_sc_reg_offset);
}
-void _initialize_i386gnu_tdep ();
-void
-_initialize_i386gnu_tdep ()
+INIT_GDB_FILE (i386gnu_tdep)
{
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_HURD, i386gnu_init_abi);
}
diff --git a/gdb/i386-go32-tdep.c b/gdb/i386-go32-tdep.c
index 4db09b3..e6a1721 100644
--- a/gdb/i386-go32-tdep.c
+++ b/gdb/i386-go32-tdep.c
@@ -61,9 +61,7 @@ i386_coff_osabi_sniffer (bfd *abfd)
}
-void _initialize_i386_go32_tdep ();
-void
-_initialize_i386_go32_tdep ()
+INIT_GDB_FILE (i386_go32_tdep)
{
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
i386_coff_osabi_sniffer);
diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
index a5d5582..f5112d2 100644
--- a/gdb/i386-linux-nat.c
+++ b/gdb/i386-linux-nat.c
@@ -696,9 +696,7 @@ i386_linux_nat_target::low_resume (ptid_t ptid, int step, enum gdb_signal signal
perror_with_name (("ptrace"));
}
-void _initialize_i386_linux_nat ();
-void
-_initialize_i386_linux_nat ()
+INIT_GDB_FILE (i386_linux_nat)
{
linux_target = &the_i386_linux_nat_target;
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index 4b05cc6..3360e96 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -30,6 +30,7 @@
#include "i386-tdep.h"
#include "i386-linux-tdep.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "utils.h"
#include "glibc-tdep.h"
#include "solib-svr4.h"
@@ -1104,11 +1105,10 @@ i386_linux_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
/* See i386-linux-tdep.h. */
bool
-i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
+i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch, bfd &cbfd,
x86_xsave_layout &layout)
{
- return i386_linux_core_read_xsave_info (current_program_space->core_bfd (),
- layout) != 0;
+ return i386_linux_core_read_xsave_info (&cbfd, layout) != 0;
}
/* See arch/x86-linux-tdesc.h. */
@@ -1461,8 +1461,7 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* GNU/Linux uses SVR4-style shared libraries. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
/* GNU/Linux uses the dynamic linker included in the GNU C Library. */
set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
@@ -1490,9 +1489,7 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
i386_linux_get_syscall_number);
}
-void _initialize_i386_linux_tdep ();
-void
-_initialize_i386_linux_tdep ()
+INIT_GDB_FILE (i386_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_LINUX,
i386_linux_init_abi);
diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h
index de98256..3a0e056 100644
--- a/gdb/i386-linux-tdep.h
+++ b/gdb/i386-linux-tdep.h
@@ -47,6 +47,7 @@ extern uint64_t i386_linux_core_read_xsave_info (bfd *abfd,
/* Implement the core_read_x86_xsave_layout gdbarch method. */
extern bool i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
+ bfd &cbfd,
x86_xsave_layout &layout);
extern int i386_linux_gregset_reg_offset[];
diff --git a/gdb/i386-netbsd-nat.c b/gdb/i386-netbsd-nat.c
index 0f39fe1..efbf361 100644
--- a/gdb/i386-netbsd-nat.c
+++ b/gdb/i386-netbsd-nat.c
@@ -72,9 +72,7 @@ i386nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
static i386_bsd_nat_target<nbsd_nat_target> the_i386_nbsd_nat_target;
-void _initialize_i386nbsd_nat ();
-void
-_initialize_i386nbsd_nat ()
+INIT_GDB_FILE (i386nbsd_nat)
{
add_inf_child_target (&the_i386_nbsd_nat_target);
diff --git a/gdb/i386-netbsd-tdep.c b/gdb/i386-netbsd-tdep.c
index 701ce04..a1124d0 100644
--- a/gdb/i386-netbsd-tdep.c
+++ b/gdb/i386-netbsd-tdep.c
@@ -415,16 +415,13 @@ i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
i386_elf_init_abi (info, gdbarch);
/* NetBSD ELF uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
/* NetBSD ELF uses -fpcc-struct-return by default. */
tdep->struct_return = pcc_struct_return;
}
-void _initialize_i386nbsd_tdep ();
-void
-_initialize_i386nbsd_tdep ()
+INIT_GDB_FILE (i386nbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD,
i386nbsdelf_init_abi);
diff --git a/gdb/i386-obsd-nat.c b/gdb/i386-obsd-nat.c
index 323acdb..f478e73 100644
--- a/gdb/i386-obsd-nat.c
+++ b/gdb/i386-obsd-nat.c
@@ -89,9 +89,7 @@ i386obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
static i386_bsd_nat_target<obsd_nat_target> the_i386_obsd_nat_target;
-void _initialize_i386obsd_nat ();
-void
-_initialize_i386obsd_nat ()
+INIT_GDB_FILE (i386obsd_nat)
{
add_inf_child_target (&i386_obsd_nat_target);
diff --git a/gdb/i386-obsd-tdep.c b/gdb/i386-obsd-tdep.c
index be65668..1126597 100644
--- a/gdb/i386-obsd-tdep.c
+++ b/gdb/i386-obsd-tdep.c
@@ -441,13 +441,10 @@ i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
frame_unwind_prepend_unwinder (gdbarch, &i386obsd_trapframe_unwind);
/* OpenBSD ELF uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
}
-void _initialize_i386obsd_tdep ();
-void
-_initialize_i386obsd_tdep ()
+INIT_GDB_FILE (i386obsd_tdep)
{
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD,
i386obsd_init_abi);
diff --git a/gdb/i386-sol2-nat.c b/gdb/i386-sol2-nat.c
index d0fb836..1e87007 100644
--- a/gdb/i386-sol2-nat.c
+++ b/gdb/i386-sol2-nat.c
@@ -252,9 +252,7 @@ fill_fpregset (const struct regcache *regcache,
#endif
-void _initialize_amd64_sol2_nat ();
-void
-_initialize_amd64_sol2_nat ()
+INIT_GDB_FILE (amd64_sol2_nat)
{
#if PR_MODEL_NATIVE == PR_MODEL_LP64
amd64_native_gregset32_reg_offset = amd64_sol2_gregset32_reg_offset;
diff --git a/gdb/i386-sol2-tdep.c b/gdb/i386-sol2-tdep.c
index e842236..4ff08d2 100644
--- a/gdb/i386-sol2-tdep.c
+++ b/gdb/i386-sol2-tdep.c
@@ -86,8 +86,7 @@ i386_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->sc_num_regs = tdep->gregset_num_regs;
/* Solaris has SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
}
@@ -102,9 +101,7 @@ i386_sol2_osabi_sniffer (bfd *abfd)
return GDB_OSABI_UNKNOWN;
}
-void _initialize_i386_sol2_tdep ();
-void
-_initialize_i386_sol2_tdep ()
+INIT_GDB_FILE (i386_sol2_tdep)
{
/* Register an ELF OS ABI sniffer for Solaris 2 binaries. */
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 23788b4..d3ad402 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -60,10 +60,7 @@
#include "stap-probe.h"
#include "user-regs.h"
-#include "cli/cli-utils.h"
#include "expression.h"
-#include "parser-defs.h"
-#include <ctype.h>
#include <algorithm>
#include <unordered_set>
#include "producer.h"
@@ -899,6 +896,22 @@ i386_displaced_step_fixup (struct gdbarch *gdbarch,
displaced_debug_printf ("relocated return addr at %s to %s",
paddress (gdbarch, esp),
paddress (gdbarch, retaddr));
+
+ /* If shadow stack is enabled, we need to correct the return address
+ on the shadow stack too. */
+ bool shadow_stack_enabled;
+ std::optional<CORE_ADDR> ssp
+ = gdbarch_get_shadow_stack_pointer (gdbarch, regs,
+ shadow_stack_enabled);
+ if (shadow_stack_enabled)
+ {
+ gdb_assert (ssp.has_value ());
+ write_memory_unsigned_integer (*ssp, retaddr_len, byte_order,
+ retaddr);
+ displaced_debug_printf ("relocated shadow stack return addr at %s "
+ "to %s", paddress (gdbarch, *ssp),
+ paddress (gdbarch, retaddr));
+ }
}
}
@@ -3881,9 +3894,9 @@ int
i386_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
{
return (*s == '$' /* Literal number. */
- || (isdigit (*s) && s[1] == '(' && s[2] == '%') /* Displacement. */
+ || (c_isdigit (*s) && s[1] == '(' && s[2] == '%') /* Displacement. */
|| (*s == '(' && s[1] == '%') /* Register indirection. */
- || (*s == '%' && isalpha (s[1]))); /* Register access. */
+ || (*s == '%' && c_isalpha (s[1]))); /* Register access. */
}
/* Helper function for i386_stap_parse_special_token.
@@ -3900,7 +3913,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
{
const char *s = p->arg;
- if (isdigit (*s) || *s == '-' || *s == '+')
+ if (c_isdigit (*s) || *s == '-' || *s == '+')
{
bool got_minus[3];
int i;
@@ -3918,7 +3931,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
got_minus[0] = true;
}
- if (!isdigit ((unsigned char) *s))
+ if (!c_isdigit (*s))
return {};
displacements[0] = strtol (s, &endp, 10);
@@ -3939,7 +3952,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
got_minus[1] = true;
}
- if (!isdigit ((unsigned char) *s))
+ if (!c_isdigit (*s))
return {};
displacements[1] = strtol (s, &endp, 10);
@@ -3960,7 +3973,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
got_minus[2] = true;
}
- if (!isdigit ((unsigned char) *s))
+ if (!c_isdigit (*s))
return {};
displacements[2] = strtol (s, &endp, 10);
@@ -3972,7 +3985,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
s += 2;
start = s;
- while (isalnum (*s))
+ while (c_isalnum (*s))
++s;
if (*s++ != ')')
@@ -4033,7 +4046,7 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch,
{
const char *s = p->arg;
- if (isdigit (*s) || *s == '(' || *s == '-' || *s == '+')
+ if (c_isdigit (*s) || *s == '(' || *s == '-' || *s == '+')
{
bool offset_minus = false;
long offset = 0;
@@ -4051,10 +4064,10 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch,
offset_minus = true;
}
- if (offset_minus && !isdigit (*s))
+ if (offset_minus && !c_isdigit (*s))
return {};
- if (isdigit (*s))
+ if (c_isdigit (*s))
{
char *endp;
@@ -4068,7 +4081,7 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch,
s += 2;
start = s;
- while (isalnum (*s))
+ while (c_isalnum (*s))
++s;
if (*s != ',' || s[1] != '%')
@@ -4084,7 +4097,7 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch,
s += 2;
start = s;
- while (isalnum (*s))
+ while (c_isalnum (*s))
++s;
len_index = s - start;
@@ -4800,7 +4813,7 @@ static int i386_record_floats (struct gdbarch *gdbarch,
static int
i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
- int opcode, struct gdbarch *gdbarch)
+ struct gdbarch *gdbarch)
{
/* We need this to find YMM (and once AVX-512 is supported, ZMM) registers.
We should always save the largest available register, since an
@@ -4814,6 +4827,11 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
SCOPE_EXIT { inferior_thread ()->set_executing (true); };
inferior_thread () -> set_executing (false);
+ uint8_t opcode;
+ if (record_read_memory (gdbarch, ir->addr, &opcode, 1))
+ return -1;
+ ir->addr++;
+
switch (opcode)
{
case 0x10: /* VMOVS[S|D] XMM, mem. */
@@ -4854,12 +4872,6 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
i386_record_lea_modrm (ir);
}
break;
- case 0x14: /* VUNPCKL[PS|PD]. */
- case 0x15: /* VUNPCKH [PS|PD]. */
- i386_record_modrm (ir);
- record_full_arch_list_add_reg (ir->regcache,
- tdep->ymm0_regnum + ir->reg + vex_r * 8);
- break;
case 0x6e: /* VMOVD XMM, reg/mem */
/* This is moving from a regular register or memory region into an
XMM register. */
@@ -4915,6 +4927,16 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
return -1;
}
break;
+ case 0xd0: /* VADDSUBPD XMM1, XMM2, reg/mem */
+ /* VADDSUBPS XMM1, XMM2, reg/mem */
+ i386_record_modrm (ir);
+ /* The most significant bit of the register offset
+ is vex_r. */
+ record_full_arch_list_add_reg (ir->regcache,
+ tdep->ymm0_regnum
+ + ir->reg + vex_r * 8);
+ break;
+
case 0xd6: /* VMOVQ reg/mem XMM */
i386_record_modrm (ir);
/* This is the vmovq version that stores into a regular register
@@ -4979,6 +5001,27 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
}
break;
+ case 0x19: /* VBROADCASTSD and VEXTRACTF128. */
+ case 0x39: /* VEXTRACTI128. */
+ i386_record_modrm (ir);
+ /* vextract instructions use ModRM.R/M and VEX.B to address the
+ output register, while vbroadcast use ModRM.Reg and VEX.R.
+ They are differentiated through map_select. */
+ if (ir->map_select == 2)
+ record_full_arch_list_add_reg (ir->regcache,
+ tdep->ymm0_regnum + ir->reg
+ + 8 * vex_r);
+ else
+ record_full_arch_list_add_reg (ir->regcache,
+ tdep->ymm0_regnum + ir->rm
+ + 8 * ir->rex_b);
+ break;
+
+ case 0x18: /* VBROADCASTSS and VINSERTI128. */
+ case 0x20: /* VPINSRB. */
+ case 0x21: /* VINSERTPS. */
+ case 0x22: /* VINSR[D|Q]. */
+ case 0x38: /* VINSERTF128. */
case 0x60: /* VPUNPCKLBW */
case 0x61: /* VPUNPCKLWD */
case 0x62: /* VPUNPCKLDQ */
@@ -4987,6 +5030,7 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
case 0x69: /* VPUNPCKHWD */
case 0x6a: /* VPUNPCKHDQ */
case 0x6d: /* VPUNPCKHQDQ */
+ case 0xc4: /* VPINSRW. */
{
i386_record_modrm (ir);
int reg_offset = ir->reg + vex_r * 8;
@@ -4995,6 +5039,61 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
}
break;
+ case 0x14: /* VPEXTRB and VUNPCKL[PS|PD]. */
+ case 0x15: /* VPEXTRW (to memory) and VUNPCKH [PS|PD]. */
+ case 0x16: /* VPEXTR[D|Q], VPERMPS, VMOVLHPS and VMOVHP[S|D] to reg. */
+ {
+ i386_record_modrm (ir);
+ /* All vpextr instructions in this case use map_select == 3,
+ while vpermps has map_select == 2 and the other instructions
+ have map_select == 1. The opcode 0xc5 is for vpextr, but also
+ uses map_select == 1, but due to other inconsistencies with
+ the other vpextr instructions, it is in a separate case to
+ avoid making this even more of a mess. */
+ if (ir->map_select == 3)
+ {
+ if (ir->mod == 3)
+ {
+ /* ModRM.Mod being equal to 3 means this ModRM encodes
+ a register. */
+ record_full_arch_list_add_reg (ir->regcache,
+ ir->regmap[X86_RECORD_REAX_REGNUM
+ + ir->rm]);
+ }
+ else
+ {
+ /* Even though the test only generated ModRM.Mod == 0,
+ in theory all values != 3 are viable to encode a memory
+ address, so all of them are passed along. */
+ /* Size is mostly based on the opcode, except for
+ double/quadword difference. */
+ ir->ot = opcode - 0x14;
+ if (opcode == 0x16 && vex_w == 1)
+ ir->ot ++;
+ /* I'm not sure if this is the original use, but in here
+ rip_offset is used to indicate that the RIP pointer will
+ be 1 byte away from where the instruction expects it to
+ be, because the immediate will not have been read by the
+ time the address changed is calculated. */
+ ir->rip_offset = 1;
+ i386_record_lea_modrm (ir);
+ }
+ }
+ else
+ {
+ record_full_arch_list_add_reg (ir->regcache,
+ tdep->ymm0_regnum + ir->reg
+ + vex_r * 8);
+ }
+ break;
+ }
+ case 0xc5: /* VPEXTRW to register. */
+ i386_record_modrm (ir);
+ record_full_arch_list_add_reg (ir->regcache,
+ ir->regmap[X86_RECORD_REAX_REGNUM
+ + ir->reg]);
+ break;
+
case 0x74: /* VPCMPEQB */
case 0x75: /* VPCMPEQB */
case 0x76: /* VPCMPEQB */
@@ -5006,17 +5105,96 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
}
break;
- case 0x78: /* VPBROADCASTB */
- case 0x79: /* VPBROADCASTW */
+ case 0x71: /* VPS[LL|RA|RL]W with constant shift. */
+ case 0x72: /* VPS[LL|RA|RL]D with constant shift. */
+ case 0x73: /* VPS[LL|RL][Q|DQ] with constant shift. */
+ {
+ record_full_arch_list_add_reg (ir->regcache,
+ tdep->ymm0_regnum + ir->vvvv);
+ break;
+ }
+
+ case 0x2c: /* VCVTTSD2SI and VCVTTSS2SI. */
+ case 0x2d: /* VCVTSD2SI and VCVTSS2SI. */
+ i386_record_modrm (ir);
+ record_full_arch_list_add_reg (ir->regcache,
+ ir->regmap[X86_RECORD_REAX_REGNUM
+ + ir->reg]);
+ break;
+
+ case 0x17: /* VEXTRACTPS and VMOVHP[S|D] to memory. */
+ case 0x13: /* VMOVLPD to memory. */
+ i386_record_modrm (ir);
+ if (ir->map_select == 1) /* This is the VMOV family. */
+ {
+ ir->ot = 3;
+ i386_record_lea_modrm (ir);
+ }
+ else
+ record_full_arch_list_add_reg (ir->regcache,
+ ir->regmap[X86_RECORD_REAX_REGNUM
+ + ir->rm]);
+ break;
+
+ case 0x00: /* VSHUFB and VPERMQ. */
+ case 0x01: /* VPERMPD. */
+ case 0x02: /* VPBLENDD. */
+ case 0x04: /* VPERMILPS with immediate. */
+ case 0x05: /* VPERMILPD with immediate. */
+ case 0x06: /* VMPERM2F128. */
+ case 0x0c: /* VPERMILPS with register and VBLENDPS. */
+ case 0x0d: /* VPERMILPD with register and VBLENDPD. */
+ case 0x0e: /* VPBLENDW. */
+ case 0x12: /* VMOVDDUP, VMOVHLPS and VMOVLPD to register. */
+ case 0x1a: /* VBROADCASTF128. */
+ case 0x2a: /* VCVTSI2SS. */
+ case 0x2b: /* VPACKUSDW. */
+ case 0x36: /* VPERMD. */
+ case 0x40: /* VPMULLD */
+ case 0x46: /* VPERM2I128. */
+ case 0x4a: /* VBLENDVPS. */
+ case 0x4b: /* VBLENDVPD. */
+ case 0x4c: /* VPBLENDVB. */
+ case 0x57: /* VXORP[S|D] */
case 0x58: /* VPBROADCASTD and VADD[P|S][S|D] */
case 0x59: /* VPBROADCASTQ and VMUL[P|S][S|D] */
+ case 0x5a: /* VCVTPS2PD, VCVTSD2SS, VCVTSS2SD and VCVTPD2PS. */
+ case 0x5b: /* VCVTDQ2PS, VCVTTPS2PD and VCVTPS2DQ. */
case 0x5c: /* VSUB[P|S][S|D] */
case 0x5d: /* VMIN[P|S][S|D] */
case 0x5e: /* VDIV[P|S][S|D] */
case 0x5f: /* VMAX[P|S][S|D] */
+ case 0x63: /* VPACKSSWB. */
+ case 0X67: /* VPACKUSWB. */
+ case 0x6b: /* VPACKSSDW. */
+ case 0x70: /* VPSHUF[B|D|HW|LW]. */
+ case 0x78: /* VPBROADCASTB */
+ case 0x79: /* VPBROADCASTW */
+ case 0xc6: /* VSHUFP[S|D]. */
+ case 0xd1: /* VPSRLW, dynamic shift. */
+ case 0xd2: /* VPSRLD, dynamic shift. */
+ case 0xd3: /* VPSRLQ, dynamic shift. */
+ case 0xd4: /* VPADDQ */
+ case 0xd5: /* VPMULLW */
+ case 0xdb: /* VPAND */
+ case 0xdf: /* VPANDN */
+ case 0xe1: /* VPSRAW, dynamic shift. */
+ case 0xe2: /* VPSRAD, dynamic shift. */
+ case 0xe4: /* VPMULHUW */
+ case 0xe5: /* VPMULHW */
+ case 0xe6: /* VCVTDQ2PD, VCVTTPD2DQ and VCVTPD2DQ. */
+ case 0xf1: /* VPSLLW, dynamic shift. */
+ case 0xf2: /* VPSLLD, dynamic shift. */
+ case 0xf3: /* VPSLLQ, dynamic shift. */
+ case 0xf4: /* VPMULUDQ */
+ case 0xf6: /* VPSADBW. */
+ case 0xfc: /* VPADDB */
+ case 0xfd: /* VPADDW */
+ case 0xfe: /* VPADDD */
{
- /* vpbroadcast and arithmetic operations are differentiated
- by map_select, but it doesn't change the recording mechanics. */
+ /* This set of instructions all share the same exact way to encode
+ the destination register, so there's no reason to try and
+ differentiate them. */
i386_record_modrm (ir);
int reg_offset = ir->reg + vex_r * 8;
gdb_assert (tdep->num_ymm_regs > reg_offset);
@@ -5025,6 +5203,17 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
}
break;
+ case 0x2e: /* VUCOMIS[S|D]. */
+ case 0x2f: /* VCOMIS[S|D]. */
+ {
+ /* Despite what the manual implies, saying that the first register
+ will be written to, actual testing shows that the only register
+ changed is EFLAGS. */
+ record_full_arch_list_add_reg (ir->regcache,
+ ir->regmap[X86_RECORD_EFLAGS_REGNUM]);
+ break;
+ }
+
case 0x77:/* VZEROUPPER */
{
int num_regs = tdep->num_ymm_regs;
@@ -5117,8 +5306,11 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
"addr = %s\n",
paddress (gdbarch, ir.addr));
- /* prefixes */
- while (1)
+ /* Process the prefixes. This used to be an infinite loop, but since
+ a VEX prefix is always the last one before the opcode, according to
+ Intel's manual anyway, and some AVX opcodes may conflict with
+ prefixes, it's safe to leave the loop as soon as we see VEX. */
+ while (!vex_prefix)
{
if (record_read_memory (gdbarch, ir.addr, &opcode8, 1))
return -1;
@@ -5258,7 +5450,7 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
{
/* If we found the VEX prefix, i386 will either record or warn that
the instruction isn't supported, so we can return the VEX result. */
- return i386_record_vex (&ir, rex_w, rex_r, opcode, gdbarch);
+ return i386_record_vex (&ir, rex_w, rex_r, gdbarch);
}
reswitch:
switch (opcode)
@@ -8403,7 +8595,8 @@ i386_validate_tdesc_p (i386_gdbarch_tdep *tdep,
const struct tdesc_feature *feature_core;
const struct tdesc_feature *feature_sse, *feature_avx, *feature_avx512,
- *feature_pkeys, *feature_segments;
+ *feature_pkeys, *feature_segments,
+ *feature_pl3_ssp;
int i, num_regs, valid_p;
if (! tdesc_has_registers (tdesc))
@@ -8429,6 +8622,9 @@ i386_validate_tdesc_p (i386_gdbarch_tdep *tdep,
/* Try PKEYS */
feature_pkeys = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.pkeys");
+ /* Try Shadow Stack. */
+ feature_pl3_ssp = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.pl3_ssp");
+
valid_p = 1;
/* The XCR0 bits. */
@@ -8544,6 +8740,15 @@ i386_validate_tdesc_p (i386_gdbarch_tdep *tdep,
tdep->pkeys_register_names[i]);
}
+ if (feature_pl3_ssp != nullptr)
+ {
+ if (tdep->ssp_regnum < 0)
+ tdep->ssp_regnum = I386_PL3_SSP_REGNUM;
+
+ valid_p &= tdesc_numbered_register (feature_pl3_ssp, tdesc_data,
+ tdep->ssp_regnum, "pl3_ssp");
+ }
+
return valid_p;
}
@@ -8800,41 +9005,12 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->num_core_regs = I386_NUM_GREGS + I387_NUM_REGS;
tdep->register_names = i386_register_names;
- /* No upper YMM registers. */
- tdep->ymmh_register_names = NULL;
- tdep->ymm0h_regnum = -1;
-
- /* No upper ZMM registers. */
- tdep->zmmh_register_names = NULL;
- tdep->zmm0h_regnum = -1;
-
- /* No high XMM registers. */
- tdep->xmm_avx512_register_names = NULL;
- tdep->xmm16_regnum = -1;
-
- /* No upper YMM16-31 registers. */
- tdep->ymm16h_register_names = NULL;
- tdep->ymm16h_regnum = -1;
-
tdep->num_byte_regs = 8;
tdep->num_word_regs = 8;
tdep->num_dword_regs = 0;
tdep->num_mmx_regs = 8;
tdep->num_ymm_regs = 0;
- /* No AVX512 registers. */
- tdep->k0_regnum = -1;
- tdep->num_zmm_regs = 0;
- tdep->num_ymm_avx512_regs = 0;
- tdep->num_xmm_avx512_regs = 0;
-
- /* No PKEYS registers */
- tdep->pkru_regnum = -1;
- tdep->num_pkeys_regs = 0;
-
- /* No segment base registers. */
- tdep->fsbase_regnum = -1;
-
tdesc_arch_data_up tdesc_data = tdesc_data_alloc ();
set_gdbarch_relocate_instruction (gdbarch, i386_relocate_instruction);
@@ -8949,30 +9125,30 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
-/* Return the target description for a specified XSAVE feature mask. */
+/* See i386-tdep.h. */
const struct target_desc *
-i386_target_description (uint64_t xcr0, bool segments)
+i386_target_description (uint64_t xstate_bv, bool segments)
{
static target_desc *i386_tdescs \
- [2/*SSE*/][2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
+ [2/*SSE*/][2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*CET_U*/] \
+ [2/*segments*/] = {};
target_desc **tdesc;
- tdesc = &i386_tdescs[(xcr0 & X86_XSTATE_SSE) ? 1 : 0]
- [(xcr0 & X86_XSTATE_AVX) ? 1 : 0]
- [(xcr0 & X86_XSTATE_AVX512) ? 1 : 0]
- [(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]
+ tdesc = &i386_tdescs[(xstate_bv & X86_XSTATE_SSE) ? 1 : 0]
+ [(xstate_bv & X86_XSTATE_AVX) ? 1 : 0]
+ [(xstate_bv & X86_XSTATE_AVX512) ? 1 : 0]
+ [(xstate_bv & X86_XSTATE_PKRU) ? 1 : 0]
+ [(xstate_bv & X86_XSTATE_CET_U) ? 1 : 0]
[segments ? 1 : 0];
if (*tdesc == NULL)
- *tdesc = i386_create_target_description (xcr0, false, segments);
+ *tdesc = i386_create_target_description (xstate_bv, false, segments);
return *tdesc;
}
-void _initialize_i386_tdep ();
-void
-_initialize_i386_tdep ()
+INIT_GDB_FILE (i386_tdep)
{
gdbarch_register (bfd_arch_i386, i386_gdbarch_init);
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index e849b33..84f1bbd 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -69,56 +69,57 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base
size_t sizeof_fpregset = 0;
/* Register number for %st(0). The register numbers for the other
- registers follow from this one. Set this to -1 to indicate the
- absence of an FPU. */
- int st0_regnum = 0;
+ registers follow from this one. Set this to a value >= 0 if FPU is
+ present. */
+ int st0_regnum = -1;
/* Number of MMX registers. */
int num_mmx_regs = 0;
- /* Register number for %mm0. Set this to -1 to indicate the absence
- of MMX support. */
- int mm0_regnum = 0;
+ /* Register number for %mm0. Set this to a value >= 0 if MMX is
+ supported. */
+ int mm0_regnum = -1;
/* Number of pseudo YMM registers. */
int num_ymm_regs = 0;
- /* Register number for %ymm0. Set this to -1 to indicate the absence
- of pseudo YMM register support. */
- int ymm0_regnum = 0;
+ /* Register number for %ymm0. Set this to a value >= 0 if pseudo YMM
+ registers are supported. */
+ int ymm0_regnum = -1;
/* Number of AVX512 OpMask registers (K-registers) */
int num_k_regs = 0;
- /* Register number for %k0. Set this to -1 to indicate the absence
- of AVX512 OpMask register support. */
- int k0_regnum = 0;
+ /* Register number for %k0. Set this to a value >= 0 if AVX512 OpMask
+ is supported. */
+ int k0_regnum = -1;
/* Number of pseudo ZMM registers ($zmm0-$zmm31). */
int num_zmm_regs = 0;
- /* Register number for %zmm0. Set this to -1 to indicate the absence
- of pseudo ZMM register support. */
- int zmm0_regnum = 0;
+ /* Register number for %zmm0. Set this to a value >= 0 if pseudo ZMM
+ registers are supported. */
+ int zmm0_regnum = -1;
/* Number of byte registers. */
int num_byte_regs = 0;
- /* Register pseudo number for %al. */
- int al_regnum = 0;
+ /* Register pseudo number for %al. If supported, set this to a
+ value >= 0. */
+ int al_regnum = -1;
/* Number of pseudo word registers. */
int num_word_regs = 0;
- /* Register number for %ax. */
- int ax_regnum = 0;
+ /* Register number for %ax. If supported, set this to a value >= 0. */
+ int ax_regnum = -1;
/* Number of pseudo dword registers. */
int num_dword_regs = 0;
- /* Register number for %eax. Set this to -1 to indicate the absence
- of pseudo dword register support. */
- int eax_regnum = 0;
+ /* Register number for %eax. Set this to a value >= 0 if pseudo dword
+ registers are supported. */
+ int eax_regnum = -1;
/* Number of core registers. */
int num_core_regs = 0;
@@ -129,14 +130,16 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base
/* Number of SSE registers added in AVX512. */
int num_xmm_avx512_regs = 0;
- /* Register number of XMM16, the first XMM register added in AVX512. */
- int xmm16_regnum = 0;
+ /* Register number of XMM16, the first XMM register added in AVX512.
+ Set this to a value >= 0 if XMM registers are supported. */
+ int xmm16_regnum = -1;
/* Number of YMM registers added in AVX512. */
int num_ymm_avx512_regs = 0;
- /* Register number of YMM16, the first YMM register added in AVX512. */
- int ymm16_regnum = 0;
+ /* Register number of YMM16, the first YMM register added in AVX512.
+ Set this to a value >= 0 if YMM registers are supported. */
+ int ymm16_regnum = -1;
/* Bits of the extended control register 0 (the XFEATURE_ENABLED_MASK
register), excluding the x87 bit, which are supported by this GDB. */
@@ -152,23 +155,23 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base
/* Register names. */
const char * const *register_names = nullptr;
- /* Register number for %ymm0h. Set this to -1 to indicate the absence
- of upper YMM register support. */
- int ymm0h_regnum = 0;
+ /* Register number for %ymm0h. Set this to a value >= 0 if they are
+ supported. */
+ int ymm0h_regnum = -1;
/* Upper YMM register names. Only used for tdesc_numbered_register. */
const char * const *ymmh_register_names = nullptr;
- /* Register number for %ymm16h. Set this to -1 to indicate the absence
- of support for YMM16-31. */
- int ymm16h_regnum = 0;
+ /* Register number for %ymm16h. Set this to a value >= 0 if they are
+ supported. */
+ int ymm16h_regnum = -1;
/* YMM16-31 register names. Only used for tdesc_numbered_register. */
const char * const *ymm16h_register_names = nullptr;
- /* Register number for %zmm0h. Set this to -1 to indicate the absence
- of ZMM_HI256 register support. */
- int zmm0h_regnum = 0;
+ /* Register number for %zmm0h. Set this to a value >= 0 if ZMM_HI256
+ registers are supported. */
+ int zmm0h_regnum = -1;
/* OpMask register names. */
const char * const *k_register_names = nullptr;
@@ -185,15 +188,20 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base
/* Number of PKEYS registers. */
int num_pkeys_regs = 0;
- /* Register number for PKRU register. */
- int pkru_regnum = 0;
+ /* Register number for PKRU register. If supported, set this to a value
+ >= 0. */
+ int pkru_regnum = -1;
/* PKEYS register names. */
const char * const *pkeys_register_names = nullptr;
- /* Register number for %fsbase. Set this to -1 to indicate the
- absence of segment base registers. */
- int fsbase_regnum = 0;
+ /* Register number for the shadow stack pointer register. If supported,
+ set this to a value >= 0. */
+ int ssp_regnum = -1;
+
+ /* Register number for %fsbase. If supported, set this to a value
+ >= 0. */
+ int fsbase_regnum = -1;
/* Target description. */
const struct target_desc *tdesc = nullptr;
@@ -293,6 +301,7 @@ enum i386_regnum
I386_ZMM0H_REGNUM, /* %zmm0h */
I386_ZMM7H_REGNUM = I386_ZMM0H_REGNUM + 7,
I386_PKRU_REGNUM,
+ I386_PL3_SSP_REGNUM,
I386_FSBASE_REGNUM,
I386_GSBASE_REGNUM
};
@@ -450,8 +459,11 @@ extern int i386_svr4_reg_to_regnum (struct gdbarch *gdbarch, int reg);
extern int i386_process_record (struct gdbarch *gdbarch,
struct regcache *regcache, CORE_ADDR addr);
-extern const struct target_desc *i386_target_description (uint64_t xcr0,
- bool segments);
+
+/* Return the target description for the specified xsave features as
+ defined in XSTATE_BV and SEGMENTS. */
+extern const struct target_desc *i386_target_description
+ (uint64_t xstate_bv, bool segments);
/* Functions and variables exported from i386-bsd-tdep.c. */
diff --git a/gdb/i386-windows-nat.c b/gdb/i386-windows-nat.c
index 6c1369a..f878727 100644
--- a/gdb/i386-windows-nat.c
+++ b/gdb/i386-windows-nat.c
@@ -82,9 +82,7 @@ i386_windows_segment_register_p (int regnum)
return regnum >= I386_CS_REGNUM && regnum <= I386_GS_REGNUM;
}
-void _initialize_i386_windows_nat ();
-void
-_initialize_i386_windows_nat ()
+INIT_GDB_FILE (i386_windows_nat)
{
#ifndef __x86_64__
x86_set_debug_register_length (4);
diff --git a/gdb/i386-windows-tdep.c b/gdb/i386-windows-tdep.c
index 43ae5e4..892ecd4 100644
--- a/gdb/i386-windows-tdep.c
+++ b/gdb/i386-windows-tdep.c
@@ -229,9 +229,7 @@ i386_cygwin_core_osabi_sniffer (bfd *abfd)
return GDB_OSABI_UNKNOWN;
}
-void _initialize_i386_windows_tdep ();
-void
-_initialize_i386_windows_tdep ()
+INIT_GDB_FILE (i386_windows_tdep)
{
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
i386_windows_osabi_sniffer);
diff --git a/gdb/ia64-libunwind-tdep.c b/gdb/ia64-libunwind-tdep.c
index 3ba9cb6..6d3b265 100644
--- a/gdb/ia64-libunwind-tdep.c
+++ b/gdb/ia64-libunwind-tdep.c
@@ -574,9 +574,7 @@ libunwind_is_initialized (void)
return libunwind_initialized;
}
-void _initialize_libunwind_frame ();
-void
-_initialize_libunwind_frame ()
+INIT_GDB_FILE (libunwind_frame)
{
libunwind_initialized = libunwind_load ();
}
diff --git a/gdb/ia64-linux-nat.c b/gdb/ia64-linux-nat.c
index 964b175..e833f9d 100644
--- a/gdb/ia64-linux-nat.c
+++ b/gdb/ia64-linux-nat.c
@@ -914,9 +914,7 @@ ia64_linux_nat_target::low_status_is_event (int status)
|| WSTOPSIG (status) == SIGILL);
}
-void _initialize_ia64_linux_nat ();
-void
-_initialize_ia64_linux_nat ()
+INIT_GDB_FILE (ia64_linux_nat)
{
/* Register the target. */
linux_target = &the_ia64_linux_nat_target;
diff --git a/gdb/ia64-linux-tdep.c b/gdb/ia64-linux-tdep.c
index c45b2bb..8b4e1f9 100644
--- a/gdb/ia64-linux-tdep.c
+++ b/gdb/ia64-linux-tdep.c
@@ -26,9 +26,9 @@
#include "solib-svr4.h"
#include "symtab.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "regset.h"
-#include <ctype.h>
/* The sigtramp code is in a non-readable (executable-only) region
of memory called the ``gate page''. The addresses in question
@@ -127,9 +127,9 @@ ia64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
static int
ia64_linux_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
{
- return ((isdigit (*s) && s[1] == '[' && s[2] == 'r') /* Displacement. */
+ return ((c_isdigit (*s) && s[1] == '[' && s[2] == 'r') /* Displacement. */
|| *s == 'r' /* Register value. */
- || isdigit (*s)); /* Literal number. */
+ || c_isdigit (*s)); /* Literal number. */
}
/* Core file support. */
@@ -235,8 +235,7 @@ ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_lp64_svr4_solib_ops);
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
@@ -257,9 +256,7 @@ ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
ia64_linux_stap_is_single_operand);
}
-void _initialize_ia64_linux_tdep ();
-void
-_initialize_ia64_linux_tdep ()
+INIT_GDB_FILE (ia64_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_ia64, 0, GDB_OSABI_LINUX,
ia64_linux_init_abi);
diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
index 395b5f7..6cf2986 100644
--- a/gdb/ia64-tdep.c
+++ b/gdb/ia64-tdep.c
@@ -3432,12 +3432,12 @@ ia64_find_global_pointer_from_dynamic_section (struct gdbarch *gdbarch,
faddr_sect = find_pc_section (faddr);
if (faddr_sect != NULL)
{
- for (obj_section *osect : faddr_sect->objfile->sections ())
+ for (obj_section &osect : faddr_sect->objfile->sections ())
{
- if (strcmp (osect->the_bfd_section->name, ".dynamic") == 0)
+ if (strcmp (osect.the_bfd_section->name, ".dynamic") == 0)
{
- CORE_ADDR addr = osect->addr ();
- CORE_ADDR endaddr = osect->endaddr ();
+ CORE_ADDR addr = osect.addr ();
+ CORE_ADDR endaddr = osect.endaddr ();
while (addr < endaddr)
{
@@ -3513,12 +3513,12 @@ find_extant_func_descr (struct gdbarch *gdbarch, CORE_ADDR faddr)
if (faddr_sect != NULL)
{
- for (obj_section *osect : faddr_sect->objfile->sections ())
+ for (obj_section &osect : faddr_sect->objfile->sections ())
{
- if (strcmp (osect->the_bfd_section->name, ".opd") == 0)
+ if (strcmp (osect.the_bfd_section->name, ".opd") == 0)
{
- CORE_ADDR addr = osect->addr ();
- CORE_ADDR endaddr = osect->endaddr ();
+ CORE_ADDR addr = osect.addr ();
+ CORE_ADDR endaddr = osect.endaddr ();
while (addr < endaddr)
{
@@ -4014,9 +4014,7 @@ ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_ia64_tdep ();
-void
-_initialize_ia64_tdep ()
+INIT_GDB_FILE (ia64_tdep)
{
gdbarch_register (bfd_arch_ia64, ia64_gdbarch_init, NULL);
}
diff --git a/gdb/ia64-vms-tdep.c b/gdb/ia64-vms-tdep.c
index dcd5598..32fe5d4 100644
--- a/gdb/ia64-vms-tdep.c
+++ b/gdb/ia64-vms-tdep.c
@@ -153,9 +153,7 @@ ia64_openvms_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
#endif
}
-void _initialize_ia64_vms_tdep ();
-void
-_initialize_ia64_vms_tdep ()
+INIT_GDB_FILE (ia64_vms_tdep)
{
gdbarch_register_osabi (bfd_arch_ia64, 0, GDB_OSABI_OPENVMS,
ia64_openvms_init_abi);
diff --git a/gdb/inf-child.c b/gdb/inf-child.c
index 016f30a..57ad0b4 100644
--- a/gdb/inf-child.c
+++ b/gdb/inf-child.c
@@ -322,11 +322,11 @@ inf_child_target::fileio_fstat (int fd, struct stat *sb, fileio_error *target_er
return ret;
}
-/* Implementation of to_fileio_stat. */
+/* Implementation of to_fileio_lstat. */
int
-inf_child_target::fileio_stat (struct inferior *inf, const char *filename,
- struct stat *sb, fileio_error *target_errno)
+inf_child_target::fileio_lstat (struct inferior *inf, const char *filename,
+ struct stat *sb, fileio_error *target_errno)
{
int ret;
diff --git a/gdb/inf-child.h b/gdb/inf-child.h
index 79b5157..70de393 100644
--- a/gdb/inf-child.h
+++ b/gdb/inf-child.h
@@ -81,8 +81,8 @@ public:
int fileio_pread (int fd, gdb_byte *read_buf, int len,
ULONGEST offset, fileio_error *target_errno) override;
int fileio_fstat (int fd, struct stat *sb, fileio_error *target_errno) override;
- int fileio_stat (struct inferior *inf, const char *filename,
- struct stat *sb, fileio_error *target_errno) override;
+ int fileio_lstat (struct inferior *inf, const char *filename,
+ struct stat *sb, fileio_error *target_errno) override;
int fileio_close (int fd, fileio_error *target_errno) override;
int fileio_unlink (struct inferior *inf,
const char *filename,
diff --git a/gdb/infcall.c b/gdb/infcall.c
index 098072d..c4b4c8f 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -887,9 +887,9 @@ run_inferior_call (std::unique_ptr<call_thread_fsm> sm,
call async_enable_stdin. This changes the prompt state to
PROMPT_NEEDED.
- If the previous prompt state was PROMPT_NEEDED, then as
- async_enable_stdin has already been called, nothing additional
- needs to be done here. */
+ If the previous prompt state was PROMPT_NEEDED, then async_enable_stdin
+ may or may not have been called, so do the same changes as in
+ async_enable_stdin. */
if (current_ui->prompt_state == PROMPT_BLOCKED)
{
if (call_thread->thread_fsm ()->finished_p ())
@@ -897,6 +897,12 @@ run_inferior_call (std::unique_ptr<call_thread_fsm> sm,
else
async_enable_stdin ();
}
+ else if (current_ui->prompt_state == PROMPT_NEEDED)
+ {
+ /* Copied from async_enable_stdin. */
+ target_terminal::ours ();
+ current_ui->register_file_handler ();
+ }
/* If the infcall does NOT succeed, normal_stop will have already
finished the thread states. However, on success, normal_stop
@@ -1448,10 +1454,16 @@ call_function_by_hand_dummy (struct value *function,
/* Create the dummy stack frame. Pass in the call dummy address as,
presumably, the ABI code knows where, in the call dummy, the
return address should be pointed. */
- sp = gdbarch_push_dummy_call (gdbarch, function,
- get_thread_regcache (inferior_thread ()),
- bp_addr, args.size (), args.data (),
- sp, return_method, struct_addr);
+ regcache *regcache = get_thread_regcache (inferior_thread ());
+ sp = gdbarch_push_dummy_call (gdbarch, function, regcache, bp_addr,
+ args.size (), args.data (), sp,
+ return_method, struct_addr);
+
+ /* Push the return address of the inferior (bp_addr) to the shadow stack
+ and update the shadow stack pointer. As we don't execute a call
+ instruction to call the function we need to handle this manually. */
+ if (gdbarch_shadow_stack_push_p (gdbarch))
+ gdbarch_shadow_stack_push (gdbarch, bp_addr, regcache);
/* Set up a frame ID for the dummy frame so we can pass it to
set_momentary_breakpoint. We need to give the breakpoint a frame
@@ -1870,9 +1882,7 @@ When the function is done executing, GDB will silently stop."),
gdb_assert_not_reached ("... should not be here");
}
-void _initialize_infcall ();
-void
-_initialize_infcall ()
+INIT_GDB_FILE (infcall)
{
add_setshow_boolean_cmd ("may-call-functions", no_class,
&may_call_functions_p, _("\
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index e9b58ce..bf68a95 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -25,6 +25,7 @@
#include "inferior.h"
#include "infrun.h"
#include "gdbsupport/environ.h"
+#include "gdbsupport/common-inferior.h"
#include "value.h"
#include "cli/cli-cmds.h"
#include "cli/cli-style.h"
@@ -39,7 +40,6 @@
#include "reggroups.h"
#include "block.h"
#include "solib.h"
-#include <ctype.h>
#include "observable.h"
#include "target-descriptions.h"
#include "user-regs.h"
@@ -209,7 +209,7 @@ strip_bg_char (const char *args, int *bg_char_p)
if (p[-1] == '&')
{
p--;
- while (p > args && isspace (p[-1]))
+ while (p > args && c_isspace (p[-1]))
p--;
*bg_char_p = 1;
@@ -224,14 +224,11 @@ strip_bg_char (const char *args, int *bg_char_p)
return make_unique_xstrdup (args);
}
-/* Common actions to take after creating any sort of inferior, by any
- means (running, attaching, connecting, et cetera). The target
- should be stopped. */
+/* See inferior.h. */
void
-post_create_inferior (int from_tty)
+post_create_inferior (int from_tty, bool set_pspace_solib_ops)
{
-
/* Be sure we own the terminal in case write operations are performed. */
target_terminal::ours_for_output ();
@@ -261,6 +258,11 @@ post_create_inferior (int from_tty)
throw;
}
+ if (set_pspace_solib_ops)
+ current_program_space->set_solib_ops
+ (gdbarch_make_solib_ops (current_inferior ()->arch (),
+ current_program_space));
+
if (current_program_space->exec_bfd ())
{
const unsigned solib_add_generation
@@ -482,7 +484,7 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
/* Pass zero for FROM_TTY, because at this point the "run" command
has done its thing; now we are setting up the running program. */
- post_create_inferior (0);
+ post_create_inferior (0, true);
/* Queue a pending event so that the program stops immediately. */
if (run_how == RUN_STOP_AT_FIRST_INSN)
@@ -493,6 +495,11 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
thr->set_pending_waitstatus (ws);
}
+ /* Still call clear_proceed_status; in schedule multiple mode the proceed
+ can resume threads from other inferiors, which might need clearing
+ prior to a proceed call. */
+ clear_proceed_status (0);
+
/* Start the target running. Do not use -1 continuation as it would skip
breakpoint right at the entry point. */
proceed (regcache_read_pc (get_thread_regcache (inferior_thread ())),
@@ -988,7 +995,7 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
if (inline_skipped_frames (tp) > 0)
{
const symbol *sym = inline_skipped_symbol (tp);
- if (sym->aclass () == LOC_BLOCK)
+ if (sym->loc_class () == LOC_BLOCK)
{
const block *block = sym->value_block ();
if (block->end () < tp->control.step_range_end)
@@ -2306,12 +2313,12 @@ registers_info (const char *addr_exp, int fpregs)
resembling a register following it. */
if (addr_exp[0] == '$')
addr_exp++;
- if (isspace ((*addr_exp)) || (*addr_exp) == '\0')
+ if (c_isspace ((*addr_exp)) || (*addr_exp) == '\0')
error (_("Missing register name"));
/* Find the start/end of this register name/num/group. */
start = addr_exp;
- while ((*addr_exp) != '\0' && !isspace ((*addr_exp)))
+ while ((*addr_exp) != '\0' && !c_isspace ((*addr_exp)))
addr_exp++;
end = addr_exp;
@@ -2506,7 +2513,7 @@ setup_inferior (int from_tty)
/* Take any necessary post-attaching actions for this platform. */
target_post_attach (inferior_ptid.pid ());
- post_create_inferior (from_tty);
+ post_create_inferior (from_tty, true);
}
/* What to do after the first program stops after attaching. */
@@ -3080,9 +3087,7 @@ use \"set args\" without arguments.\n\
\n\
To start the inferior without using a shell, use \"set startup-with-shell off\"."
-void _initialize_infcmd ();
-void
-_initialize_infcmd ()
+INIT_GDB_FILE (infcmd)
{
static struct cmd_list_element *info_proc_cmdlist;
struct cmd_list_element *c = nullptr;
diff --git a/gdb/inferior.c b/gdb/inferior.c
index e8a28cd..eb895f2 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -19,6 +19,7 @@
#include "exec.h"
#include "inferior.h"
+#include "gdbsupport/common-inferior.h"
#include "target.h"
#include "command.h"
#include "completer.h"
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 54f5229..8455b79 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -54,10 +54,8 @@ struct thread_info;
#include "symfile-add-flags.h"
#include "gdbsupport/refcounted-object.h"
#include "gdbsupport/forward-scope-exit.h"
-#include "gdbsupport/gdb_unique_ptr.h"
#include "gdbsupport/intrusive_list.h"
-#include "gdbsupport/common-inferior.h"
#include "gdbthread.h"
#include "process-stratum-target.h"
@@ -213,7 +211,14 @@ extern ptid_t gdb_startup_inferior (pid_t pid, int num_traps);
extern void setup_inferior (int from_tty);
-extern void post_create_inferior (int from_tty);
+/* Common actions to take after creating any sort of inferior, by any
+ means (running, attaching, connecting, et cetera). The target
+ should be stopped.
+
+ If SET_PSPACE_SOLIB_OPS is true, initialize the program space's solib
+ provider using the current inferior's architecture. */
+
+extern void post_create_inferior (int from_tty, bool set_pspace_solib_ops);
extern void attach_command (const char *, int);
diff --git a/gdb/inflow.c b/gdb/inflow.c
index f5ae6cd..4f1c8ef 100644
--- a/gdb/inflow.c
+++ b/gdb/inflow.c
@@ -55,6 +55,20 @@ static void child_terminal_ours_1 (target_terminal_state);
static struct serial *stdin_serial;
+/* See terminal.h. */
+
+scoped_gdb_ttystate::scoped_gdb_ttystate ()
+{
+ m_ttystate = serial_get_tty_state (stdin_serial);
+}
+
+/* See terminal.h. */
+
+scoped_gdb_ttystate::~scoped_gdb_ttystate ()
+{
+ serial_set_tty_state (stdin_serial, m_ttystate);
+}
+
/* Terminal related info we need to keep track of. Each inferior
holds an instance of this structure --- we save it whenever the
corresponding inferior stops, and restore it to the terminal when
@@ -163,6 +177,15 @@ set_initial_gdb_ttystate (void)
}
}
+/* See terminal.h. */
+
+void
+restore_initial_gdb_ttystate ()
+{
+ if (initial_gdb_ttystate != nullptr)
+ serial_set_tty_state (stdin_serial, initial_gdb_ttystate);
+}
+
/* Does GDB have a terminal (on stdin)? */
static int
@@ -944,9 +967,7 @@ initialize_stdin_serial (void)
stdin_serial = serial_fdopen (0);
}
-void _initialize_inflow ();
-void
-_initialize_inflow ()
+INIT_GDB_FILE (inflow)
{
add_info ("terminal", info_terminal_command,
_("Print inferior's saved terminal status."));
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 0b87287..82e7284 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -22,7 +22,6 @@
#include "cli/cli-style.h"
#include "displaced-stepping.h"
#include "infrun.h"
-#include <ctype.h>
#include "exceptions.h"
#include "symtab.h"
#include "frame.h"
@@ -58,7 +57,6 @@
#include "target-descriptions.h"
#include "target-dcache.h"
#include "terminal.h"
-#include "solist.h"
#include "gdbsupport/event-loop.h"
#include "thread-fsm.h"
#include "gdbsupport/enum-flags.h"
@@ -68,7 +66,6 @@
#include "gdbsupport/scope-exit.h"
#include "gdbsupport/forward-scope-exit.h"
#include "gdbsupport/gdb_select.h"
-#include <unordered_map>
#include "async-event.h"
#include "gdbsupport/selftest.h"
#include "scoped-mock-context.h"
@@ -473,6 +470,7 @@ holding the child stopped. Try \"set %ps\" or \"%ps\".\n"),
inferior *parent_inf = current_inferior ();
inferior *child_inf = nullptr;
+ bool child_has_new_pspace = false;
gdb_assert (parent_inf->thread_waiting_for_vfork_done == nullptr);
@@ -537,6 +535,7 @@ holding the child stopped. Try \"set %ps\" or \"%ps\".\n"),
else
{
child_inf->pspace = new program_space (new_address_space ());
+ child_has_new_pspace = true;
child_inf->aspace = child_inf->pspace->aspace;
child_inf->removable = true;
clone_program_space (child_inf->pspace, parent_inf->pspace);
@@ -626,6 +625,7 @@ holding the child stopped. Try \"set %ps\" or \"%ps\".\n"),
else
{
child_inf->pspace = new program_space (new_address_space ());
+ child_has_new_pspace = true;
child_inf->aspace = child_inf->pspace->aspace;
child_inf->removable = true;
child_inf->symfile_flags = SYMFILE_NO_READ;
@@ -724,7 +724,8 @@ holding the child stopped. Try \"set %ps\" or \"%ps\".\n"),
maybe_restore.emplace ();
switch_to_thread (*child_inf->threads ().begin ());
- post_create_inferior (0);
+
+ post_create_inferior (0, child_has_new_pspace);
}
return false;
@@ -1322,6 +1323,7 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
we don't want those to be satisfied by the libraries of the
previous incarnation of this process. */
no_shared_libraries (current_program_space);
+ current_program_space->unset_solib_ops ();
inferior *execing_inferior = current_inferior ();
inferior *following_inferior;
@@ -1378,6 +1380,9 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
registers. */
target_find_description ();
+ following_inferior->pspace->set_solib_ops
+ (gdbarch_make_solib_ops (following_inferior->arch (),
+ following_inferior->pspace));
gdb::observers::inferior_execd.notify (execing_inferior, following_inferior);
breakpoint_re_set ();
@@ -2365,7 +2370,7 @@ maybe_software_singlestep (struct gdbarch *gdbarch)
bool hw_step = true;
if (execution_direction == EXEC_FORWARD
- && gdbarch_software_single_step_p (gdbarch))
+ && gdbarch_get_next_pcs_p (gdbarch))
hw_step = !insert_single_step_breakpoints (gdbarch);
return hw_step;
@@ -3819,7 +3824,7 @@ start_remote (int from_tty)
/* Now that the inferior has stopped, do any bookkeeping like
loading shared libraries. We want to do this before normal_stop,
so that the displayed frame is up to date. */
- post_create_inferior (from_tty);
+ post_create_inferior (from_tty, true);
normal_stop ();
}
@@ -4388,6 +4393,11 @@ wait_for_inferior (inferior *inf)
scoped_finish_thread_state finish_state
(inf->process_target (), minus_one_ptid);
+ /* The commit_resumed_state of INF should already be false at this point
+ as INF will be a newly started remote target. This might not be true
+ for other targets but this will be handled in stop_all_threads. */
+ gdb_assert (!inf->process_target ()->commit_resumed_state);
+
while (1)
{
execution_control_state ecs;
@@ -5694,6 +5704,8 @@ stop_all_threads (const char *reason, inferior *inf)
debug_prefixed_printf ("infrun", "stop_all_threads", "done");
};
+ scoped_disable_commit_resumed disable_commit_resumed ("stop all threads");
+
/* Request threads to stop, and then wait for the stops. Because
threads we already know about can spawn more threads while we're
trying to stop them, and we only learn about new threads when we
@@ -9520,6 +9532,7 @@ normal_stop ()
here, so do this before any filtered output. */
ptid_t finish_ptid = null_ptid;
+ process_stratum_target *finish_target = nullptr;
if (!non_stop)
finish_ptid = minus_one_ptid;
@@ -9532,17 +9545,30 @@ normal_stop ()
linux-fork.c automatically switches to another fork from
within target_mourn_inferior. */
if (inferior_ptid != null_ptid)
- finish_ptid = ptid_t (inferior_ptid.pid ());
+ {
+ finish_ptid = ptid_t (inferior_ptid.pid ());
+ finish_target = current_inferior ()->process_target ();
+ }
}
else if (last.kind () != TARGET_WAITKIND_NO_RESUMED
&& last.kind () != TARGET_WAITKIND_THREAD_EXITED)
- finish_ptid = inferior_ptid;
+ {
+ finish_ptid = inferior_ptid;
+ finish_target = current_inferior ()->process_target ();
+ }
std::optional<scoped_finish_thread_state> maybe_finish_thread_state;
if (finish_ptid != null_ptid)
{
- maybe_finish_thread_state.emplace
- (user_visible_resume_target (finish_ptid), finish_ptid);
+ /* It might be tempting to use user_visible_resume_target to compute
+ FINISH_TARGET from FINISH_PTID, however, that is the wrong choice
+ in this case.
+
+ When resuming, we only resume the current target unless
+ schedule-multiple is in effect. However, when handling a stop, if
+ FINISH_PTID is minus_one_ptid, then we really do want to look for
+ stop events from _any_ target. */
+ maybe_finish_thread_state.emplace (finish_target, finish_ptid);
}
/* As we're presenting a stop, and potentially removing breakpoints,
@@ -9837,7 +9863,7 @@ handle_command (const char *args, int from_tty)
for (char *arg : built_argv)
{
wordlen = strlen (arg);
- for (digits = 0; isdigit (arg[digits]); digits++)
+ for (digits = 0; c_isdigit (arg[digits]); digits++)
{;
}
allsigs = 0;
@@ -10532,9 +10558,7 @@ infrun_thread_ptid_changed ()
#endif /* GDB_SELF_TEST */
-void _initialize_infrun ();
-void
-_initialize_infrun ()
+INIT_GDB_FILE (infrun)
{
struct cmd_list_element *c;
diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c
index d724c28..2191282 100644
--- a/gdb/inline-frame.c
+++ b/gdb/inline-frame.c
@@ -615,9 +615,7 @@ maintenance_info_inline_frames (const char *arg, int from_tty)
-void _initialize_inline_frame ();
-void
-_initialize_inline_frame ()
+INIT_GDB_FILE (inline_frame)
{
add_cmd ("inline-frames", class_maintenance, maintenance_info_inline_frames,
_("\
diff --git a/gdb/interps.c b/gdb/interps.c
index 00796bc..b4de3c7 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -575,9 +575,7 @@ interps_notify_memory_changed (inferior *inf, CORE_ADDR addr, ssize_t len,
}
/* This just adds the "interpreter-exec" command. */
-void _initialize_interpreter ();
-void
-_initialize_interpreter ()
+INIT_GDB_FILE (interpreter)
{
struct cmd_list_element *c;
diff --git a/gdb/interps.h b/gdb/interps.h
index 8d35309..c74495b 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -23,6 +23,7 @@
#define GDB_INTERPS_H
#include "gdbsupport/intrusive_list.h"
+#include "gdbsupport/event-loop.h"
struct bpstat;
struct ui_out;
@@ -78,6 +79,13 @@ public:
virtual void pre_command_loop ()
{}
+ /* Service one event.
+ This gives the interpreter a chance to handle its own private
+ events that cannot be fed into the gdb event mechanism.
+ In all cases, this should call gdb_do_one_event at some point. */
+ virtual int do_one_event (int mstimeout = -1)
+ { return gdb_do_one_event (mstimeout); }
+
/* Returns true if this interpreter supports using the readline
library; false if it uses GDB's own simplified readline
emulation. */
diff --git a/gdb/iq2000-tdep.c b/gdb/iq2000-tdep.c
index 49ae744..58a4dfb 100644
--- a/gdb/iq2000-tdep.c
+++ b/gdb/iq2000-tdep.c
@@ -840,9 +840,7 @@ iq2000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
Initializer function for the iq2000 module.
Called by gdb at start-up. */
-void _initialize_iq2000_tdep ();
-void
-_initialize_iq2000_tdep ()
+INIT_GDB_FILE (iq2000_tdep)
{
gdbarch_register (bfd_arch_iq2000, iq2000_gdbarch_init);
}
diff --git a/gdb/jit.c b/gdb/jit.c
index 1944e8a..b105697 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -584,7 +584,7 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
/* The name. */
block_name->set_domain (FUNCTION_DOMAIN);
- block_name->set_aclass_index (LOC_BLOCK);
+ block_name->set_loc_class_index (LOC_BLOCK);
block_name->set_symtab (filetab);
block_name->set_type (lookup_function_type (block_type));
block_name->set_value_block (new_block);
@@ -1313,9 +1313,7 @@ show_jit_reader_directory (const char *args, int from_tty)
jit_reader_dir.c_str ()));
}
-void _initialize_jit ();
-void
-_initialize_jit ()
+INIT_GDB_FILE (jit)
{
jit_reader_dir = relocate_gdb_directory (JIT_READER_DIR,
JIT_READER_DIR_RELOCATABLE);
diff --git a/gdb/language.c b/gdb/language.c
index 18a7c9c..c070169 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -28,7 +28,6 @@
return data out of a "language-specific" struct pointer that is set
whenever the working language changes. That would be a lot faster. */
-#include <ctype.h>
#include "symtab.h"
#include "gdbtypes.h"
#include "value.h"
@@ -976,7 +975,7 @@ language_arch_info::type_and_symbol::alloc_type_symbol
symbol->set_section_index (0);
symbol->set_type (type);
symbol->set_domain (TYPE_DOMAIN);
- symbol->set_aclass_index (LOC_TYPEDEF);
+ symbol->set_loc_class_index (LOC_TYPEDEF);
return symbol;
}
@@ -1095,9 +1094,7 @@ language_lookup_primitive_type_as_symbol (const struct language_defn *la,
/* Initialize the language routines. */
-void _initialize_language ();
-void
-_initialize_language ()
+INIT_GDB_FILE (language)
{
static const char *const type_or_range_names[]
= { "on", "off", "warn", "auto", NULL };
diff --git a/gdb/linespec.c b/gdb/linespec.c
index d42420c..2ddc495 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -35,7 +35,6 @@
#include "interps.h"
#include "target.h"
#include "arch-utils.h"
-#include <ctype.h>
#include "cli/cli-utils.h"
#include "filenames.h"
#include "ada-lang.h"
@@ -230,7 +229,7 @@ collect_info::add_symbol (block_symbol *bsym)
{
/* In list mode, add all matching symbols, regardless of class.
This allows the user to type "list a_global_variable". */
- if (bsym->symbol->aclass () == LOC_BLOCK || this->state->list_mode)
+ if (bsym->symbol->loc_class () == LOC_BLOCK || this->state->list_mode)
this->result.symbols->push_back (*bsym);
/* Continue iterating. */
@@ -459,7 +458,7 @@ linespec_lexer_lex_number (linespec_parser *parser, linespec_token *tokenp)
++(parser->lexer.stream);
}
- while (isdigit (*parser->lexer.stream))
+ while (c_isdigit (*parser->lexer.stream))
{
++tokenp->data.string.length;
++(parser->lexer.stream);
@@ -468,7 +467,7 @@ linespec_lexer_lex_number (linespec_parser *parser, linespec_token *tokenp)
/* If the next character in the input buffer is not a space, comma,
quote, or colon, this input does not represent a number. */
if (*parser->lexer.stream != '\0'
- && !isspace (*parser->lexer.stream) && *parser->lexer.stream != ','
+ && !c_isspace (*parser->lexer.stream) && *parser->lexer.stream != ','
&& *parser->lexer.stream != ':'
&& !strchr (linespec_quote_characters, *parser->lexer.stream))
{
@@ -512,7 +511,7 @@ linespec_lexer_lex_keyword (const char *p)
if (i == FORCE_KEYWORD_INDEX && p[len] == '\0')
return linespec_keywords[i];
- if (!isspace (p[len]))
+ if (!c_isspace (p[len]))
continue;
if (i == FORCE_KEYWORD_INDEX)
@@ -524,7 +523,7 @@ linespec_lexer_lex_keyword (const char *p)
int nextlen = strlen (linespec_keywords[j]);
if (strncmp (p, linespec_keywords[j], nextlen) == 0
- && isspace (p[nextlen]))
+ && c_isspace (p[nextlen]))
return linespec_keywords[i];
}
}
@@ -538,7 +537,7 @@ linespec_lexer_lex_keyword (const char *p)
int nextlen = strlen (linespec_keywords[j]);
if (strncmp (p, linespec_keywords[j], nextlen) == 0
- && isspace (p[nextlen]))
+ && c_isspace (p[nextlen]))
return NULL;
}
}
@@ -763,7 +762,7 @@ linespec_lexer_lex_string (linespec_parser *parser)
while (1)
{
- if (isspace (*parser->lexer.stream))
+ if (c_isspace (*parser->lexer.stream))
{
p = skip_spaces (parser->lexer.stream);
/* When we get here we know we've found something followed by
@@ -841,14 +840,14 @@ linespec_lexer_lex_string (linespec_parser *parser)
{
const char *op = parser->lexer.stream;
- while (op > start && isspace (op[-1]))
+ while (op > start && c_isspace (op[-1]))
op--;
if (op - start >= CP_OPERATOR_LEN)
{
op -= CP_OPERATOR_LEN;
if (strncmp (op, CP_OPERATOR_STR, CP_OPERATOR_LEN) == 0
&& (op == start
- || !(isalnum (op[-1]) || op[-1] == '_')))
+ || !(c_isalnum (op[-1]) || op[-1] == '_')))
{
/* This is an operator name. Keep going. */
++(parser->lexer.stream);
@@ -1016,7 +1015,7 @@ linespec_lexer_consume_token (linespec_parser *parser)
if (*parser->lexer.stream != '\0')
{
parser->completion_quote_char = '\0';
- parser->completion_quote_end = NULL;;
+ parser->completion_quote_end = NULL;
}
}
@@ -1074,6 +1073,12 @@ add_sal_to_sals (struct linespec_state *self,
struct symtab_and_line *sal,
const char *symname, bool literal_canonical)
{
+ /* We don't want two SALs with the same PC from the
+ same program space. */
+ for (const auto &s : *sals)
+ if (sal->pc == s.pc && sal->pspace == s.pspace)
+ return;
+
sals->push_back (*sal);
if (self->canonical)
@@ -1134,12 +1139,7 @@ iterate_over_all_matching_symtabs
for (objfile *objfile : pspace->objfiles ())
{
- objfile->expand_symtabs_matching (NULL, &lookup_name, NULL, NULL,
- (SEARCH_GLOBAL_BLOCK
- | SEARCH_STATIC_BLOCK),
- domain);
-
- for (compunit_symtab *cu : objfile->compunits ())
+ auto expand_callback = [&] (compunit_symtab *cu)
{
struct symtab *symtab = cu->primary_filetab ();
@@ -1166,7 +1166,12 @@ iterate_over_all_matching_symtabs
});
}
}
- }
+
+ return true;
+ };
+
+ objfile->search (nullptr, &lookup_name, nullptr, expand_callback,
+ SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK, domain);
}
}
}
@@ -1636,7 +1641,7 @@ linespec_parse_line_offset (const char *string)
else
line_offset.sign = LINE_OFFSET_NONE;
- if (*string != '\0' && !isdigit (*string))
+ if (*string != '\0' && !c_isdigit (*string))
error (_("malformed line offset: \"%s\""), start);
/* Right now, we only allow base 10 for offsets. */
@@ -2123,7 +2128,7 @@ create_sals_line_offset (struct linespec_state *self,
line 16 will also result in a breakpoint in main, at line 17. */
if (!was_exact
&& sym != nullptr
- && sym->aclass () == LOC_BLOCK
+ && sym->loc_class () == LOC_BLOCK
&& sal.pc == sym->value_block ()->entry_pc ()
&& val.line < sym->line ())
continue;
@@ -2218,7 +2223,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec *ls)
if (state->funfirstline
&& !ls->minimal_symbols.empty ()
- && sym.symbol->aclass () == LOC_BLOCK)
+ && sym.symbol->loc_class () == LOC_BLOCK)
{
const CORE_ADDR addr
= sym.symbol->value_block ()->entry_pc ();
@@ -3355,7 +3360,7 @@ decode_compound_collector::operator () (block_symbol *bsym)
struct type *t;
struct symbol *sym = bsym->symbol;
- if (sym->aclass () != LOC_TYPEDEF)
+ if (sym->loc_class () != LOC_TYPEDEF)
return true; /* Continue iterating. */
t = sym->type ();
@@ -3407,30 +3412,52 @@ lookup_prefix_sym (struct linespec_state *state,
return collector.release_symbols ();
}
-/* A std::sort comparison function for symbols. The resulting order does
- not actually matter; we just need to be able to sort them so that
- symbols with the same program space end up next to each other. */
+/* Compare pspace A and B based on program space ID. Return 0 if equal,
+ 1 if A->num > B->num, -1 otherwise (modeled on strcmp). */
-static bool
-compare_symbols (const block_symbol &a, const block_symbol &b)
+static int
+compare_pspace (const struct program_space *a, const struct program_space *b)
{
- uintptr_t uia, uib;
+ if (a->num > b->num)
+ return 1;
- uia = (uintptr_t) a.symbol->symtab ()->compunit ()->objfile ()->pspace ();
- uib = (uintptr_t) b.symbol->symtab ()->compunit ()->objfile ()->pspace ();
+ if (a->num < b->num)
+ return -1;
- if (uia < uib)
- return true;
- if (uia > uib)
- return false;
+ return 0;
+}
+
+/* An std::sort comparison function for pointers. Don't use this if stable
+ sorting results are required. */
+
+static bool
+compare_pointers (void *a, void *b)
+{
+ return (uintptr_t)a < (uintptr_t)b;
+}
- uia = (uintptr_t) a.symbol;
- uib = (uintptr_t) b.symbol;
+/* An std::sort comparison function for symbols. The requirement is that
+ symbols with the same program space end up next to each other. This is for
+ the purpose of iterating over the symbols and doing something once for each
+ program space. */
- if (uia < uib)
+static bool
+compare_symbols (const block_symbol &a, const block_symbol &b)
+{
+ /* To check for same program space, we could just use a pointer comparison,
+ which gives unstable sorting results. While the assumption is that this
+ doesn't matter, play it safe and compare program space IDs instead. */
+ int cmp
+ = compare_pspace (a.symbol->symtab ()->compunit ()->objfile ()->pspace (),
+ b.symbol->symtab ()->compunit ()->objfile ()->pspace ());
+ if (cmp == -1)
return true;
+ if (cmp == 1)
+ return false;
- return false;
+ /* This gives unstable sorting results. We assume that this doesn't
+ matter. */
+ return compare_pointers (a.symbol, b.symbol);
}
/* Like compare_symbols but for minimal symbols. */
@@ -3438,23 +3465,16 @@ compare_symbols (const block_symbol &a, const block_symbol &b)
static bool
compare_msymbols (const bound_minimal_symbol &a, const bound_minimal_symbol &b)
{
- uintptr_t uia, uib;
-
- uia = (uintptr_t) a.objfile->pspace ();
- uib = (uintptr_t) a.objfile->pspace ();
-
- if (uia < uib)
+ /* See comment in compare_symbols for use of compare_pspace. */
+ int cmp = compare_pspace (a.objfile->pspace (), a.objfile->pspace ());
+ if (cmp == -1)
return true;
- if (uia > uib)
+ if (cmp == 1)
return false;
- uia = (uintptr_t) a.minsym;
- uib = (uintptr_t) b.minsym;
-
- if (uia < uib)
- return true;
-
- return false;
+ /* This gives unstable sorting results. We assume that this doesn't
+ matter. */
+ return compare_pointers (a.minsym, b.minsym);
}
/* Look for all the matching instances of each symbol in NAMES. Only
@@ -3747,7 +3767,7 @@ find_linespec_symbols (struct linespec_state *state,
if (canon != nullptr)
lookup_name = canon.get ();
- /* It's important to not call expand_symtabs_matching unnecessarily
+ /* It's important to not call search unnecessarily
as it can really slow things down (by unnecessarily expanding
potentially 1000s of symtabs, which when debugging some apps can
cost 100s of seconds). Avoid this to some extent by *first* calling
@@ -4092,7 +4112,12 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
sal.pspace = current_program_space;
}
- sal.section = msymbol->obj_section (objfile);
+ /* Don't use the section from the msymbol, the code above might have
+ adjusted FUNC_ADDR, in which case the msymbol's section might not be
+ the section containing FUNC_ADDR. It might not even be in the same
+ objfile. As the section is primarily to assist with overlay
+ debugging, it should reflect the SAL's pc value. */
+ sal.section = find_pc_overlay (sal.pc);
if (self->maybe_add_address (objfile->pspace (), sal.pc))
add_sal_to_sals (self, result, &sal, msymbol->natural_name (), false);
@@ -4295,14 +4320,14 @@ static bool
symbol_to_sal (struct symtab_and_line *result,
bool funfirstline, struct symbol *sym)
{
- if (sym->aclass () == LOC_BLOCK)
+ if (sym->loc_class () == LOC_BLOCK)
{
*result = find_function_start_sal (sym, funfirstline);
return true;
}
else
{
- if (sym->aclass () == LOC_LABEL && sym->value_address () != 0)
+ if (sym->loc_class () == LOC_LABEL && sym->value_address () != 0)
{
*result = {};
result->symtab = sym->symtab ();
diff --git a/gdb/linux-fork.c b/gdb/linux-fork.c
index 338ba03..0171259 100644
--- a/gdb/linux-fork.c
+++ b/gdb/linux-fork.c
@@ -37,7 +37,6 @@
#include "gdbsupport/eintr.h"
#include "target/waitstatus.h"
#include <dirent.h>
-#include <ctype.h>
#include <list>
@@ -421,7 +420,7 @@ fork_save_infrun_state (struct fork_info *fp)
/* Now find actual file positions. */
rewinddir (d);
while ((de = readdir (d)) != NULL)
- if (isdigit (de->d_name[0]))
+ if (c_isdigit (de->d_name[0]))
{
tmp = strtol (&de->d_name[0], NULL, 10);
fp->filepos[tmp] = call_lseek (tmp, 0, SEEK_CUR);
@@ -1115,9 +1114,7 @@ restart_command (const char *args, int from_tty)
linux_fork_context (fp, from_tty, inf);
}
-void _initialize_linux_fork ();
-void
-_initialize_linux_fork ()
+INIT_GDB_FILE (linux_fork)
{
/* Checkpoint command: create a fork of the inferior process
and set it aside for later debugging. */
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 2f98060..87fb800 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -42,7 +42,6 @@
#include "elf-bfd.h"
#include "gregset.h"
#include "gdbcore.h"
-#include <ctype.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "inf-loop.h"
@@ -51,17 +50,13 @@
#include <pwd.h>
#include <sys/types.h>
#include <dirent.h>
-#include "xml-support.h"
#include <sys/vfs.h>
-#include "solib.h"
#include "nat/linux-osdata.h"
#include "linux-tdep.h"
-#include "symfile.h"
#include "gdbsupport/agent.h"
#include "tracepoint.h"
#include "target-descriptions.h"
#include "gdbsupport/filestuff.h"
-#include "objfiles.h"
#include "nat/linux-namespaces.h"
#include "gdbsupport/block-signals.h"
#include "gdbsupport/fileio.h"
@@ -553,8 +548,8 @@ linux_nat_target::follow_fork (inferior *child_inf, ptid_t child_ptid,
/* Note that we consult the parent's architecture instead of
the child's because there's no inferior for the child at
this point. */
- if (!gdbarch_software_single_step_p (target_thread_architecture
- (parent_ptid)))
+ if (!gdbarch_get_next_pcs_p (target_thread_architecture
+ (parent_ptid)))
{
int status;
@@ -2129,7 +2124,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status)
open_proc_mem_file (lp->ptid);
ourstatus->set_execd
- (make_unique_xstrdup (linux_proc_pid_to_exec_file (pid)));
+ (make_unique_xstrdup (linux_target->pid_to_exec_file (pid)));
/* The thread that execed must have been resumed, but, when a
thread execs, it changes its tid to the tgid, and the old
@@ -4000,7 +3995,14 @@ linux_nat_target::thread_name (struct thread_info *thr)
const char *
linux_nat_target::pid_to_exec_file (int pid)
{
- return linux_proc_pid_to_exec_file (pid);
+ /* If there's no sysroot. Or the sysroot is just 'target:' and the
+ inferior is in the same mount namespce, then we can consider the
+ filesystem local. */
+ bool local_fs = (gdb_sysroot.empty ()
+ || (gdb_sysroot == TARGET_SYSROOT_PREFIX
+ && linux_ns_same (pid, LINUX_NS_MNT)));
+
+ return linux_proc_pid_to_exec_file (pid, local_fs);
}
/* Object representing an /proc/PID/mem open file. We keep one such
@@ -4585,6 +4587,20 @@ linux_nat_target::fileio_open (struct inferior *inf, const char *filename,
return fd;
}
+/* Implementation of to_fileio_lstat. */
+
+int
+linux_nat_target::fileio_lstat (struct inferior *inf, const char *filename,
+ struct stat *sb, fileio_error *target_errno)
+{
+ int r = linux_mntns_lstat (linux_nat_fileio_pid_of (inf), filename, sb);
+
+ if (r == -1)
+ *target_errno = host_to_fileio_error (errno);
+
+ return r;
+}
+
/* Implementation of to_fileio_readlink. */
std::optional<std::string>
@@ -4707,9 +4723,7 @@ maintenance_info_lwps (const char *arg, int from_tty)
}
}
-void _initialize_linux_nat ();
-void
-_initialize_linux_nat ()
+INIT_GDB_FILE (linux_nat)
{
add_setshow_boolean_cmd ("linux-nat", class_maintenance,
&debug_linux_nat, _("\
diff --git a/gdb/linux-nat.h b/gdb/linux-nat.h
index 6e53991..7cbe9a9 100644
--- a/gdb/linux-nat.h
+++ b/gdb/linux-nat.h
@@ -108,6 +108,9 @@ public:
const char *filename,
fileio_error *target_errno) override;
+ int fileio_lstat (struct inferior *inf, const char *filename,
+ struct stat *sb, fileio_error *target_errno) override;
+
int fileio_unlink (struct inferior *inf,
const char *filename,
fileio_error *target_errno) override;
@@ -276,12 +279,12 @@ struct lwp_info : intrusive_list_node<lwp_info>
will be recorded here, while 'status == 0' is ambiguous. */
struct target_waitstatus waitstatus;
- /* Signal whether we are in a SYSCALL_ENTRY or
- in a SYSCALL_RETURN event.
- Values:
- - TARGET_WAITKIND_SYSCALL_ENTRY
- - TARGET_WAITKIND_SYSCALL_RETURN */
- enum target_waitkind syscall_state;
+ /* Signal whether we are in a SYSCALL_ENTRY or SYSCALL_RETURN event.
+
+ Valid values are TARGET_WAITKIND_SYSCALL_ENTRY,
+ TARGET_WAITKIND_SYSCALL_RETURN, or TARGET_WAITKIND_SYSCALL_IGNORE, when
+ not stopped at a syscall. */
+ target_waitkind syscall_state = TARGET_WAITKIND_IGNORE;
/* The processor core this LWP was last seen on. */
int core = -1;
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index bbffb3d..4b679c8 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -46,7 +46,7 @@
#include "cli/cli-style.h"
#include "gdbsupport/unordered_map.h"
-#include <ctype.h>
+#include <algorithm>
/* This enum represents the values that the user can choose when
informing the Linux kernel about which memory mappings will be
@@ -96,6 +96,10 @@ struct smaps_vmflags
/* Memory map has memory tagging enabled. */
unsigned int memory_tagging : 1;
+
+ /* Memory map used for shadow stack. */
+
+ unsigned int shadow_stack_memory : 1;
};
/* Data structure that holds the information contained in the
@@ -483,7 +487,7 @@ read_mapping (const char *line)
p = skip_spaces (p);
const char *permissions_start = p;
- while (*p && !isspace (*p))
+ while (*p && !c_isspace (*p))
p++;
mapping.permissions = std::string (permissions_start,
(size_t) (p - permissions_start));
@@ -492,7 +496,7 @@ read_mapping (const char *line)
p = skip_spaces (p);
const char *device_start = p;
- while (*p && !isspace (*p))
+ while (*p && !c_isspace (*p))
p++;
mapping.device = {device_start, (size_t) (p - device_start)};
@@ -537,6 +541,8 @@ decode_vmflags (char *p, struct smaps_vmflags *v)
v->shared_mapping = 1;
else if (strcmp (s, "mt") == 0)
v->memory_tagging = 1;
+ else if (strcmp (s, "ss") == 0)
+ v->shadow_stack_memory = 1;
}
}
@@ -630,9 +636,9 @@ mapping_is_anonymous_p (const char *filename)
return 0;
}
-/* Return 0 if the memory mapping (which is related to FILTERFLAGS, V,
- MAYBE_PRIVATE_P, MAPPING_ANONYMOUS_P, ADDR and OFFSET) should not
- be dumped, or greater than 0 if it should.
+/* Return false if the memory mapping represented by MAP should not be
+ dumped, or true if it should. FILTERFLAGS guides which mappings
+ should be dumped.
In a nutshell, this is the logic that we follow in order to decide
if a mapping should be dumped or not.
@@ -677,11 +683,14 @@ mapping_is_anonymous_p (const char *filename)
header (of a DSO or an executable, for example). If it is, and
if the user is interested in dump it, then we should dump it. */
-static int
-dump_mapping_p (filter_flags filterflags, const struct smaps_vmflags *v,
- int maybe_private_p, int mapping_anon_p, int mapping_file_p,
- const char *filename, ULONGEST addr, ULONGEST offset)
+static bool
+dump_mapping_p (filter_flags filterflags, const smaps_data &map)
{
+ /* Older Linux kernels did not support the "Anonymous:" counter.
+ If it is missing, we can't be sure what to dump, so dump everything. */
+ if (!map.has_anonymous)
+ return true;
+
/* Initially, we trust in what we received from our caller. This
value may not be very precise (i.e., it was probably gathered
from the permission line in the /proc/PID/smaps list, which
@@ -689,41 +698,42 @@ dump_mapping_p (filter_flags filterflags, const struct smaps_vmflags *v,
what we have until we take a look at the "VmFlags:" field
(assuming that the version of the Linux kernel being used
supports it, of course). */
- int private_p = maybe_private_p;
- int dump_p;
+ int private_p = map.priv;
/* We always dump vDSO and vsyscall mappings, because it's likely that
there'll be no file to read the contents from at core load time.
The kernel does the same. */
- if (strcmp ("[vdso]", filename) == 0
- || strcmp ("[vsyscall]", filename) == 0)
- return 1;
+ if (map.filename == "[vdso]" || map.filename == "[vsyscall]")
+ return true;
- if (v->initialized_p)
+ if (map.vmflags.initialized_p)
{
/* We never dump I/O mappings. */
- if (v->io_page)
- return 0;
+ if (map.vmflags.io_page)
+ return false;
/* Check if we should exclude this mapping. */
- if (!dump_excluded_mappings && v->exclude_coredump)
- return 0;
+ if (!dump_excluded_mappings && map.vmflags.exclude_coredump)
+ return false;
/* Update our notion of whether this mapping is shared or
private based on a trustworthy value. */
- private_p = !v->shared_mapping;
+ private_p = !map.vmflags.shared_mapping;
/* HugeTLB checking. */
- if (v->uses_huge_tlb)
+ if (map.vmflags.uses_huge_tlb)
{
if ((private_p && (filterflags & COREFILTER_HUGETLB_PRIVATE))
|| (!private_p && (filterflags & COREFILTER_HUGETLB_SHARED)))
- return 1;
+ return true;
- return 0;
+ return false;
}
}
+ int mapping_anon_p = map.mapping_anon_p;
+ int mapping_file_p = map.mapping_file_p;
+ bool dump_p;
if (private_p)
{
if (mapping_anon_p && mapping_file_p)
@@ -763,7 +773,7 @@ dump_mapping_p (filter_flags filterflags, const struct smaps_vmflags *v,
A mapping contains an ELF header if it is a private mapping, its
offset is zero, and its first word is ELFMAG. */
- if (!dump_p && private_p && offset == 0
+ if (!dump_p && private_p && map.offset == 0
&& (filterflags & COREFILTER_ELF_HEADERS) != 0)
{
/* Useful define specifying the size of the ELF magical
@@ -774,7 +784,7 @@ dump_mapping_p (filter_flags filterflags, const struct smaps_vmflags *v,
/* Let's check if we have an ELF header. */
gdb_byte h[SELFMAG];
- if (target_read_memory (addr, h, SELFMAG) == 0)
+ if (target_read_memory (map.start_address, h, SELFMAG) == 0)
{
/* The EI_MAG* and ELFMAG* constants come from
<elf/common.h>. */
@@ -783,7 +793,7 @@ dump_mapping_p (filter_flags filterflags, const struct smaps_vmflags *v,
{
/* This mapping contains an ELF header, so we
should dump it. */
- dump_p = 1;
+ dump_p = true;
}
}
}
@@ -794,20 +804,24 @@ dump_mapping_p (filter_flags filterflags, const struct smaps_vmflags *v,
/* As above, but return true only when we should dump the NT_FILE
entry. */
-static int
-dump_note_entry_p (filter_flags filterflags, const struct smaps_vmflags *v,
- int maybe_private_p, int mapping_anon_p, int mapping_file_p,
- const char *filename, ULONGEST addr, ULONGEST offset)
+static bool
+dump_note_entry_p (filter_flags filterflags, const smaps_data &map)
{
- /* vDSO and vsyscall mappings will end up in the core file. Don't
- put them in the NT_FILE note. */
- if (strcmp ("[vdso]", filename) == 0
- || strcmp ("[vsyscall]", filename) == 0)
- return 0;
+ /* No NT_FILE entry for mappings with no filename. */
+ if (map.filename.length () == 0)
+ return false;
+
+ /* Special kernel mappings, those with names like '[vdso]' and
+ '[vsyscall]' will be placed in the core file, but shouldn't get an
+ NT_FILE entry. These special mappings all have a zero inode. */
+ if (map.inode == 0
+ && map.filename.front () == '['
+ && map.filename.back () == ']')
+ return false;
/* Otherwise, any other file-based mapping should be placed in the
note. */
- return 1;
+ return true;
}
/* Implement the "info proc" command. */
@@ -828,7 +842,7 @@ linux_info_proc (struct gdbarch *gdbarch, const char *args,
char filename[100];
fileio_error target_errno;
- if (args && isdigit (args[0]))
+ if (args && c_isdigit (args[0]))
{
char *tem;
@@ -1139,8 +1153,8 @@ linux_read_core_file_mappings
}
gdb::byte_vector contents (note_size);
- if (!bfd_get_section_contents (current_program_space->core_bfd (), section,
- contents.data (), 0, note_size))
+ if (!bfd_get_section_contents (cbfd, section, contents.data (), 0,
+ note_size))
{
warning (_("could not get core note contents"));
return;
@@ -1155,13 +1169,10 @@ linux_read_core_file_mappings
return;
}
- ULONGEST count = bfd_get (addr_size_bits, current_program_space->core_bfd (),
- descdata);
+ ULONGEST count = bfd_get (addr_size_bits, cbfd, descdata);
descdata += addr_size;
- ULONGEST page_size = bfd_get (addr_size_bits,
- current_program_space->core_bfd (),
- descdata);
+ ULONGEST page_size = bfd_get (addr_size_bits, cbfd, descdata);
descdata += addr_size;
if (note_size < 2 * addr_size + count * 3 * addr_size)
@@ -1208,12 +1219,11 @@ linux_read_core_file_mappings
for (int i = 0; i < count; i++)
{
- ULONGEST start = bfd_get (addr_size_bits, current_program_space->core_bfd (), descdata);
+ ULONGEST start = bfd_get (addr_size_bits, cbfd, descdata);
descdata += addr_size;
- ULONGEST end = bfd_get (addr_size_bits, current_program_space->core_bfd (), descdata);
+ ULONGEST end = bfd_get (addr_size_bits, cbfd, descdata);
descdata += addr_size;
- ULONGEST file_ofs
- = bfd_get (addr_size_bits, current_program_space->core_bfd (), descdata) * page_size;
+ ULONGEST file_ofs = bfd_get (addr_size_bits, cbfd, descdata) * page_size;
descdata += addr_size;
char * filename = filenames;
filenames += strlen ((char *) filenames) + 1;
@@ -1227,14 +1237,15 @@ linux_read_core_file_mappings
}
}
-/* Implement "info proc mappings" for a corefile. */
+/* Implement "info proc mappings" for corefile CBFD. */
static void
-linux_core_info_proc_mappings (struct gdbarch *gdbarch, const char *args)
+linux_core_info_proc_mappings (struct gdbarch *gdbarch, struct bfd *cbfd,
+ const char *args)
{
std::optional<ui_out_emit_table> emitter;
- linux_read_core_file_mappings (gdbarch, current_program_space->core_bfd (),
+ linux_read_core_file_mappings (gdbarch, cbfd,
[&] (ULONGEST count)
{
gdb_printf (_("Mapped address spaces:\n\n"));
@@ -1263,19 +1274,18 @@ linux_core_info_proc_mappings (struct gdbarch *gdbarch, const char *args)
});
}
-/* Implement "info proc" for a corefile. */
+/* Implement "info proc" for corefile CBFD. */
static void
-linux_core_info_proc (struct gdbarch *gdbarch, const char *args,
- enum info_proc_what what)
+linux_core_info_proc (struct gdbarch *gdbarch, struct bfd *cbfd,
+ const char *args, enum info_proc_what what)
{
int exe_f = (what == IP_MINIMAL || what == IP_EXE || what == IP_ALL);
int mappings_f = (what == IP_MAPPINGS || what == IP_ALL);
if (exe_f)
{
- const char *exe
- = bfd_core_file_failing_command (current_program_space->core_bfd ());
+ const char *exe = bfd_core_file_failing_command (cbfd);
if (exe != NULL)
gdb_printf ("exe = '%s'\n", exe);
@@ -1284,7 +1294,7 @@ linux_core_info_proc (struct gdbarch *gdbarch, const char *args,
}
if (mappings_f)
- linux_core_info_proc_mappings (gdbarch, args);
+ linux_core_info_proc_mappings (gdbarch, cbfd, args);
if (!exe_f && !mappings_f)
error (_("unable to handle request"));
@@ -1296,39 +1306,30 @@ linux_core_info_proc (struct gdbarch *gdbarch, const char *args,
interface. */
static LONGEST
-linux_core_xfer_siginfo (struct gdbarch *gdbarch, gdb_byte *readbuf,
- ULONGEST offset, ULONGEST len)
+linux_core_xfer_siginfo (struct gdbarch *gdbarch, struct bfd &cbfd,
+ gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
{
thread_section_name section_name (".note.linuxcore.siginfo", inferior_ptid);
- asection *section
- = bfd_get_section_by_name (current_program_space->core_bfd (),
- section_name.c_str ());
- if (section == NULL)
+ asection *section = bfd_get_section_by_name (&cbfd, section_name.c_str ());
+ if (section == nullptr)
return -1;
- if (!bfd_get_section_contents (current_program_space->core_bfd (), section,
- readbuf, offset, len))
+ if (!bfd_get_section_contents (&cbfd, section, readbuf, offset, len))
return -1;
return len;
}
typedef int linux_find_memory_region_ftype (ULONGEST vaddr, ULONGEST size,
- ULONGEST offset, ULONGEST inode,
+ ULONGEST offset,
int read, int write,
int exec, int modified,
bool memory_tagged,
- const char *filename,
+ const std::string &filename,
void *data);
-typedef int linux_dump_mapping_p_ftype (filter_flags filterflags,
- const struct smaps_vmflags *v,
- int maybe_private_p,
- int mapping_anon_p,
- int mapping_file_p,
- const char *filename,
- ULONGEST addr,
- ULONGEST offset);
+typedef bool linux_dump_mapping_p_ftype (filter_flags filterflags,
+ const smaps_data &map);
/* Helper function to parse the contents of /proc/<pid>/smaps into a data
structure, for easy access.
@@ -1590,35 +1591,15 @@ linux_find_memory_regions_full (struct gdbarch *gdbarch,
for (const struct smaps_data &map : smaps)
{
- int should_dump_p = 0;
-
- if (map.has_anonymous)
- {
- should_dump_p
- = should_dump_mapping_p (filterflags, &map.vmflags,
- map.priv,
- map.mapping_anon_p,
- map.mapping_file_p,
- map.filename.c_str (),
- map.start_address,
- map.offset);
- }
- else
- {
- /* Older Linux kernels did not support the "Anonymous:" counter.
- If it is missing, we can't be sure - dump all the pages. */
- should_dump_p = 1;
- }
-
/* Invoke the callback function to create the corefile segment. */
- if (should_dump_p)
+ if (should_dump_mapping_p (filterflags, map))
{
func (map.start_address, map.end_address - map.start_address,
- map.offset, map.inode, map.read, map.write, map.exec,
+ map.offset, map.read, map.write, map.exec,
1, /* MODIFIED is true because we want to dump
the mapping. */
map.vmflags.memory_tagging != 0,
- map.filename.c_str (), obfd);
+ map.filename, obfd);
}
}
@@ -1644,10 +1625,10 @@ struct linux_find_memory_regions_data
static int
linux_find_memory_regions_thunk (ULONGEST vaddr, ULONGEST size,
- ULONGEST offset, ULONGEST inode,
+ ULONGEST offset,
int read, int write, int exec, int modified,
bool memory_tagged,
- const char *filename, void *arg)
+ const std::string &filename, void *arg)
{
struct linux_find_memory_regions_data *data
= (struct linux_find_memory_regions_data *) arg;
@@ -1693,8 +1674,6 @@ struct linux_make_mappings_data
struct type *long_type;
};
-static linux_find_memory_region_ftype linux_make_mappings_callback;
-
/* A callback for linux_find_memory_regions_full that updates the
mappings data for linux_make_mappings_corefile_notes.
@@ -1703,17 +1682,16 @@ static linux_find_memory_region_ftype linux_make_mappings_callback;
static int
linux_make_mappings_callback (ULONGEST vaddr, ULONGEST size,
- ULONGEST offset, ULONGEST inode,
+ ULONGEST offset,
int read, int write, int exec, int modified,
bool memory_tagged,
- const char *filename, void *data)
+ const std::string &filename, void *data)
{
struct linux_make_mappings_data *map_data
= (struct linux_make_mappings_data *) data;
gdb_byte buf[sizeof (ULONGEST)];
- if (*filename == '\0' || inode == 0)
- return 0;
+ gdb_assert (filename.length () > 0);
++map_data->file_count;
@@ -1724,7 +1702,7 @@ linux_make_mappings_callback (ULONGEST vaddr, ULONGEST size,
pack_long (buf, map_data->long_type, offset);
obstack_grow (map_data->data_obstack, buf, map_data->long_type->length ());
- obstack_grow_str0 (map_data->filename_obstack, filename);
+ obstack_grow_str0 (map_data->filename_obstack, filename.c_str ());
return 0;
}
@@ -2248,7 +2226,7 @@ linux_fill_prpsinfo (struct elf_internal_linux_prpsinfo *p)
specifically under the entry of `/proc/[pid]/stat'. */
/* Getting rid of the PID, since we already have it. */
- while (isdigit (*proc_stat))
+ while (c_isdigit (*proc_stat))
++proc_stat;
proc_stat = skip_spaces (proc_stat);
@@ -2320,10 +2298,10 @@ linux_fill_prpsinfo (struct elf_internal_linux_prpsinfo *p)
{
/* Advancing the pointer to the beginning of the UID. */
tmpstr += sizeof ("Uid:");
- while (*tmpstr != '\0' && !isdigit (*tmpstr))
+ while (*tmpstr != '\0' && !c_isdigit (*tmpstr))
++tmpstr;
- if (isdigit (*tmpstr))
+ if (c_isdigit (*tmpstr))
p->pr_uid = strtol (tmpstr, &tmpstr, 10);
}
@@ -2333,10 +2311,10 @@ linux_fill_prpsinfo (struct elf_internal_linux_prpsinfo *p)
{
/* Advancing the pointer to the beginning of the GID. */
tmpstr += sizeof ("Gid:");
- while (*tmpstr != '\0' && !isdigit (*tmpstr))
+ while (*tmpstr != '\0' && !c_isdigit (*tmpstr))
++tmpstr;
- if (isdigit (*tmpstr))
+ if (c_isdigit (*tmpstr))
p->pr_gid = strtol (tmpstr, &tmpstr, 10);
}
@@ -3057,6 +3035,46 @@ show_dump_excluded_mappings (struct ui_file *file, int from_tty,
" flag is %s.\n"), value);
}
+/* See linux-tdep.h. */
+
+bool
+linux_address_in_shadow_stack_mem_range
+ (CORE_ADDR addr, std::pair<CORE_ADDR, CORE_ADDR> *range)
+{
+ if (!target_has_execution () || current_inferior ()->fake_pid_p)
+ return false;
+
+ const int pid = current_inferior ()->pid;
+
+ std::string smaps_file = string_printf ("/proc/%d/smaps", pid);
+
+ gdb::unique_xmalloc_ptr<char> data
+ = target_fileio_read_stralloc (nullptr, smaps_file.c_str ());
+
+ if (data == nullptr)
+ return false;
+
+ const std::vector<smaps_data> smaps
+ = parse_smaps_data (data.get (), std::move (smaps_file));
+
+ auto find_addr_mem_range = [&addr] (const smaps_data &map)
+ {
+ bool addr_in_mem_range
+ = (addr >= map.start_address && addr < map.end_address);
+ return (addr_in_mem_range && map.vmflags.shadow_stack_memory);
+ };
+ auto it = std::find_if (smaps.begin (), smaps.end (), find_addr_mem_range);
+
+ if (it != smaps.end ())
+ {
+ range->first = it->start_address;
+ range->second = it->end_address;
+ return true;
+ }
+
+ return false;
+}
+
/* To be called from the various GDB_OSABI_LINUX handlers for the
various GNU/Linux architectures and machine types.
@@ -3102,9 +3120,7 @@ linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch,
linux_corefile_parse_exec_context);
}
-void _initialize_linux_tdep ();
-void
-_initialize_linux_tdep ()
+INIT_GDB_FILE (linux_tdep)
{
/* Observers used to invalidate the cache when needed. */
gdb::observers::inferior_exit.attach (invalidate_linux_cache_inf,
@@ -3139,64 +3155,3 @@ more information about this file, refer to the manpage of proc(5) and core(5).")
&setlist, &showlist);
}
-
-/* Fetch (and possibly build) an appropriate `link_map_offsets' for
- ILP32/LP64 Linux systems which don't have the r_ldsomap field. */
-
-link_map_offsets *
-linux_ilp32_fetch_link_map_offsets ()
-{
- static link_map_offsets lmo;
- static link_map_offsets *lmp = nullptr;
-
- if (lmp == nullptr)
- {
- lmp = &lmo;
-
- lmo.r_version_offset = 0;
- lmo.r_version_size = 4;
- lmo.r_map_offset = 4;
- lmo.r_brk_offset = 8;
- lmo.r_ldsomap_offset = -1;
- lmo.r_next_offset = 20;
-
- /* Everything we need is in the first 20 bytes. */
- lmo.link_map_size = 20;
- lmo.l_addr_offset = 0;
- lmo.l_name_offset = 4;
- lmo.l_ld_offset = 8;
- lmo.l_next_offset = 12;
- lmo.l_prev_offset = 16;
- }
-
- return lmp;
-}
-
-link_map_offsets *
-linux_lp64_fetch_link_map_offsets ()
-{
- static link_map_offsets lmo;
- static link_map_offsets *lmp = nullptr;
-
- if (lmp == nullptr)
- {
- lmp = &lmo;
-
- lmo.r_version_offset = 0;
- lmo.r_version_size = 4;
- lmo.r_map_offset = 8;
- lmo.r_brk_offset = 16;
- lmo.r_ldsomap_offset = -1;
- lmo.r_next_offset = 40;
-
- /* Everything we need is in the first 40 bytes. */
- lmo.link_map_size = 40;
- lmo.l_addr_offset = 0;
- lmo.l_name_offset = 8;
- lmo.l_ld_offset = 16;
- lmo.l_next_offset = 24;
- lmo.l_prev_offset = 32;
- }
-
- return lmp;
-}
diff --git a/gdb/linux-tdep.h b/gdb/linux-tdep.h
index 7485fc1..a4f0f53 100644
--- a/gdb/linux-tdep.h
+++ b/gdb/linux-tdep.h
@@ -22,10 +22,22 @@
#include "bfd.h"
#include "displaced-stepping.h"
+#include "solib.h"
struct inferior;
struct regcache;
+#ifndef SEGV_CPERR
+#define SEGV_CPERR 10 /* Control protection error. */
+#endif
+
+/* Flag which enables shadow stack in PR_SET_SHADOW_STACK_STATUS prctl. */
+#ifndef PR_SHADOW_STACK_ENABLE
+#define PR_SHADOW_STACK_ENABLE (1UL << 0)
+#define PR_SHADOW_STACK_WRITE (1UL << 1)
+#define PR_SHADOW_STACK_PUSH (1UL << 2)
+#endif
+
/* Enum used to define the extra fields of the siginfo type used by an
architecture. */
enum linux_siginfo_extra_field_values
@@ -112,9 +124,11 @@ extern CORE_ADDR linux_get_hwcap2 (const std::optional<gdb::byte_vector> &auxv,
extern CORE_ADDR linux_get_hwcap2 ();
-/* Fetch (and possibly build) an appropriate `struct link_map_offsets'
- for ILP32 and LP64 Linux systems. */
-extern struct link_map_offsets *linux_ilp32_fetch_link_map_offsets ();
-extern struct link_map_offsets *linux_lp64_fetch_link_map_offsets ();
+/* Returns true if ADDR belongs to a shadow stack memory range. If this
+ is the case, assign the shadow stack memory range to RANGE
+ [start_address, end_address). */
+
+extern bool linux_address_in_shadow_stack_mem_range
+ (CORE_ADDR addr, std::pair<CORE_ADDR, CORE_ADDR> *range);
#endif /* GDB_LINUX_TDEP_H */
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index f60116a..82bfe08 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -43,7 +43,6 @@
#include "auto-load.h"
#include "cli/cli-utils.h"
#include <signal.h>
-#include <ctype.h>
#include "nat/linux-namespaces.h"
#include <algorithm>
#include "gdbsupport/pathstuff.h"
@@ -1981,9 +1980,7 @@ maintenance_check_libthread_db (const char *args, int from_tty)
check_thread_db (info, true);
}
-void _initialize_thread_db ();
-void
-_initialize_thread_db ()
+INIT_GDB_FILE (thread_db)
{
/* Defer loading of libthread_db.so until inferior is running.
This allows gdb to load correct libthread_db for a given
diff --git a/gdb/lm32-tdep.c b/gdb/lm32-tdep.c
index ef956b8..cee2e51 100644
--- a/gdb/lm32-tdep.c
+++ b/gdb/lm32-tdep.c
@@ -536,9 +536,7 @@ lm32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_lm32_tdep ();
-void
-_initialize_lm32_tdep ()
+INIT_GDB_FILE (lm32_tdep)
{
gdbarch_register (bfd_arch_lm32, lm32_gdbarch_init);
}
diff --git a/gdb/location.c b/gdb/location.c
index 378fafc..197c47b 100644
--- a/gdb/location.c
+++ b/gdb/location.c
@@ -26,7 +26,6 @@
#include "probe.h"
#include "cp-support.h"
-#include <ctype.h>
#include <string.h>
static std::string
@@ -408,15 +407,15 @@ explicit_location_spec_lex_one (const char **inp,
whitespace or comma. */
if (*start == '-' || *start == '+')
{
- while (*inp[0] != '\0' && *inp[0] != ',' && !isspace (*inp[0]))
+ while (*inp[0] != '\0' && *inp[0] != ',' && !c_isspace (*inp[0]))
++(*inp);
}
else
{
/* Handle numbers first, stopping at the next whitespace or ','. */
- while (isdigit (*inp[0]))
+ while (c_isdigit (*inp[0]))
++(*inp);
- if (*inp[0] == '\0' || isspace (*inp[0]) || *inp[0] == ',')
+ if (*inp[0] == '\0' || c_isspace (*inp[0]) || *inp[0] == ',')
return gdb::unique_xmalloc_ptr<char> (savestring (start,
*inp - start));
@@ -425,7 +424,7 @@ explicit_location_spec_lex_one (const char **inp,
*inp = start;
while ((*inp)[0]
&& (*inp)[0] != ','
- && !(isspace ((*inp)[0])
+ && !(c_isspace ((*inp)[0])
|| linespec_lexer_lex_keyword (&(*inp)[1])))
{
/* Special case: C++ operator,. */
@@ -454,14 +453,14 @@ is_cp_operator (const char *start, const char *comma)
{
const char *p = comma;
- while (p > start && isspace (p[-1]))
+ while (p > start && c_isspace (p[-1]))
p--;
if (p - start >= CP_OPERATOR_LEN)
{
p -= CP_OPERATOR_LEN;
if (strncmp (p, CP_OPERATOR_STR, CP_OPERATOR_LEN) == 0
&& (p == start
- || !(isalnum (p[-1]) || p[-1] == '_')))
+ || !(c_isalnum (p[-1]) || p[-1] == '_')))
{
return true;
}
@@ -624,7 +623,7 @@ string_to_explicit_location_spec (const char **argp,
if (argp == NULL
|| *argp == NULL
|| *argp[0] != '-'
- || !isalpha ((*argp)[1])
+ || !c_isalpha ((*argp)[1])
|| ((*argp)[0] == '-' && (*argp)[1] == 'p'))
return NULL;
@@ -728,7 +727,7 @@ string_to_explicit_location_spec (const char **argp,
}
/* Only emit an "invalid argument" error for options
that look like option strings. */
- else if (opt.get ()[0] == '-' && !isdigit (opt.get ()[1]))
+ else if (opt.get ()[0] == '-' && !c_isdigit (opt.get ()[1]))
{
if (completion_info == NULL)
error (_("invalid explicit location argument, \"%s\""), opt.get ());
diff --git a/gdb/loongarch-linux-nat.c b/gdb/loongarch-linux-nat.c
index 3efaa5f..1360acf 100644
--- a/gdb/loongarch-linux-nat.c
+++ b/gdb/loongarch-linux-nat.c
@@ -72,8 +72,6 @@ public:
struct expression *cond) override;
int remove_watchpoint (CORE_ADDR addr, int len, enum target_hw_bp_type type,
struct expression *cond) override;
- bool watchpoint_addr_within_range (CORE_ADDR addr, CORE_ADDR start,
- int length) override;
/* Add our hardware breakpoint and watchpoint implementation. */
bool stopped_by_watchpoint () override;
@@ -581,15 +579,6 @@ loongarch_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len,
}
-bool
-loongarch_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr,
- CORE_ADDR start,
- int length)
-{
- return start <= addr && start + length - 1 >= addr;
-}
-
-
/* Implement the "stopped_data_address" target_ops method. */
bool
@@ -751,9 +740,7 @@ loongarch_linux_nat_target::low_forget_process (pid_t pid)
/* Initialize LoongArch Linux native support. */
-void _initialize_loongarch_linux_nat ();
-void
-_initialize_loongarch_linux_nat ()
+INIT_GDB_FILE (loongarch_linux_nat)
{
linux_target = &the_loongarch_linux_nat_target;
add_inf_child_target (&the_loongarch_linux_nat_target);
diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c
index 38485e0..3766338 100644
--- a/gdb/loongarch-linux-tdep.c
+++ b/gdb/loongarch-linux-tdep.c
@@ -25,6 +25,7 @@
#include "inferior.h"
#include "linux-record.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "loongarch-tdep.h"
#include "record-full.h"
#include "regset.h"
@@ -1145,10 +1146,9 @@ loongarch_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
linux_init_abi (info, gdbarch, 0);
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- info.bfd_arch_info->bits_per_address == 32
- ? linux_ilp32_fetch_link_map_offsets
- : linux_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, (info.bfd_arch_info->bits_per_address == 32
+ ? make_linux_ilp32_svr4_solib_ops
+ : make_linux_lp64_svr4_solib_ops));
/* GNU/Linux uses SVR4-style shared libraries. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
@@ -1183,9 +1183,7 @@ loongarch_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Initialize LoongArch Linux target support. */
-void _initialize_loongarch_linux_tdep ();
-void
-_initialize_loongarch_linux_tdep ()
+INIT_GDB_FILE (loongarch_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_loongarch, bfd_mach_loongarch32,
GDB_OSABI_LINUX, loongarch_linux_init_abi);
diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c
index 092127dd..f88fb5f 100644
--- a/gdb/loongarch-tdep.c
+++ b/gdb/loongarch-tdep.c
@@ -26,6 +26,7 @@
#include "gdbcore.h"
#include "linux-record.h"
#include "loongarch-tdep.h"
+#include "prologue-value.h"
#include "record.h"
#include "record-full.h"
#include "reggroups.h"
@@ -34,6 +35,33 @@
#include "trad-frame.h"
#include "user-regs.h"
+/* LoongArch frame cache structure. */
+struct loongarch_frame_cache
+{
+ /* The program counter at the start of the function. It is used to
+ identify this frame as a prologue frame. */
+ CORE_ADDR func;
+
+ /* The stack pointer at the time this frame was created; i.e. the
+ caller's stack pointer when this function was called. It is used
+ to identify this frame. */
+ CORE_ADDR prev_sp;
+
+ CORE_ADDR pc;
+
+ int available_p;
+
+ /* This register stores the frame base of the frame. */
+ int framebase_reg;
+
+ /* The framebase_offset is the distance from frame base to the prev_sp,
+ so the value of framebase_reg is just prev_sp - framebase_offset. */
+ int framebase_offset;
+
+ /* Saved register offsets. */
+ trad_frame_saved_reg *saved_regs;
+};
+
/* Fetch the instruction at PC. */
static insn_t
@@ -74,7 +102,9 @@ loongarch_insn_is_cond_branch (insn_t insn)
|| (insn & 0xfc000000) == 0x68000000 /* bltu */
|| (insn & 0xfc000000) == 0x6c000000 /* bgeu */
|| (insn & 0xfc000000) == 0x40000000 /* beqz */
- || (insn & 0xfc000000) == 0x44000000) /* bnez */
+ || (insn & 0xfc000000) == 0x44000000 /* bnez */
+ || (insn & 0xfc000300) == 0x48000000 /* bceqz */
+ || (insn & 0xfc000300) == 0x48000100) /* bcnez */
return true;
return false;
}
@@ -96,7 +126,9 @@ static bool
loongarch_insn_is_ll (insn_t insn)
{
if ((insn & 0xff000000) == 0x20000000 /* ll.w */
- || (insn & 0xff000000) == 0x22000000) /* ll.d */
+ || (insn & 0xff000000) == 0x22000000 /* ll.d */
+ || (insn & 0xfffffc00) == 0x38578000 /* llacq.w */
+ || (insn & 0xfffffc00) == 0x38578800) /* llacq.d */
return true;
return false;
}
@@ -107,7 +139,10 @@ static bool
loongarch_insn_is_sc (insn_t insn)
{
if ((insn & 0xff000000) == 0x21000000 /* sc.w */
- || (insn & 0xff000000) == 0x23000000) /* sc.d */
+ || (insn & 0xff000000) == 0x23000000 /* sc.d */
+ || (insn & 0xffff8000) == 0x38570000 /* sc.q */
+ || (insn & 0xfffffc00) == 0x38578400 /* screl.w */
+ || (insn & 0xfffffc00) == 0x38578c00) /* screl.d */
return true;
return false;
}
@@ -118,13 +153,23 @@ loongarch_insn_is_sc (insn_t insn)
static CORE_ADDR
loongarch_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc,
CORE_ADDR limit_pc, const frame_info_ptr &this_frame,
- struct trad_frame_cache *this_cache)
+ struct loongarch_frame_cache *this_cache)
{
CORE_ADDR cur_pc = start_pc, prologue_end = 0;
int32_t sp = LOONGARCH_SP_REGNUM;
int32_t fp = LOONGARCH_FP_REGNUM;
+ int32_t ra = LOONGARCH_RA_REGNUM;
int32_t reg_value[32] = {0};
int32_t reg_used[32] = {1, 0};
+ int i;
+
+ /* Track 32 GPR, ORIG_A0, PC, BADV in prologue. */
+ pv_t regs[LOONGARCH_USED_NUM_GREGSET];
+
+ for (i = 0; i < LOONGARCH_USED_NUM_GREGSET; i++)
+ regs[i] = pv_register (i, 0);
+
+ pv_area stack (LOONGARCH_SP_REGNUM, gdbarch_addr_bit (gdbarch));
while (cur_pc < limit_pc)
{
@@ -134,27 +179,40 @@ loongarch_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc,
int32_t rj = loongarch_decode_imm ("5:5", insn, 0);
int32_t rk = loongarch_decode_imm ("10:5", insn, 0);
int32_t si12 = loongarch_decode_imm ("10:12", insn, 1);
+ int32_t si14 = loongarch_decode_imm ("10:14", insn, 1);
int32_t si20 = loongarch_decode_imm ("5:20", insn, 1);
if ((insn & 0xffc00000) == 0x02c00000 /* addi.d sp,sp,si12 */
&& rd == sp && rj == sp && si12 < 0)
{
prologue_end = cur_pc + insn_len;
+ regs[rd] = pv_add_constant (regs[rj], si12);
}
else if ((insn & 0xffc00000) == 0x02c00000 /* addi.d fp,sp,si12 */
&& rd == fp && rj == sp && si12 > 0)
{
prologue_end = cur_pc + insn_len;
+ regs[rd] = pv_add_constant (regs[rj], si12);
}
else if ((insn & 0xffc00000) == 0x29c00000 /* st.d rd,sp,si12 */
&& rj == sp)
{
prologue_end = cur_pc + insn_len;
+ /* ra, fp, s0~s8 are saved by callee with sp as a base */
+ if ((rd >= fp && rd <= fp + 9) || rd == ra)
+ {
+ stack.store (pv_add_constant (regs[sp], si12), register_size (gdbarch, rd), regs[rd]);
+ }
}
else if ((insn & 0xff000000) == 0x27000000 /* stptr.d rd,sp,si14 */
&& rj == sp)
{
prologue_end = cur_pc + insn_len;
+ /* ra, fp, s0~s8 are saved by callee with sp as a base */
+ if ((rd >= fp && rd <= fp + 9) || rd == ra)
+ {
+ stack.store (pv_add_constant (regs[sp], si14), register_size (gdbarch, rd), regs[rd]);
+ }
}
else if ((insn & 0xfe000000) == 0x14000000) /* lu12i.w rd,si20 */
{
@@ -189,6 +247,38 @@ loongarch_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc,
if (prologue_end == 0)
prologue_end = cur_pc;
+ if (this_cache == NULL)
+ return prologue_end;
+
+ if (pv_is_register (regs[LOONGARCH_FP_REGNUM], LOONGARCH_SP_REGNUM))
+ {
+ /* Frame pointer is fp. */
+ this_cache->framebase_reg = LOONGARCH_FP_REGNUM;
+ this_cache->framebase_offset = -regs[LOONGARCH_FP_REGNUM].k;
+ }
+ else if (pv_is_register (regs[LOONGARCH_SP_REGNUM], LOONGARCH_SP_REGNUM))
+ {
+ /* Try the stack pointer. */
+ this_cache->framebase_reg = LOONGARCH_SP_REGNUM;
+ this_cache->framebase_offset = -regs[LOONGARCH_SP_REGNUM].k;
+ }
+ else
+ {
+ /* We're just out of luck. We don't know where the frame is. */
+ this_cache->framebase_reg = -1;
+ this_cache->framebase_offset = 0;
+ }
+
+ for (i = 0; i < LOONGARCH_USED_NUM_GREGSET; i++)
+ {
+ CORE_ADDR offset;
+
+ if (stack.find_reg (gdbarch, i, &offset))
+ {
+ this_cache->saved_regs[i].set_addr (offset);
+ }
+ }
+
return prologue_end;
}
@@ -314,6 +404,20 @@ loongarch_next_pc (struct regcache *regcache, CORE_ADDR cur_pc)
if (rj != 0)
next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
}
+ else if ((insn & 0xfc000300) == 0x48000000) /* bceqz cj, offs21 */
+ {
+ LONGEST cj = regcache_raw_get_signed (regcache,
+ loongarch_decode_imm ("5:3", insn, 0) + LOONGARCH_FIRST_FCC_REGNUM);
+ if (cj == 0)
+ next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
+ }
+ else if ((insn & 0xfc000300) == 0x48000100) /* bcnez cj, offs21 */
+ {
+ LONGEST cj = regcache_raw_get_signed (regcache,
+ loongarch_decode_imm ("5:3", insn, 0) + LOONGARCH_FIRST_FCC_REGNUM);
+ if (cj != 0)
+ next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
+ }
else if ((insn & 0xffff8000) == 0x002b0000) /* syscall */
{
if (tdep->syscall_next_pc != nullptr)
@@ -323,13 +427,50 @@ loongarch_next_pc (struct regcache *regcache, CORE_ADDR cur_pc)
return next_pc;
}
+/* Calculate the destination address of a condition branch instruction under an
+ assumed true condition */
+
+static CORE_ADDR
+cond_branch_destination_address (CORE_ADDR cur_pc, insn_t insn)
+{
+ size_t insn_len = loongarch_insn_length (insn);
+ CORE_ADDR next_pc = cur_pc + insn_len;
+
+ if ((insn & 0xfc000000) == 0x58000000) /* beq rj, rd, offs16 */
+ next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
+ else if ((insn & 0xfc000000) == 0x5c000000) /* bne rj, rd, offs16 */
+ next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
+ else if ((insn & 0xfc000000) == 0x60000000) /* blt rj, rd, offs16 */
+ next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
+ else if ((insn & 0xfc000000) == 0x64000000) /* bge rj, rd, offs16 */
+ next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
+ else if ((insn & 0xfc000000) == 0x68000000) /* bltu rj, rd, offs16 */
+ next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
+ else if ((insn & 0xfc000000) == 0x6c000000) /* bgeu rj, rd, offs16 */
+ next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
+ else if ((insn & 0xfc000000) == 0x40000000) /* beqz rj, offs21 */
+ next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
+ else if ((insn & 0xfc000000) == 0x44000000) /* bnez rj, offs21 */
+ next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
+ else if ((insn & 0xfc000300) == 0x48000000) /* bceqz cj, offs21 */
+ next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
+ else if ((insn & 0xfc000300) == 0x48000100) /* bcnez cj, offs21 */
+ next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
+
+ return next_pc;
+}
+
/* We can't put a breakpoint in the middle of a ll/sc atomic sequence,
- so look for the end of the sequence and put the breakpoint there. */
+ so a breakpoint should be outside of atomic sequence in any case,
+ just look for the start and end of the sequence, and then restrict
+ the breakpoint outside of the atomic sequence. */
static std::vector<CORE_ADDR>
loongarch_deal_with_atomic_sequence (struct regcache *regcache, CORE_ADDR cur_pc)
{
CORE_ADDR next_pc;
+ CORE_ADDR ll_insn_addr;
+ CORE_ADDR sc_insn_addr;
std::vector<CORE_ADDR> next_pcs;
insn_t insn = loongarch_fetch_instruction (cur_pc);
size_t insn_len = loongarch_insn_length (insn);
@@ -340,6 +481,30 @@ loongarch_deal_with_atomic_sequence (struct regcache *regcache, CORE_ADDR cur_pc
if (!loongarch_insn_is_ll (insn))
return {};
+ /* Record the address of a Load Linked instruction */
+ ll_insn_addr = cur_pc;
+
+ for (int insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
+ {
+ cur_pc += insn_len;
+ insn = loongarch_fetch_instruction (cur_pc);
+
+ if (loongarch_insn_is_sc (insn))
+ {
+ /* Record the address of a Store Conditional instruction */
+ sc_insn_addr = cur_pc;
+ found_atomic_sequence_endpoint = true;
+ break;
+ }
+ }
+
+ /* We didn't find a closing Store Conditional instruction, fallback to the standard code. */
+ if (!found_atomic_sequence_endpoint)
+ return {};
+
+ /* Restore current PC with the address of a Load Linked instruction */
+ cur_pc = ll_insn_addr;
+
/* Assume that no atomic sequence is longer than "atomic_sequence_length" instructions. */
for (int insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
{
@@ -355,24 +520,20 @@ loongarch_deal_with_atomic_sequence (struct regcache *regcache, CORE_ADDR cur_pc
which is outside of the ll/sc atomic instruction sequence. */
else if (loongarch_insn_is_cond_branch (insn))
{
- next_pc = loongarch_next_pc (regcache, cur_pc);
- if (next_pc != cur_pc + insn_len)
+ next_pc = cond_branch_destination_address (cur_pc, insn);
+ /* Restrict the breakpoint outside of the atomic sequence. */
+ if (next_pc < ll_insn_addr || next_pc > sc_insn_addr)
next_pcs.push_back (next_pc);
}
/* Look for a Store Conditional instruction which closes the atomic sequence. */
else if (loongarch_insn_is_sc (insn))
{
- found_atomic_sequence_endpoint = true;
next_pc = cur_pc + insn_len;
next_pcs.push_back (next_pc);
break;
}
}
- /* We didn't find a closing Store Conditional instruction, fallback to the standard code. */
- if (!found_atomic_sequence_endpoint)
- return {};
-
return next_pcs;
}
@@ -410,38 +571,157 @@ loongarch_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
return align_down (addr, 16);
}
+/* Analyze the function prologue for THIS_FRAME and populate the frame
+ cache CACHE. */
+
+static void
+loongarch_analyze_prologue (const frame_info_ptr &this_frame,
+ struct loongarch_frame_cache *cache)
+{
+ CORE_ADDR block_addr = get_frame_address_in_block (this_frame);
+ CORE_ADDR prologue_start = 0;
+ CORE_ADDR prologue_end = 0;
+ CORE_ADDR pc = get_frame_pc (this_frame);
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+
+ cache->pc = pc;
+
+ /* Assume we do not find a frame. */
+ cache->framebase_reg = -1;
+ cache->framebase_offset = 0;
+
+
+ if (find_pc_partial_function (block_addr, NULL, &prologue_start,
+ &prologue_end))
+ {
+ struct symtab_and_line sal = find_pc_line (prologue_start, 0);
+
+ if (sal.line == 0)
+ {
+ /* No line info so use the current PC. */
+ prologue_end = pc;
+ }
+ else if (sal.end < prologue_end)
+ {
+ if (sal.symtab != NULL && sal.symtab->language () == language_asm)
+ {
+ /* This sal.end usually cannot point to prologue_end correctly
+ in asm file. */
+ prologue_end = pc;
+ }
+ else
+ {
+ /* The next line begins after the prologue_end. */
+ prologue_end = sal.end;
+ }
+ }
+
+ }
+ else
+ {
+ /* We're in the boondocks: we have no idea where the start of the
+ function is. */
+ return;
+ }
+
+ prologue_end = std::min (prologue_end, pc);
+ loongarch_scan_prologue (gdbarch, prologue_start, prologue_end, nullptr, cache);
+}
+
+/* Fill in *CACHE with information about the prologue of *THIS_FRAME. */
+
+static void
+loongarch_frame_cache_1 (const frame_info_ptr &this_frame,
+ struct loongarch_frame_cache *cache)
+{
+ CORE_ADDR unwound_fp;
+ int reg;
+
+ loongarch_analyze_prologue (this_frame, cache);
+
+ if (cache->framebase_reg == -1)
+ return;
+
+ unwound_fp = get_frame_register_unsigned (this_frame, cache->framebase_reg);
+ if (unwound_fp == 0)
+ return;
+
+ cache->prev_sp = unwound_fp;
+ cache->prev_sp += cache->framebase_offset;
+
+ /* Calculate actual addresses of saved registers using offsets
+ determined by loongarch_scan_prologue. */
+ for (reg = 0; reg < gdbarch_num_regs (get_frame_arch (this_frame)); reg++)
+ if (cache->saved_regs[reg].is_addr ())
+ cache->saved_regs[reg].set_addr (cache->saved_regs[reg].addr ()
+ + cache->prev_sp);
+
+ cache->func = get_frame_func (this_frame);
+
+ cache->available_p = 1;
+}
+
/* Generate, or return the cached frame cache for frame unwinder. */
-static struct trad_frame_cache *
+static struct loongarch_frame_cache *
loongarch_frame_cache (const frame_info_ptr &this_frame, void **this_cache)
{
- struct trad_frame_cache *cache;
- CORE_ADDR pc;
+ struct loongarch_frame_cache *cache;
- if (*this_cache != nullptr)
- return (struct trad_frame_cache *) *this_cache;
+ if (*this_cache != NULL)
+ return (struct loongarch_frame_cache *) *this_cache;
- cache = trad_frame_cache_zalloc (this_frame);
+ cache = FRAME_OBSTACK_ZALLOC (struct loongarch_frame_cache);
+ cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
*this_cache = cache;
- trad_frame_set_reg_realreg (cache, LOONGARCH_PC_REGNUM, LOONGARCH_RA_REGNUM);
-
- pc = get_frame_address_in_block (this_frame);
- trad_frame_set_id (cache, frame_id_build_unavailable_stack (pc));
+ try
+ {
+ loongarch_frame_cache_1 (this_frame, cache);
+ }
+ catch (const gdb_exception_error &ex)
+ {
+ if (ex.error != NOT_AVAILABLE_ERROR)
+ throw;
+ }
return cache;
}
+/* Implement the "stop_reason" frame_unwind method. */
+
+static enum unwind_stop_reason
+loongarch_frame_unwind_stop_reason (const frame_info_ptr &this_frame,
+ void **this_cache)
+{
+ struct loongarch_frame_cache *cache
+ = loongarch_frame_cache (this_frame, this_cache);
+
+ if (!cache->available_p)
+ return UNWIND_UNAVAILABLE;
+
+ /* We've hit a wall, stop. */
+ if (cache->prev_sp == 0)
+ return UNWIND_OUTERMOST;
+
+ return UNWIND_NO_REASON;
+}
+
/* Implement the this_id callback for frame unwinder. */
static void
loongarch_frame_this_id (const frame_info_ptr &this_frame, void **prologue_cache,
struct frame_id *this_id)
{
- struct trad_frame_cache *info;
+ struct loongarch_frame_cache *cache
+ = loongarch_frame_cache (this_frame, prologue_cache);
- info = loongarch_frame_cache (this_frame, prologue_cache);
- trad_frame_get_id (info, this_id);
+ /* Our frame ID for a normal frame is the current function's starting
+ PC and the caller's SP when we were called. */
+ if (!cache->available_p)
+ *this_id = frame_id_build_unavailable_stack (cache->func);
+ else
+ *this_id = frame_id_build (cache->prev_sp, cache->func);
}
/* Implement the prev_register callback for frame unwinder. */
@@ -450,17 +730,55 @@ static struct value *
loongarch_frame_prev_register (const frame_info_ptr &this_frame,
void **prologue_cache, int regnum)
{
- struct trad_frame_cache *info;
+ struct loongarch_frame_cache *cache
+ = loongarch_frame_cache (this_frame, prologue_cache);
+
+ /* If we are asked to unwind the PC, then we need to return the RA
+ instead. The prologue may save PC, but it will point into this
+ frame's prologue, not the previou frame's resume location. */
+ if (regnum == LOONGARCH_PC_REGNUM)
+ {
+ CORE_ADDR ra;
+ ra = frame_unwind_register_unsigned (this_frame, LOONGARCH_RA_REGNUM);
+
+ return frame_unwind_got_constant (this_frame, regnum, ra);
+ }
+
+ /* SP is generally not saved to the stack, but this frame is
+ identified by the next frame's stack pointer at the time of the
+ call. The value was already reconstructed into PREV_SP. */
+ /*
+ addi.d $sp, $sp, -32
+ st.d $ra, $sp, 24
+ st.d $fp, $sp, 16
+ addi.d $fp, $sp, 32
+
+ +->+----------+
+ | | saved ra |
+ | | saved fp |
+ | | |
+ | | |
+ | +----------+ <- Previous SP == FP
+ | | saved ra |
+ +--| saved fp |
+ | |
+ | |
+ +----------+ <- SP
+ */
+
+ if (regnum == LOONGARCH_SP_REGNUM)
+ return frame_unwind_got_constant (this_frame, regnum, cache->prev_sp);
+
+ return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
- info = loongarch_frame_cache (this_frame, prologue_cache);
- return trad_frame_get_register (info, this_frame, regnum);
}
+/* LoongArch prologue unwinder. */
static const struct frame_unwind_legacy loongarch_frame_unwind (
"loongarch prologue",
/*.type =*/NORMAL_FRAME,
/*.unwinder_class=*/FRAME_UNWIND_ARCH,
- /*.stop_reason =*/default_frame_unwind_stop_reason,
+ /*.stop_reason =*/loongarch_frame_unwind_stop_reason,
/*.this_id =*/loongarch_frame_this_id,
/*.prev_register =*/loongarch_frame_prev_register,
/*.unwind_data =*/nullptr,
@@ -1879,7 +2197,7 @@ loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_frame_align (gdbarch, loongarch_frame_align);
/* Breakpoint manipulation. */
- set_gdbarch_software_single_step (gdbarch, loongarch_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, loongarch_software_single_step);
set_gdbarch_breakpoint_kind_from_pc (gdbarch, loongarch_breakpoint::kind_from_pc);
set_gdbarch_sw_breakpoint_from_kind (gdbarch, loongarch_breakpoint::bp_from_kind);
set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
@@ -2405,9 +2723,7 @@ loongarch_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
return ret;
}
-void _initialize_loongarch_tdep ();
-void
-_initialize_loongarch_tdep ()
+INIT_GDB_FILE (loongarch_tdep)
{
gdbarch_register (bfd_arch_loongarch, loongarch_gdbarch_init, nullptr);
}
diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y
index 5c31a5e..55d5f2e 100644
--- a/gdb/m2-exp.y
+++ b/gdb/m2-exp.y
@@ -507,7 +507,7 @@ fblock : block COLONCOLON BLOCKNAME
{ struct symbol *tem
= lookup_symbol (copy_name ($3).c_str (), $1,
SEARCH_VFT, 0).symbol;
- if (!tem || tem->aclass () != LOC_BLOCK)
+ if (!tem || tem->loc_class () != LOC_BLOCK)
error (_("No function \"%s\" in specified context."),
copy_name ($3).c_str ());
$$ = tem;
@@ -928,7 +928,7 @@ yylex (void)
sym = lookup_symbol (tmp.c_str (), pstate->expression_context_block,
SEARCH_VFT, 0).symbol;
- if (sym && sym->aclass () == LOC_BLOCK)
+ if (sym && sym->loc_class () == LOC_BLOCK)
return BLOCKNAME;
if (lookup_typename (pstate->language (),
tmp.c_str (), pstate->expression_context_block, 1))
@@ -936,7 +936,7 @@ yylex (void)
if(sym)
{
- switch(sym->aclass ())
+ switch(sym->loc_class ())
{
case LOC_STATIC:
case LOC_REGISTER:
diff --git a/gdb/m32c-tdep.c b/gdb/m32c-tdep.c
index f8937a2..8d99839 100644
--- a/gdb/m32c-tdep.c
+++ b/gdb/m32c-tdep.c
@@ -2653,9 +2653,7 @@ m32c_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_m32c_tdep ();
-void
-_initialize_m32c_tdep ()
+INIT_GDB_FILE (m32c_tdep)
{
gdbarch_register (bfd_arch_m32c, m32c_gdbarch_init);
diff --git a/gdb/m32r-linux-nat.c b/gdb/m32r-linux-nat.c
index 7607bd2..c186693 100644
--- a/gdb/m32r-linux-nat.c
+++ b/gdb/m32r-linux-nat.c
@@ -234,9 +234,7 @@ m32r_linux_nat_target::store_registers (struct regcache *regcache, int regno)
internal_error (_("Got request to store bad register number %d."), regno);
}
-void _initialize_m32r_linux_nat ();
-void
-_initialize_m32r_linux_nat ()
+INIT_GDB_FILE (m32r_linux_nat)
{
/* Register the target. */
linux_target = &the_m32r_linux_nat_target;
diff --git a/gdb/m32r-linux-tdep.c b/gdb/m32r-linux-tdep.c
index 4fbe7d9..03000cc 100644
--- a/gdb/m32r-linux-tdep.c
+++ b/gdb/m32r-linux-tdep.c
@@ -36,6 +36,7 @@
#include "m32r-tdep.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "gdbarch.h"
@@ -461,8 +462,7 @@ m32r_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* GNU/Linux uses SVR4-style shared libraries. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
/* Core file support. */
set_gdbarch_iterate_over_regset_sections
@@ -473,9 +473,7 @@ m32r_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
svr4_fetch_objfile_link_map);
}
-void _initialize_m32r_linux_tdep ();
-void
-_initialize_m32r_linux_tdep ()
+INIT_GDB_FILE (m32r_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_m32r, 0, GDB_OSABI_LINUX,
m32r_linux_init_abi);
diff --git a/gdb/m32r-tdep.c b/gdb/m32r-tdep.c
index 6b6ad03..4ac08fd 100644
--- a/gdb/m32r-tdep.c
+++ b/gdb/m32r-tdep.c
@@ -908,9 +908,7 @@ m32r_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_m32r_tdep ();
-void
-_initialize_m32r_tdep ()
+INIT_GDB_FILE (m32r_tdep)
{
gdbarch_register (bfd_arch_m32r, m32r_gdbarch_init);
}
diff --git a/gdb/m68hc11-tdep.c b/gdb/m68hc11-tdep.c
index dd8cbda..5389fee 100644
--- a/gdb/m68hc11-tdep.c
+++ b/gdb/m68hc11-tdep.c
@@ -1527,9 +1527,7 @@ m68hc11_gdbarch_init (struct gdbarch_info info,
return gdbarch;
}
-void _initialize_m68hc11_tdep ();
-void
-_initialize_m68hc11_tdep ()
+INIT_GDB_FILE (m68hc11_tdep)
{
gdbarch_register (bfd_arch_m68hc11, m68hc11_gdbarch_init);
gdbarch_register (bfd_arch_m68hc12, m68hc11_gdbarch_init);
diff --git a/gdb/m68k-bsd-nat.c b/gdb/m68k-bsd-nat.c
index 04542fd..ae8fa4d 100644
--- a/gdb/m68k-bsd-nat.c
+++ b/gdb/m68k-bsd-nat.c
@@ -225,9 +225,7 @@ m68kbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
return 1;
}
-void _initialize_m68kbsd_nat ();
-void
-_initialize_m68kbsd_nat ()
+INIT_GDB_FILE (m68kbsd_nat)
{
add_inf_child_target (&the_m68k_bsd_nat_target);
diff --git a/gdb/m68k-bsd-tdep.c b/gdb/m68k-bsd-tdep.c
index 09c57c6..37c1464 100644
--- a/gdb/m68k-bsd-tdep.c
+++ b/gdb/m68k-bsd-tdep.c
@@ -147,13 +147,10 @@ m68kbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->struct_return = pcc_struct_return;
/* NetBSD ELF uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
}
-void _initialize_m68kbsd_tdep ();
-void
-_initialize_m68kbsd_tdep ()
+INIT_GDB_FILE (m68kbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD,
m68kbsd_init_abi);
diff --git a/gdb/m68k-linux-nat.c b/gdb/m68k-linux-nat.c
index d43ed68..02286ff 100644
--- a/gdb/m68k-linux-nat.c
+++ b/gdb/m68k-linux-nat.c
@@ -508,9 +508,7 @@ ps_get_thread_area (struct ps_prochandle *ph,
return PS_OK;
}
-void _initialize_m68k_linux_nat ();
-void
-_initialize_m68k_linux_nat ()
+INIT_GDB_FILE (m68k_linux_nat)
{
/* Register the target. */
linux_target = &the_m68k_linux_nat_target;
diff --git a/gdb/m68k-linux-tdep.c b/gdb/m68k-linux-tdep.c
index cfc37ab..bd2a14a 100644
--- a/gdb/m68k-linux-tdep.c
+++ b/gdb/m68k-linux-tdep.c
@@ -35,6 +35,7 @@
#include "observable.h"
#include "elf/common.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "regset.h"
/* Offsets (in target ints) into jmp_buf. */
@@ -407,8 +408,7 @@ m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Shared library handling. */
/* GNU/Linux uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
/* GNU/Linux uses the dynamic linker included in the GNU C Library. */
set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
@@ -424,9 +424,7 @@ m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
svr4_fetch_objfile_link_map);
}
-void _initialize_m68k_linux_tdep ();
-void
-_initialize_m68k_linux_tdep ()
+INIT_GDB_FILE (m68k_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_LINUX,
m68k_linux_init_abi);
diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c
index 4e25518..94bfddb 100644
--- a/gdb/m68k-tdep.c
+++ b/gdb/m68k-tdep.c
@@ -1365,9 +1365,7 @@ m68k_osabi_sniffer (bfd *abfd)
return osabi;
}
-void _initialize_m68k_tdep ();
-void
-_initialize_m68k_tdep ()
+INIT_GDB_FILE (m68k_tdep)
{
gdbarch_register (bfd_arch_m68k, m68k_gdbarch_init, m68k_dump_tdep);
diff --git a/gdb/machoread.c b/gdb/machoread.c
index cc8aca3..30d376c 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -901,13 +901,13 @@ macho_symfile_offsets (struct objfile *objfile,
for (i = 0; i < addrs.size (); i++)
{
- for (obj_section *osect : objfile->sections ())
+ for (obj_section &osect : objfile->sections ())
{
- const char *bfd_sect_name = osect->the_bfd_section->name;
+ const char *bfd_sect_name = osect.the_bfd_section->name;
if (bfd_sect_name == addrs[i].name)
{
- osect->set_offset (addrs[i].addr);
+ osect.set_offset (addrs[i].addr);
break;
}
}
@@ -915,10 +915,10 @@ macho_symfile_offsets (struct objfile *objfile,
objfile->sect_index_text = 0;
- for (obj_section *osect : objfile->sections ())
+ for (obj_section &osect : objfile->sections ())
{
- const char *bfd_sect_name = osect->the_bfd_section->name;
- int sect_index = osect - objfile->sections_start;
+ const char *bfd_sect_name = osect.the_bfd_section->name;
+ int sect_index = &osect - objfile->sections_start;
if (startswith (bfd_sect_name, "LC_SEGMENT."))
bfd_sect_name += 11;
@@ -940,9 +940,7 @@ static const struct sym_fns macho_sym_fns = {
NULL, /* sym_get_probes */
};
-void _initialize_machoread ();
-void
-_initialize_machoread ()
+INIT_GDB_FILE (machoread)
{
add_symtab_fns (bfd_target_mach_o_flavour, &macho_sym_fns);
diff --git a/gdb/macrocmd.c b/gdb/macrocmd.c
index 0192a00..d805f3d 100644
--- a/gdb/macrocmd.c
+++ b/gdb/macrocmd.c
@@ -57,11 +57,11 @@ macro_expand_command (const char *exp, int from_tty)
" expression you\n"
"want to expand."));
- gdb::unique_xmalloc_ptr<macro_scope> ms = default_macro_scope ();
+ macro_scope ms = default_macro_scope ();
- if (ms != nullptr)
+ if (ms.is_valid ())
{
- gdb::unique_xmalloc_ptr<char> expanded = macro_expand (exp, *ms);
+ gdb::unique_xmalloc_ptr<char> expanded = macro_expand (exp, ms);
gdb_puts ("expands to: ");
gdb_puts (expanded.get ());
@@ -85,11 +85,11 @@ macro_expand_once_command (const char *exp, int from_tty)
" the expression\n"
"you want to expand."));
- gdb::unique_xmalloc_ptr<macro_scope> ms = default_macro_scope ();
+ macro_scope ms = default_macro_scope ();
- if (ms != nullptr)
+ if (ms.is_valid ())
{
- gdb::unique_xmalloc_ptr<char> expanded = macro_expand_once (exp, *ms);
+ gdb::unique_xmalloc_ptr<char> expanded = macro_expand_once (exp, ms);
gdb_puts ("expands to: ");
gdb_puts (expanded.get ());
@@ -169,7 +169,6 @@ print_macro_definition (const char *name,
static void
info_macro_command (const char *args, int from_tty)
{
- gdb::unique_xmalloc_ptr<struct macro_scope> ms;
const char *name;
int show_all_macros_named = 0;
const char *arg_start = args;
@@ -201,15 +200,15 @@ info_macro_command (const char *args, int from_tty)
" of the macro\n"
"whose definition you want to see."));
- ms = default_macro_scope ();
+ macro_scope ms = default_macro_scope ();
- if (! ms)
+ if (!ms.is_valid ())
macro_inform_no_debuginfo ();
else if (show_all_macros_named)
- macro_for_each (ms->file->table, [&] (const char *macro_name,
- const macro_definition *macro,
- macro_source_file *source,
- int line)
+ macro_for_each (ms.file->table, [&] (const char *macro_name,
+ const macro_definition *macro,
+ macro_source_file *source,
+ int line)
{
if (strcmp (name, macro_name) == 0)
print_macro_definition (name, macro, source, line);
@@ -218,12 +217,12 @@ info_macro_command (const char *args, int from_tty)
{
struct macro_definition *d;
- d = macro_lookup_definition (ms->file, ms->line, name);
+ d = macro_lookup_definition (ms.file, ms.line, name);
if (d)
{
int line;
struct macro_source_file *file
- = macro_definition_location (ms->file, ms->line, name, &line);
+ = macro_definition_location (ms.file, ms.line, name, &line);
print_macro_definition (name, d, file, line);
}
@@ -232,7 +231,7 @@ info_macro_command (const char *args, int from_tty)
gdb_printf ("The symbol `%s' has no definition as a C/C++"
" preprocessor macro\n"
"at ", name);
- show_pp_source_pos (gdb_stdout, ms->file, ms->line);
+ show_pp_source_pos (gdb_stdout, ms.file, ms.line);
}
}
}
@@ -241,7 +240,7 @@ info_macro_command (const char *args, int from_tty)
static void
info_macros_command (const char *args, int from_tty)
{
- gdb::unique_xmalloc_ptr<struct macro_scope> ms;
+ macro_scope ms;
if (args == NULL)
ms = default_macro_scope ();
@@ -254,10 +253,10 @@ info_macros_command (const char *args, int from_tty)
ms = sal_macro_scope (sals[0]);
}
- if (! ms || ! ms->file || ! ms->file->table)
+ if (!ms.is_valid () || ms.file->table == nullptr)
macro_inform_no_debuginfo ();
else
- macro_for_each_in_scope (ms->file, ms->line, print_macro_definition);
+ macro_for_each_in_scope (ms.file, ms.line, print_macro_definition);
}
@@ -409,9 +408,7 @@ macro_list_command (const char *exp, int from_tty)
/* Initializing the `macrocmd' module. */
-void _initialize_macrocmd ();
-void
-_initialize_macrocmd ()
+INIT_GDB_FILE (macrocmd)
{
/* We introduce a new command prefix, `macro', under which we'll put
the various commands for working with preprocessor macros. */
diff --git a/gdb/macroscope.c b/gdb/macroscope.c
index 97b41b6..a8b78c9 100644
--- a/gdb/macroscope.c
+++ b/gdb/macroscope.c
@@ -34,28 +34,29 @@
struct macro_table *macro_user_macros;
-gdb::unique_xmalloc_ptr<struct macro_scope>
+macro_scope
sal_macro_scope (struct symtab_and_line sal)
{
+ macro_scope result;
struct macro_source_file *main_file, *inclusion;
struct compunit_symtab *cust;
if (sal.symtab == NULL)
- return NULL;
+ return result;
cust = sal.symtab->compunit ();
if (cust->macro_table () == NULL)
- return NULL;
+ return result;
- gdb::unique_xmalloc_ptr<struct macro_scope> ms (XNEW (struct macro_scope));
+ macro_scope ms;
main_file = macro_main (cust->macro_table ());
inclusion = macro_lookup_inclusion (main_file, sal.symtab->filename_for_id);
if (inclusion)
{
- ms->file = inclusion;
- ms->line = sal.line;
+ ms.file = inclusion;
+ ms.line = sal.line;
}
else
{
@@ -73,8 +74,8 @@ sal_macro_scope (struct symtab_and_line sal)
For the time being, though, we'll just treat these as
occurring at the end of the main source file. */
- ms->file = main_file;
- ms->line = -1;
+ ms.file = main_file;
+ ms.line = -1;
complaint (_("symtab found for `%s', but that file\n"
"is not covered in the compilation unit's macro information"),
@@ -85,27 +86,23 @@ sal_macro_scope (struct symtab_and_line sal)
}
-gdb::unique_xmalloc_ptr<struct macro_scope>
-user_macro_scope (void)
+macro_scope
+user_macro_scope ()
{
- gdb::unique_xmalloc_ptr<struct macro_scope> ms (XNEW (struct macro_scope));
- ms->file = macro_main (macro_user_macros);
- ms->line = -1;
- return ms;
+ return { macro_main (macro_user_macros), -1 };
}
-gdb::unique_xmalloc_ptr<struct macro_scope>
-default_macro_scope (void)
+macro_scope
+default_macro_scope ()
{
struct symtab_and_line sal;
- gdb::unique_xmalloc_ptr<struct macro_scope> ms;
frame_info_ptr frame;
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
/* If there's a selected frame, use its PC. */
frame = deprecated_safe_get_selected_frame ();
- if (frame && get_frame_pc_if_available (frame, &pc))
- sal = find_pc_line (pc, 0);
+ if (frame && (pc = get_frame_pc_if_available (frame)))
+ sal = find_pc_line (*pc, 0);
/* Fall back to the current listing position. */
else
@@ -128,8 +125,8 @@ default_macro_scope (void)
sal.line = cursal.line;
}
- ms = sal_macro_scope (sal);
- if (! ms)
+ macro_scope ms = sal_macro_scope (sal);
+ if (!ms.is_valid ())
ms = user_macro_scope ();
return ms;
@@ -152,9 +149,7 @@ standard_macro_lookup (const char *name, const macro_scope &ms)
return result;
}
-void _initialize_macroscope ();
-void
-_initialize_macroscope ()
+INIT_GDB_FILE (macroscope)
{
macro_user_macros = new_macro_table (NULL, NULL, NULL);
macro_set_main (macro_user_macros, "<user-defined>");
diff --git a/gdb/macroscope.h b/gdb/macroscope.h
index de3186d..2cb6a0f 100644
--- a/gdb/macroscope.h
+++ b/gdb/macroscope.h
@@ -31,21 +31,25 @@ extern struct macro_table *macro_user_macros;
in scope: a source file (either a main source file or an
#inclusion), and a line number in that file. */
struct macro_scope {
- struct macro_source_file *file;
- int line;
+ struct macro_source_file *file = nullptr;
+ int line = 0;
+
+ /* Return true if this scope is valid. */
+ bool is_valid () const
+ {
+ return file != nullptr;
+ }
};
/* Return a `struct macro_scope' object corresponding to the symtab
and line given in SAL. If we have no macro information for that
- location, or if SAL's pc is zero, return zero. */
-gdb::unique_xmalloc_ptr<struct macro_scope> sal_macro_scope
- (struct symtab_and_line sal);
-
+ location, or if SAL's pc is zero, return an invalid scope. */
+macro_scope sal_macro_scope (struct symtab_and_line sal);
/* Return a `struct macro_scope' object representing just the
user-defined macros. */
-gdb::unique_xmalloc_ptr<struct macro_scope> user_macro_scope (void);
+macro_scope user_macro_scope ();
/* Return a `struct macro_scope' object describing the scope the `macro
expand' and `macro expand-once' commands should use for looking up
@@ -54,7 +58,7 @@ gdb::unique_xmalloc_ptr<struct macro_scope> user_macro_scope (void);
If we have no macro information for the current location, return
the user macro scope. */
-gdb::unique_xmalloc_ptr<struct macro_scope> default_macro_scope (void);
+macro_scope default_macro_scope ();
/* Look up the definition of the macro named NAME in scope at the source
location given by MS. */
diff --git a/gdb/main.c b/gdb/main.c
index 9220092..04c3363 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -19,6 +19,7 @@
#include "annotate.h"
#include "exceptions.h"
+#include "gdbsupport/common-inferior.h"
#include "top.h"
#include "ui.h"
#include "target.h"
@@ -29,7 +30,6 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <ctype.h>
#include "gdbsupport/event-loop.h"
#include "ui-out.h"
@@ -399,7 +399,7 @@ start_event_loop ()
try
{
- result = gdb_do_one_event ();
+ result = current_interpreter ()->do_one_event ();
}
catch (const gdb_exception_forced_quit &ex)
{
@@ -420,6 +420,7 @@ start_event_loop ()
get around to resetting the prompt, which leaves readline
in a messed-up state. Reset it here. */
current_ui->prompt_state = PROMPT_NEEDED;
+ current_ui->line_buffer.clear ();
top_level_interpreter ()->on_command_error ();
/* This call looks bizarre, but it is required. If the user
entered a command that caused an error,
@@ -616,9 +617,20 @@ captured_main_1 (struct captured_main_args *context)
char **argv = context->argv;
static int quiet = 0;
- static int set_args = 0;
static int inhibit_home_gdbinit = 0;
+ /* Has the user passed inferior arguments on the command line. */
+ enum {
+ /* No arguments passed. */
+ NO_ARGS,
+
+ /* Arguments passed with --args. */
+ SET_ESC_ARGS,
+
+ /* Arguments passed with --no-escape-args. */
+ SET_NO_ESC_ARGS
+ } set_args = NO_ARGS;
+
/* Pointers to various arguments from command line. */
char *symarg = NULL;
char *execarg = NULL;
@@ -672,6 +684,8 @@ captured_main_1 (struct captured_main_args *context)
/* Ensure stderr is unbuffered. A Cygwin pty or pipe is implemented
as a Windows pipe, and Windows buffers on pipes. */
setvbuf (stderr, NULL, _IONBF, BUFSIZ);
+
+ windows_initialize_console ();
#endif
/* Note: `error' cannot be called before this point, because the
@@ -766,7 +780,9 @@ captured_main_1 (struct captured_main_args *context)
OPT_EIX,
OPT_EIEX,
OPT_READNOW,
- OPT_READNEVER
+ OPT_READNEVER,
+ OPT_SET_ESC_ARGS,
+ OPT_SET_NO_ESC_ARGS,
};
/* This struct requires int* in the struct, but write_files is a bool.
So use this temporary int that we write back after argument parsing. */
@@ -839,7 +855,8 @@ captured_main_1 (struct captured_main_args *context)
{"windows", no_argument, NULL, OPT_WINDOWS},
{"statistics", no_argument, 0, OPT_STATISTICS},
{"write", no_argument, &write_files_1, 1},
- {"args", no_argument, &set_args, 1},
+ {"args", no_argument, nullptr, OPT_SET_ESC_ARGS},
+ {"no-escape-args", no_argument, nullptr, OPT_SET_NO_ESC_ARGS},
{"l", required_argument, 0, 'l'},
{"return-child-result", no_argument, &return_child_result, 1},
{0, no_argument, 0, 0}
@@ -851,7 +868,7 @@ captured_main_1 (struct captured_main_args *context)
c = getopt_long_only (argc, argv, "",
long_options, &option_index);
- if (c == EOF || set_args)
+ if (c == EOF || set_args != NO_ARGS)
break;
/* Long option that takes an argument. */
@@ -932,6 +949,12 @@ captured_main_1 (struct captured_main_args *context)
case OPT_EIEX:
cmdarg_vec.emplace_back (CMDARG_EARLYINIT_COMMAND, optarg);
break;
+ case OPT_SET_ESC_ARGS:
+ set_args = SET_ESC_ARGS;
+ break;
+ case OPT_SET_NO_ESC_ARGS:
+ set_args = SET_NO_ESC_ARGS;
+ break;
case 'B':
batch_flag = batch_silent = 1;
gdb_stdout = new null_file ();
@@ -1065,7 +1088,7 @@ captured_main_1 (struct captured_main_args *context)
/* Now that gdb_init has created the initial inferior, we're in
position to set args for that inferior. */
- if (set_args)
+ if (set_args != NO_ARGS)
{
/* The remaining options are the command-line options for the
inferior. The first one is the sym/exec file, and the rest
@@ -1077,10 +1100,9 @@ captured_main_1 (struct captured_main_args *context)
symarg = argv[optind];
execarg = argv[optind];
++optind;
- current_inferior ()->set_args
- (gdb::array_view<char * const> (&argv[optind], argc - optind),
- startup_with_shell);
- }
+ gdb::array_view<char * const> arg_view (&argv[optind], argc - optind);
+ current_inferior ()->set_args (arg_view, (set_args == SET_ESC_ARGS));
+ }
else
{
/* OK, that's all the options. */
@@ -1250,7 +1272,7 @@ captured_main_1 (struct captured_main_args *context)
If pid_or_core_arg's first character is a digit, try attach
first and then corefile. Otherwise try just corefile. */
- if (isdigit (pid_or_core_arg[0]))
+ if (c_isdigit (pid_or_core_arg[0]))
{
ret = catch_command_errors (attach_command, pid_or_core_arg,
!batch_flag);
@@ -1327,10 +1349,8 @@ captured_main_1 (struct captured_main_args *context)
}
static void
-captured_main (void *data)
+captured_main (captured_main_args *context)
{
- struct captured_main_args *context = (struct captured_main_args *) data;
-
captured_main_1 (context);
/* NOTE: cagney/1999-11-07: There is probably no reason for not
@@ -1399,7 +1419,8 @@ This is the GNU debugger. Usage:\n\n\
gdb_puts (_("\
Selection of debuggee and its files:\n\n\
--args Arguments after executable-file are passed to inferior.\n\
- --core=COREFILE Analyze the core dump COREFILE.\n\
+ --no-escape-args Like --args, but arguments are not escaped.\n \
+ --core=COREFILE Analyze the core dump COREFILE.\n \
--exec=EXECFILE Use EXECFILE as the executable.\n\
--pid=PID Attach to running process PID.\n\
--directory=DIR Search for source files in DIR.\n\
diff --git a/gdb/main.h b/gdb/main.h
index 4830b59..0f50b71 100644
--- a/gdb/main.h
+++ b/gdb/main.h
@@ -44,6 +44,9 @@ extern std::string interpreter_p;
return value is in malloc'ed storage. */
extern char *windows_get_absolute_argv0 (const char *argv0);
+/* Initialize Windows console settings. */
+extern void windows_initialize_console ();
+
extern void set_gdb_data_directory (const char *new_data_dir);
#endif /* GDB_MAIN_H */
diff --git a/gdb/maint-test-options.c b/gdb/maint-test-options.c
index 25f609b..97236c9 100644
--- a/gdb/maint-test-options.c
+++ b/gdb/maint-test-options.c
@@ -429,9 +429,7 @@ maintenance_test_options_unknown_is_operand_command_completer
static cmd_list_element *maintenance_test_options_list;
-void _initialize_maint_test_options ();
-void
-_initialize_maint_test_options ()
+INIT_GDB_FILE (maint_test_options)
{
cmd_list_element *cmd;
diff --git a/gdb/maint-test-settings.c b/gdb/maint-test-settings.c
index 663190a..c7b12c6 100644
--- a/gdb/maint-test-settings.c
+++ b/gdb/maint-test-settings.c
@@ -78,9 +78,7 @@ maintenance_show_test_settings_value_cmd
}
-void _initialize_maint_test_settings ();
-void
-_initialize_maint_test_settings ()
+INIT_GDB_FILE (maint_test_settings)
{
maintenance_test_settings_filename = "/foo/bar";
diff --git a/gdb/maint.c b/gdb/maint.c
index c6f9b32..8bc2856 100644
--- a/gdb/maint.c
+++ b/gdb/maint.c
@@ -21,7 +21,6 @@
#include "arch-utils.h"
-#include <ctype.h>
#include <cmath>
#include <signal.h>
#include "command.h"
@@ -571,9 +570,9 @@ maintenance_translate_address (const char *arg, int from_tty)
sect = NULL;
p = arg;
- if (!isdigit (*p))
+ if (!c_isdigit (*p))
{ /* See if we have a valid section name. */
- while (*p && !isspace (*p)) /* Find end of section name. */
+ while (*p && !c_isspace (*p)) /* Find end of section name. */
p++;
if (*p == '\000') /* End of command? */
error (_("Need to specify section name and address"));
@@ -582,9 +581,9 @@ maintenance_translate_address (const char *arg, int from_tty)
p = skip_spaces (p + 1);
for (objfile *objfile : current_program_space->objfiles ())
- for (obj_section *iter : objfile->sections ())
+ for (obj_section &iter : objfile->sections ())
{
- if (strncmp (iter->the_bfd_section->name, arg, arg_len) == 0)
+ if (strncmp (iter.the_bfd_section->name, arg, arg_len) == 0)
goto found;
}
@@ -920,9 +919,9 @@ maintenance_show_worker_threads (struct ui_file *file, int from_tty,
}
-/* If true, display time usage both at startup and for each command. */
+/* See maint.h. */
-static bool per_command_time;
+bool per_command_time;
/* If true, display space usage both at startup and for each command. */
@@ -1151,10 +1150,32 @@ set_per_command_cmd (const char *args, int from_tty)
}
}
+/* Handle "mt set per-command time". Warn if per-thread run time
+ information is not possible. */
+
+static void
+maintenance_set_command_time_cmd (const char *args, int from_tty,
+ cmd_list_element *c)
+{
+ /* No point warning if this platform can't use multiple threads at
+ all. */
+#if CXX_STD_THREAD
+ static bool already_warned = false;
+ if (per_command_time
+ && !get_run_time_thread_scope_available ()
+ && !already_warned)
+ {
+ warning (_("\
+per-thread run time information not available on this platform"));
+ already_warned = true;
+ }
+#endif
+}
+
/* See maint.h. */
-scoped_time_it::scoped_time_it (const char *what)
- : m_enabled (per_command_time),
+scoped_time_it::scoped_time_it (const char *what, bool enabled)
+ : m_enabled (enabled),
m_what (what),
m_start_wall (m_enabled
? std::chrono::steady_clock::now ()
@@ -1279,9 +1300,7 @@ Selftests have been disabled for this build.\n"));
}
-void _initialize_maint_cmds ();
-void
-_initialize_maint_cmds ()
+INIT_GDB_FILE (maint_cmds)
{
struct cmd_list_element *cmd;
@@ -1423,7 +1442,7 @@ Show whether to display per-command execution time."),
_("\
If enabled, the execution time for each command will be\n\
displayed following the command's output."),
- NULL, NULL,
+ maintenance_set_command_time_cmd, NULL,
&per_command_setlist, &per_command_showlist);
add_setshow_boolean_cmd ("space", class_maintenance,
diff --git a/gdb/maint.h b/gdb/maint.h
index 28e6280..6930018 100644
--- a/gdb/maint.h
+++ b/gdb/maint.h
@@ -61,7 +61,9 @@ class scoped_command_stats
bool m_symtab_enabled : 1;
run_time_clock::time_point m_start_cpu_time;
std::chrono::steady_clock::time_point m_start_wall_time;
+#ifdef HAVE_USEFUL_SBRK
long m_start_space;
+#endif
/* Total number of symtabs (over all objfiles). */
int m_start_nr_symtabs;
/* A count of the compunits. */
@@ -70,13 +72,17 @@ class scoped_command_stats
int m_start_nr_blocks;
};
+/* If true, display time usage both at startup and for each command. */
+
+extern bool per_command_time;
+
/* RAII structure used to measure the time spent by the current thread in a
given scope. */
struct scoped_time_it
{
/* WHAT is the prefix to show when the summary line is printed. */
- scoped_time_it (const char *what);
+ scoped_time_it (const char *what, bool enabled = per_command_time);
DISABLE_COPY_AND_ASSIGN (scoped_time_it);
~scoped_time_it ();
diff --git a/gdb/make-init-c b/gdb/make-init-c
index 4f0185c..6834b43 100755
--- a/gdb/make-init-c
+++ b/gdb/make-init-c
@@ -25,12 +25,13 @@
#
# Where SOURCE-FILES is the list of source files to extract init functions from.
#
-# Formatting conventions: The name of the initialization routines must begin
-# with `_initialize_`, must start in column zero, and be followed with exactly
-# ` ()`. For example:
+
+# An initialization function is introduced using the "INIT_GDB_FILE"
+# macro. In ordinary code this expands to a function declaration (to
+# avoid a warning) and then the start of a definition. In the
+# generated init.c, though, it is expanded differently. For example:
#
-# void
-# _initialize_foo ()
+# INIT_GDB_FILE (foo)
# {
# ...
# }
@@ -43,19 +44,21 @@ echo "/* Do not modify this file. */"
echo "/* It is created automatically by the Makefile. */"
echo "#include <algorithm>"
echo ""
-sed -n -e 's/^\(_initialize_[a-zA-Z0-9_]*\) ()$/\1/p' "$@" | while read -r name; do
- echo "extern initialize_file_ftype $name;"
-done
+echo "#undef INIT_GDB_FILE"
+echo "#define INIT_GDB_FILE(NAME) extern void _initialize_ ## NAME ();"
+grep -h '^[ ]*INIT_GDB_FILE\b' "$@"
echo ""
echo "void initialize_all_files ();"
echo "void"
echo "initialize_all_files ()"
echo "{"
+echo " typedef void initialize_file_ftype (void);"
+echo ""
echo " std::vector<initialize_file_ftype *> functions ="
echo " {"
-sed -n -e 's/^\(_initialize_[a-zA-Z0-9_]*\) ()$/\1/p' "$@" | while read -r name; do
- echo " $name,"
-done
+echo "#undef INIT_GDB_FILE"
+echo "#define INIT_GDB_FILE(NAME) _initialize_ ## NAME,"
+grep -h '^[ ]*INIT_GDB_FILE\b' "$@"
echo " };"
echo ""
echo " /* If GDB_REVERSE_INIT_FUNCTIONS is set (any value), reverse the"
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index 72af117..a7d26c3 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -248,7 +248,7 @@ static struct type *parse_type (int, union aux_ext *, unsigned int, int *,
int, const char *);
static struct symbol *mylookup_symbol (const char *, const struct block *,
- domain_enum, enum address_class);
+ domain_enum, location_class);
static void sort_blocks (struct symtab *);
@@ -329,7 +329,7 @@ fdr_name (FDR *f)
/* Read in and parse the symtab of the file OBJFILE. Symbols from
different sections are relocated via the SECTION_OFFSETS. */
-void
+static void
mdebug_build_psymtabs (minimal_symbol_reader &reader,
struct objfile *objfile,
const struct ecoff_debug_swap *swap,
@@ -550,7 +550,7 @@ static const struct symbol_register_ops mdebug_register_funcs = {
mdebug_reg_to_regnum
};
-/* The "aclass" indices for computed symbols. */
+/* The "loc_class" indices for computed symbols. */
static int mdebug_register_index;
static int mdebug_regparm_index;
@@ -559,11 +559,11 @@ static int mdebug_regparm_index;
static void
add_data_symbol (SYMR *sh, union aux_ext *ax, int bigend,
- struct symbol *s, int aclass_index, struct block *b,
+ struct symbol *s, int loc_class_index, struct block *b,
struct objfile *objfile, const char *name)
{
s->set_domain (VAR_DOMAIN);
- s->set_aclass_index (aclass_index);
+ s->set_loc_class_index (loc_class_index);
add_symbol (s, top_stack->cur_st, b);
/* Type could be missing if file is compiled without debugging info. */
@@ -688,19 +688,19 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
{
case scRegister:
/* Pass by value in register. */
- s->set_aclass_index (mdebug_register_index);
+ s->set_loc_class_index (mdebug_register_index);
break;
case scVar:
/* Pass by reference on stack. */
- s->set_aclass_index (LOC_REF_ARG);
+ s->set_loc_class_index (LOC_REF_ARG);
break;
case scVarRegister:
/* Pass by reference in register. */
- s->set_aclass_index (mdebug_regparm_index);
+ s->set_loc_class_index (mdebug_regparm_index);
break;
default:
/* Pass by value on stack. */
- s->set_aclass_index (LOC_ARG);
+ s->set_loc_class_index (LOC_ARG);
break;
}
s->set_value_longest (svalue);
@@ -711,7 +711,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
case stLabel: /* label, goes into current block. */
s = new_symbol (name);
s->set_domain (LABEL_DOMAIN); /* So that it can be used */
- s->set_aclass_index (LOC_LABEL); /* but not misused. */
+ s->set_loc_class_index (LOC_LABEL); /* but not misused. */
s->set_section_index (section_index);
s->set_value_address (sh->value);
s->set_type (builtin_type (objfile)->builtin_int);
@@ -753,7 +753,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
}
s = new_symbol (name);
s->set_domain (FUNCTION_DOMAIN);
- s->set_aclass_index (LOC_BLOCK);
+ s->set_loc_class_index (LOC_BLOCK);
s->set_section_index (section_index);
/* Type of the return value. */
if (SC_IS_UNDEF (sh->sc) || sh->sc == scNil)
@@ -1034,7 +1034,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
t->set_code (type_code);
t->set_length (sh->value);
t->alloc_fields (nfields);
- f = t->fields();
+ f = t->fields ().data ();
if (type_code == TYPE_CODE_ENUM)
{
@@ -1074,7 +1074,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
enum_sym->set_linkage_name
(obstack_strdup (&mdebugread_objfile->objfile_obstack,
f->name ()));
- enum_sym->set_aclass_index (LOC_CONST);
+ enum_sym->set_loc_class_index (LOC_CONST);
enum_sym->set_type (t);
enum_sym->set_domain (VAR_DOMAIN);
enum_sym->set_value_longest (tsym.value);
@@ -1107,7 +1107,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
s = new_symbol (name);
s->set_domain (STRUCT_DOMAIN);
- s->set_aclass_index (LOC_TYPEDEF);
+ s->set_loc_class_index (LOC_TYPEDEF);
s->set_value_longest (0);
s->set_type (t);
add_symbol (s, top_stack->cur_st, top_stack->cur_block);
@@ -1164,7 +1164,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
/* Make up special symbol to contain procedure specific info. */
s = new_symbol (MDEBUG_EFI_SYMBOL_NAME);
s->set_domain (LABEL_DOMAIN);
- s->set_aclass_index (LOC_CONST);
+ s->set_loc_class_index (LOC_CONST);
s->set_type (builtin_type (mdebugread_objfile)->builtin_void);
e = OBSTACK_ZALLOC (&mdebugread_objfile->objfile_obstack,
mdebug_extra_func_info);
@@ -1297,7 +1297,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
break;
s = new_symbol (name);
s->set_domain (TYPE_DOMAIN);
- s->set_aclass_index (LOC_TYPEDEF);
+ s->set_loc_class_index (LOC_TYPEDEF);
s->set_value_block (top_stack->cur_block);
s->set_type (t);
add_symbol (s, top_stack->cur_st, top_stack->cur_block);
@@ -3369,7 +3369,7 @@ parse_partial_symbols (minimal_symbol_reader &reader,
for (cur_sdx = 0; cur_sdx < fh->csym;)
{
char *sym_name;
- enum address_class theclass;
+ location_class loc_class;
unrelocated_addr minsym_value;
int section = -1;
@@ -3526,7 +3526,7 @@ parse_partial_symbols (minimal_symbol_reader &reader,
reader.record_with_info (sym_name, minsym_value,
mst_file_bss,
SECT_OFF_BSS (objfile));
- theclass = LOC_STATIC;
+ loc_class = LOC_STATIC;
break;
case stIndirect: /* Irix5 forward declaration */
@@ -3538,11 +3538,11 @@ parse_partial_symbols (minimal_symbol_reader &reader,
structs from alpha and mips cc. */
if (sh.iss == 0 || has_opaque_xref (fh, &sh))
goto skip;
- theclass = LOC_TYPEDEF;
+ loc_class = LOC_TYPEDEF;
break;
case stConstant: /* Constant decl */
- theclass = LOC_CONST;
+ loc_class = LOC_CONST;
break;
case stUnion:
@@ -3600,7 +3600,7 @@ parse_partial_symbols (minimal_symbol_reader &reader,
}
/* Use this gdb symbol. */
pst->add_psymbol (sym_name, true,
- VAR_DOMAIN, theclass, section,
+ VAR_DOMAIN, loc_class, section,
psymbol_placement::STATIC,
unrelocated_addr (sh.value),
psymtab_language,
@@ -3616,7 +3616,7 @@ parse_partial_symbols (minimal_symbol_reader &reader,
PST_PRIVATE (save_pst)->extern_tab = ext_ptr;
for (; --cur_sdx >= 0; ext_ptr++)
{
- enum address_class theclass;
+ location_class loc_class;
SYMR *psh;
CORE_ADDR svalue;
int section;
@@ -3663,7 +3663,7 @@ parse_partial_symbols (minimal_symbol_reader &reader,
Ignore them, as parse_external will ignore them too. */
continue;
case stLabel:
- theclass = LOC_LABEL;
+ loc_class = LOC_LABEL;
break;
default:
unknown_ext_complaint (debug_info->ssext + psh->iss);
@@ -3675,12 +3675,12 @@ parse_partial_symbols (minimal_symbol_reader &reader,
if (SC_IS_COMMON (psh->sc))
continue;
- theclass = LOC_STATIC;
+ loc_class = LOC_STATIC;
break;
}
char *sym_name = debug_info->ssext + psh->iss;
pst->add_psymbol (sym_name, true,
- VAR_DOMAIN, theclass,
+ VAR_DOMAIN, loc_class,
section,
psymbol_placement::GLOBAL,
unrelocated_addr (svalue),
@@ -3991,7 +3991,7 @@ mdebug_expand_psymtab (legacy_psymtab *pst, struct objfile *objfile)
struct symbol *s = new_symbol (MDEBUG_EFI_SYMBOL_NAME);
s->set_domain (LABEL_DOMAIN);
- s->set_aclass_index (LOC_CONST);
+ s->set_loc_class_index (LOC_CONST);
s->set_type (builtin_type (objfile)->builtin_void);
s->set_value_bytes ((gdb_byte *) e);
e->pdr.framereg = -1;
@@ -4464,7 +4464,7 @@ cross_ref (int fd, union aux_ext *ax, struct type **tpp,
static struct symbol *
mylookup_symbol (const char *name, const struct block *block,
- domain_enum domain, enum address_class theclass)
+ domain_enum domain, location_class loc_class)
{
int inc;
@@ -4473,14 +4473,14 @@ mylookup_symbol (const char *name, const struct block *block,
{
if (sym->linkage_name ()[0] == inc
&& sym->domain () == domain
- && sym->aclass () == theclass
+ && sym->loc_class () == loc_class
&& strcmp (sym->linkage_name (), name) == 0)
return sym;
}
block = block->superblock ();
if (block)
- return mylookup_symbol (name, block, domain, theclass);
+ return mylookup_symbol (name, block, domain, loc_class);
return 0;
}
@@ -4792,9 +4792,28 @@ elfmdebug_build_psymtabs (struct objfile *objfile,
reader.install ();
}
-void _initialize_mdebugread ();
+/* see mdebugread.h. */
+
void
-_initialize_mdebugread ()
+mipsmdebug_build_psymtabs (struct objfile *objfile,
+ const struct ecoff_debug_swap *swap,
+ struct ecoff_debug_info *info)
+{
+ bfd *abfd = objfile->obfd.get ();
+
+ minimal_symbol_reader reader (objfile);
+
+ if (!(*swap->read_debug_info) (abfd, nullptr,
+ info))
+ error (_("Error reading ECOFF debugging information: %s"),
+ bfd_errmsg (bfd_get_error ()));
+
+ mdebug_build_psymtabs (reader, objfile, swap, info);
+
+ reader.install ();
+}
+
+INIT_GDB_FILE (mdebugread)
{
mdebug_register_index
= register_symbol_register_impl (LOC_REGISTER, &mdebug_register_funcs);
diff --git a/gdb/mdebugread.h b/gdb/mdebugread.h
index be26f46..f7e9f98 100644
--- a/gdb/mdebugread.h
+++ b/gdb/mdebugread.h
@@ -37,13 +37,38 @@ struct mdebug_extra_func_info
#define MDEBUG_EFI_SYMBOL_NAME "__GDB_EFI_INFO__"
-extern void mdebug_build_psymtabs (minimal_symbol_reader &,
- struct objfile *,
- const struct ecoff_debug_swap *,
- struct ecoff_debug_info *);
+#if defined(MDEBUG_FORMAT_AVAILABLE)
extern void elfmdebug_build_psymtabs (struct objfile *,
const struct ecoff_debug_swap *,
asection *);
+/* Read ECOFF debugging information from a BFD section. This is
+ called from mipsread.c. It parses the section into a
+ ecoff_debug_info struct, and then lets the rest of the file handle
+ it as normal. */
+extern void mipsmdebug_build_psymtabs (struct objfile *,
+ const struct ecoff_debug_swap *,
+ struct ecoff_debug_info *);
+
+#else /* MDEBUG_FORMAT_AVAILABLE */
+
+static inline void
+elfmdebug_build_psymtabs (struct objfile *,
+ const struct ecoff_debug_swap *,
+ asection *)
+{
+ warning (_("No mdebug support available"));
+}
+
+static inline void
+mipsmdebug_build_psymtabs (struct objfile *,
+ const struct ecoff_debug_swap *,
+ struct ecoff_debug_info *)
+{
+ warning (_("No mdebug support available"));
+}
+
+#endif /* MDEBUG_FORMAT_AVAILABLE */
+
#endif /* GDB_MDEBUGREAD_H */
diff --git a/gdb/memattr.c b/gdb/memattr.c
index 81d0de0..9d26d31 100644
--- a/gdb/memattr.c
+++ b/gdb/memattr.c
@@ -592,9 +592,7 @@ delete_mem_command (const char *args, int from_tty)
static struct cmd_list_element *mem_set_cmdlist;
static struct cmd_list_element *mem_show_cmdlist;
-void _initialize_mem ();
-void
-_initialize_mem ()
+INIT_GDB_FILE (mem)
{
add_com ("mem", class_vars, mem_command, _("\
Define or reset attributes for memory regions.\n\
diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c
index 60bae3a..30a6018 100644
--- a/gdb/mep-tdep.c
+++ b/gdb/mep-tdep.c
@@ -2459,9 +2459,7 @@ mep_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_mep_tdep ();
-void
-_initialize_mep_tdep ()
+INIT_GDB_FILE (mep_tdep)
{
mep_csr_reggroup = reggroup_new ("csr", USER_REGGROUP);
mep_cr_reggroup = reggroup_new ("cr", USER_REGGROUP);
diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c
index e4cb2e7..1cb8435 100644
--- a/gdb/mi/mi-cmd-break.c
+++ b/gdb/mi/mi-cmd-break.c
@@ -28,7 +28,6 @@
#include "language.h"
#include "location.h"
#include "linespec.h"
-#include <ctype.h>
#include "tracepoint.h"
enum
@@ -133,7 +132,7 @@ mi_argv_to_format (const char *const *argv, int argc)
result += "\\\"";
break;
default:
- if (isprint (argv[0][i]))
+ if (c_isprint (argv[0][i]))
result += argv[0][i];
else
{
diff --git a/gdb/mi/mi-cmd-env.c b/gdb/mi/mi-cmd-env.c
index e79af9c..bc2fe77 100644
--- a/gdb/mi/mi-cmd-env.c
+++ b/gdb/mi/mi-cmd-env.c
@@ -236,9 +236,7 @@ mi_cmd_inferior_tty_show (const char *command, const char *const *argv,
current_uiout->field_string ("inferior_tty_terminal", inferior_tty);
}
-void _initialize_mi_cmd_env ();
-void
-_initialize_mi_cmd_env ()
+INIT_GDB_FILE (mi_cmd_env)
{
const char *env;
diff --git a/gdb/mi/mi-cmd-file.c b/gdb/mi/mi-cmd-file.c
index 2354012..cf7991f 100644
--- a/gdb/mi/mi-cmd-file.c
+++ b/gdb/mi/mi-cmd-file.c
@@ -25,7 +25,6 @@
#include "symtab.h"
#include "source.h"
#include "solib.h"
-#include "solist.h"
/* Return to the client the absolute path and line number of the
current file being executed. */
@@ -163,10 +162,10 @@ mi_cmd_file_list_shared_libraries (const char *command,
for (const solib &so : current_program_space->solibs ())
{
- if (so.so_name.empty ())
+ if (so.name.empty ())
continue;
- if (pattern != nullptr && !re_exec (so.so_name.c_str ()))
+ if (pattern != nullptr && !re_exec (so.name.c_str ()))
continue;
ui_out_emit_tuple tuple_emitter (uiout, NULL);
diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index cc26747..52ae11b 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -29,10 +29,8 @@
#include "valprint.h"
#include "mi-getopt.h"
#include "extension.h"
-#include <ctype.h>
#include "mi-parse.h"
#include <optional>
-#include "gdbsupport/gdb-safe-ctype.h"
#include "inferior.h"
enum what_to_list { locals, arguments, all };
@@ -604,7 +602,7 @@ list_args_or_locals (const frame_print_options &fp_opts,
{
int print_me = 0;
- switch (sym->aclass ())
+ switch (sym->loc_class ())
{
default:
case LOC_UNDEF: /* catches errors */
diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c
index 9cbb857..09d6107 100644
--- a/gdb/mi/mi-cmd-var.c
+++ b/gdb/mi/mi-cmd-var.c
@@ -25,7 +25,6 @@
#include "varobj.h"
#include "language.h"
#include "value.h"
-#include <ctype.h>
#include "mi-getopt.h"
#include "gdbthread.h"
#include "mi-parse.h"
@@ -109,7 +108,7 @@ mi_cmd_var_create (const char *command, const char *const *argv, int argc)
gen_name = varobj_gen_name ();
name = gen_name.c_str ();
}
- else if (!isalpha (name[0]))
+ else if (!c_isalpha (name[0]))
error (_("-var-create: name of object must begin with a letter"));
if (strcmp (frame, "*") == 0)
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index 53cdcc9..abd3fb9 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -369,9 +369,7 @@ mi_cmd_lookup (const char *command)
return it->second.get ();
}
-void _initialize_mi_cmds ();
-void
-_initialize_mi_cmds ()
+INIT_GDB_FILE (mi_cmds)
{
add_builtin_mi_commands ();
}
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index ae1070e..8373e1a 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -34,7 +34,7 @@
#include "mi-common.h"
#include "observable.h"
#include "gdbthread.h"
-#include "solist.h"
+#include "solib.h"
#include "objfiles.h"
#include "tracepoint.h"
#include "cli-out.h"
@@ -726,9 +726,9 @@ mi_output_solib_attribs_1 (ui_out *uiout, const solib &solib,
{
gdbarch *gdbarch = current_inferior ()->arch ();
- uiout->field_string ("id", solib.so_original_name);
- uiout->field_string ("target-name", solib.so_original_name);
- uiout->field_string ("host-name", solib.so_name);
+ uiout->field_string ("id", solib.original_name);
+ uiout->field_string ("target-name", solib.original_name);
+ uiout->field_string ("host-name", solib.name);
if (include_symbols_loaded_p)
uiout->field_signed ("symbols-loaded", solib.symbols_loaded);
if (!gdbarch_has_global_solist (current_inferior ()->arch ()))
@@ -935,9 +935,7 @@ mi_interp_factory (const char *name)
return new mi_interp (name);
}
-void _initialize_mi_interp ();
-void
-_initialize_mi_interp ()
+INIT_GDB_FILE (mi_interp)
{
/* The various interpreter levels. */
interp_factory_register (INTERP_MI2, mi_interp_factory);
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index cda72ca..bcc32f9 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -52,7 +52,6 @@
#include <optional>
#include "gdbsupport/byte-vector.h"
-#include <ctype.h>
#include "gdbsupport/run-time-clock.h"
#include <chrono>
#include "progspace-and-thread.h"
@@ -2768,9 +2767,7 @@ mi_parse_thread_group_id (const char *id)
return (int) num;
}
-void _initialize_mi_main ();
-void
-_initialize_mi_main ()
+INIT_GDB_FILE (mi_main)
{
set_show_commands mi_async_cmds
= add_setshow_boolean_cmd ("mi-async", class_run,
diff --git a/gdb/mi/mi-parse.c b/gdb/mi/mi-parse.c
index 0af90cb..58bdf4a 100644
--- a/gdb/mi/mi-parse.c
+++ b/gdb/mi/mi-parse.c
@@ -22,7 +22,6 @@
#include "mi-cmds.h"
#include "mi-parse.h"
-#include <ctype.h>
#include "cli/cli-utils.h"
#include "language.h"
@@ -61,7 +60,7 @@ mi_parse_escape (const char **string_ptr)
while (++count < 3)
{
c = (**string_ptr);
- if (isdigit (c) && c != '8' && c != '9')
+ if (c_isdigit (c) && c != '8' && c != '9')
{
(*string_ptr)++;
i *= 8;
@@ -162,7 +161,7 @@ mi_parse::parse_argv ()
return;
}
/* Insist on trailing white space. */
- if (chp[1] != '\0' && !isspace (chp[1]))
+ if (chp[1] != '\0' && !c_isspace (chp[1]))
{
freeargv (argv);
return;
@@ -193,7 +192,7 @@ mi_parse::parse_argv ()
int len;
const char *start = chp;
- while (*chp != '\0' && !isspace (*chp))
+ while (*chp != '\0' && !c_isspace (*chp))
{
chp++;
}
@@ -313,7 +312,7 @@ mi_parse::mi_parse (const char *cmd, std::string *token)
{
const char *tmp = chp + 1; /* discard ``-'' */
- for (; *chp && !isspace (*chp); chp++)
+ for (; *chp && !c_isspace (*chp); chp++)
;
this->command = make_unique_xstrndup (tmp, chp - tmp);
}
@@ -391,7 +390,7 @@ mi_parse::mi_parse (const char *cmd, std::string *token)
else
break;
- if (*chp != '\0' && !isspace (*chp))
+ if (*chp != '\0' && !c_isspace (*chp))
error (_("Invalid value for the '%s' option"), option);
chp = skip_spaces (chp);
}
diff --git a/gdb/microblaze-linux-tdep.c b/gdb/microblaze-linux-tdep.c
index 8dcbeaa..0fdda18 100644
--- a/gdb/microblaze-linux-tdep.c
+++ b/gdb/microblaze-linux-tdep.c
@@ -35,6 +35,7 @@
#include "frame-unwind.h"
#include "tramp-frame.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
static int
microblaze_linux_memory_remove_breakpoint (struct gdbarch *gdbarch,
@@ -125,17 +126,14 @@ microblaze_linux_init_abi (struct gdbarch_info info,
microblaze_linux_memory_remove_breakpoint);
/* Shared library handling. */
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
/* Trampolines. */
tramp_frame_prepend_unwinder (gdbarch,
&microblaze_linux_sighandler_tramp_frame);
}
-void _initialize_microblaze_linux_tdep ();
-void
-_initialize_microblaze_linux_tdep ()
+INIT_GDB_FILE (microblaze_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_microblaze, 0, GDB_OSABI_LINUX,
microblaze_linux_init_abi);
diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c
index bc728b6..404e4cd 100644
--- a/gdb/microblaze-tdep.c
+++ b/gdb/microblaze-tdep.c
@@ -590,6 +590,98 @@ microblaze_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type)
return (type->length () == 16);
}
+/* Return next pc values : next in sequence and/or branch/return target. */
+
+static std::vector<CORE_ADDR>
+microblaze_get_next_pcs (regcache *regcache)
+{
+ CORE_ADDR pc = regcache_read_pc (regcache);
+ unsigned long insn = microblaze_fetch_instruction (pc);
+
+ enum microblaze_instr_type insn_type;
+ short delay_slots;
+ bool isunsignednum;
+
+ /* If the current instruction is an imm, look at the inst after. */
+
+ get_insn_microblaze (insn, &isunsignednum, &insn_type, &delay_slots);
+
+ int imm;
+ bool immfound = false;
+
+ if (insn_type == immediate_inst)
+ {
+ int rd, ra, rb;
+ immfound = true;
+ microblaze_decode_insn (insn, &rd, &ra, &rb, &imm);
+ pc += INST_WORD_SIZE;
+ insn = microblaze_fetch_instruction (pc);
+ get_insn_microblaze (insn, &isunsignednum, &insn_type, &delay_slots);
+ }
+
+ std::optional<CORE_ADDR> next_pc, branch_or_return_pc;
+
+ /* Compute next instruction address - skip delay slots if any. */
+
+ if (insn_type != return_inst)
+ next_pc = pc + INST_WORD_SIZE + (delay_slots * INST_WORD_SIZE);
+
+ microblaze_debug ("single-step insn_type=0x%x pc=%s insn=0x%lx",
+ insn_type, core_addr_to_string_nz (pc), insn);
+
+ /* Compute target instruction address for branch or return instruction. */
+ if (insn_type == branch_inst || insn_type == return_inst)
+ {
+ int limm;
+ int lrd, lra, lrb;
+ bool targetvalid;
+ bool unconditionalbranch;
+
+ microblaze_decode_insn (insn, &lrd, &lra, &lrb, &limm);
+
+ ULONGEST ra = regcache_raw_get_unsigned (regcache, lra);
+ ULONGEST rb = regcache_raw_get_unsigned (regcache, lrb);
+
+ branch_or_return_pc
+ = microblaze_get_target_address (insn, immfound,
+ imm, pc, ra, rb, &targetvalid,
+ &unconditionalbranch);
+
+ microblaze_debug ("single-step uncondbr=%d targetvalid=%d target=%s",
+ unconditionalbranch, targetvalid,
+ core_addr_to_string_nz (*branch_or_return_pc));
+
+ /* Can't reach next address. */
+ if (unconditionalbranch)
+ next_pc.reset ();
+
+ /* Can't reach a distinct (not here) target address. */
+ if (!targetvalid
+ || branch_or_return_pc == pc
+ || (next_pc.has_value () && (branch_or_return_pc == next_pc)))
+ branch_or_return_pc.reset ();
+ } /* if (branch or return instruction). */
+
+ /* Create next_pcs vector to return. */
+
+ std::vector<CORE_ADDR> next_pcs;
+
+ if (next_pc.has_value ())
+ {
+ next_pcs.push_back (*next_pc);
+ microblaze_debug ("push_back next_pc(%s)",
+ core_addr_to_string_nz (*next_pc));
+ }
+
+ if (branch_or_return_pc.has_value ())
+ {
+ next_pcs.push_back (*branch_or_return_pc);
+ microblaze_debug ("push_back branch_or_return_pc(%s)",
+ core_addr_to_string_nz (*branch_or_return_pc));
+ }
+
+ return next_pcs;
+}
static int dwarf2_to_reg_map[78] =
{ 0 /* r0 */, 1 /* r1 */, 2 /* r2 */, 3 /* r3 */, /* 0- 3 */
@@ -715,6 +807,8 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_sw_breakpoint_from_kind (gdbarch,
microblaze_breakpoint::bp_from_kind);
+ set_gdbarch_get_next_pcs (gdbarch, microblaze_get_next_pcs);
+
set_gdbarch_frame_args_skip (gdbarch, 8);
set_gdbarch_unwind_pc (gdbarch, microblaze_unwind_pc);
@@ -736,9 +830,7 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_microblaze_tdep ();
-void
-_initialize_microblaze_tdep ()
+INIT_GDB_FILE (microblaze_tdep)
{
gdbarch_register (bfd_arch_microblaze, microblaze_gdbarch_init);
diff --git a/gdb/microblaze-tdep.h b/gdb/microblaze-tdep.h
index b2fb5e7..852c9eb 100644
--- a/gdb/microblaze-tdep.h
+++ b/gdb/microblaze-tdep.h
@@ -118,6 +118,6 @@ struct microblaze_frame_cache
/* MICROBLAZE_BREAKPOINT defines the breakpoint that should be used.
Only used for native debugging. */
-#define MICROBLAZE_BREAKPOINT {0xb9, 0xcc, 0x00, 0x60}
+#define MICROBLAZE_BREAKPOINT {0xba, 0x0c, 0x00, 0x18}
#endif /* GDB_MICROBLAZE_TDEP_H */
diff --git a/gdb/mingw-hdep.c b/gdb/mingw-hdep.c
index dc7ca42..a4e9cf5 100644
--- a/gdb/mingw-hdep.c
+++ b/gdb/mingw-hdep.c
@@ -22,6 +22,9 @@
#include "gdbsupport/event-loop.h"
#include "gdbsupport/gdb_select.h"
#include "inferior.h"
+#include "cli/cli-style.h"
+#include "command.h"
+#include "cli/cli-cmds.h"
#include <windows.h>
#include <signal.h>
@@ -212,7 +215,30 @@ static int mingw_console_initialized;
static HANDLE hstdout = INVALID_HANDLE_VALUE;
/* Text attribute to use for normal text (the "none" pseudo-color). */
-static SHORT norm_attr;
+static SHORT norm_attr;
+
+/* Initialize settings related to the console. */
+
+void
+windows_initialize_console ()
+{
+ hstdout = (HANDLE)_get_osfhandle (fileno (stdout));
+ DWORD cmode;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+ if (hstdout != INVALID_HANDLE_VALUE
+ && GetConsoleMode (hstdout, &cmode) != 0
+ && GetConsoleScreenBufferInfo (hstdout, &csbi))
+ {
+ norm_attr = csbi.wAttributes;
+ mingw_console_initialized = 1;
+ }
+ else if (hstdout != INVALID_HANDLE_VALUE)
+ mingw_console_initialized = -1; /* valid, but not a console device */
+
+ if (mingw_console_initialized > 0)
+ no_emojis ();
+}
/* The most recently applied style. */
static ui_file_style last_style;
@@ -223,22 +249,6 @@ static ui_file_style last_style;
int
gdb_console_fputs (const char *linebuf, FILE *fstream)
{
- if (!mingw_console_initialized)
- {
- hstdout = (HANDLE)_get_osfhandle (fileno (fstream));
- DWORD cmode;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
-
- if (hstdout != INVALID_HANDLE_VALUE
- && GetConsoleMode (hstdout, &cmode) != 0
- && GetConsoleScreenBufferInfo (hstdout, &csbi))
- {
- norm_attr = csbi.wAttributes;
- mingw_console_initialized = 1;
- }
- else if (hstdout != INVALID_HANDLE_VALUE)
- mingw_console_initialized = -1; /* valid, but not a console device */
- }
/* If our stdout is not a console device, let the default 'fputs'
handle the task. */
if (mingw_console_initialized <= 0)
@@ -437,3 +447,62 @@ install_sigint_handler (c_c_handler_ftype *fn)
current_handler = fn;
return result;
}
+
+/* Set stdout and stderr handles to translation mode MODE. */
+
+static void
+set_console_translation_mode (int mode)
+{
+ setmode (fileno (stdout), mode);
+ setmode (fileno (stderr), mode);
+}
+
+/* Arg in "maint set console-translation-mode <arg>. */
+
+static std::string maint_console_translation_mode;
+
+/* Current value of "maint set/show console-translation-mode". */
+
+static std::string console_translation_mode = "unknown";
+
+/* Sets the console translation mode. */
+
+static void
+set_maint_console_translation_mode (const char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ if (maint_console_translation_mode == "binary")
+ set_console_translation_mode (O_BINARY);
+ else if (maint_console_translation_mode == "text")
+ set_console_translation_mode (O_TEXT);
+ else
+ error (_("Invalid console translation mode: %s"),
+ maint_console_translation_mode.c_str ());
+
+ console_translation_mode = maint_console_translation_mode;
+}
+
+/* Shows the console translation mode. */
+
+static void
+show_maint_console_translation_mode (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ gdb_printf (file, _("Console translation mode is %s.\n"),
+ console_translation_mode.c_str ());
+}
+
+INIT_GDB_FILE (mingw_hdep)
+{
+ add_setshow_string_cmd ("console-translation-mode",
+ class_maintenance,
+ &maint_console_translation_mode, _("\
+Set the translation mode of stdout/stderr."), _("\
+Show the translation mode of stdout/stderr."), _("\
+Use \"binary\", or \"text\""),
+ set_maint_console_translation_mode,
+ show_maint_console_translation_mode,
+ &maintenance_set_cmdlist,
+ &maintenance_show_cmdlist);
+}
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index 124d96d..c4a0fa8 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -36,7 +36,6 @@
to figure out what full symbol table entries need to be read in. */
-#include <ctype.h>
#include "maint.h"
#include "symtab.h"
#include "bfd.h"
@@ -52,7 +51,6 @@
#include "cli/cli-utils.h"
#include "gdbsupport/symbol.h"
#include <algorithm>
-#include "gdbsupport/gdb-safe-ctype.h"
#include "gdbsupport/parallel-for.h"
#include "inferior.h"
@@ -712,11 +710,11 @@ static int
frob_address (struct objfile *objfile, CORE_ADDR pc,
unrelocated_addr *unrel_addr)
{
- for (obj_section *iter : objfile->sections ())
+ for (obj_section &iter : objfile->sections ())
{
- if (iter->contains (pc))
+ if (iter.contains (pc))
{
- *unrel_addr = unrelocated_addr (pc - iter->offset ());
+ *unrel_addr = unrelocated_addr (pc - iter.offset ());
return 1;
}
}
@@ -1479,7 +1477,7 @@ minimal_symbol_reader::install ()
msymbols = m_objfile->per_bfd->msymbols.get ();
/* Arbitrarily require at least 10 elements in a thread. */
- gdb::parallel_for_each (10, &msymbols[0], &msymbols[mcount],
+ gdb::parallel_for_each<10> (&msymbols[0], &msymbols[mcount],
[&] (minimal_symbol *start, minimal_symbol *end)
{
scoped_time_it time_it ("minsyms install worker");
diff --git a/gdb/minsyms.h b/gdb/minsyms.h
index 709faa5..dcab475 100644
--- a/gdb/minsyms.h
+++ b/gdb/minsyms.h
@@ -195,7 +195,7 @@ unsigned int msymbol_hash_iw (const char *);
requirements. */
#define SYMBOL_HASH_NEXT(hash, c) \
- ((hash) * 67 + TOLOWER ((unsigned char) (c)) - 113)
+ ((hash) * 67 + c_tolower (c) - 113)
diff --git a/gdb/mips-fbsd-nat.c b/gdb/mips-fbsd-nat.c
index 667a4bc..8d97849 100644
--- a/gdb/mips-fbsd-nat.c
+++ b/gdb/mips-fbsd-nat.c
@@ -125,9 +125,7 @@ mips_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
}
}
-void _initialize_mips_fbsd_nat ();
-void
-_initialize_mips_fbsd_nat ()
+INIT_GDB_FILE (mips_fbsd_nat)
{
add_inf_child_target (&the_mips_fbsd_nat_target);
}
diff --git a/gdb/mips-fbsd-tdep.c b/gdb/mips-fbsd-tdep.c
index c280527..dc549b5 100644
--- a/gdb/mips-fbsd-tdep.c
+++ b/gdb/mips-fbsd-tdep.c
@@ -476,12 +476,30 @@ mips_fbsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
return fbsd_skip_solib_resolver (gdbarch, pc);
}
-/* FreeBSD/mips uses a slightly different `struct link_map' than the
- other FreeBSD platforms as it includes an additional `l_off'
- member. */
+/* solib_ops for ILP32 FreeBSD/MIPS systems. */
-static struct link_map_offsets *
-mips_fbsd_ilp32_fetch_link_map_offsets (void)
+struct mips_fbsd_ilp32_solib_ops : public svr4_solib_ops
+{
+ using svr4_solib_ops::svr4_solib_ops;
+
+ /* FreeBSD/MIPS uses a slightly different `struct link_map' than the
+ other FreeBSD platforms as it includes an additional `l_off' member. */
+
+ link_map_offsets *fetch_link_map_offsets () const override;
+};
+
+/* Return a new solib_ops for ILP32 FreeBSD/MIPS systems. */
+
+static solib_ops_up
+make_mips_fbsd_ilp32_solib_ops (program_space *pspace)
+{
+ return std::make_unique<mips_fbsd_ilp32_solib_ops> (pspace);
+}
+
+/* See mips_fbsd_ilp32_solib_ops. */
+
+link_map_offsets *
+mips_fbsd_ilp32_solib_ops::fetch_link_map_offsets () const
{
static struct link_map_offsets lmo;
static struct link_map_offsets *lmp = NULL;
@@ -508,8 +526,30 @@ mips_fbsd_ilp32_fetch_link_map_offsets (void)
return lmp;
}
-static struct link_map_offsets *
-mips_fbsd_lp64_fetch_link_map_offsets (void)
+/* solib_ops for LP64 FreeBSD/MIPS systems. */
+
+struct mips_fbsd_lp64_solib_ops : public svr4_solib_ops
+{
+ using svr4_solib_ops::svr4_solib_ops;
+
+ /* FreeBSD/MIPS uses a slightly different `struct link_map' than the
+ other FreeBSD platforms as it includes an additional `l_off' member. */
+
+ link_map_offsets *fetch_link_map_offsets () const override;
+};
+
+/* Return a new solib_ops for LP64 FreeBSD/MIPS systems. */
+
+static solib_ops_up
+make_mips_fbsd_lp64_solib_ops (program_space *pspace)
+{
+ return std::make_unique<mips_fbsd_lp64_solib_ops> (pspace);
+}
+
+/* See mips_fbsd_lp64_solib_ops. */
+
+link_map_offsets *
+mips_fbsd_lp64_solib_ops::fetch_link_map_offsets () const
{
static struct link_map_offsets lmo;
static struct link_map_offsets *lmp = NULL;
@@ -544,7 +584,7 @@ mips_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Generic FreeBSD support. */
fbsd_init_abi (info, gdbarch);
- set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, mips_software_single_step);
switch (abi)
{
@@ -565,15 +605,12 @@ mips_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_skip_solib_resolver (gdbarch, mips_fbsd_skip_solib_resolver);
/* FreeBSD/mips has SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ?
- mips_fbsd_ilp32_fetch_link_map_offsets :
- mips_fbsd_lp64_fetch_link_map_offsets));
+ set_solib_svr4_ops (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32
+ ? make_mips_fbsd_ilp32_solib_ops
+ : make_mips_fbsd_lp64_solib_ops));
}
-void _initialize_mips_fbsd_tdep ();
-void
-_initialize_mips_fbsd_tdep ()
+INIT_GDB_FILE (mips_fbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_FREEBSD,
mips_fbsd_init_abi);
diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c
index b4b5788..e22e904 100644
--- a/gdb/mips-linux-nat.c
+++ b/gdb/mips-linux-nat.c
@@ -784,9 +784,7 @@ mips_linux_nat_target::close ()
linux_nat_trad_target::close ();
}
-void _initialize_mips_linux_nat ();
-void
-_initialize_mips_linux_nat ()
+INIT_GDB_FILE (mips_linux_nat)
{
add_setshow_boolean_cmd ("show-debug-regs", class_maintenance,
&show_debug_regs, _("\
diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
index 418892b..b668bcb 100644
--- a/gdb/mips-linux-tdep.c
+++ b/gdb/mips-linux-tdep.c
@@ -30,13 +30,13 @@
#include "gdbtypes.h"
#include "objfiles.h"
#include "solib.h"
-#include "solist.h"
#include "symtab.h"
#include "target-descriptions.h"
#include "regset.h"
#include "mips-linux-tdep.h"
#include "glibc-tdep.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "xml-syscall.h"
#include "gdbsupport/gdb_signals.h"
#include "inferior.h"
@@ -46,8 +46,6 @@
#include "features/mips64-linux.c"
#include "features/mips64-dsp-linux.c"
-static solib_ops mips_svr4_so_ops;
-
/* This enum represents the signals' numbers on the MIPS
architecture. It just contains the signal definitions which are
different from the generic implementation.
@@ -667,24 +665,59 @@ mips_linux_in_dynsym_stub (CORE_ADDR pc)
return 1;
}
-/* Return non-zero iff PC belongs to the dynamic linker resolution
- code, a PLT entry, or a lazy binding stub. */
+/* Mix-in class to add Linux/MIPS-specific methods to a base solib_ops
+ class. */
-static int
-mips_linux_in_dynsym_resolve_code (CORE_ADDR pc)
+template <typename Base>
+struct mips_linux_svr4_solib_ops : public Base
+{
+ using Base::Base;
+
+ bool in_dynsym_resolve_code (CORE_ADDR pc) const override;
+};
+
+template <typename Base>
+bool
+mips_linux_svr4_solib_ops<Base>::in_dynsym_resolve_code (CORE_ADDR pc) const
{
/* Check whether PC is in the dynamic linker. This also checks
whether it is in the .plt section, used by non-PIC executables. */
- if (svr4_in_dynsym_resolve_code (pc))
- return 1;
+ if (Base::in_dynsym_resolve_code (pc))
+ return true;
/* Likewise for the stubs. They live in the .MIPS.stubs section these
days, so we check if the PC is within, than fall back to a pattern
match. */
if (mips_linux_in_dynsym_stub (pc))
- return 1;
+ return true;
+
+ return false;
+}
+
+/* solib_ops for ILP32 Linux/MIPS systems. */
+
+using mips_linux_ilp32_svr4_solib_ops
+ = mips_linux_svr4_solib_ops<linux_ilp32_svr4_solib_ops>;
- return 0;
+/* Return a new solib_ops for ILP32 Linux/MIPS systems. */
+
+static solib_ops_up
+make_mips_linux_ilp32_svr4_solib_ops (program_space *pspace)
+{
+ return std::make_unique<mips_linux_ilp32_svr4_solib_ops> (pspace);
+}
+
+/* solib_ops for LP64 Linux/MIPS systems. */
+
+using mips_linux_lp64_svr4_solib_ops
+ = mips_linux_svr4_solib_ops<linux_lp64_svr4_solib_ops>;
+
+/* Return a new solib_ops for LP64 Linux/MIPS systems. */
+
+static solib_ops_up
+make_mips_linux_lp64_svr4_solib_ops (program_space *pspace)
+{
+ return std::make_unique<mips_linux_lp64_svr4_solib_ops> (pspace);
}
/* See the comments for SKIP_SOLIB_RESOLVER at the top of infrun.c,
@@ -1538,8 +1571,7 @@ mips_linux_init_abi (struct gdbarch_info info,
case MIPS_ABI_O32:
set_gdbarch_get_longjmp_target (gdbarch,
mips_linux_get_longjmp_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_mips_linux_ilp32_svr4_solib_ops);
tramp_frame_prepend_unwinder (gdbarch, &micromips_linux_o32_sigframe);
tramp_frame_prepend_unwinder (gdbarch,
&micromips_linux_o32_rt_sigframe);
@@ -1550,8 +1582,7 @@ mips_linux_init_abi (struct gdbarch_info info,
case MIPS_ABI_N32:
set_gdbarch_get_longjmp_target (gdbarch,
mips_linux_get_longjmp_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_mips_linux_ilp32_svr4_solib_ops);
set_gdbarch_long_double_bit (gdbarch, 128);
set_gdbarch_long_double_format (gdbarch, floatformats_ieee_quad);
tramp_frame_prepend_unwinder (gdbarch,
@@ -1562,8 +1593,7 @@ mips_linux_init_abi (struct gdbarch_info info,
case MIPS_ABI_N64:
set_gdbarch_get_longjmp_target (gdbarch,
mips64_linux_get_longjmp_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_mips_linux_lp64_svr4_solib_ops);
set_gdbarch_long_double_bit (gdbarch, 128);
set_gdbarch_long_double_format (gdbarch, floatformats_ieee_quad);
tramp_frame_prepend_unwinder (gdbarch,
@@ -1577,22 +1607,12 @@ mips_linux_init_abi (struct gdbarch_info info,
set_gdbarch_skip_solib_resolver (gdbarch, mips_linux_skip_resolver);
- set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, mips_software_single_step);
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
- /* Initialize this lazily, to avoid an initialization order
- dependency on solib-svr4.c's _initialize routine. */
- if (mips_svr4_so_ops.in_dynsym_resolve_code == NULL)
- {
- mips_svr4_so_ops = svr4_so_ops;
- mips_svr4_so_ops.in_dynsym_resolve_code
- = mips_linux_in_dynsym_resolve_code;
- }
- set_gdbarch_so_ops (gdbarch, &mips_svr4_so_ops);
-
set_gdbarch_write_pc (gdbarch, mips_linux_write_pc);
set_gdbarch_core_read_description (gdbarch,
@@ -1629,9 +1649,7 @@ mips_linux_init_abi (struct gdbarch_info info,
}
}
-void _initialize_mips_linux_tdep ();
-void
-_initialize_mips_linux_tdep ()
+INIT_GDB_FILE (mips_linux_tdep)
{
const struct bfd_arch_info *arch_info;
diff --git a/gdb/mips-netbsd-nat.c b/gdb/mips-netbsd-nat.c
index 51e3878..91b870b 100644
--- a/gdb/mips-netbsd-nat.c
+++ b/gdb/mips-netbsd-nat.c
@@ -115,9 +115,7 @@ mips_nbsd_nat_target::store_registers (struct regcache *regcache, int regno)
}
}
-void _initialize_mipsnbsd_nat ();
-void
-_initialize_mipsnbsd_nat ()
+INIT_GDB_FILE (mipsnbsd_nat)
{
add_inf_child_target (&the_mips_nbsd_nat_target);
}
diff --git a/gdb/mips-netbsd-tdep.c b/gdb/mips-netbsd-tdep.c
index c9bdaa6..3c54c32 100644
--- a/gdb/mips-netbsd-tdep.c
+++ b/gdb/mips-netbsd-tdep.c
@@ -288,13 +288,29 @@ mipsnbsd_cannot_store_register (struct gdbarch *gdbarch, int regno)
|| regno == mips_regnum (gdbarch)->fp_implementation_revision);
}
-/* Shared library support. */
+/* solib_ops for ILP32 NetBSD/MIPS systems. */
-/* NetBSD/mips uses a slightly different `struct link_map' than the
- other NetBSD platforms. */
+struct mips_nbsd_ilp32_svr4_solib_ops : public svr4_solib_ops
+{
+ using svr4_solib_ops::svr4_solib_ops;
+
+ /* NetBSD/MIPS uses a slightly different `struct link_map' than the
+ other NetBSD platforms. */
+ link_map_offsets *fetch_link_map_offsets () const override;
+};
+
+/* Return a new solib_ops for ILP32 NetBSD/MIPS systems. */
+
+static solib_ops_up
+make_mips_nbsd_ilp32_svr4_solib_ops (program_space *pspace)
+{
+ return std::make_unique<mips_nbsd_ilp32_svr4_solib_ops> (pspace);
+}
+
+/* See mips_nbsd_ilp32_svr4_solib_ops. */
-static struct link_map_offsets *
-mipsnbsd_ilp32_fetch_link_map_offsets (void)
+link_map_offsets *
+mips_nbsd_ilp32_svr4_solib_ops::fetch_link_map_offsets () const
{
static struct link_map_offsets lmo;
static struct link_map_offsets *lmp = NULL;
@@ -322,8 +338,29 @@ mipsnbsd_ilp32_fetch_link_map_offsets (void)
return lmp;
}
-static struct link_map_offsets *
-mipsnbsd_lp64_fetch_link_map_offsets (void)
+/* solib_ops for LP64 NetBSD/MIPS systems. */
+
+struct mips_nbsd_lp64_svr4_solib_ops : public svr4_solib_ops
+{
+ using svr4_solib_ops::svr4_solib_ops;
+
+ /* NetBSD/MIPS uses a slightly different `struct link_map' than the
+ other NetBSD platforms. */
+ link_map_offsets *fetch_link_map_offsets () const override;
+};
+
+/* Return a new solib_ops for LP64 NetBSD/MIPS systems. */
+
+static solib_ops_up
+make_mips_nbsd_lp64_svr4_solib_ops (program_space *pspace)
+{
+ return std::make_unique<mips_nbsd_lp64_svr4_solib_ops> (pspace);
+}
+
+/* See mips_nbsd_lp64_svr4_solib_ops. */
+
+link_map_offsets *
+mips_nbsd_lp64_svr4_solib_ops::fetch_link_map_offsets () const
{
static struct link_map_offsets lmo;
static struct link_map_offsets *lmp = NULL;
@@ -366,18 +403,15 @@ mipsnbsd_init_abi (struct gdbarch_info info,
set_gdbarch_cannot_fetch_register (gdbarch, mipsnbsd_cannot_fetch_register);
set_gdbarch_cannot_store_register (gdbarch, mipsnbsd_cannot_store_register);
- set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, mips_software_single_step);
/* NetBSD/mips has SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ?
- mipsnbsd_ilp32_fetch_link_map_offsets :
- mipsnbsd_lp64_fetch_link_map_offsets));
+ set_solib_svr4_ops (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32
+ ? make_mips_nbsd_ilp32_svr4_solib_ops
+ : make_mips_nbsd_lp64_svr4_solib_ops));
}
-void _initialize_mipsnbsd_tdep ();
-void
-_initialize_mipsnbsd_tdep ()
+INIT_GDB_FILE (mipsnbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD,
mipsnbsd_init_abi);
diff --git a/gdb/mips-sde-tdep.c b/gdb/mips-sde-tdep.c
index 1f50ef0..5278afb 100644
--- a/gdb/mips-sde-tdep.c
+++ b/gdb/mips-sde-tdep.c
@@ -254,9 +254,7 @@ mips_sde_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
frame_base_append_sniffer (gdbarch, mips_sde_frame_base_sniffer);
}
-void _initialize_mips_sde_tdep ();
-void
-_initialize_mips_sde_tdep ()
+INIT_GDB_FILE (mips_sde_tdep)
{
gdbarch_register_osabi_sniffer (bfd_arch_mips,
bfd_target_elf_flavour,
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index c64cd47..d072b9a 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -487,7 +487,7 @@ msymbol_is_micromips (struct minimal_symbol *msym)
static void
mips_make_symbol_special (struct symbol *sym, struct objfile *objfile)
{
- if (sym->aclass () == LOC_BLOCK)
+ if (sym->loc_class () == LOC_BLOCK)
{
/* We are in symbol reading so it is OK to cast away constness. */
struct block *block = (struct block *) sym->value_block ();
@@ -8972,9 +8972,7 @@ mips_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
mips_fpu_type_str (mips_get_fpu_type (gdbarch)));
}
-void _initialize_mips_tdep ();
-void
-_initialize_mips_tdep ()
+INIT_GDB_FILE (mips_tdep)
{
static struct cmd_list_element *mipsfpulist = NULL;
diff --git a/gdb/mips64-obsd-nat.c b/gdb/mips64-obsd-nat.c
index 26fc1b9..d77c77e 100644
--- a/gdb/mips64-obsd-nat.c
+++ b/gdb/mips64-obsd-nat.c
@@ -114,9 +114,7 @@ mips64_obsd_nat_target::store_registers (struct regcache *regcache, int regnum)
perror_with_name (_("Couldn't write registers"));
}
-void _initialize_mips64obsd_nat ();
-void
-_initialize_mips64obsd_nat ()
+INIT_GDB_FILE (mips64obsd_nat)
{
add_inf_child_target (&the_mips64_obsd_nat_target);
}
diff --git a/gdb/mips64-obsd-tdep.c b/gdb/mips64-obsd-tdep.c
index d0c9a1c..b9a6fe5 100644
--- a/gdb/mips64-obsd-tdep.c
+++ b/gdb/mips64-obsd-tdep.c
@@ -150,13 +150,10 @@ mips64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
obsd_init_abi(info, gdbarch);
/* OpenBSD/mips64 has SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
}
-void _initialize_mips64obsd_tdep ();
-void
-_initialize_mips64obsd_tdep ()
+INIT_GDB_FILE (mips64obsd_tdep)
{
gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_OPENBSD,
mips64obsd_init_abi);
diff --git a/gdb/mipsread.c b/gdb/mipsread.c
index 5ffb97f..1d76b8f 100644
--- a/gdb/mipsread.c
+++ b/gdb/mipsread.c
@@ -66,20 +66,16 @@ mipscoff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
{
bfd *abfd = objfile->obfd.get ();
- minimal_symbol_reader reader (objfile);
-
/* Now that the executable file is positioned at symbol table,
process it and define symbols accordingly. */
- if (!((*ecoff_backend (abfd)->debug_swap.read_debug_info)
- (abfd, NULL, &ecoff_data (abfd)->debug_info)))
- error (_("Error reading symbol table: %s"), bfd_errmsg (bfd_get_error ()));
-
- mdebug_build_psymtabs (reader, objfile, &ecoff_backend (abfd)->debug_swap,
- &ecoff_data (abfd)->debug_info);
+ mipsmdebug_build_psymtabs (objfile, &ecoff_backend (abfd)->debug_swap,
+ &ecoff_data (abfd)->debug_info);
/* Add alpha coff dynamic symbols. */
+ minimal_symbol_reader reader (objfile);
+
read_alphacoff_dynamic_symtab (reader, objfile);
/* Install any minimal symbols that have been collected as the current
@@ -374,9 +370,7 @@ static const struct sym_fns ecoff_sym_fns =
NULL, /* sym_probe_fns */
};
-void _initialize_mipsread ();
-void
-_initialize_mipsread ()
+INIT_GDB_FILE (mipsread)
{
add_symtab_fns (bfd_target_ecoff_flavour, &ecoff_sym_fns);
}
diff --git a/gdb/mn10300-linux-tdep.c b/gdb/mn10300-linux-tdep.c
index 3334ca0..6c31241 100644
--- a/gdb/mn10300-linux-tdep.c
+++ b/gdb/mn10300-linux-tdep.c
@@ -29,6 +29,7 @@
#include "trad-frame.h"
#include "tramp-frame.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "gdbarch.h"
/* Transliterated from <asm-mn10300/elf.h>... */
@@ -707,16 +708,13 @@ am33_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_iterate_over_regset_sections
(gdbarch, am33_iterate_over_regset_sections);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
tramp_frame_prepend_unwinder (gdbarch, &am33_linux_sigframe);
tramp_frame_prepend_unwinder (gdbarch, &am33_linux_rt_sigframe);
}
-void _initialize_mn10300_linux_tdep ();
-void
-_initialize_mn10300_linux_tdep ()
+INIT_GDB_FILE (mn10300_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_mn10300, 0,
GDB_OSABI_LINUX, am33_linux_init_osabi);
diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c
index c82a302..fbaeacf 100644
--- a/gdb/mn10300-tdep.c
+++ b/gdb/mn10300-tdep.c
@@ -1413,9 +1413,7 @@ mn10300_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
tdep->am33_mode);
}
-void _initialize_mn10300_tdep ();
-void
-_initialize_mn10300_tdep ()
+INIT_GDB_FILE (mn10300_tdep)
{
gdbarch_register (bfd_arch_mn10300, mn10300_gdbarch_init, mn10300_dump_tdep);
}
diff --git a/gdb/moxie-tdep.c b/gdb/moxie-tdep.c
index ddb9efb..bb48877 100644
--- a/gdb/moxie-tdep.c
+++ b/gdb/moxie-tdep.c
@@ -1088,7 +1088,7 @@ moxie_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
frame_unwind_append_unwinder (gdbarch, &moxie_frame_unwind);
/* Single stepping. */
- set_gdbarch_software_single_step (gdbarch, moxie_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, moxie_software_single_step);
/* Support simple overlay manager. */
set_gdbarch_overlay_update (gdbarch, simple_overlay_update);
@@ -1101,9 +1101,7 @@ moxie_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Register this machine's init routine. */
-void _initialize_moxie_tdep ();
-void
-_initialize_moxie_tdep ()
+INIT_GDB_FILE (moxie_tdep)
{
gdbarch_register (bfd_arch_moxie, moxie_gdbarch_init);
}
diff --git a/gdb/msp430-tdep.c b/gdb/msp430-tdep.c
index 441831e..7ac26b9 100644
--- a/gdb/msp430-tdep.c
+++ b/gdb/msp430-tdep.c
@@ -996,9 +996,7 @@ msp430_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Register the initialization routine. */
-void _initialize_msp430_tdep ();
-void
-_initialize_msp430_tdep ()
+INIT_GDB_FILE (msp430_tdep)
{
gdbarch_register (bfd_arch_msp430, msp430_gdbarch_init);
}
diff --git a/gdb/nat/aarch64-hw-point.c b/gdb/nat/aarch64-hw-point.c
index 6d8dce8..8c0854b 100644
--- a/gdb/nat/aarch64-hw-point.c
+++ b/gdb/nat/aarch64-hw-point.c
@@ -710,10 +710,8 @@ aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
itself. For instance, the access size of an stp instruction is 16.
So, if we use stp to store to address p, and set a watchpoint on
address p + 8, the reported ADDR_TRAP can be p + 8 (observed on
- RK3399 SOC). But it also can be p (observed on M1 SOC). Checking
- for this situation introduces the possibility of false positives,
- so we only do this for hw_write watchpoints. */
- const CORE_ADDR max_access_size = type == hw_write ? 16 : 8;
+ RK3399 SOC). But it also can be p (observed on M1 SOC). */
+ const CORE_ADDR max_access_size = 16;
const CORE_ADDR addr_watch_base = addr_watch_aligned -
(max_access_size - AARCH64_HWP_MAX_LEN_PER_REG);
if (!(addr_trap >= addr_watch_base
diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
index ea94fdd..2a65fb0 100644
--- a/gdb/nat/linux-namespaces.c
+++ b/gdb/nat/linux-namespaces.c
@@ -233,6 +233,12 @@ enum mnsh_msg_type
MNSH_RET_INT. */
MNSH_REQ_SETNS,
+ /* A request that the helper call lstat. The single
+ argument (the filename) should be passed in BUF, and
+ should include a terminating NUL character. The helper
+ should respond with a MNSH_RET_INTSTR. */
+ MNSH_REQ_LSTAT,
+
/* A request that the helper call open. Arguments should
be passed in BUF, INT1 and INT2. The filename (in BUF)
should include a terminating NUL character. The helper
@@ -265,62 +271,69 @@ enum mnsh_msg_type
MNSH_RET_INTSTR,
};
-/* Print a string representation of a message using debug_printf.
- This function is not async-signal-safe so should never be
- called from the helper. */
+/* Return a string representation of a message. This function is not
+ async-signal-safe so should never be called from the helper. */
-static void
+static std::string
mnsh_debug_print_message (enum mnsh_msg_type type,
int fd, int int1, int int2,
const void *buf, int bufsiz)
{
+ std::string res;
+
gdb_byte *c = (gdb_byte *) buf;
gdb_byte *cl = c + bufsiz;
switch (type)
{
case MNSH_MSG_ERROR:
- debug_printf ("ERROR");
+ res += "ERROR";
+ break;
+
+ case MNSH_REQ_LSTAT:
+ res += "LSTAT";
break;
case MNSH_REQ_SETNS:
- debug_printf ("SETNS");
+ res += "SETNS";
break;
case MNSH_REQ_OPEN:
- debug_printf ("OPEN");
+ res += "OPEN";
break;
case MNSH_REQ_UNLINK:
- debug_printf ("UNLINK");
+ res += "UNLINK";
break;
case MNSH_REQ_READLINK:
- debug_printf ("READLINK");
+ res += "READLINK";
break;
case MNSH_RET_INT:
- debug_printf ("INT");
+ res += "INT";
break;
case MNSH_RET_FD:
- debug_printf ("FD");
+ res += "FD";
break;
case MNSH_RET_INTSTR:
- debug_printf ("INTSTR");
+ res += "INTSTR";
break;
default:
- debug_printf ("unknown-packet-%d", type);
+ res += string_printf ("unknown-packet-%d", type);
}
- debug_printf (" %d %d %d \"", fd, int1, int2);
+ res += string_printf (" %d %d %d \"", fd, int1, int2);
for (; c < cl; c++)
- debug_printf (*c >= ' ' && *c <= '~' ? "%c" : "\\%o", *c);
+ res += string_printf (*c >= ' ' && *c <= '~' ? "%c" : "\\%o", *c);
- debug_printf ("\"");
+ res += "\"";
+
+ return res;
}
/* Forward declaration. */
@@ -390,12 +403,10 @@ mnsh_send_message (int sock, enum mnsh_msg_type type,
if (size < 0)
mnsh_maybe_mourn_peer ();
- if (debug_linux_namespaces)
- {
- debug_printf ("mnsh: send: ");
- mnsh_debug_print_message (type, fd, int1, int2, buf, bufsiz);
- debug_printf (" -> %s\n", pulongest (size));
- }
+ linux_namespaces_debug_printf
+ ("send: %s -> %s",
+ mnsh_debug_print_message (type, fd, int1, int2, buf, bufsiz).c_str (),
+ pulongest (size));
return size;
}
@@ -445,9 +456,8 @@ mnsh_recv_message (int sock, enum mnsh_msg_type *type,
size = recvmsg (sock, &msg, MSG_CMSG_CLOEXEC);
if (size < 0)
{
- if (debug_linux_namespaces)
- debug_printf ("namespace-helper: recv failed (%s)\n",
- pulongest (size));
+ linux_namespaces_debug_printf
+ ("namespace-helper: recv failed (%s)", pulongest (size));
mnsh_maybe_mourn_peer ();
@@ -457,9 +467,9 @@ mnsh_recv_message (int sock, enum mnsh_msg_type *type,
/* Check for truncation. */
if (size < fixed_size || (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)))
{
- if (debug_linux_namespaces)
- debug_printf ("namespace-helper: recv truncated (%s 0x%x)\n",
- pulongest (size), msg.msg_flags);
+ linux_namespaces_debug_printf
+ ("namespace-helper: recv truncated (%s 0x%x)",
+ pulongest (size), msg.msg_flags);
mnsh_maybe_mourn_peer ();
@@ -477,13 +487,10 @@ mnsh_recv_message (int sock, enum mnsh_msg_type *type,
else
*fd = -1;
- if (debug_linux_namespaces)
- {
- debug_printf ("mnsh: recv: ");
- mnsh_debug_print_message (*type, *fd, *int1, *int2, buf,
- size - fixed_size);
- debug_printf ("\n");
- }
+ linux_namespaces_debug_printf
+ ("recv: %s",
+ mnsh_debug_print_message (*type, *fd, *int1, *int2, buf,
+ size - fixed_size).c_str ());
/* Return the number of bytes of data in BUF. */
return size - fixed_size;
@@ -514,6 +521,20 @@ mnsh_handle_setns (int sock, int fd, int nstype)
return mnsh_return_int (sock, result, errno);
}
+
+/* Handle a MNSH_REQ_LSTAT message. Must be async-signal-safe. */
+
+static ssize_t
+mnsh_handle_lstat (int sock, const char *filename)
+{
+ struct stat sb;
+ int stat_ok = lstat (filename, &sb);
+
+ return mnsh_return_intstr (sock, stat_ok, &sb,
+ stat_ok == -1 ? 0 : sizeof (sb),
+ errno);
+}
+
/* Handle a MNSH_REQ_OPEN message. Must be async-signal-safe. */
static ssize_t
@@ -574,6 +595,11 @@ mnsh_main (int sock)
response = mnsh_handle_setns (sock, fd, int1);
break;
+ case MNSH_REQ_LSTAT:
+ if (size > 0 && buf[size - 1] == '\0')
+ response = mnsh_handle_lstat (sock, buf);
+ break;
+
case MNSH_REQ_OPEN:
if (size > 0 && buf[size - 1] == '\0')
response = mnsh_handle_open (sock, buf, int1, int2);
@@ -673,7 +699,7 @@ linux_mntns_get_helper (void)
mnsh_creator_pid = helper_creator;
/* Debug printing isn't async-signal-safe. */
- debug_linux_namespaces = 0;
+ debug_linux_namespaces = false;
mnsh_main (sv[1]);
}
@@ -685,9 +711,8 @@ linux_mntns_get_helper (void)
helper->sock = sv[0];
helper->nsid = ns->id;
- if (debug_linux_namespaces)
- debug_printf ("Started mount namespace helper process %d\n",
- helper->pid);
+ linux_namespaces_debug_printf
+ ("Started mount namespace helper process %d", helper->pid);
}
return helper;
@@ -765,6 +790,10 @@ mnsh_maybe_mourn_peer (void)
mnsh_send_message (helper->sock, MNSH_REQ_OPEN, -1, flags, mode, \
filename, strlen (filename) + 1)
+#define mnsh_send_lstat(helper, filename) \
+ mnsh_send_message (helper->sock, MNSH_REQ_LSTAT, -1, 0, 0, \
+ filename, strlen (filename) + 1)
+
#define mnsh_send_unlink(helper, filename) \
mnsh_send_message (helper->sock, MNSH_REQ_UNLINK, -1, 0, 0, \
filename, strlen (filename) + 1)
@@ -884,7 +913,7 @@ linux_mntns_access_fs (pid_t pid)
struct stat sb;
struct linux_mnsh *helper;
ssize_t size;
- int fd;
+ int fd, fd_user = -1;
if (pid == getpid ())
return MNSH_FS_DIRECT;
@@ -901,6 +930,8 @@ linux_mntns_access_fs (pid_t pid)
{
int save_errno = errno;
close (fd);
+ if (fd_user >= 0)
+ close (fd_user);
errno = save_errno;
};
@@ -910,6 +941,13 @@ linux_mntns_access_fs (pid_t pid)
if (sb.st_ino == ns->id)
return MNSH_FS_DIRECT;
+ struct linux_ns *ns_user = linux_ns_get_namespace (LINUX_NS_USER);
+ if (ns_user != nullptr)
+ {
+ const char *ns_filename = linux_ns_filename (ns_user, pid);
+ fd_user = gdb_open_cloexec (ns_filename, O_RDONLY, 0).release ();
+ }
+
helper = linux_mntns_get_helper ();
if (helper == NULL)
return MNSH_FS_ERROR;
@@ -918,6 +956,19 @@ linux_mntns_access_fs (pid_t pid)
{
int result, error;
+ /* Try to enter the user namespace first. The current user might
+ have elevated privileges within the user namespace, which would
+ then allow the attempt to enter the mount namespace to succeed. */
+ if (fd_user >= 0)
+ {
+ size = mnsh_send_setns (helper, fd_user, 0);
+ if (size < 0)
+ return MNSH_FS_ERROR;
+
+ if (mnsh_recv_int (helper, &result, &error) != 0)
+ return MNSH_FS_ERROR;
+ }
+
size = mnsh_send_setns (helper, fd, 0);
if (size < 0)
return MNSH_FS_ERROR;
@@ -948,6 +999,42 @@ linux_mntns_access_fs (pid_t pid)
/* See nat/linux-namespaces.h. */
int
+linux_mntns_lstat (pid_t pid, const char *filename,
+ struct stat *sb)
+{
+ enum mnsh_fs_code access = linux_mntns_access_fs (pid);
+
+ if (access == MNSH_FS_ERROR)
+ return -1;
+
+ if (access == MNSH_FS_DIRECT)
+ return lstat (filename, sb);
+
+ gdb_assert (access == MNSH_FS_HELPER);
+
+ struct linux_mnsh *helper = linux_mntns_get_helper ();
+
+ ssize_t size = mnsh_send_lstat (helper, filename);
+ if (size < 0)
+ return -1;
+
+ int stat_ok, error;
+ size = mnsh_recv_intstr (helper, &stat_ok, &error, sb, sizeof (*sb));
+
+ if (size < 0)
+ {
+ stat_ok = -1;
+ errno = error;
+ }
+ else
+ gdb_assert (stat_ok == -1 || size == sizeof (*sb));
+
+ return stat_ok;
+}
+
+/* See nat/linux-namespaces.h. */
+
+int
linux_mntns_open_cloexec (pid_t pid, const char *filename,
int flags, mode_t mode)
{
diff --git a/gdb/nat/linux-namespaces.h b/gdb/nat/linux-namespaces.h
index a548d83..a9a99f1 100644
--- a/gdb/nat/linux-namespaces.h
+++ b/gdb/nat/linux-namespaces.h
@@ -24,6 +24,12 @@
extern bool debug_linux_namespaces;
+/* Print a "linux-namespaces" debug statement. */
+
+#define linux_namespaces_debug_printf(fmt, ...) \
+ debug_prefixed_printf_cond (debug_linux_namespaces, "linux-namespaces", \
+ fmt, ##__VA_ARGS__)
+
/* Enumeration of Linux namespace types. */
enum linux_ns_type
@@ -58,6 +64,11 @@ enum linux_ns_type
extern int linux_ns_same (pid_t pid, enum linux_ns_type type);
+/* Like lstat(2), but in the mount namespace of process PID. */
+
+extern int linux_mntns_lstat (pid_t pid, const char *filename,
+ struct stat *sb);
+
/* Like gdb_open_cloexec, but in the mount namespace of process
PID. */
diff --git a/gdb/nat/linux-osdata.c b/gdb/nat/linux-osdata.c
index b52a8ed..0a309b8 100644
--- a/gdb/nat/linux-osdata.c
+++ b/gdb/nat/linux-osdata.c
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <sys/sysinfo.h>
-#include <ctype.h>
#include <utmp.h>
#include <time.h>
#include <unistd.h>
@@ -205,7 +204,7 @@ get_cores_used_by_process (PID_T pid, int *cores, const int num_cores)
PID_T tid;
int core;
- if (!isdigit (dp->d_name[0])
+ if (!c_isdigit (dp->d_name[0])
|| NAMELEN (dp) > MAX_PID_T_STRLEN)
continue;
@@ -310,7 +309,7 @@ linux_xfer_osdata_processes ()
std::string cores_str;
int i;
- if (!isdigit (dp->d_name[0])
+ if (!c_isdigit (dp->d_name[0])
|| NAMELEN (dp) > MAX_PID_T_STRLEN)
continue;
@@ -419,7 +418,7 @@ linux_xfer_osdata_processgroups ()
{
PID_T pid, pgid;
- if (!isdigit (dp->d_name[0])
+ if (!c_isdigit (dp->d_name[0])
|| NAMELEN (dp) > MAX_PID_T_STRLEN)
continue;
@@ -483,7 +482,7 @@ linux_xfer_osdata_threads ()
struct stat statbuf;
char procentry[sizeof ("/proc/4294967295")];
- if (!isdigit (dp->d_name[0])
+ if (!c_isdigit (dp->d_name[0])
|| NAMELEN (dp) > sizeof ("4294967295") - 1)
continue;
@@ -513,7 +512,7 @@ linux_xfer_osdata_threads ()
PID_T tid;
int core;
- if (!isdigit (dp2->d_name[0])
+ if (!c_isdigit (dp2->d_name[0])
|| NAMELEN (dp2) > sizeof ("4294967295") - 1)
continue;
@@ -633,7 +632,7 @@ linux_xfer_osdata_fds ()
struct stat statbuf;
char procentry[sizeof ("/proc/4294967295")];
- if (!isdigit (dp->d_name[0])
+ if (!c_isdigit (dp->d_name[0])
|| NAMELEN (dp) > sizeof ("4294967295") - 1)
continue;
@@ -662,7 +661,7 @@ linux_xfer_osdata_fds ()
char buf[1000];
ssize_t rslt;
- if (!isdigit (dp2->d_name[0]))
+ if (!c_isdigit (dp2->d_name[0]))
continue;
std::string fdname
diff --git a/gdb/nat/linux-procfs.c b/gdb/nat/linux-procfs.c
index a72df2a..d4f9af3 100644
--- a/gdb/nat/linux-procfs.c
+++ b/gdb/nat/linux-procfs.c
@@ -424,7 +424,7 @@ linux_proc_task_list_dir_exists (pid_t pid)
/* See linux-procfs.h. */
const char *
-linux_proc_pid_to_exec_file (int pid)
+linux_proc_pid_to_exec_file (int pid, bool is_local_fs)
{
static char buf[PATH_MAX];
char name[PATH_MAX];
@@ -437,9 +437,31 @@ linux_proc_pid_to_exec_file (int pid)
else
buf[len] = '\0';
- /* Use /proc/PID/exe if the actual file can't be read, but /proc/PID/exe
- can be. */
- if (access (buf, R_OK) != 0 && access (name, R_OK) == 0)
+ /* If the inferior and GDB can see the same filesystem, and NAME
+ cannot be read, maybe the file has been deleted, then we can
+ potentially use /proc/PID/exe instead.
+
+ GDB always interprets the results of this function within the
+ current sysroot (which is 'target:' by default). This means
+ that, if we return /proc/PID/exe, GDB will try to find this file
+ within the sysroot.
+
+ This doesn't make sense if GDB is using a sysroot like:
+ '/some/random/directory/', not only is it possible that NAME
+ could be found within the sysroot, it is unlikely that
+ /proc/PID/exe will exist within the sysroot.
+
+ Similarly, if the sysroot is 'target:', but the inferior is
+ running within a separate MNT namespace, then it is more than
+ likely that the inferior will also be running in a separate PID
+ namespace, in this case PID is the pid on the host system,
+ /proc/PID/exe will not be correct within the inferiors MNT/PID
+ namespace.
+
+ So, we can fallback to use /proc/PID/exe only if IS_LOCAL_FS is
+ true, this indicates that GDB and the inferior are using the same
+ MNT namespace, and GDB's sysroot is either empty, or 'target:'. */
+ if (is_local_fs && access (buf, R_OK) != 0 && access (name, R_OK) == 0)
strcpy (buf, name);
return buf;
diff --git a/gdb/nat/linux-procfs.h b/gdb/nat/linux-procfs.h
index 0c80622..4b02d31 100644
--- a/gdb/nat/linux-procfs.h
+++ b/gdb/nat/linux-procfs.h
@@ -87,9 +87,19 @@ extern int linux_proc_task_list_dir_exists (pid_t pid);
/* Return the full absolute name of the executable file that was run
to create the process PID. The returned value persists until this
- function is next called. */
+ function is next called.
-extern const char *linux_proc_pid_to_exec_file (int pid);
+ LOCAL_FS should be true if the file returned from the function will
+ be searched for in the same filesystem as GDB itself is running.
+ In practice, this means LOCAL_FS should be true if PID and GDB are
+ running in the same MNT namespace and GDB's sysroot is either the
+ empty string, or is 'target:'.
+
+ When used from gdbserver, where there is no sysroot, the only check
+ that matters is that PID and gdbserver are running in the same MNT
+ namespace. */
+
+extern const char *linux_proc_pid_to_exec_file (int pid, bool local_fs);
/* Display possible problems on this system. Display them only once
per GDB execution. */
diff --git a/gdb/nat/linux-ptrace.c b/gdb/nat/linux-ptrace.c
index 0510b39..f73058b 100644
--- a/gdb/nat/linux-ptrace.c
+++ b/gdb/nat/linux-ptrace.c
@@ -23,6 +23,7 @@
#include <sys/procfs.h>
#endif
#include "gdbsupport/eintr.h"
+#include "gdbsupport/signals-state-save-restore.h"
/* Stores the ptrace options supported by the running kernel.
A value of -1 means we did not check for features yet. A value
@@ -148,6 +149,9 @@ linux_ptrace_test_ret_to_nx (void)
return;
case 0:
+ /* Set signal handlers to their default because it doesn't make sense
+ to call GDB-specific handlers any more in the child process. */
+ restore_original_signals_state ();
l = ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) NULL,
(PTRACE_TYPE_ARG4) NULL);
if (l != 0)
diff --git a/gdb/nat/x86-gcc-cpuid.h b/gdb/nat/x86-gcc-cpuid.h
index 1498100..9e27fd8 100644
--- a/gdb/nat/x86-gcc-cpuid.h
+++ b/gdb/nat/x86-gcc-cpuid.h
@@ -1,5 +1,5 @@
/*
- * Helper cpuid.h file copied from gcc-6.0.0. Code in gdb should not
+ * Helper cpuid.h file copied from gcc-14.2.0. Code in gdb should not
* include this directly, but pull in x86-cpuid.h and use that func.
*/
@@ -55,7 +55,7 @@
#define bit_SSE (1 << 25)
#define bit_SSE2 (1 << 26)
-/* Extended Features */
+/* Extended Features (%eax == 0x80000001) */
/* %ecx */
#define bit_LAHF_LM (1 << 0)
#define bit_ABM (1 << 5)
@@ -68,29 +68,28 @@
#define bit_MWAITX (1 << 29)
/* %edx */
-#define bit_AVX5124VNNIW (1 << 2)
-#define bit_AVX5124FMAPS (1 << 3)
#define bit_MMXEXT (1 << 22)
#define bit_LM (1 << 29)
#define bit_3DNOWP (1 << 30)
-#define bit_3DNOW (1 << 31)
+#define bit_3DNOW (1u << 31)
-/* %ebx. */
+/* %ebx */
#define bit_CLZERO (1 << 0)
+#define bit_WBNOINVD (1 << 9)
-/* Extended Features (%eax == 7) */
+/* Extended Features Leaf (%eax == 7, %ecx == 0) */
/* %ebx */
#define bit_FSGSBASE (1 << 0)
-#define bit_BMI (1 << 3)
-#define bit_HLE (1 << 4)
+#define bit_SGX (1 << 2)
+#define bit_BMI (1 << 3)
+#define bit_HLE (1 << 4)
#define bit_AVX2 (1 << 5)
#define bit_BMI2 (1 << 8)
-#define bit_RTM (1 << 11)
-#define bit_MPX (1 << 14)
+#define bit_RTM (1 << 11)
#define bit_AVX512F (1 << 16)
#define bit_AVX512DQ (1 << 17)
#define bit_RDSEED (1 << 18)
-#define bit_ADX (1 << 19)
+#define bit_ADX (1 << 19)
#define bit_AVX512IFMA (1 << 21)
#define bit_CLFLUSHOPT (1 << 23)
#define bit_CLWB (1 << 24)
@@ -99,23 +98,85 @@
#define bit_AVX512CD (1 << 28)
#define bit_SHA (1 << 29)
#define bit_AVX512BW (1 << 30)
-#define bit_AVX512VL (1 << 31)
+#define bit_AVX512VL (1u << 31)
/* %ecx */
-#define bit_PREFETCHWT1 (1 << 0)
+#define bit_PREFETCHWT1 (1 << 0)
#define bit_AVX512VBMI (1 << 1)
-#define bit_PKU (1 << 3)
+#define bit_PKU (1 << 3)
#define bit_OSPKE (1 << 4)
+#define bit_WAITPKG (1 << 5)
+#define bit_AVX512VBMI2 (1 << 6)
+#define bit_SHSTK (1 << 7)
+#define bit_GFNI (1 << 8)
+#define bit_VAES (1 << 9)
+#define bit_VPCLMULQDQ (1 << 10)
+#define bit_AVX512VNNI (1 << 11)
+#define bit_AVX512BITALG (1 << 12)
+#define bit_AVX512VPOPCNTDQ (1 << 14)
+#define bit_RDPID (1 << 22)
+#define bit_KL (1 << 23)
+#define bit_CLDEMOTE (1 << 25)
+#define bit_MOVDIRI (1 << 27)
+#define bit_MOVDIR64B (1 << 28)
+#define bit_ENQCMD (1 << 29)
-/* XFEATURE_ENABLED_MASK register bits (%eax == 13, %ecx == 0) */
-#define bit_BNDREGS (1 << 3)
-#define bit_BNDCSR (1 << 4)
+/* %edx */
+#define bit_AVX5124VNNIW (1 << 2)
+#define bit_AVX5124FMAPS (1 << 3)
+#define bit_UINTR (1 << 5)
+#define bit_AVX512VP2INTERSECT (1 << 8)
+#define bit_SERIALIZE (1 << 14)
+#define bit_TSXLDTRK (1 << 16)
+#define bit_PCONFIG (1 << 18)
+#define bit_IBT (1 << 20)
+#define bit_AMX_BF16 (1 << 22)
+#define bit_AVX512FP16 (1 << 23)
+#define bit_AMX_TILE (1 << 24)
+#define bit_AMX_INT8 (1 << 25)
+
+/* Extended Features Sub-leaf (%eax == 7, %ecx == 1) */
+/* %eax */
+#define bit_SHA512 (1 << 0)
+#define bit_SM3 (1 << 1)
+#define bit_SM4 (1 << 2)
+#define bit_RAOINT (1 << 3)
+#define bit_AVXVNNI (1 << 4)
+#define bit_AVX512BF16 (1 << 5)
+#define bit_CMPCCXADD (1 << 7)
+#define bit_AMX_COMPLEX (1 << 8)
+#define bit_AMX_FP16 (1 << 21)
+#define bit_HRESET (1 << 22)
+#define bit_AVXIFMA (1 << 23)
-/* Extended State Enumeration Sub-leaf (%eax == 13, %ecx == 1) */
+/* %edx */
+#define bit_AVXVNNIINT8 (1 << 4)
+#define bit_AVXNECONVERT (1 << 5)
+#define bit_AVXVNNIINT16 (1 << 10)
+#define bit_PREFETCHI (1 << 14)
+#define bit_USER_MSR (1 << 15)
+#define bit_AVX10 (1 << 19)
+#define bit_APX_F (1 << 21)
+
+/* Extended State Enumeration Sub-leaf (%eax == 0xd, %ecx == 1) */
#define bit_XSAVEOPT (1 << 0)
#define bit_XSAVEC (1 << 1)
#define bit_XSAVES (1 << 3)
+/* PT sub leaf (%eax == 0x14, %ecx == 0) */
+/* %ebx */
+#define bit_PTWRITE (1 << 4)
+
+/* Keylocker leaf (%eax == 0x19) */
+/* %ebx */
+#define bit_AESKLE ( 1<<0 )
+#define bit_WIDEKL ( 1<<2 )
+
+/* AVX10 sub leaf (%eax == 0x24) */
+/* %ebx */
+#define bit_AVX10_256 (1 << 17)
+#define bit_AVX10_512 (1 << 18)
+
/* Signatures for different CPU implementations as returned in uses
of cpuid with level 0. */
#define signature_AMD_ebx 0x68747541
@@ -170,19 +231,40 @@
#define signature_VORTEX_ecx 0x436f5320
#define signature_VORTEX_edx 0x36387865
-#define __cpuid(level, a, b, c, d) \
- __asm__ ("cpuid\n\t" \
- : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
- : "0" (level))
+#define signature_SHANGHAI_ebx 0x68532020
+#define signature_SHANGHAI_ecx 0x20206961
+#define signature_SHANGHAI_edx 0x68676e61
-#define __cpuid_count(level, count, a, b, c, d) \
- __asm__ ("cpuid\n\t" \
- : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
- : "0" (level), "2" (count))
+#ifndef __x86_64__
+/* At least one cpu (Winchip 2) does not set %ebx and %ecx
+ for cpuid leaf 1. Forcibly zero the two registers before
+ calling cpuid as a precaution. */
+#define __cpuid(level, a, b, c, d) \
+ do { \
+ if (__builtin_constant_p (level) && (level) != 1) \
+ __asm__ __volatile__ ("cpuid\n\t" \
+ : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
+ : "0" (level)); \
+ else \
+ __asm__ __volatile__ ("cpuid\n\t" \
+ : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
+ : "0" (level), "1" (0), "2" (0)); \
+ } while (0)
+#else
+#define __cpuid(level, a, b, c, d) \
+ __asm__ __volatile__ ("cpuid\n\t" \
+ : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
+ : "0" (level))
+#endif
+
+#define __cpuid_count(level, count, a, b, c, d) \
+ __asm__ __volatile__ ("cpuid\n\t" \
+ : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
+ : "0" (level), "2" (count))
/* Return highest supported input value for cpuid instruction. ext can
- be either 0x0 or 0x8000000 to return highest supported value for
+ be either 0x0 or 0x80000000 to return highest supported value for
basic or extended cpuid information. Function returns 0 if cpuid
is not supported or whatever cpuid returns in eax register. If sig
pointer is non-null, then first four bytes of the signature
@@ -225,7 +307,7 @@ __get_cpuid_max (unsigned int __ext, unsigned int *__sig)
: "i" (0x00200000));
#endif
- if (!((__eax ^ __ebx) & 0x00200000))
+ if (__builtin_expect (!((__eax ^ __ebx) & 0x00200000), 0))
return 0;
#endif
@@ -249,8 +331,9 @@ __get_cpuid (unsigned int __leaf,
unsigned int *__ecx, unsigned int *__edx)
{
unsigned int __ext = __leaf & 0x80000000;
+ unsigned int __maxlevel = __get_cpuid_max (__ext, 0);
- if (__get_cpuid_max (__ext, 0) < __leaf)
+ if (__maxlevel == 0 || __maxlevel < __leaf)
return 0;
__cpuid (__leaf, *__eax, *__ebx, *__ecx, *__edx);
@@ -265,12 +348,20 @@ __get_cpuid_count (unsigned int __leaf, unsigned int __subleaf,
unsigned int *__ecx, unsigned int *__edx)
{
unsigned int __ext = __leaf & 0x80000000;
+ unsigned int __maxlevel = __get_cpuid_max (__ext, 0);
- if (__get_cpuid_max (__ext, 0) < __leaf)
+ if (__builtin_expect (__maxlevel == 0, 0) || __maxlevel < __leaf)
return 0;
__cpuid_count (__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx);
return 1;
}
+static __inline void
+__cpuidex (int __cpuid_info[4], int __leaf, int __subleaf)
+{
+ __cpuid_count (__leaf, __subleaf, __cpuid_info[0], __cpuid_info[1],
+ __cpuid_info[2], __cpuid_info[3]);
+}
+
#endif /* GDB_NAT_X86_GCC_CPUID_H */
diff --git a/gdb/nat/x86-linux-tdesc.c b/gdb/nat/x86-linux-tdesc.c
index 80e4337..5bc36b6 100644
--- a/gdb/nat/x86-linux-tdesc.c
+++ b/gdb/nat/x86-linux-tdesc.c
@@ -43,7 +43,7 @@
/* See nat/x86-linux-tdesc.h. */
const target_desc *
-x86_linux_tdesc_for_tid (int tid, uint64_t *xcr0_storage,
+x86_linux_tdesc_for_tid (int tid, uint64_t *xstate_bv_storage,
x86_xsave_layout *xsave_layout_storage)
{
#ifdef __x86_64__
@@ -96,30 +96,34 @@ x86_linux_tdesc_for_tid (int tid, uint64_t *xcr0_storage,
these bits being set we generate a completely empty tdesc for
i386 which will be rejected by GDB. */
have_ptrace_getregset = TRIBOOL_FALSE;
- *xcr0_storage = X86_XSTATE_SSE_MASK;
+ *xstate_bv_storage = X86_XSTATE_SSE_MASK;
}
else
{
have_ptrace_getregset = TRIBOOL_TRUE;
/* Get XCR0 from XSAVE extended state. */
- *xcr0_storage = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
+ uint64_t xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
/ sizeof (uint64_t))];
*xsave_layout_storage
- = x86_fetch_xsave_layout (*xcr0_storage, x86_xsave_length ());
+ = x86_fetch_xsave_layout (xcr0, x86_xsave_length ());
+
+ *xstate_bv_storage = xcr0;
+ if (x86_check_ssp_support (tid))
+ *xstate_bv_storage |= X86_XSTATE_CET_U;
}
}
- /* Use cached xcr0 value. */
- uint64_t xcr0_features_bits = *xcr0_storage & X86_XSTATE_ALL_MASK;
+ /* Use cached XSTATE_BV_STORAGE value. */
+ uint64_t xstate_bv_features_bits = *xstate_bv_storage & X86_XSTATE_ALL_MASK;
#ifdef __x86_64__
if (is_64bit)
- return amd64_linux_read_description (xcr0_features_bits, is_x32);
+ return amd64_linux_read_description (xstate_bv_features_bits, is_x32);
else
#endif
- return i386_linux_read_description (xcr0_features_bits);
+ return i386_linux_read_description (xstate_bv_features_bits);
}
#endif /* !IN_PROCESS_AGENT */
diff --git a/gdb/nat/x86-linux-tdesc.h b/gdb/nat/x86-linux-tdesc.h
index 38c71f1..19aa84f 100644
--- a/gdb/nat/x86-linux-tdesc.h
+++ b/gdb/nat/x86-linux-tdesc.h
@@ -27,9 +27,9 @@ struct x86_xsave_layout;
/* Return the target description for Linux thread TID.
- The storage pointed to by XCR0_STORAGE and XSAVE_LAYOUT_STORAGE must
+ The storage pointed to by XSTATE_BV_STORAGE and XSAVE_LAYOUT_STORAGE must
exist until the program (GDB or gdbserver) terminates, this storage is
- used to cache the xcr0 and xsave layout values. The values pointed to
+ used to cache the xstate_bv and xsave layout values. The values pointed to
by these arguments are only updated at most once, the first time this
function is called if the have_ptrace_getregset global is set to
TRIBOOL_UNKNOWN.
@@ -45,6 +45,7 @@ struct x86_xsave_layout;
returned. */
extern const target_desc *x86_linux_tdesc_for_tid
- (int tid, uint64_t *xcr0_storage, x86_xsave_layout *xsave_layout_storage);
+ (int tid, uint64_t *xstate_bv_storage,
+ x86_xsave_layout *xsave_layout_storage);
#endif /* GDB_NAT_X86_LINUX_TDESC_H */
diff --git a/gdb/nat/x86-linux.c b/gdb/nat/x86-linux.c
index 0bdff73..5515826 100644
--- a/gdb/nat/x86-linux.c
+++ b/gdb/nat/x86-linux.c
@@ -17,6 +17,12 @@
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 "elf/common.h"
+#include "gdbsupport/common-defs.h"
+#include "nat/gdb_ptrace.h"
+#include "nat/linux-ptrace.h"
+#include "nat/x86-cpuid.h"
+#include <sys/uio.h>
#include "x86-linux.h"
#include "x86-linux-dregs.h"
#include "nat/gdb_ptrace.h"
@@ -126,3 +132,56 @@ x86_linux_ptrace_get_arch_size (int tid)
return x86_linux_arch_size (false, false);
#endif
}
+
+/* See nat/x86-linux.h. */
+
+bool
+x86_check_ssp_support (const int tid)
+{
+ /* It's not enough to check shadow stack support with the ptrace call
+ below only, as we cannot distinguish between shadow stack not enabled
+ for the current thread and shadow stack is not supported by HW. In
+ both scenarios the ptrace call fails with ENODEV. In case shadow
+ stack is not enabled for the current thread, we still want to return
+ true. */
+ unsigned int eax, ebx, ecx, edx;
+ eax = ebx = ecx = edx = 0;
+
+ if (!__get_cpuid_count (7, 0, &eax, &ebx, &ecx, &edx))
+ return false;
+
+ if ((ecx & bit_SHSTK) == 0)
+ return false;
+
+ /* Further check for NT_X86_SHSTK kernel support. */
+ uint64_t ssp;
+ iovec iov {&ssp, sizeof (ssp) };
+
+ errno = 0;
+ int res = ptrace (PTRACE_GETREGSET, tid, NT_X86_SHSTK, &iov);
+ if (res < 0)
+ {
+ if (errno == EINVAL)
+ {
+ /* The errno EINVAL for a PTRACE_GETREGSET call indicates that
+ kernel support is not available. */
+ return false;
+ }
+ else if (errno == ENODEV)
+ {
+ /* At this point, since we already checked CPUID, the errno
+ ENODEV for a PTRACE_GETREGSET call indicates that shadow
+ stack is not enabled for the current thread. As it could be
+ enabled later, we still want to return true here. */
+ return true;
+ }
+ else
+ {
+ warning (_("Unknown ptrace error for NT_X86_SHSTK: %s"),
+ safe_strerror (errno));
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/gdb/nat/x86-linux.h b/gdb/nat/x86-linux.h
index dbdef08..1783aae 100644
--- a/gdb/nat/x86-linux.h
+++ b/gdb/nat/x86-linux.h
@@ -75,4 +75,8 @@ private:
extern x86_linux_arch_size x86_linux_ptrace_get_arch_size (int tid);
+/* Check shadow stack hardware and kernel support. */
+
+extern bool x86_check_ssp_support (const int tid);
+
#endif /* GDB_NAT_X86_LINUX_H */
diff --git a/gdb/nds32-tdep.c b/gdb/nds32-tdep.c
index 7d826fc..9180cd0 100644
--- a/gdb/nds32-tdep.c
+++ b/gdb/nds32-tdep.c
@@ -2086,9 +2086,7 @@ nds32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_nds32_tdep ();
-void
-_initialize_nds32_tdep ()
+INIT_GDB_FILE (nds32_tdep)
{
/* Initialize gdbarch. */
gdbarch_register (bfd_arch_nds32, nds32_gdbarch_init);
diff --git a/gdb/netbsd-nat.c b/gdb/netbsd-nat.c
index 060134f..207e69c 100644
--- a/gdb/netbsd-nat.c
+++ b/gdb/netbsd-nat.c
@@ -318,7 +318,7 @@ nbsd_nat_target::info_proc (const char *args, enum info_proc_what what)
if (pid == 0)
error (_("No current process: you must name one."));
}
- else if (built_argv.count () == 1 && isdigit (built_argv[0][0]))
+ else if (built_argv.count () == 1 && c_isdigit (built_argv[0][0]))
pid = strtol (built_argv[0], NULL, 10);
else
error (_("Invalid arguments."));
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index 5341b05..492020d 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -46,7 +46,6 @@
#include "cli/cli-utils.h"
#include "c-exp.h"
-#include <ctype.h>
#include <algorithm>
struct objc_object {
@@ -850,9 +849,9 @@ parse_selector (char *method, char **selector)
for (;;)
{
- if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
+ if (c_isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
*s1++ = *s2;
- else if (isspace (*s2))
+ else if (c_isspace (*s2))
;
else if ((*s2 == '\0') || (*s2 == '\''))
break;
@@ -914,7 +913,7 @@ parse_method (char *method, char *type, char **theclass,
s1++;
nclass = s1;
- while (isalnum (*s1) || (*s1 == '_'))
+ while (c_isalnum (*s1) || (*s1 == '_'))
s1++;
s2 = s1;
@@ -925,7 +924,7 @@ parse_method (char *method, char *type, char **theclass,
s2++;
s2 = skip_spaces (s2);
ncategory = s2;
- while (isalnum (*s2) || (*s2 == '_'))
+ while (c_isalnum (*s2) || (*s2 == '_'))
s2++;
*s2++ = '\0';
}
@@ -938,9 +937,9 @@ parse_method (char *method, char *type, char **theclass,
for (;;)
{
- if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
+ if (c_isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
*s1++ = *s2;
- else if (isspace (*s2))
+ else if (c_isspace (*s2))
;
else if (*s2 == ']')
break;
@@ -1327,9 +1326,7 @@ find_objc_msgcall (CORE_ADDR pc, CORE_ADDR *new_pc)
return 0;
}
-void _initialize_objc_language ();
-void
-_initialize_objc_language ()
+INIT_GDB_FILE (objc_language)
{
add_info ("selectors", info_selectors_command,
_("All Objective-C selectors, or those matching REGEXP."));
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index 3c5a554..d0eb678 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -189,7 +189,7 @@ objfile_lookup_static_link (struct objfile *objfile,
static void
add_to_objfile_sections (struct bfd *abfd, struct bfd_section *asect,
- struct objfile *objfile, int force)
+ struct objfile *objfile, int force)
{
struct obj_section *section;
@@ -521,8 +521,8 @@ relocate_one_symbol (struct symbol *sym, struct objfile *objfile,
any symbols in STRUCT_DOMAIN or UNDEF_DOMAIN.
But I'm leaving out that test, on the theory that
they can't possibly pass the tests below. */
- if ((sym->aclass () == LOC_LABEL
- || sym->aclass () == LOC_STATIC)
+ if ((sym->loc_class () == LOC_LABEL
+ || sym->loc_class () == LOC_STATIC)
&& sym->section_index () >= 0)
sym->set_value_address (sym->value_address ()
+ delta[sym->section_index ()]);
@@ -587,12 +587,12 @@ objfile_relocate1 (struct objfile *objfile,
get_objfile_pspace_data (objfile->pspace ())->section_map_dirty = 1;
/* Update the table in exec_ops, used to read memory. */
- for (obj_section *s : objfile->sections ())
+ for (obj_section &s : objfile->sections ())
{
- int idx = s - objfile->sections_start;
+ int idx = &s - objfile->sections_start;
exec_set_section_address (bfd_get_filename (objfile->obfd.get ()), idx,
- s->addr ());
+ s.addr ());
}
/* Data changed. */
@@ -673,18 +673,18 @@ objfile_rebase (struct objfile *objfile, CORE_ADDR slide)
/* See objfiles.h. */
bool
-objfile_has_full_symbols (objfile *objfile)
+objfile::has_full_symbols ()
{
- return objfile->compunit_symtabs != nullptr;
+ return this->compunit_symtabs != nullptr;
}
/* See objfiles.h. */
bool
-objfile_has_symbols (objfile *objfile)
+objfile::has_symbols ()
{
- for (::objfile *o : objfile->separate_debug_objfiles ())
- if (o->has_partial_symbols () || objfile_has_full_symbols (o))
+ for (::objfile *o : this->separate_debug_objfiles ())
+ if (o->has_partial_symbols () || o->has_full_symbols ())
return true;
return false;
@@ -708,7 +708,7 @@ bool
have_full_symbols (program_space *pspace)
{
for (objfile *ofp : pspace->objfiles ())
- if (objfile_has_full_symbols (ofp))
+ if (ofp->has_full_symbols ())
return true;
return false;
@@ -790,10 +790,10 @@ sort_cmp (const struct obj_section *sect1, const obj_section *sect2)
second case shouldn't occur during normal use, but std::sort
does check that '!(a < a)' when compiled in debug mode. */
- for (const obj_section *osect : objfile1->sections ())
- if (osect == sect2)
+ for (const obj_section &osect : objfile1->sections ())
+ if (&osect == sect2)
return false;
- else if (osect == sect1)
+ else if (&osect == sect1)
return true;
/* We should have found one of the sections before getting here. */
@@ -994,8 +994,8 @@ update_section_map (struct program_space *pspace,
alloc_size = 0;
for (objfile *objfile : pspace->objfiles ())
- for (obj_section *s : objfile->sections ())
- if (insert_section_p (objfile->obfd.get (), s->the_bfd_section))
+ for (obj_section &s : objfile->sections ())
+ if (insert_section_p (objfile->obfd.get (), s.the_bfd_section))
alloc_size += 1;
/* This happens on detach/attach (e.g. in gdb.base/attach.exp). */
@@ -1010,9 +1010,9 @@ update_section_map (struct program_space *pspace,
i = 0;
for (objfile *objfile : pspace->objfiles ())
- for (obj_section *s : objfile->sections ())
- if (insert_section_p (objfile->obfd.get (), s->the_bfd_section))
- map[i++] = s;
+ for (obj_section &s : objfile->sections ())
+ if (insert_section_p (objfile->obfd.get (), s.the_bfd_section))
+ map[i++] = &s;
std::sort (map, map + alloc_size, sort_cmp);
map_size = filter_debuginfo_sections(map, alloc_size);
@@ -1127,12 +1127,12 @@ is_addr_in_objfile (CORE_ADDR addr, const struct objfile *objfile)
if (objfile == NULL)
return false;
- for (obj_section *osect : objfile->sections ())
+ for (obj_section &osect : objfile->sections ())
{
- if (section_is_overlay (osect) && !section_is_mapped (osect))
+ if (section_is_overlay (&osect) && !section_is_mapped (&osect))
continue;
- if (osect->contains (addr))
+ if (osect.contains (addr))
return true;
}
return false;
@@ -1154,24 +1154,6 @@ shared_objfile_contains_address_p (struct program_space *pspace,
return false;
}
-/* The default implementation for the "iterate_over_objfiles_in_search_order"
- gdbarch method. It is equivalent to use the objfiles iterable,
- searching the objfiles in the order they are stored internally,
- ignoring CURRENT_OBJFILE.
-
- On most platforms, it should be close enough to doing the best
- we can without some knowledge specific to the architecture. */
-
-void
-default_iterate_over_objfiles_in_search_order
- (gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb,
- objfile *current_objfile)
-{
- for (objfile *objfile : current_program_space->objfiles ())
- if (cb (objfile))
- return;
-}
-
/* See objfiles.h. */
const char *
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index bb2f05d..1ce5092 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -395,7 +395,9 @@ struct obj_section
return addr >= this->addr () && addr < endaddr ();
}
- /* BFD section pointer */
+ /* BFD section pointer. This is nullptr if the corresponding BFD section is
+ not allocatable (!SEC_ALLOC), in which case this obj_section can be
+ considered NULL / empty. */
struct bfd_section *the_bfd_section;
/* Objfile this section is part of. */
@@ -515,10 +517,16 @@ public:
return per_bfd->gdbarch;
}
- /* Return true if OBJFILE has partial symbols. */
-
+ /* Return true if this objfile has partial symbols. */
bool has_partial_symbols ();
+ /* Return true if this objfile has full symbols. */
+ bool has_full_symbols ();
+
+ /* Return true if this objfile has full or partial symbols, either directly
+ or through a separate debug file. */
+ bool has_symbols ();
+
/* Look for a separate debug symbol file for this objfile, make use of
build-id, debug-link, and debuginfod as necessary. If a suitable
separate debug symbol file is found then it is loaded using a call to
@@ -577,10 +585,6 @@ public:
/* See quick_symbol_functions. */
void dump ();
- /* Find all the symbols in OBJFILE named FUNC_NAME, and ensure that
- the corresponding symbol tables are loaded. */
- void expand_symtabs_for_function (const char *func_name);
-
/* See quick_symbol_functions. */
void expand_all_symtabs ();
@@ -592,14 +596,14 @@ public:
void expand_symtabs_with_fullname (const char *fullname);
/* See quick_symbol_functions. */
- bool expand_symtabs_matching
- (expand_symtabs_file_matcher file_matcher,
+ bool search
+ (search_symtabs_file_matcher file_matcher,
const lookup_name_info *lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
+ search_symtabs_symbol_matcher symbol_matcher,
+ search_symtabs_expansion_listener listener,
block_search_flags search_flags,
domain_search_flags domain,
- expand_symtabs_lang_matcher lang_matcher = nullptr);
+ search_symtabs_lang_matcher lang_matcher = nullptr);
/* See quick_symbol_functions. */
struct compunit_symtab *
@@ -649,61 +653,18 @@ public:
this->section_offsets[idx] = offset;
}
- class section_iterator
+ /* Filter function for section_iterator. */
+ struct filter_out_null_bfd_section
{
- public:
- section_iterator (const section_iterator &) = default;
- section_iterator (section_iterator &&) = default;
- section_iterator &operator= (const section_iterator &) = default;
- section_iterator &operator= (section_iterator &&) = default;
-
- typedef section_iterator self_type;
- typedef obj_section *value_type;
-
- value_type operator* ()
- { return m_iter; }
-
- section_iterator &operator++ ()
- {
- ++m_iter;
- skip_null ();
- return *this;
- }
-
- bool operator== (const section_iterator &other) const
- { return m_iter == other.m_iter && m_end == other.m_end; }
-
- bool operator!= (const section_iterator &other) const
- { return !(*this == other); }
-
- private:
-
- friend class objfile;
-
- section_iterator (obj_section *iter, obj_section *end)
- : m_iter (iter),
- m_end (end)
- {
- skip_null ();
- }
-
- void skip_null ()
- {
- while (m_iter < m_end && m_iter->the_bfd_section == nullptr)
- ++m_iter;
- }
-
- value_type m_iter;
- value_type m_end;
+ bool operator() (const obj_section &sec) const noexcept
+ { return sec.the_bfd_section != nullptr; }
};
- iterator_range<section_iterator> sections ()
- {
- return (iterator_range<section_iterator>
- (section_iterator (sections_start, sections_end),
- section_iterator (sections_end, sections_end)));
- }
+ using section_iterator = filtered_iterator<obj_section *, filter_out_null_bfd_section>;
+ /* Return an iterable that yields the "non-null" sections of this objfile.
+ That is, the sections for which obj_section::the_bfd_section is
+ non-nullptr. */
iterator_range<section_iterator> sections () const
{
return (iterator_range<section_iterator>
@@ -938,15 +899,6 @@ extern void free_objfile_separate_debug (struct objfile *);
extern void objfile_relocate (struct objfile *, const section_offsets &);
extern void objfile_rebase (struct objfile *, CORE_ADDR);
-/* Return true if OBJFILE has full symbols. */
-
-extern bool objfile_has_full_symbols (objfile *objfile);
-
-/* Return true if OBJFILE has full or partial symbols, either directly
- or through a separate debug file. */
-
-extern bool objfile_has_symbols (objfile *objfile);
-
/* Return true if any objfile of PSPACE has partial symbols. */
extern bool have_partial_symbols (program_space *pspace);
@@ -992,10 +944,10 @@ extern struct obj_section *find_pc_section (CORE_ADDR pc);
/* Return true if PC is in a section called NAME. */
extern bool pc_in_section (CORE_ADDR, const char *);
-/* Return non-zero if PC is in a SVR4-style procedure linkage table
+/* Return true if PC is in a SVR4-style procedure linkage table
section. */
-static inline int
+static inline bool
in_plt_section (CORE_ADDR pc)
{
return (pc_in_section (pc, ".plt")
@@ -1013,10 +965,6 @@ in_plt_section (CORE_ADDR pc)
extern scoped_restore_tmpl<int> inhibit_section_map_updates
(struct program_space *pspace);
-extern void default_iterate_over_objfiles_in_search_order
- (gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb,
- objfile *current_objfile);
-
/* Reset the per-BFD storage area on OBJ. */
void set_objfile_per_bfd (struct objfile *obj);
diff --git a/gdb/observable.c b/gdb/observable.c
index 734a5f6..1233a19 100644
--- a/gdb/observable.c
+++ b/gdb/observable.c
@@ -87,9 +87,7 @@ show_observer_debug (struct ui_file *file, int from_tty,
gdb_printf (file, _("Observer debugging is %s.\n"), value);
}
-void _initialize_observer ();
-void
-_initialize_observer ()
+INIT_GDB_FILE (observer)
{
add_setshow_boolean_cmd ("observer", class_maintenance,
&gdb::observers::observer_debug, _("\
diff --git a/gdb/or1k-linux-nat.c b/gdb/or1k-linux-nat.c
index 3a80dc9..cc682ea 100644
--- a/gdb/or1k-linux-nat.c
+++ b/gdb/or1k-linux-nat.c
@@ -199,9 +199,7 @@ or1k_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
/* Initialize OpenRISC Linux native support. */
-void _initialize_or1k_linux_nat ();
-void
-_initialize_or1k_linux_nat ()
+INIT_GDB_FILE (or1k_linux_nat)
{
/* Register the target. */
linux_target = &the_or1k_linux_nat_target;
diff --git a/gdb/or1k-linux-tdep.c b/gdb/or1k-linux-tdep.c
index 4784e0b..9fbf75f 100644
--- a/gdb/or1k-linux-tdep.c
+++ b/gdb/or1k-linux-tdep.c
@@ -20,6 +20,7 @@
#include "osabi.h"
#include "glibc-tdep.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "solib-svr4.h"
#include "regset.h"
#include "tramp-frame.h"
@@ -144,8 +145,7 @@ or1k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
linux_init_abi (info, gdbarch, 0);
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
/* GNU/Linux uses SVR4-style shared libraries. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
@@ -153,7 +153,7 @@ or1k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* GNU/Linux uses the dynamic linker included in the GNU C Library. */
set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
- set_gdbarch_software_single_step (gdbarch, or1k_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, or1k_software_single_step);
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
@@ -167,9 +167,7 @@ or1k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Initialize OpenRISC Linux target support. */
-void _initialize_or1k_linux_tdep ();
-void
-_initialize_or1k_linux_tdep ()
+INIT_GDB_FILE (or1k_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_or1k, 0, GDB_OSABI_LINUX,
or1k_linux_init_abi);
diff --git a/gdb/or1k-tdep.c b/gdb/or1k-tdep.c
index 8e76419..2db207d 100644
--- a/gdb/or1k-tdep.c
+++ b/gdb/or1k-tdep.c
@@ -29,7 +29,6 @@
#include "gdbtypes.h"
#include "target.h"
#include "regcache.h"
-#include "gdbsupport/gdb-safe-ctype.h"
#include "reggroups.h"
#include "arch-utils.h"
#include "frame-unwind.h"
@@ -1286,9 +1285,7 @@ or1k_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
}
-void _initialize_or1k_tdep ();
-void
-_initialize_or1k_tdep ()
+INIT_GDB_FILE (or1k_tdep)
{
/* Register this architecture. */
gdbarch_register (bfd_arch_or1k, or1k_gdbarch_init, or1k_dump_tdep);
diff --git a/gdb/osabi.c b/gdb/osabi.c
index ae14f74..1459368 100644
--- a/gdb/osabi.c
+++ b/gdb/osabi.c
@@ -609,9 +609,7 @@ show_osabi (struct ui_file *file, int from_tty, struct cmd_list_element *c,
gdbarch_osabi_name (GDB_OSABI_DEFAULT));
}
-void _initialize_gdb_osabi ();
-void
-_initialize_gdb_osabi ()
+INIT_GDB_FILE (gdb_osabi)
{
/* Register a generic sniffer for ELF flavoured files. */
gdbarch_register_osabi_sniffer (bfd_arch_unknown,
diff --git a/gdb/osdata.c b/gdb/osdata.c
index 5cc584d..788dd2a 100644
--- a/gdb/osdata.c
+++ b/gdb/osdata.c
@@ -287,9 +287,7 @@ info_osdata_command (const char *arg, int from_tty)
info_osdata (arg);
}
-void _initialize_osdata ();
-void
-_initialize_osdata ()
+INIT_GDB_FILE (osdata)
{
add_info ("os", info_osdata_command,
_("Show OS data ARG."));
diff --git a/gdb/p-exp.y b/gdb/p-exp.y
index cbf6b44..a68443a 100644
--- a/gdb/p-exp.y
+++ b/gdb/p-exp.y
@@ -43,7 +43,6 @@
Probably also lots of other problems, less well defined PM. */
%{
-#include <ctype.h>
#include "expression.h"
#include "value.h"
#include "parser-defs.h"
@@ -817,13 +816,13 @@ parse_number (struct parser_state *par_state,
{
/* Handle suffixes: 'f' for float, 'l' for long double.
FIXME: This appears to be an extension -- do we want this? */
- if (len >= 1 && tolower (p[len - 1]) == 'f')
+ if (len >= 1 && c_tolower (p[len - 1]) == 'f')
{
putithere->typed_val_float.type
= parse_type (par_state)->builtin_float;
len--;
}
- else if (len >= 1 && tolower (p[len - 1]) == 'l')
+ else if (len >= 1 && c_tolower (p[len - 1]) == 'l')
{
putithere->typed_val_float.type
= parse_type (par_state)->builtin_long_double;
@@ -1089,9 +1088,9 @@ yylex (void)
if (explen > 2)
for (const auto &token : tokentab3)
if (strncasecmp (tokstart, token.oper, 3) == 0
- && (!isalpha (token.oper[0]) || explen == 3
- || (!isalpha (tokstart[3])
- && !isdigit (tokstart[3]) && tokstart[3] != '_')))
+ && (!c_isalpha (token.oper[0]) || explen == 3
+ || (!c_isalpha (tokstart[3])
+ && !c_isdigit (tokstart[3]) && tokstart[3] != '_')))
{
pstate->lexptr += 3;
yylval.opcode = token.opcode;
@@ -1102,9 +1101,9 @@ yylex (void)
if (explen > 1)
for (const auto &token : tokentab2)
if (strncasecmp (tokstart, token.oper, 2) == 0
- && (!isalpha (token.oper[0]) || explen == 2
- || (!isalpha (tokstart[2])
- && !isdigit (tokstart[2]) && tokstart[2] != '_')))
+ && (!c_isalpha (token.oper[0]) || explen == 2
+ || (!c_isalpha (tokstart[2])
+ && !c_isdigit (tokstart[2]) && tokstart[2] != '_')))
{
pstate->lexptr += 2;
yylval.opcode = token.opcode;
@@ -1519,7 +1518,7 @@ yylex (void)
/* Call lookup_symtab, not lookup_partial_symtab, in case there are
no psymtabs (coff, xcoff, or some future change to blow away the
psymtabs once once symbols are read). */
- if ((sym && sym->aclass () == LOC_BLOCK)
+ if ((sym && sym->loc_class () == LOC_BLOCK)
|| lookup_symtab (current_program_space, tmp.c_str ()))
{
yylval.ssym.sym.symbol = sym;
@@ -1528,7 +1527,7 @@ yylex (void)
free (uptokstart);
return BLOCKNAME;
}
- if (sym && sym->aclass () == LOC_TYPEDEF)
+ if (sym && sym->loc_class () == LOC_TYPEDEF)
{
#if 1
/* Despite the following flaw, we need to keep this code enabled.
@@ -1597,7 +1596,7 @@ yylex (void)
SEARCH_VFT, NULL).symbol;
if (cur_sym)
{
- if (cur_sym->aclass () == LOC_TYPEDEF)
+ if (cur_sym->loc_class () == LOC_TYPEDEF)
{
best_sym = cur_sym;
pstate->lexptr = p;
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index 3ded152..1dc1a34 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -30,7 +30,6 @@
#include "p-lang.h"
#include "valprint.h"
#include "value.h"
-#include <ctype.h>
#include "c-lang.h"
#include "gdbarch.h"
#include "cli/cli-style.h"
diff --git a/gdb/p-typeprint.c b/gdb/p-typeprint.c
index 7994ccf..8b5f2b5 100644
--- a/gdb/p-typeprint.c
+++ b/gdb/p-typeprint.c
@@ -30,7 +30,6 @@
#include "p-lang.h"
#include "typeprint.h"
#include "gdb-demangle.h"
-#include <ctype.h>
#include "cli/cli-style.h"
/* See language.h. */
@@ -138,13 +137,13 @@ pascal_language::type_print_method_args (const char *physname,
{
gdb_puts (" (", stream);
/* We must demangle this. */
- while (isdigit (physname[0]))
+ while (c_isdigit (physname[0]))
{
int len = 0;
int i, j;
char *argname;
- while (isdigit (physname[len]))
+ while (c_isdigit (physname[len]))
{
len++;
}
diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c
index 5dcdbcd..8228ca0 100644
--- a/gdb/p-valprint.c
+++ b/gdb/p-valprint.c
@@ -860,9 +860,7 @@ pascal_object_print_static_field (struct value *val,
common_val_print (val, stream, recurse, &opts, current_language);
}
-void _initialize_pascal_valprint ();
-void
-_initialize_pascal_valprint ()
+INIT_GDB_FILE (pascal_valprint)
{
add_setshow_boolean_cmd ("pascal_static-members", class_support,
&user_print_options.pascal_static_field_print, _("\
diff --git a/gdb/pager.h b/gdb/pager.h
index 052337d..b5425d4 100644
--- a/gdb/pager.h
+++ b/gdb/pager.h
@@ -68,6 +68,16 @@ private:
/* Flush the wrap buffer to STREAM, if necessary. */
void flush_wrap_buffer ();
+ /* Set the style of m_stream to STYLE. */
+ void set_stream_style (const ui_file_style &style)
+ {
+ if (m_stream->can_emit_style_escape () && m_stream_style != style)
+ {
+ m_stream->puts (style.to_ansi ().c_str ());
+ m_stream_style = style;
+ }
+ }
+
/* Contains characters which are waiting to be output (they have
already been counted in chars_printed). */
std::string m_wrap_buffer;
@@ -82,6 +92,12 @@ private:
/* The style applied at the time that wrap_here was called. */
ui_file_style m_wrap_style;
+ /* The style currently applied to m_stream. While m_applied_style is the
+ style that is applied to new content added to m_wrap_buffer, the
+ m_stream_style reflects changes that have been flushed to the managed
+ stream. */
+ ui_file_style m_stream_style;
+
/* This is temporarily set when paging. This will cause some
methods to change their behavior to ignore the wrap buffer. */
bool m_paging = false;
diff --git a/gdb/parse.c b/gdb/parse.c
index 64653c8..e24a0d0 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -29,7 +29,6 @@
during the process of parsing; the lower levels of the tree always
come first in the result. */
-#include <ctype.h>
#include "arch-utils.h"
#include "symtab.h"
#include "gdbtypes.h"
@@ -617,9 +616,7 @@ parser_fprintf (FILE *x, const char *y, ...)
va_end (args);
}
-void _initialize_parse ();
-void
-_initialize_parse ()
+INIT_GDB_FILE (parse)
{
add_setshow_zuinteger_cmd ("expression", class_maintenance,
&expressiondebug,
diff --git a/gdb/ppc-fbsd-nat.c b/gdb/ppc-fbsd-nat.c
index e8853cf..e59791d 100644
--- a/gdb/ppc-fbsd-nat.c
+++ b/gdb/ppc-fbsd-nat.c
@@ -200,9 +200,7 @@ ppcfbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
return 1;
}
-void _initialize_ppcfbsd_nat ();
-void
-_initialize_ppcfbsd_nat ()
+INIT_GDB_FILE (ppcfbsd_nat)
{
add_inf_child_target (&the_ppc_fbsd_nat_target);
diff --git a/gdb/ppc-fbsd-tdep.c b/gdb/ppc-fbsd-tdep.c
index 3bab031..a666509 100644
--- a/gdb/ppc-fbsd-tdep.c
+++ b/gdb/ppc-fbsd-tdep.c
@@ -332,8 +332,7 @@ ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_return_value (gdbarch, ppcfbsd_return_value);
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
frame_unwind_append_unwinder (gdbarch, &ppcfbsd_sigtramp_frame_unwind);
set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc");
@@ -347,8 +346,7 @@ ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
ppc64_elf_make_msymbol_special);
set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code);
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc");
}
@@ -361,9 +359,7 @@ ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
ppcfbsd_get_thread_local_address);
}
-void _initialize_ppcfbsd_tdep ();
-void
-_initialize_ppcfbsd_tdep ()
+INIT_GDB_FILE (ppcfbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc, GDB_OSABI_FREEBSD,
ppcfbsd_init_abi);
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 0397ccb..568202a 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -3232,9 +3232,7 @@ ppc_linux_nat_target::get_arch_lwp_info (struct lwp_info *lp)
return lwp_arch_private_info (lp);
}
-void _initialize_ppc_linux_nat ();
-void
-_initialize_ppc_linux_nat ()
+INIT_GDB_FILE (ppc_linux_nat)
{
linux_target = &the_ppc_linux_nat_target;
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 441f317..b5f8bbf 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -32,7 +32,6 @@
#include "regset.h"
#include "solib-svr4.h"
#include "solib.h"
-#include "solist.h"
#include "ppc-tdep.h"
#include "ppc64-tdep.h"
#include "ppc-linux-tdep.h"
@@ -49,6 +48,7 @@
#include "arch-utils.h"
#include "xml-syscall.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "svr4-tls-tdep.h"
#include "linux-record.h"
#include "record-full.h"
@@ -61,7 +61,6 @@
#include "cli/cli-utils.h"
#include "parser-defs.h"
#include "user-regs.h"
-#include <ctype.h>
#include "elf-bfd.h"
#include "producer.h"
#include "target-float.h"
@@ -87,8 +86,6 @@
#include "features/rs6000/powerpc-e500l.c"
#include "dwarf2/frame.h"
-/* Shared library operations for PowerPC-Linux. */
-static solib_ops powerpc_so_ops;
/* The syscall's XML filename for PPC and PPC64. */
#define XML_SYSCALL_FILENAME_PPC "syscalls/ppc-linux.xml"
@@ -307,26 +304,45 @@ static const struct ppc_insn_pattern powerpc32_plt_stub_so_2[] =
/* The max number of insns we check using ppc_insns_match_pattern. */
#define POWERPC32_PLT_CHECK_LEN (ARRAY_SIZE (powerpc32_plt_stub) - 1)
-/* Check if PC is in PLT stub. For non-secure PLT, stub is in .plt
- section. For secure PLT, stub is in .text and we need to check
- instruction patterns. */
+/* solib_ops for ILP32 PowerPC/Linux systems. */
-static int
-powerpc_linux_in_dynsym_resolve_code (CORE_ADDR pc)
+struct ppc_linux_ilp32_svr4_solib_ops : public linux_ilp32_svr4_solib_ops
+{
+ using linux_ilp32_svr4_solib_ops::linux_ilp32_svr4_solib_ops;
+
+ /* Check if PC is in PLT stub. For non-secure PLT, stub is in .plt
+ section. For secure PLT, stub is in .text and we need to check
+ instruction patterns. */
+
+ bool in_dynsym_resolve_code (CORE_ADDR pc) const override;
+};
+
+/* Return a new solib_ops for ILP32 PowerPC/Linux systems. */
+
+static solib_ops_up
+make_ppc_linux_ilp32_svr4_solib_ops (program_space *pspace)
+{
+ return std::make_unique<ppc_linux_ilp32_svr4_solib_ops> (pspace);
+}
+
+/* See ppc_linux_ilp32_svr4_solib_ops. */
+
+bool
+ppc_linux_ilp32_svr4_solib_ops::in_dynsym_resolve_code (CORE_ADDR pc) const
{
/* Check whether PC is in the dynamic linker. This also checks
whether it is in the .plt section, used by non-PIC executables. */
- if (svr4_in_dynsym_resolve_code (pc))
- return 1;
+ if (linux_ilp32_svr4_solib_ops::in_dynsym_resolve_code (pc))
+ return true;
/* Check if we are in the resolver. */
bound_minimal_symbol sym = lookup_minimal_symbol_by_pc (pc);
- if (sym.minsym != NULL
- && (strcmp (sym.minsym->linkage_name (), "__glink") == 0
- || strcmp (sym.minsym->linkage_name (), "__glink_PLTresolve") == 0))
- return 1;
- return 0;
+ if (sym.minsym == nullptr)
+ return false;
+
+ return (strcmp (sym.minsym->linkage_name (), "__glink") == 0
+ || strcmp (sym.minsym->linkage_name (), "__glink_PLTresolve") == 0);
}
/* Follow PLT stub to actual routine.
@@ -1695,10 +1711,10 @@ static int
ppc_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
{
return (*s == 'i' /* Literal number. */
- || (isdigit (*s) && s[1] == '('
- && isdigit (s[2])) /* Displacement. */
- || (*s == '(' && isdigit (s[1])) /* Register indirection. */
- || isdigit (*s)); /* Register value. */
+ || (c_isdigit (*s) && s[1] == '('
+ && c_isdigit (s[2])) /* Displacement. */
+ || (*s == '(' && c_isdigit (s[1])) /* Register indirection. */
+ || c_isdigit (*s)); /* Register value. */
}
/* Implementation of `gdbarch_stap_parse_special_token', as defined in
@@ -1708,7 +1724,7 @@ static expr::operation_up
ppc_stap_parse_special_token (struct gdbarch *gdbarch,
struct stap_parse_info *p)
{
- if (isdigit (*p->arg))
+ if (c_isdigit (*p->arg))
{
/* This temporary pointer is needed because we have to do a lookahead.
We could be dealing with a register displacement, and in such case
@@ -1717,7 +1733,7 @@ ppc_stap_parse_special_token (struct gdbarch *gdbarch,
char *regname;
int len;
- while (isdigit (*s))
+ while (c_isdigit (*s))
++s;
if (*s == '(')
@@ -2266,8 +2282,6 @@ ppc_linux_init_abi (struct gdbarch_info info,
/* Shared library handling. */
set_gdbarch_skip_trampoline_code (gdbarch, ppc_skip_trampoline_code);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_ilp32_fetch_link_map_offsets);
/* Setting the correct XML syscall filename. */
set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_PPC);
@@ -2284,14 +2298,7 @@ ppc_linux_init_abi (struct gdbarch_info info,
else
set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc");
- if (powerpc_so_ops.in_dynsym_resolve_code == NULL)
- {
- powerpc_so_ops = svr4_so_ops;
- /* Override dynamic resolve function. */
- powerpc_so_ops.in_dynsym_resolve_code =
- powerpc_linux_in_dynsym_resolve_code;
- }
- set_gdbarch_so_ops (gdbarch, &powerpc_so_ops);
+ set_solib_svr4_ops (gdbarch, make_ppc_linux_ilp32_svr4_solib_ops);
set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
}
@@ -2318,8 +2325,7 @@ ppc_linux_init_abi (struct gdbarch_info info,
/* Shared library handling. */
set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_lp64_svr4_solib_ops);
/* Setting the correct XML syscall filename. */
set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_PPC64);
@@ -2393,9 +2399,7 @@ ppc_linux_init_abi (struct gdbarch_info info,
}
-void _initialize_ppc_linux_tdep ();
-void
-_initialize_ppc_linux_tdep ()
+INIT_GDB_FILE (ppc_linux_tdep)
{
/* Register for all sub-families of the POWER/PowerPC: 32-bit and
64-bit PowerPC, and the older rs6k. */
diff --git a/gdb/ppc-netbsd-nat.c b/gdb/ppc-netbsd-nat.c
index a8e65bb..dfb855a 100644
--- a/gdb/ppc-netbsd-nat.c
+++ b/gdb/ppc-netbsd-nat.c
@@ -183,9 +183,7 @@ ppcnbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
return 1;
}
-void _initialize_ppcnbsd_nat ();
-void
-_initialize_ppcnbsd_nat ()
+INIT_GDB_FILE (ppcnbsd_nat)
{
/* Support debugging kernel virtual memory images. */
bsd_kvm_add_target (ppcnbsd_supply_pcb);
diff --git a/gdb/ppc-netbsd-tdep.c b/gdb/ppc-netbsd-tdep.c
index 911c012..9913592 100644
--- a/gdb/ppc-netbsd-tdep.c
+++ b/gdb/ppc-netbsd-tdep.c
@@ -179,8 +179,7 @@ ppcnbsd_init_abi (struct gdbarch_info info,
set_gdbarch_return_value (gdbarch, ppcnbsd_return_value);
/* NetBSD uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
set_gdbarch_iterate_over_regset_sections
(gdbarch, ppcnbsd_iterate_over_regset_sections);
@@ -189,9 +188,7 @@ ppcnbsd_init_abi (struct gdbarch_info info,
tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd2_sigtramp);
}
-void _initialize_ppcnbsd_tdep ();
-void
-_initialize_ppcnbsd_tdep ()
+INIT_GDB_FILE (ppcnbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_NETBSD,
ppcnbsd_init_abi);
diff --git a/gdb/ppc-obsd-nat.c b/gdb/ppc-obsd-nat.c
index 1431aa6..48df9d7 100644
--- a/gdb/ppc-obsd-nat.c
+++ b/gdb/ppc-obsd-nat.c
@@ -186,9 +186,7 @@ ppcobsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
return 1;
}
-void _initialize_ppcobsd_nat ();
-void
-_initialize_ppcobsd_nat ()
+INIT_GDB_FILE (ppcobsd_nat)
{
add_inf_child_target (&the_ppc_obsd_nat_target);
diff --git a/gdb/ppc-obsd-tdep.c b/gdb/ppc-obsd-tdep.c
index 5e271c1..18f4d79 100644
--- a/gdb/ppc-obsd-tdep.c
+++ b/gdb/ppc-obsd-tdep.c
@@ -254,8 +254,7 @@ ppcobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_return_value (gdbarch, ppc_sysv_abi_broken_return_value);
/* OpenBSD uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
set_gdbarch_iterate_over_regset_sections
(gdbarch, ppcobsd_iterate_over_regset_sections);
@@ -263,9 +262,7 @@ ppcobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
frame_unwind_append_unwinder (gdbarch, &ppcobsd_sigtramp_frame_unwind);
}
-void _initialize_ppcobsd_tdep ();
-void
-_initialize_ppcobsd_tdep ()
+INIT_GDB_FILE (ppcobsd_tdep)
{
gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_OPENBSD,
ppcobsd_init_abi);
diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c
index bcf4e2a..f872f73 100644
--- a/gdb/ppc-sysv-tdep.c
+++ b/gdb/ppc-sysv-tdep.c
@@ -2060,10 +2060,12 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
}
/* Small character arrays are returned, right justified, in r3. */
- if (valtype->code () == TYPE_CODE_ARRAY
+ if (tdep->elf_abi == POWERPC_ELF_V1
+ && valtype->code () == TYPE_CODE_ARRAY
&& !valtype->is_vector ()
&& valtype->length () <= 8
- && valtype->target_type ()->code () == TYPE_CODE_INT
+ && (valtype->target_type ()->code () == TYPE_CODE_INT
+ || valtype->target_type ()->code () == TYPE_CODE_CHAR)
&& valtype->target_type ()->length () == 1)
{
int regnum = tdep->ppc_gp0_regnum + 3;
@@ -2112,6 +2114,7 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
/* In the ELFv2 ABI, aggregate types of up to 16 bytes are
returned in registers r3:r4. */
if (tdep->elf_abi == POWERPC_ELF_V2
+ && !TYPE_HAS_DYNAMIC_LENGTH (valtype)
&& valtype->length () <= 16
&& (valtype->code () == TYPE_CODE_STRUCT
|| valtype->code () == TYPE_CODE_UNION
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 6659c5a..53827ef 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -54,7 +54,6 @@
#include "source.h"
#include "gdbsupport/byte-vector.h"
#include <optional>
-#include "gdbsupport/gdb-safe-ctype.h"
#include "inferior.h"
/* Chain containing all defined memory-tag subcommands. */
@@ -753,10 +752,10 @@ pc_prefix (CORE_ADDR addr)
if (has_stack_frames ())
{
frame_info_ptr frame;
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
frame = get_selected_frame (NULL);
- if (get_frame_pc_if_available (frame, &pc) && pc == addr)
+ if ((pc = get_frame_pc_if_available (frame)) && *pc == addr)
return "=> ";
}
return " ";
@@ -1290,7 +1289,9 @@ should_validate_memtags (gdbarch *gdbarch, struct value *value)
return false;
/* We do. Check whether it includes any tags. */
- return target_is_address_tagged (gdbarch, value_as_address (value));
+ struct type *val_type = value->type ();
+ const gdb_byte *data = value->contents ().data ();
+ return target_is_address_tagged (gdbarch, unpack_pointer (val_type, data));
}
/* Helper for parsing arguments for print_command_1. */
@@ -1492,27 +1493,27 @@ info_symbol_command (const char *arg, int from_tty)
addr = parse_and_eval_address (arg);
for (objfile *objfile : current_program_space->objfiles ())
- for (obj_section *osect : objfile->sections ())
+ for (obj_section &osect : objfile->sections ())
{
/* Only process each object file once, even if there's a separate
debug file. */
if (objfile->separate_debug_objfile_backlink)
continue;
- sect_addr = overlay_mapped_address (addr, osect);
+ sect_addr = overlay_mapped_address (addr, &osect);
- if (osect->contains (sect_addr)
+ if (osect.contains (sect_addr)
&& (msymbol
= lookup_minimal_symbol_by_pc_section (sect_addr,
- osect).minsym))
+ &osect).minsym))
{
const char *obj_name, *mapped, *sec_name, *msym_name;
const char *loc_string;
matches = 1;
offset = sect_addr - msymbol->value_address (objfile);
- mapped = section_is_mapped (osect) ? _("mapped") : _("unmapped");
- sec_name = osect->the_bfd_section->name;
+ mapped = section_is_mapped (&osect) ? _("mapped") : _("unmapped");
+ sec_name = osect.the_bfd_section->name;
msym_name = msymbol->print_name ();
/* Don't print the offset if it is zero.
@@ -1526,12 +1527,12 @@ info_symbol_command (const char *arg, int from_tty)
else
loc_string = msym_name;
- gdb_assert (osect->objfile && objfile_name (osect->objfile));
- obj_name = objfile_name (osect->objfile);
+ gdb_assert (osect.objfile && objfile_name (osect.objfile));
+ obj_name = objfile_name (osect.objfile);
if (current_program_space->multi_objfile_p ())
- if (pc_in_unmapped_range (addr, osect))
- if (section_is_overlay (osect))
+ if (pc_in_unmapped_range (addr, &osect))
+ if (section_is_overlay (&osect))
gdb_printf (_("%s in load address range of "
"%s overlay section %s of %s\n"),
loc_string, mapped, sec_name, obj_name);
@@ -1540,15 +1541,15 @@ info_symbol_command (const char *arg, int from_tty)
"section %s of %s\n"),
loc_string, sec_name, obj_name);
else
- if (section_is_overlay (osect))
+ if (section_is_overlay (&osect))
gdb_printf (_("%s in %s overlay section %s of %s\n"),
loc_string, mapped, sec_name, obj_name);
else
gdb_printf (_("%s in section %s of %s\n"),
loc_string, sec_name, obj_name);
else
- if (pc_in_unmapped_range (addr, osect))
- if (section_is_overlay (osect))
+ if (pc_in_unmapped_range (addr, &osect))
+ if (section_is_overlay (&osect))
gdb_printf (_("%s in load address range of %s overlay "
"section %s\n"),
loc_string, mapped, sec_name);
@@ -1557,7 +1558,7 @@ info_symbol_command (const char *arg, int from_tty)
(_("%s in load address range of section %s\n"),
loc_string, sec_name);
else
- if (section_is_overlay (osect))
+ if (section_is_overlay (&osect))
gdb_printf (_("%s in %s overlay section %s\n"),
loc_string, mapped, sec_name);
else
@@ -1653,7 +1654,7 @@ info_address_command (const char *exp, int from_tty)
return;
}
- switch (sym->aclass ())
+ switch (sym->loc_class ())
{
case LOC_CONST:
case LOC_CONST_BYTES:
@@ -2394,7 +2395,7 @@ printf_c_string (struct ui_file *stream, const char *format,
}
else
{
- CORE_ADDR tem = value_as_address (value);;
+ CORE_ADDR tem = value_as_address (value);
if (tem == 0)
{
@@ -3183,9 +3184,7 @@ memory_tag_check_command (const char *args, int from_tty)
}
}
-void _initialize_printcmd ();
-void
-_initialize_printcmd ()
+INIT_GDB_FILE (printcmd)
{
struct cmd_list_element *c;
diff --git a/gdb/probe.c b/gdb/probe.c
index e6788ff..c2b8270 100644
--- a/gdb/probe.c
+++ b/gdb/probe.c
@@ -33,7 +33,6 @@
#include "ax.h"
#include "ax-gdb.h"
#include "location.h"
-#include <ctype.h>
#include <algorithm>
#include <optional>
@@ -826,7 +825,7 @@ probe_is_linespec_by_keyword (const char **linespecp, const char *const *keyword
const char *keyword = *csp;
size_t len = strlen (keyword);
- if (strncmp (s, keyword, len) == 0 && isspace (s[len]))
+ if (strncmp (s, keyword, len) == 0 && c_isspace (s[len]))
{
*linespecp += len + 1;
return 1;
@@ -973,9 +972,7 @@ static const struct internalvar_funcs probe_funcs =
std::vector<const static_probe_ops *> all_static_probe_ops;
-void _initialize_probe ();
-void
-_initialize_probe ()
+INIT_GDB_FILE (probe)
{
all_static_probe_ops.push_back (&any_static_probe_ops);
diff --git a/gdb/proc-api.c b/gdb/proc-api.c
index 7a45ba9..f3d4e14 100644
--- a/gdb/proc-api.c
+++ b/gdb/proc-api.c
@@ -413,9 +413,7 @@ proc_prettyfprint_status (long flags, int why, int what, int thread)
}
}
-void _initialize_proc_api ();
-void
-_initialize_proc_api ()
+INIT_GDB_FILE (proc_api)
{
add_setshow_boolean_cmd ("procfs-trace", no_class, &procfs_trace, _("\
Set tracing for /proc api calls."), _("\
diff --git a/gdb/proc-events.c b/gdb/proc-events.c
index 23af639..c6ed1f4 100644
--- a/gdb/proc-events.c
+++ b/gdb/proc-events.c
@@ -759,9 +759,7 @@ proc_prettyprint_actionset (struct sigaction *actions, int verbose)
{
}
-void _initialize_proc_events ();
-void
-_initialize_proc_events ()
+INIT_GDB_FILE (proc_events)
{
init_syscall_table ();
}
diff --git a/gdb/proc-service.c b/gdb/proc-service.c
index af92335..4f2be0f 100644
--- a/gdb/proc-service.c
+++ b/gdb/proc-service.c
@@ -206,9 +206,7 @@ ps_getpid (struct ps_prochandle *ph)
return ph->thread->ptid.pid ();
}
-void _initialize_proc_service ();
-void
-_initialize_proc_service ()
+INIT_GDB_FILE (proc_service)
{
/* This function solely exists to make sure this module is linked
into the final binary. */
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 76a6168..ca7ecbb 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -38,7 +38,6 @@
#include <sys/syscall.h>
#include "gdbsupport/gdb_wait.h"
#include <signal.h>
-#include <ctype.h>
#include "gdb_bfd.h"
#include "auxv.h"
#include "procfs.h"
@@ -3304,7 +3303,7 @@ procfs_target::info_proc (const char *args, enum info_proc_what what)
gdb_argv built_argv (args);
for (char *arg : built_argv)
{
- if (isdigit (arg[0]))
+ if (c_isdigit (arg[0]))
{
pid = strtoul (arg, &tmp, 10);
if (*tmp == '/')
@@ -3415,7 +3414,7 @@ proc_trace_syscalls (const char *args, int from_tty, int entry_or_exit, int mode
error_no_arg (_("system call to trace"));
pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
- if (isdigit (args[0]))
+ if (c_isdigit (args[0]))
{
const int syscallnum = atoi (args);
@@ -3447,9 +3446,7 @@ proc_untrace_sysexit_cmd (const char *args, int from_tty)
proc_trace_syscalls (args, from_tty, PR_SYSEXIT, FLAG_RESET);
}
-void _initialize_procfs ();
-void
-_initialize_procfs ()
+INIT_GDB_FILE (procfs)
{
add_com ("proc-trace-entry", no_class, proc_trace_sysentry_cmd,
_("Give a trace of entries into the syscall."));
@@ -3550,21 +3547,17 @@ procfs_corefile_thread_callback (procinfo *pi, procinfo *thread, void *data)
return 0;
}
-static int
-find_signalled_thread (struct thread_info *info, void *data)
+static bool
+find_signalled_thread (struct thread_info *info)
{
- if (info->stop_signal () != GDB_SIGNAL_0
- && info->ptid.pid () == inferior_ptid.pid ())
- return 1;
-
- return 0;
+ return (info->stop_signal () != GDB_SIGNAL_0
+ && info->ptid.pid () == inferior_ptid.pid ());
}
static enum gdb_signal
find_stop_signal (void)
{
- struct thread_info *info =
- iterate_over_threads (find_signalled_thread, NULL);
+ struct thread_info *info = iterate_over_threads (find_signalled_thread);
if (info)
return info->stop_signal ();
diff --git a/gdb/producer.c b/gdb/producer.c
index d8cbded..71e1b92 100644
--- a/gdb/producer.c
+++ b/gdb/producer.c
@@ -66,9 +66,9 @@ producer_is_gcc (const char *producer, int *major, int *minor)
"GNU Fortran 4.8.2 20140120 (Red Hat 4.8.2-16) -mtune=generic ..."
"GNU C++14 5.0.0 20150123 (experimental)"
*/
- while (*cs && !isspace (*cs))
+ while (*cs && !c_isspace (*cs))
cs++;
- if (*cs && isspace (*cs))
+ if (*cs && c_isspace (*cs))
cs++;
if (sscanf (cs, "%d.%d", major, minor) == 2)
return 1;
@@ -335,9 +335,7 @@ Version 18.0 Beta";
}
#endif
-void _initialize_producer ();
-void
-_initialize_producer ()
+INIT_GDB_FILE (producer)
{
#if defined GDB_SELF_TEST
selftests::register_test
diff --git a/gdb/progspace.c b/gdb/progspace.c
index eda6379..9928c16 100644
--- a/gdb/progspace.c
+++ b/gdb/progspace.c
@@ -21,7 +21,6 @@
#include "objfiles.h"
#include "gdbcore.h"
#include "solib.h"
-#include "solist.h"
#include "gdbthread.h"
#include "inferior.h"
#include <algorithm>
@@ -147,6 +146,21 @@ program_space::free_all_objfiles ()
/* See progspace.h. */
void
+program_space::iterate_over_objfiles_in_search_order
+ (iterate_over_objfiles_in_search_order_cb_ftype cb, objfile *current_objfile)
+{
+ if (m_solib_ops != nullptr)
+ return m_solib_ops->iterate_over_objfiles_in_search_order
+ (cb, current_objfile);
+
+ for (const auto objfile : this->objfiles ())
+ if (cb (objfile))
+ return;
+}
+
+/* See progspace.h. */
+
+void
program_space::add_objfile (std::unique_ptr<objfile> &&objfile,
struct objfile *before)
{
diff --git a/gdb/progspace.h b/gdb/progspace.h
index 1ae826d..270a71d 100644
--- a/gdb/progspace.h
+++ b/gdb/progspace.h
@@ -21,12 +21,13 @@
#ifndef GDB_PROGSPACE_H
#define GDB_PROGSPACE_H
+#include "solib.h"
#include "target.h"
#include "gdb_bfd.h"
#include "registry.h"
-#include "solist.h"
#include "gdbsupport/safe-iterator.h"
#include "gdbsupport/intrusive_list.h"
+#include "gdbsupport/owning_intrusive_list.h"
#include "gdbsupport/refcounted-object.h"
#include "gdbsupport/gdb_ref_ptr.h"
#include <vector>
@@ -211,6 +212,18 @@ struct program_space
(objfiles_range (objfiles_iterator (m_objfiles_list.begin ())));
}
+ /* Iterate over all objfiles of the program space in the order that makes the
+ most sense to make global symbol searches.
+
+ CB is a callback function passed an objfile to be searched. The iteration stops
+ if this function returns true.
+
+ If not nullptr, CURRENT_OBJFILE corresponds to the objfile being
+ inspected when the symbol search was requested. */
+ void iterate_over_objfiles_in_search_order
+ (iterate_over_objfiles_in_search_order_cb_ftype cb,
+ objfile *current_objfile);
+
/* Add OBJFILE to the list of objfiles, putting it just before
BEFORE. If BEFORE is nullptr, it will go at the end of the
list. */
@@ -231,9 +244,30 @@ struct program_space
is outside all objfiles in this progspace. */
struct objfile *objfile_for_address (CORE_ADDR address);
- /* Return the list of all the solibs in this program space. */
+ /* Set this program space's solib provider.
+
+ The solib provider must be unset prior to calling this method. */
+ void set_solib_ops (solib_ops_up ops)
+ {
+ gdb_assert (m_solib_ops == nullptr);
+ m_solib_ops = std::move (ops);
+ };
+
+ /* Unset and free this program space's solib provider. */
+ void unset_solib_ops ()
+ { m_solib_ops = nullptr; }
+
+ /* Unset and return this program space's solib provider. */
+ solib_ops_up release_solib_ops ()
+ { return std::move (m_solib_ops); }
+
+ /* Get this program space's solib provider. */
+ const struct solib_ops *solib_ops () const
+ { return m_solib_ops.get (); }
+
+ /* Return the list of all the solibs in this program space. */
owning_intrusive_list<solib> &solibs ()
- { return so_list; }
+ { return m_solib_list; }
/* Similar to `bfd_get_filename (exec_bfd ())` but in original form given
by user, without symbolic links and pathname resolved. It is not nullptr
@@ -337,10 +371,6 @@ struct program_space
(e.g. the argument to the "symbol-file" or "file" command). */
struct objfile *symfile_object_file = NULL;
- /* List of shared objects mapped into this space. Managed by
- solib.c. */
- owning_intrusive_list<solib> so_list;
-
/* Number of calls to solib_add. */
unsigned int solib_add_generation = 0;
@@ -359,6 +389,13 @@ private:
/* All known objfiles are kept in a linked list. */
owning_intrusive_list<objfile> m_objfiles_list;
+ /* solib_ops implementation used to provide solibs in this program space. */
+ solib_ops_up m_solib_ops;
+
+ /* List of shared objects mapped into this space. Managed by
+ solib.c. */
+ owning_intrusive_list<solib> m_solib_list;
+
/* The set of target sections matching the sections mapped into
this program space. Managed by both exec_ops and solib.c. */
std::vector<target_section> m_target_sections;
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index 986ef44..6d19e76 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -228,7 +228,7 @@ find_pc_sect_psymbol (struct objfile *objfile,
for (const partial_symbol *p : psymtab->global_psymbols)
{
if (p->domain == VAR_DOMAIN
- && p->aclass == LOC_BLOCK
+ && p->loc_class == LOC_BLOCK
&& pc >= p->address (objfile)
&& (p->address (objfile) > best_pc
|| (psymtab->text_low (objfile) == 0
@@ -248,7 +248,7 @@ find_pc_sect_psymbol (struct objfile *objfile,
for (const partial_symbol *p : psymtab->static_psymbols)
{
if (p->domain == VAR_DOMAIN
- && p->aclass == LOC_BLOCK
+ && p->loc_class == LOC_BLOCK
&& pc >= p->address (objfile)
&& (p->address (objfile) > best_pc
|| (psymtab->text_low (objfile) == 0
@@ -537,7 +537,7 @@ print_partial_symbols (struct gdbarch *gdbarch, struct objfile *objfile,
gdb_puts ("<invalid domain>, ", outfile);
break;
}
- switch (p->aclass)
+ switch (p->loc_class)
{
case LOC_UNDEF:
gdb_puts ("undefined", outfile);
@@ -790,7 +790,7 @@ psymtab_to_fullname (struct partial_symtab *ps)
return ps->fullname;
}
-/* A helper for psym_expand_symtabs_matching that handles searching
+/* A helper for psymbol_functions::search that handles searching
included psymtabs. This returns true if a symbol is found, and
false otherwise. It also updates the 'searched_flag' on the
various psymtabs that it searches. */
@@ -800,7 +800,7 @@ recursively_search_psymtabs (partial_symtab *ps, objfile *objfile,
block_search_flags search_flags,
domain_search_flags domain,
const lookup_name_info &lookup_name,
- expand_symtabs_symbol_matcher sym_matcher)
+ search_symtabs_symbol_matcher sym_matcher)
{
int keep_going = 1;
enum psymtab_search_status result = PST_SEARCHED_AND_NOT_FOUND;
@@ -885,19 +885,19 @@ recursively_search_psymtabs (partial_symtab *ps, objfile *objfile,
return result == PST_SEARCHED_AND_FOUND;
}
-/* Psymtab version of expand_symtabs_matching. See its definition in
+/* Psymtab version of search. See its definition in
the definition of quick_symbol_functions in symfile.h. */
bool
-psymbol_functions::expand_symtabs_matching
+psymbol_functions::search
(struct objfile *objfile,
- expand_symtabs_file_matcher file_matcher,
+ search_symtabs_file_matcher file_matcher,
const lookup_name_info *lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
+ search_symtabs_symbol_matcher symbol_matcher,
+ search_symtabs_expansion_listener listener,
block_search_flags search_flags,
domain_search_flags domain,
- expand_symtabs_lang_matcher lang_matcher ATTRIBUTE_UNUSED)
+ search_symtabs_lang_matcher lang_matcher ATTRIBUTE_UNUSED)
{
/* Clear the search flags. */
for (partial_symtab *ps : partial_symbols (objfile))
@@ -914,9 +914,6 @@ psymbol_functions::expand_symtabs_matching
{
QUIT;
- if (ps->readin_p (objfile))
- continue;
-
if (file_matcher)
{
bool match;
@@ -944,8 +941,8 @@ psymbol_functions::expand_symtabs_matching
{
compunit_symtab *cust = psymtab_to_symtab (objfile, ps);
- if (cust != nullptr && expansion_notify != nullptr)
- if (!expansion_notify (cust))
+ if (cust != nullptr && listener != nullptr)
+ if (!listener (cust))
return false;
}
}
@@ -1022,12 +1019,12 @@ psymbol_bcache::hash (const void *addr, int length)
struct partial_symbol *psymbol = (struct partial_symbol *) addr;
unsigned int lang = psymbol->ginfo.language ();
unsigned int domain = psymbol->domain;
- unsigned int theclass = psymbol->aclass;
+ unsigned int loc_class = psymbol->loc_class;
h = fast_hash (&psymbol->ginfo.m_value, sizeof (psymbol->ginfo.m_value), h);
h = fast_hash (&lang, sizeof (unsigned int), h);
h = fast_hash (&domain, sizeof (unsigned int), h);
- h = fast_hash (&theclass, sizeof (unsigned int), h);
+ h = fast_hash (&loc_class, sizeof (unsigned int), h);
/* Note that psymbol names are interned via compute_and_set_names, so
there's no need to hash the contents of the name here. */
h = fast_hash (&psymbol->ginfo.m_name, sizeof (psymbol->ginfo.m_name), h);
@@ -1047,7 +1044,7 @@ psymbol_bcache::compare (const void *addr1, const void *addr2, int length)
sizeof (sym1->ginfo.m_value)) == 0
&& sym1->ginfo.language () == sym2->ginfo.language ()
&& sym1->domain == sym2->domain
- && sym1->aclass == sym2->aclass
+ && sym1->loc_class == sym2->loc_class
/* Note that psymbol names are interned via
compute_and_set_names, so there's no need to compare the
contents of the name here. */
@@ -1085,7 +1082,7 @@ partial_symtab::add_psymbol (const partial_symbol &psymbol,
void
partial_symtab::add_psymbol (std::string_view name, bool copy_name,
domain_enum domain,
- enum address_class theclass,
+ location_class loc_class,
int section,
psymbol_placement where,
unrelocated_addr coreaddr,
@@ -1099,7 +1096,7 @@ partial_symtab::add_psymbol (std::string_view name, bool copy_name,
psymbol.set_unrelocated_address (coreaddr);
psymbol.ginfo.set_section_index (section);
psymbol.domain = domain;
- psymbol.aclass = theclass;
+ psymbol.loc_class = loc_class;
psymbol.ginfo.set_language (language, partial_symtabs->obstack ());
psymbol.ginfo.compute_and_set_names (name, copy_name, objfile->per_bfd);
@@ -1498,7 +1495,7 @@ maintenance_check_psymtabs (const char *ignore, int from_tty)
{
/* Skip symbols for inlined functions without address. These may
or may not have a match in the full symtab. */
- if (psym->aclass == LOC_BLOCK
+ if (psym->loc_class == LOC_BLOCK
&& psym->ginfo.value_address () == 0)
continue;
@@ -1552,9 +1549,7 @@ maintenance_check_psymtabs (const char *ignore, int from_tty)
}
}
-void _initialize_psymtab ();
-void
-_initialize_psymtab ()
+INIT_GDB_FILE (psymtab)
{
add_cmd ("psymbols", class_maintenance, maintenance_print_psymbols, _("\
Print dump of current partial symbol definitions.\n\
diff --git a/gdb/psymtab.h b/gdb/psymtab.h
index ad0b2ff..b1c3ad7 100644
--- a/gdb/psymtab.h
+++ b/gdb/psymtab.h
@@ -184,10 +184,10 @@ struct partial_symbol
ENUM_BITFIELD(domain_enum) domain : SYMBOL_DOMAIN_BITS;
/* Address class (for info_symbols). Note that we don't allow
- synthetic "aclass" values here at present, simply because there's
+ synthetic "loc_class" values here at present, simply because there's
no need. */
- ENUM_BITFIELD(address_class) aclass : SYMBOL_ACLASS_BITS;
+ ENUM_BITFIELD(location_class) loc_class : SYMBOL_LOC_CLASS_BITS;
};
/* A convenience enum to give names to some constants used when
@@ -333,7 +333,7 @@ struct partial_symtab
If COPY_NAME is true, make a copy of NAME, otherwise use the passed
reference.
- THECLASS is the type of symbol.
+ LOC_CLASS is the type of symbol.
SECTION is the index of the section of OBJFILE in which the symbol is found.
@@ -348,7 +348,7 @@ struct partial_symtab
void add_psymbol (std::string_view name,
bool copy_name, domain_enum domain,
- enum address_class theclass,
+ location_class loc_class,
int section,
psymbol_placement where,
unrelocated_addr coreaddr,
@@ -626,15 +626,15 @@ struct psymbol_functions : public quick_symbol_functions
void expand_all_symtabs (struct objfile *objfile) override;
- bool expand_symtabs_matching
+ bool search
(struct objfile *objfile,
- expand_symtabs_file_matcher file_matcher,
+ search_symtabs_file_matcher file_matcher,
const lookup_name_info *lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
+ search_symtabs_symbol_matcher symbol_matcher,
+ search_symtabs_expansion_listener listener,
block_search_flags search_flags,
domain_search_flags kind,
- expand_symtabs_lang_matcher lang_matcher) override;
+ search_symtabs_lang_matcher lang_matcher) override;
struct compunit_symtab *find_pc_sect_compunit_symtab
(struct objfile *objfile, bound_minimal_symbol msymbol, CORE_ADDR pc,
diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py
index 4ea5d06..cedd897 100644
--- a/gdb/python/lib/gdb/__init__.py
+++ b/gdb/python/lib/gdb/__init__.py
@@ -19,17 +19,22 @@ import sys
import threading
import traceback
from contextlib import contextmanager
+from importlib import reload
-# Python 3 moved "reload"
-if sys.version_info >= (3, 4):
- from importlib import reload
-else:
- from imp import reload
-
-import _gdb
-
+# The star import imports _gdb names. When the names are used locally, they
+# trigger F405 warnings unless added to the explicit import list.
# Note that two indicators are needed here to silence flake8.
from _gdb import * # noqa: F401,F403
+from _gdb import (
+ STDERR,
+ STDOUT,
+ Command,
+ execute,
+ flush,
+ parameter,
+ selected_inferior,
+ write,
+)
# isort: split
@@ -60,14 +65,14 @@ class _GdbFile(object):
self.write(line)
def flush(self):
- _gdb.flush(stream=self.stream)
+ flush(stream=self.stream)
def write(self, s):
- _gdb.write(s, stream=self.stream)
+ write(s, stream=self.stream)
-sys.stdout = _GdbFile(_gdb.STDOUT)
-sys.stderr = _GdbFile(_gdb.STDERR)
+sys.stdout = _GdbFile(STDOUT)
+sys.stderr = _GdbFile(STDERR)
# Default prompt hook does nothing.
prompt_hook = None
@@ -189,7 +194,7 @@ def GdbSetPythonDirectory(dir):
def current_progspace():
"Return the current Progspace."
- return _gdb.selected_inferior().progspace
+ return selected_inferior().progspace
def objfiles():
@@ -226,14 +231,14 @@ def set_parameter(name, value):
value = "on"
else:
value = "off"
- _gdb.execute("set " + name + " " + str(value), to_string=True)
+ execute("set " + name + " " + str(value), to_string=True)
@contextmanager
def with_parameter(name, value):
"""Temporarily set the GDB parameter NAME to VALUE.
Note that this is a context manager."""
- old_value = _gdb.parameter(name)
+ old_value = parameter(name)
set_parameter(name, value)
try:
# Nothing that useful to return.
@@ -392,3 +397,121 @@ def _handle_missing_objfile(pspace, buildid, filename):
return _handle_missing_files(
pspace, "objfile", lambda h: h(pspace, buildid, filename)
)
+
+
+class ParameterPrefix:
+ # A wrapper around gdb.Command for creating set/show prefixes.
+ #
+ # When creating a gdb.Parameter sub-classes, it is sometimes necessary
+ # to first create a gdb.Command object in order to create the needed
+ # command prefix. However, for parameters, we actually need two
+ # prefixes, a 'set' prefix, and a 'show' prefix. With this helper
+ # class, a single instance of this class will create both prefixes at
+ # once.
+ #
+ # It is important that this class-level documentation not be a __doc__
+ # string. Users are expected to sub-class this ParameterPrefix class
+ # and add their own documentation. If they don't, then GDB will
+ # generate a suitable doc string. But, if this (parent) class has a
+ # __doc__ string of its own, then sub-classes will inherit that __doc__
+ # string, and GDB will not understand that it needs to generate one.
+
+ class _PrefixCommand(Command):
+ """A gdb.Command used to implement both the set and show prefixes.
+
+ This documentation string is not used as the prefix command
+ documentation as it is overridden in the __init__ method below."""
+
+ # This private method is connected to the 'invoke' attribute within
+ # this _PrefixCommand object if the containing ParameterPrefix
+ # object has an invoke_set or invoke_show method.
+ #
+ # This method records within self.__delegate which _PrefixCommand
+ # object is currently active, and then calls the correct invoke
+ # method on the delegat object (the ParameterPrefix sub-class
+ # object).
+ #
+ # Recording the currently active _PrefixCommand object is important;
+ # if from the invoke method the user calls dont_repeat, then this is
+ # forwarded to the currently active _PrefixCommand object.
+ def __invoke(self, args, from_tty):
+
+ # A helper class for use as part of a Python 'with' block.
+ # Records which gdb.Command object is currently running its
+ # invoke method.
+ class MarkActiveCallback:
+ # The CMD is a _PrefixCommand object, and the DELEGATE is
+ # the ParameterPrefix class, or sub-class object. At this
+ # point we simple record both of these within the
+ # MarkActiveCallback object.
+ def __init__(self, cmd, delegate):
+ self.__cmd = cmd
+ self.__delegate = delegate
+
+ # Record the currently active _PrefixCommand object within
+ # the outer ParameterPrefix sub-class object.
+ def __enter__(self):
+ self.__delegate.active_prefix = self.__cmd
+
+ # Once the invoke method has completed, then clear the
+ # _PrefixCommand object that was stored into the outer
+ # ParameterPrefix sub-class object.
+ def __exit__(self, exception_type, exception_value, traceback):
+ self.__delegate.active_prefix = None
+
+ # The self.__cb attribute is set when the _PrefixCommand object
+ # is created, and is either invoke_set or invoke_show within the
+ # ParameterPrefix sub-class object.
+ assert callable(self.__cb)
+
+ # Record the currently active _PrefixCommand object within the
+ # ParameterPrefix sub-class object, then call the relevant
+ # invoke method within the ParameterPrefix sub-class object.
+ with MarkActiveCallback(self, self.__delegate):
+ self.__cb(args, from_tty)
+
+ @staticmethod
+ def __find_callback(delegate, mode):
+ """The MODE is either 'set' or 'show'. Look for an invoke_MODE method
+ on DELEGATE, if a suitable method is found, then return it, otherwise,
+ return None.
+ """
+ cb = getattr(delegate, "invoke_" + mode, None)
+ if callable(cb):
+ return cb
+ return None
+
+ def __init__(self, mode, name, cmd_class, delegate, doc=None):
+ """Setup this gdb.Command. Mode is a string, either 'set' or 'show'.
+ NAME is the name for this prefix command, that is, the
+ words that appear after both 'set' and 'show' in the
+ command name. CMD_CLASS is the usual enum. And DELEGATE
+ is the gdb.ParameterPrefix object this prefix is part of.
+ """
+ assert mode == "set" or mode == "show"
+ if doc is None:
+ self.__doc__ = delegate.__doc__
+ else:
+ self.__doc__ = doc
+ self.__cb = self.__find_callback(delegate, mode)
+ self.__delegate = delegate
+ if self.__cb is not None:
+ self.invoke = self.__invoke
+ super().__init__(mode + " " + name, cmd_class, prefix=True)
+
+ def __init__(self, name, cmd_class, doc=None):
+ """Create a _PrefixCommand for both the set and show prefix commands.
+ NAME is the command name without either the leading 'set ' or
+ 'show ' strings, and CMD_CLASS is the usual enum value.
+ """
+ self.active_prefix = None
+ self._set_prefix_cmd = self._PrefixCommand("set", name, cmd_class, self, doc)
+ self._show_prefix_cmd = self._PrefixCommand("show", name, cmd_class, self, doc)
+
+ # When called from within an invoke method the self.active_prefix
+ # attribute should be set to a gdb.Command sub-class (a _PrefixCommand
+ # object, see above). Forward the dont_repeat call to this object to
+ # register the actual command as none repeating.
+ def dont_repeat(self):
+ if self.active_prefix is not None:
+ self.active_prefix.dont_repeat()
diff --git a/gdb/python/lib/gdb/dap/breakpoint.py b/gdb/python/lib/gdb/dap/breakpoint.py
index 59da120..4d4ca18 100644
--- a/gdb/python/lib/gdb/dap/breakpoint.py
+++ b/gdb/python/lib/gdb/dap/breakpoint.py
@@ -326,7 +326,7 @@ def _rewrite_fn_breakpoint(
}
-@request("setFunctionBreakpoints")
+@request("setFunctionBreakpoints", expect_stopped=False)
@capability("supportsFunctionBreakpoints")
def set_fn_breakpoint(*, breakpoints: Sequence, **args):
specs = [_rewrite_fn_breakpoint(**bp) for bp in breakpoints]
@@ -359,7 +359,7 @@ def _rewrite_insn_breakpoint(
}
-@request("setInstructionBreakpoints")
+@request("setInstructionBreakpoints", expect_stopped=False)
@capability("supportsInstructionBreakpoints")
def set_insn_breakpoints(
*, breakpoints: Sequence, offset: Optional[int] = None, **args
@@ -410,7 +410,7 @@ def _rewrite_exception_breakpoint(
}
-@request("setExceptionBreakpoints")
+@request("setExceptionBreakpoints", expect_stopped=False)
@capability("supportsExceptionFilterOptions")
@capability(
"exceptionBreakpointFilters",
diff --git a/gdb/python/lib/gdb/dap/completions.py b/gdb/python/lib/gdb/dap/completions.py
index 85acc43..e5003ff 100644
--- a/gdb/python/lib/gdb/dap/completions.py
+++ b/gdb/python/lib/gdb/dap/completions.py
@@ -39,8 +39,11 @@ def completions(
line = 1
else:
line = import_line(line)
- text = text.splitlines()[line - 1]
- text = text[: column - 1]
+ if text:
+ text = text.splitlines()[line - 1]
+ text = text[: column - 1]
+ else:
+ text = ""
mi_result = exec_mi_and_log("-complete", text)
result = []
completion = None
diff --git a/gdb/python/lib/gdb/dap/evaluate.py b/gdb/python/lib/gdb/dap/evaluate.py
index 55538e6..fcbcc99 100644
--- a/gdb/python/lib/gdb/dap/evaluate.py
+++ b/gdb/python/lib/gdb/dap/evaluate.py
@@ -69,7 +69,7 @@ def _repl(command, frame_id):
}
-@request("evaluate")
+@request("evaluate", defer_events=False)
@capability("supportsEvaluateForHovers")
@capability("supportsValueFormattingOptions")
def eval_request(
@@ -110,7 +110,7 @@ def variables(
@capability("supportsSetExpression")
-@request("setExpression")
+@request("setExpression", defer_events=False)
def set_expression(
*, expression: str, value: str, frameId: Optional[int] = None, format=None, **args
):
@@ -126,7 +126,7 @@ def set_expression(
@capability("supportsSetVariable")
-@request("setVariable")
+@request("setVariable", defer_events=False)
def set_variable(
*, variablesReference: int, name: str, value: str, format=None, **args
):
diff --git a/gdb/python/lib/gdb/dap/events.py b/gdb/python/lib/gdb/dap/events.py
index 4dc9d65..e8f2655 100644
--- a/gdb/python/lib/gdb/dap/events.py
+++ b/gdb/python/lib/gdb/dap/events.py
@@ -17,12 +17,12 @@ import gdb
from .modules import is_module, make_module
from .scopes import set_finish_value
-from .server import send_event, send_event_maybe_later
+from .server import send_event
from .startup import exec_and_log, in_gdb_thread, log
# True when the inferior is thought to be running, False otherwise.
# This may be accessed from any thread, which can be racy. However,
-# this unimportant because this global is only used for the
+# this is unimportant because this global is only used for the
# 'notStopped' response, which itself is inherently racy.
inferior_running = False
@@ -240,7 +240,7 @@ def _on_stop(event):
else:
obj["reason"] = stop_reason_map[event.details["reason"]]
_expected_pause = False
- send_event_maybe_later("stopped", obj)
+ send_event("stopped", obj)
# This keeps a bit of state between the start of an inferior call and
diff --git a/gdb/python/lib/gdb/dap/next.py b/gdb/python/lib/gdb/dap/next.py
index ddf4e05..898fff1 100644
--- a/gdb/python/lib/gdb/dap/next.py
+++ b/gdb/python/lib/gdb/dap/next.py
@@ -16,7 +16,7 @@
import gdb
from .events import exec_and_expect_stop
-from .server import capability, request, send_gdb, send_gdb_with_response
+from .server import capability, request
from .startup import in_gdb_thread
from .state import set_thread
@@ -73,19 +73,14 @@ def step_in(
exec_and_expect_stop(cmd)
-@request("stepOut", defer_stop_events=True)
+@request("stepOut")
def step_out(*, threadId: int, singleThread: bool = False, **args):
_handle_thread_step(threadId, singleThread, True)
exec_and_expect_stop("finish &", propagate_exception=True)
-# This is a server-side request because it is funny: it wants to
-# 'continue' but also return a result, which precludes using
-# response=False. Using 'continue &' would mostly work ok, but this
-# yields races when a stop occurs before the response is sent back to
-# the client.
-@request("continue", on_dap_thread=True)
+@request("continue")
def continue_request(*, threadId: int, singleThread: bool = False, **args):
- locked = send_gdb_with_response(lambda: _handle_thread_step(threadId, singleThread))
- send_gdb(lambda: exec_and_expect_stop("continue"))
+ locked = _handle_thread_step(threadId, singleThread)
+ exec_and_expect_stop("continue &")
return {"allThreadsContinued": not locked}
diff --git a/gdb/python/lib/gdb/dap/server.py b/gdb/python/lib/gdb/dap/server.py
index c4fa781..7dab582 100644
--- a/gdb/python/lib/gdb/dap/server.py
+++ b/gdb/python/lib/gdb/dap/server.py
@@ -74,6 +74,13 @@ class DeferredRequest:
self._result = result
@in_dap_thread
+ def defer_events(self):
+ """Return True if events should be deferred during execution.
+
+ This may be overridden by subclasses."""
+ return True
+
+ @in_dap_thread
def invoke(self):
"""Implement the deferred request.
@@ -95,7 +102,10 @@ class DeferredRequest:
"""
with _server.canceller.current_request(self._req):
+ if self.defer_events():
+ _server.set_defer_events()
_server.invoke_request(self._req, self._result, self.invoke)
+ _server.emit_pending_events()
# A subclass of Exception that is used solely for reporting that a
@@ -230,7 +240,7 @@ class Server:
self._out_stream = out_stream
self._child_stream = child_stream
self._delayed_fns_lock = threading.Lock()
- self.defer_stop_events = False
+ self._defer_events = False
self._delayed_fns = []
# This queue accepts JSON objects that are then sent to the
# DAP client. Writing is done in a separate thread to avoid
@@ -316,7 +326,7 @@ class Server:
def _read_inferior_output(self):
while True:
line = self._child_stream.readline()
- self.send_event(
+ self.send_event_maybe_later(
"output",
{
"category": "stdout",
@@ -356,6 +366,17 @@ class Server:
self._read_queue.put(None)
@in_dap_thread
+ def emit_pending_events(self):
+ """Emit any pending events."""
+ fns = None
+ with self._delayed_fns_lock:
+ fns = self._delayed_fns
+ self._delayed_fns = []
+ self._defer_events = False
+ for fn in fns:
+ fn()
+
+ @in_dap_thread
def main_loop(self):
"""The main loop of the DAP server."""
# Before looping, start the thread that writes JSON to the
@@ -371,13 +392,7 @@ class Server:
req = cmd["seq"]
with self.canceller.current_request(req):
self._handle_command(cmd)
- fns = None
- with self._delayed_fns_lock:
- fns = self._delayed_fns
- self._delayed_fns = []
- self.defer_stop_events = False
- for fn in fns:
- fn()
+ self.emit_pending_events()
# Got the terminate request. This is handled by the
# JSON-writing thread, so that we can ensure that all
# responses are flushed to the client before exiting.
@@ -386,13 +401,13 @@ class Server:
send_gdb("quit")
@in_dap_thread
- def send_event_later(self, event, body=None):
- """Send a DAP event back to the client, but only after the
- current request has completed."""
+ def set_defer_events(self):
+ """Defer any events until the current request has completed."""
with self._delayed_fns_lock:
- self._delayed_fns.append(lambda: self.send_event(event, body))
+ self._defer_events = True
- @in_gdb_thread
+ # Note that this does not need to be run in any particular thread,
+ # because it uses locks for thread-safety.
def send_event_maybe_later(self, event, body=None):
"""Send a DAP event back to the client, but if a request is in-flight
within the dap thread and that request is configured to delay the event,
@@ -401,10 +416,10 @@ class Server:
with self.canceller.lock:
if self.canceller.in_flight_dap_thread:
with self._delayed_fns_lock:
- if self.defer_stop_events:
- self._delayed_fns.append(lambda: self.send_event(event, body))
+ if self._defer_events:
+ self._delayed_fns.append(lambda: self._send_event(event, body))
return
- self.send_event(event, body)
+ self._send_event(event, body)
@in_dap_thread
def call_function_later(self, fn):
@@ -415,7 +430,7 @@ class Server:
# Note that this does not need to be run in any particular thread,
# because it just creates an object and writes it to a thread-safe
# queue.
- def send_event(self, event, body=None):
+ def _send_event(self, event, body=None):
"""Send an event to the DAP client.
EVENT is the name of the event, a string.
BODY is the body of the event, an arbitrary object."""
@@ -439,14 +454,6 @@ def send_event(event, body=None):
"""Send an event to the DAP client.
EVENT is the name of the event, a string.
BODY is the body of the event, an arbitrary object."""
- _server.send_event(event, body)
-
-
-def send_event_maybe_later(event, body=None):
- """Send a DAP event back to the client, but if a request is in-flight
- within the dap thread and that request is configured to delay the event,
- wait until the response has been sent until the event is sent back to
- the client."""
_server.send_event_maybe_later(event, body)
@@ -476,7 +483,7 @@ def request(
response: bool = True,
on_dap_thread: bool = False,
expect_stopped: bool = True,
- defer_stop_events: bool = False
+ defer_events: bool = True
):
"""A decorator for DAP requests.
@@ -498,9 +505,9 @@ def request(
inferior is running. When EXPECT_STOPPED is False, the request
will proceed regardless of the inferior's state.
- If DEFER_STOP_EVENTS is True, then make sure any stop events sent
- during the request processing are not sent to the client until the
- response has been sent.
+ If DEFER_EVENTS is True, then make sure any events sent during the
+ request processing are not sent to the client until the response
+ has been sent.
"""
# Validate the parameters.
@@ -523,26 +530,33 @@ def request(
# Verify that the function is run on the correct thread.
if on_dap_thread:
- cmd = in_dap_thread(func)
+ check_cmd = in_dap_thread(func)
else:
func = in_gdb_thread(func)
if response:
- if defer_stop_events:
- if _server is not None:
- with _server.delayed_events_lock:
- _server.defer_stop_events = True
def sync_call(**args):
return send_gdb_with_response(lambda: func(**args))
- cmd = sync_call
+ check_cmd = sync_call
else:
def non_sync_call(**args):
return send_gdb(lambda: func(**args))
- cmd = non_sync_call
+ check_cmd = non_sync_call
+
+ if defer_events:
+
+ def deferring(**args):
+ _server.set_defer_events()
+ return check_cmd(**args)
+
+ cmd = deferring
+
+ else:
+ cmd = check_cmd
# If needed, check that the inferior is not running. This
# wrapping is done last, so the check is done first, before
@@ -582,7 +596,7 @@ def client_bool_capability(name, default=False):
@request("initialize", on_dap_thread=True)
def initialize(**args):
_server.config = args
- _server.send_event_later("initialized")
+ _server.send_event_maybe_later("initialized")
global _lines_start_at_1
_lines_start_at_1 = client_bool_capability("linesStartAt1", True)
global _columns_start_at_1
diff --git a/gdb/python/lib/gdb/dap/sources.py b/gdb/python/lib/gdb/dap/sources.py
index 625c01f..efcd799 100644
--- a/gdb/python/lib/gdb/dap/sources.py
+++ b/gdb/python/lib/gdb/dap/sources.py
@@ -64,9 +64,9 @@ def decode_source(source):
"""Decode a Source object.
Finds and returns the filename of a given Source object."""
- if "path" in source:
- return source["path"]
- if "sourceReference" not in source:
+ if "sourceReference" not in source or source["sourceReference"] <= 0:
+ if "path" in source:
+ return source["path"]
raise DAPException("either 'path' or 'sourceReference' must appear in Source")
ref = source["sourceReference"]
if ref not in _id_map:
diff --git a/gdb/python/lib/gdb/dap/threads.py b/gdb/python/lib/gdb/dap/threads.py
index c271961..89046a8 100644
--- a/gdb/python/lib/gdb/dap/threads.py
+++ b/gdb/python/lib/gdb/dap/threads.py
@@ -16,27 +16,32 @@
import gdb
from .server import request
+from .startup import in_gdb_thread
+@in_gdb_thread
def _thread_name(thr):
if thr.name is not None:
return thr.name
if thr.details is not None:
return thr.details
- return None
+ # Always return a name, as the protocol doesn't allow for nameless
+ # threads. Use the local thread number here... it doesn't matter
+ # without multi-inferior but in that case it might make more
+ # sense.
+ return f"Thread #{thr.num}"
-@request("threads")
+@request("threads", expect_stopped=False)
def threads(**args):
result = []
for thr in gdb.selected_inferior().threads():
- one_result = {
- "id": thr.global_num,
- }
- name = _thread_name(thr)
- if name is not None:
- one_result["name"] = name
- result.append(one_result)
+ result.append(
+ {
+ "id": thr.global_num,
+ "name": _thread_name(thr),
+ }
+ )
return {
"threads": result,
}
diff --git a/gdb/python/lib/gdb/dap/varref.py b/gdb/python/lib/gdb/dap/varref.py
index 8a13c51..d18197b 100644
--- a/gdb/python/lib/gdb/dap/varref.py
+++ b/gdb/python/lib/gdb/dap/varref.py
@@ -146,6 +146,10 @@ class BaseReference(ABC):
if self._children is None:
self._children = [None] * self.child_count()
for idx in range(start, start + count):
+ if idx >= len(self._children):
+ raise DAPException(
+ f"requested child {idx} outside range of variable {self._ref}"
+ )
if self._children[idx] is None:
(name, value) = self.fetch_one_child(idx)
name = self._compute_name(name)
@@ -242,7 +246,11 @@ class VariableReference(BaseReference):
# changed DAP to allow memory references for any of the
# variable response requests, and to lift the restriction
# to pointer-to-function from Variable.
- if self._value.type.strip_typedefs().code == gdb.TYPE_CODE_PTR:
+ if (
+ self._value.type.strip_typedefs().code == gdb.TYPE_CODE_PTR
+ and not self._value.is_optimized_out
+ and not self._value.is_unavailable
+ ):
result["memoryReference"] = hex(int(self._value))
if client_bool_capability("supportsVariableType"):
result["type"] = str(self._value.type)
diff --git a/gdb/python/lib/gdb/printing.py b/gdb/python/lib/gdb/printing.py
index cba27d2..cda033f 100644
--- a/gdb/python/lib/gdb/printing.py
+++ b/gdb/python/lib/gdb/printing.py
@@ -415,11 +415,17 @@ def make_visualizer(value):
result = NoOpArrayPrinter(ty, value)
elif ty.code in (gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION):
result = NoOpStructPrinter(ty, value)
- elif ty.code in (
- gdb.TYPE_CODE_PTR,
- gdb.TYPE_CODE_REF,
- gdb.TYPE_CODE_RVALUE_REF,
+ elif (
+ ty.code
+ in (
+ gdb.TYPE_CODE_PTR,
+ gdb.TYPE_CODE_REF,
+ gdb.TYPE_CODE_RVALUE_REF,
+ )
+ and ty.target().code != gdb.TYPE_CODE_VOID
):
+ # Note we avoid "void *" here because those pointers can't
+ # be dereferenced without a cast.
result = NoOpPointerReferencePrinter(value)
else:
result = NoOpScalarPrinter(value)
diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c
index fa7dd19..66ccad7 100644
--- a/gdb/python/py-block.c
+++ b/gdb/python/py-block.c
@@ -356,6 +356,9 @@ block_to_block_object (const struct block *block, struct objfile *objfile)
}
result = PyObject_New (block_object, &block_object_type);
+ if (result == nullptr)
+ return nullptr;
+
result->block = block;
result->objfile = objfile;
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 58998f5..9ce8671 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -1537,9 +1537,7 @@ PyTypeObject breakpoint_object_type =
0, /* tp_alloc */
};
-void _initialize_py_breakpoint ();
-void
-_initialize_py_breakpoint ()
+INIT_GDB_FILE (py_breakpoint)
{
add_setshow_boolean_cmd
("py-breakpoint", class_maintenance, &pybp_debug,
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index 5d98d03..dc5e270 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -105,19 +105,17 @@ cmdpy_function (const char *args, int from_tty, cmd_list_element *command)
gdbpy_enter enter_py;
- if (! obj)
+ if (obj == nullptr)
error (_("Invalid invocation of Python command object."));
- if (! PyObject_HasAttr ((PyObject *) obj, invoke_cst))
- {
- if (obj->command->is_prefix ())
- {
- /* A prefix command does not need an invoke method. */
- return;
- }
- error (_("Python command object missing 'invoke' method."));
- }
- if (! args)
+ /* If we get here for a prefix command then the prefix command had an
+ 'invoke' method when it was created. If the 'invoke' method is now
+ missing, then the user has done something weird (like deleting the
+ invoke method, yuck!). */
+ if (!PyObject_HasAttr ((PyObject *) obj, invoke_cst))
+ error (_("Python command object missing 'invoke' method."));
+
+ if (args == nullptr)
args = "";
gdbpy_ref<> argobj (PyUnicode_Decode (args, strlen (args), host_charset (),
NULL));
@@ -336,24 +334,30 @@ cmdpy_completer (struct cmd_list_element *command,
name of the new command. All earlier words must be existing prefix
commands.
- *BASE_LIST is set to the final prefix command's list of
- *sub-commands.
+ *BASE_LIST is set to the final prefix command's list of sub-commands.
START_LIST is the list in which the search starts.
+ When PREFIX_CMD is not NULL then *PREFIX_CMD is set to the prefix
+ command itself, or NULL, if there is no prefix command.
+
This function returns the name of the new command. On error sets the Python
error and returns NULL. */
gdb::unique_xmalloc_ptr<char>
gdbpy_parse_command_name (const char *name,
struct cmd_list_element ***base_list,
- struct cmd_list_element **start_list)
+ struct cmd_list_element **start_list,
+ struct cmd_list_element **prefix_cmd)
{
struct cmd_list_element *elt;
int len = strlen (name);
int i, lastchar;
const char *prefix_text2;
+ if (prefix_cmd != nullptr)
+ *prefix_cmd = nullptr;
+
/* Skip trailing whitespace. */
for (i = len - 1; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i)
;
@@ -368,9 +372,8 @@ gdbpy_parse_command_name (const char *name,
for (; i > 0 && valid_cmd_char_p (name[i - 1]); --i)
;
- gdb::unique_xmalloc_ptr<char> result ((char *) xmalloc (lastchar - i + 2));
- memcpy (result.get (), &name[i], lastchar - i + 1);
- result.get ()[lastchar - i + 1] = '\0';
+ gdb::unique_xmalloc_ptr<char> result
+ = make_unique_xstrndup (&name[i], lastchar - i + 1);
/* Skip whitespace again. */
for (--i; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i)
@@ -385,7 +388,7 @@ gdbpy_parse_command_name (const char *name,
prefix_text2 = prefix_text.c_str ();
elt = lookup_cmd_1 (&prefix_text2, *start_list, NULL, NULL, 1);
- if (elt == NULL || elt == CMD_LIST_AMBIGUOUS)
+ if (elt == nullptr || elt == CMD_LIST_AMBIGUOUS || *prefix_text2 != '\0')
{
PyErr_Format (PyExc_RuntimeError, _("Could not find command prefix %s."),
prefix_text.c_str ());
@@ -395,6 +398,8 @@ gdbpy_parse_command_name (const char *name,
if (elt->is_prefix ())
{
*base_list = elt->subcommands;
+ if (prefix_cmd != nullptr)
+ *prefix_cmd = elt;
return result;
}
@@ -469,8 +474,9 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
return -1;
}
+ cmd_list_element *prefix_cmd = nullptr;
gdb::unique_xmalloc_ptr<char> cmd_name
- = gdbpy_parse_command_name (name, &cmd_list, &cmdlist);
+ = gdbpy_parse_command_name (name, &cmd_list, &cmdlist, &prefix_cmd);
if (cmd_name == nullptr)
return -1;
@@ -507,26 +513,64 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
if (is_prefix)
{
- int allow_unknown;
-
- /* If we have our own "invoke" method, then allow unknown
- sub-commands. */
- allow_unknown = PyObject_HasAttr (self, invoke_cst);
- cmd = add_prefix_cmd (cmd_name.get (),
- (enum command_class) cmdtype,
- NULL, docstring.release (), &obj->sub_list,
- allow_unknown, cmd_list);
+ bool has_invoke = PyObject_HasAttr (self, invoke_cst) == 1;
+ if (has_invoke)
+ {
+ /* If there's an 'invoke' method, then create the prefix
+ command, but call cmdpy_function to dispatch to the invoke
+ method when the user runs the prefix with no sub-command. */
+ cmd = add_prefix_cmd (cmd_name.get (),
+ (enum command_class) cmdtype,
+ nullptr,
+ docstring.release (), &obj->sub_list,
+ 1 /* allow_unknown */, cmd_list);
+ cmd->func = cmdpy_function;
+ }
+ else
+ {
+ /* If there is no 'invoke' method, then create the prefix
+ using the standard prefix callbacks. This means that for
+ 'set prefix' the user will get the help text listing all
+ of the sub-commands, and for 'show prefix', the user will
+ see all of the sub-command values. */
+ if (prefix_cmd != nullptr)
+ {
+ while (prefix_cmd->prefix != nullptr)
+ prefix_cmd = prefix_cmd->prefix;
+ }
+
+ bool is_show = (prefix_cmd != nullptr
+ && prefix_cmd->subcommands == &showlist);
+
+ if (is_show)
+ cmd = add_show_prefix_cmd (cmd_name.get (),
+ (enum command_class) cmdtype,
+ docstring.release (),
+ &obj->sub_list,
+ 0 /* allow_unknown */, cmd_list);
+ else
+ cmd = add_basic_prefix_cmd (cmd_name.get (),
+ (enum command_class) cmdtype,
+ docstring.release (),
+ &obj->sub_list,
+ 0 /* allow_unknown */, cmd_list);
+ }
}
else
- cmd = add_cmd (cmd_name.get (), (enum command_class) cmdtype,
- docstring.release (), cmd_list);
+ {
+ /* For non-prefix commands, arrange to call cmdpy_function, which
+ invokes the Python 'invoke' method, or raises an exception if
+ the 'invoke' method is missing. */
+ cmd = add_cmd (cmd_name.get (), (enum command_class) cmdtype,
+ docstring.release (), cmd_list);
+ cmd->func = cmdpy_function;
+ }
/* If successful, the above takes ownership of the name, since we set
name_allocated, so release it. */
cmd_name.release ();
- /* There appears to be no API to set this. */
- cmd->func = cmdpy_function;
+ /* There appears to be no API to set these member variables. */
cmd->destroyer = cmdpy_destroyer;
cmd->doc_allocated = 1;
cmd->name_allocated = 1;
diff --git a/gdb/python/py-color.c b/gdb/python/py-color.c
index e208506..3bbd22d 100644
--- a/gdb/python/py-color.c
+++ b/gdb/python/py-color.c
@@ -21,6 +21,7 @@
#include "python-internal.h"
#include "py-color.h"
#include "cli/cli-decode.h"
+#include "cli/cli-style.h"
/* Colorspace constants and their values. */
static struct {
@@ -152,8 +153,12 @@ colorpy_escape_sequence (PyObject *self, PyObject *args, PyObject *kwargs)
/* The argument parsing ensures we have a bool. */
gdb_assert (PyBool_Check (is_fg_obj));
- bool is_fg = is_fg_obj == Py_True;
- std::string s = gdbpy_get_color (self).to_ansi (is_fg);
+ std::string s;
+ if (term_cli_styling ())
+ {
+ bool is_fg = is_fg_obj == Py_True;
+ s = gdbpy_get_color (self).to_ansi (is_fg);
+ }
return host_string_to_python_string (s.c_str ()).release ();
}
diff --git a/gdb/python/py-connection.c b/gdb/python/py-connection.c
index 93757ac..a6d9ad0 100644
--- a/gdb/python/py-connection.c
+++ b/gdb/python/py-connection.c
@@ -428,9 +428,7 @@ connpy_send_packet (PyObject *self, PyObject *args, PyObject *kw)
/* Global initialization for this file. */
-void _initialize_py_connection ();
-void
-_initialize_py_connection ()
+INIT_GDB_FILE (py_connection)
{
gdb::observers::connection_removed.attach (connpy_connection_removed,
"py-connection");
diff --git a/gdb/python/py-dap.c b/gdb/python/py-dap.c
index 7196d6c..9a9875a 100644
--- a/gdb/python/py-dap.c
+++ b/gdb/python/py-dap.c
@@ -110,9 +110,7 @@ dap_interp::pre_command_loop ()
call_dap_fn ("pre_command_loop");
}
-void _initialize_py_interp ();
-void
-_initialize_py_interp ()
+INIT_GDB_FILE (py_interp)
{
/* The dap code uses module typing, available starting python 3.5. */
#if PY_VERSION_HEX >= 0x03050000
diff --git a/gdb/python/py-disasm.c b/gdb/python/py-disasm.c
index 17064dc..47ae99c 100644
--- a/gdb/python/py-disasm.c
+++ b/gdb/python/py-disasm.c
@@ -254,15 +254,15 @@ disasm_info_object_is_valid (disasm_info_object *obj)
/* Fill in OBJ with all the other arguments. */
static void
-disasm_info_fill (disasm_info_object *obj, struct gdbarch *gdbarch,
+disasm_info_fill (disasm_info_object &obj, struct gdbarch *gdbarch,
program_space *progspace, bfd_vma address,
disassemble_info *di, disasm_info_object *next)
{
- obj->gdbarch = gdbarch;
- obj->program_space = progspace;
- obj->address = address;
- obj->gdb_info = di;
- obj->next = next;
+ obj.gdbarch = gdbarch;
+ obj.program_space = progspace;
+ obj.address = address;
+ obj.gdb_info = di;
+ obj.next = next;
}
/* Implement DisassembleInfo.__init__. Takes a single argument that must
@@ -281,7 +281,7 @@ disasm_info_init (PyObject *self, PyObject *args, PyObject *kwargs)
disasm_info_object *other = (disasm_info_object *) info_obj;
disasm_info_object *info = (disasm_info_object *) self;
- disasm_info_fill (info, other->gdbarch, other->program_space,
+ disasm_info_fill (*info, other->gdbarch, other->program_space,
other->address, other->gdb_info, other->next);
other->next = info;
@@ -1156,19 +1156,18 @@ gdbpy_disassembler::gdbpy_disassembler (disasm_info_object *obj)
happens when gdbpy_print_insn returns. This class is responsible for
marking the DisassembleInfo as invalid in its destructor. */
-struct scoped_disasm_info_object
+struct scoped_invalidate_disasm_info
{
- /* Constructor. */
- scoped_disasm_info_object (struct gdbarch *gdbarch, CORE_ADDR memaddr,
- disassemble_info *info)
- : m_disasm_info (allocate_disasm_info_object ())
+ /* Constructor. Just cache DISASM_INFO for use in the destructor. */
+ scoped_invalidate_disasm_info
+ (gdbpy_ref<disasm_info_object> disasm_info)
+ : m_disasm_info (std::move (disasm_info))
{
- disasm_info_fill (m_disasm_info.get (), gdbarch, current_program_space,
- memaddr, info, nullptr);
+ /* Nothing. */
}
/* Upon destruction mark m_disasm_info as invalid. */
- ~scoped_disasm_info_object ()
+ ~scoped_invalidate_disasm_info ()
{
/* Invalidate the original DisassembleInfo object as well as any copies
that the user might have made. */
@@ -1178,30 +1177,15 @@ struct scoped_disasm_info_object
obj->gdb_info = nullptr;
}
- /* Return a pointer to the underlying disasm_info_object instance. */
- disasm_info_object *
- get () const
- {
- return m_disasm_info.get ();
- }
-
private:
- /* Wrapper around the call to PyObject_New, this wrapper function can be
- called from the constructor initialization list, while PyObject_New, a
- macro, can't. */
- static disasm_info_object *
- allocate_disasm_info_object ()
- {
- return (disasm_info_object *) PyObject_New (disasm_info_object,
- &disasm_info_object_type);
- }
-
/* A reference to a gdb.disassembler.DisassembleInfo object. When this
- containing instance goes out of scope this reference is released,
- however, the user might be holding other references to the
- DisassembleInfo object in Python code, so the underlying object might
- not be deleted. */
+ object goes out of scope this reference is released, however, the user
+ might be holding other references to the DisassembleInfo (either
+ directly, or via copies of this object), in which case the underlying
+ object will not be deleted. The destructor of this class ensures
+ that this DisassembleInfo object, and any copies, are all marked
+ invalid. */
gdbpy_ref<disasm_info_object> m_disasm_info;
};
@@ -1242,17 +1226,30 @@ gdbpy_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
return {};
}
- /* Create the new DisassembleInfo object we will pass into Python. This
- object will be marked as invalid when we leave this scope. */
- scoped_disasm_info_object scoped_disasm_info (gdbarch, memaddr, info);
- disasm_info_object *disasm_info = scoped_disasm_info.get ();
+ /* Create the new DisassembleInfo object we will pass into Python. */
+ gdbpy_ref<disasm_info_object> disasm_info
+ ((disasm_info_object *) PyObject_New (disasm_info_object,
+ &disasm_info_object_type));
+ if (disasm_info == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+
+ /* Initialise the DisassembleInfo object. */
+ disasm_info_fill (*disasm_info.get (), gdbarch, current_program_space,
+ memaddr, info, nullptr);
+
+ /* Ensure the DisassembleInfo, along with any copies the user makes, are
+ marked as invalid when we leave this scope. */
+ scoped_invalidate_disasm_info invalidate_disasm (disasm_info);
/* Call into the registered disassembler to (possibly) perform the
disassembly. */
- PyObject *insn_disas_obj = (PyObject *) disasm_info;
- gdbpy_ref<> result (PyObject_CallFunctionObjArgs (hook.get (),
- insn_disas_obj,
- nullptr));
+ gdbpy_ref<> result
+ (PyObject_CallFunctionObjArgs (hook.get (),
+ (PyObject *) disasm_info.get (),
+ nullptr));
if (result == nullptr)
{
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index 0ea629f..70e1684 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -175,7 +175,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
struct frame_id frame_id;
PyObject *internal = NULL;
int internal_bp = 0;
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords,
&frame_obj, &internal))
@@ -249,9 +249,9 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
try
{
- if (get_frame_pc_if_available (frame, &pc))
+ if ((pc = get_frame_pc_if_available (frame)))
{
- struct symbol *function = find_pc_function (pc);
+ struct symbol *function = find_pc_function (*pc);
if (function != nullptr)
{
struct type *ret_type =
diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
index adf4233..db8c274 100644
--- a/gdb/python/py-framefilter.c
+++ b/gdb/python/py-framefilter.c
@@ -168,7 +168,7 @@ mi_should_print (struct symbol *sym, enum mi_print_types type)
{
int print_me = 0;
- switch (sym->aclass ())
+ switch (sym->loc_class ())
{
default:
case LOC_UNDEF: /* catches errors */
diff --git a/gdb/python/py-gdb-readline.c b/gdb/python/py-gdb-readline.c
index ea3a385..70ceebb 100644
--- a/gdb/python/py-gdb-readline.c
+++ b/gdb/python/py-gdb-readline.c
@@ -29,11 +29,7 @@
static char *
gdbpy_readline_wrapper (FILE *sys_stdin, FILE *sys_stdout,
-#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 4
const char *prompt)
-#else
- char *prompt)
-#endif
{
int n;
const char *p = NULL;
diff --git a/gdb/python/py-infevents.c b/gdb/python/py-infevents.c
index e63ba52..f74fb01 100644
--- a/gdb/python/py-infevents.c
+++ b/gdb/python/py-infevents.c
@@ -40,7 +40,7 @@ create_inferior_call_event_object (inferior_call_kind flag, ptid_t ptid,
gdb_assert_not_reached ("invalid inferior_call_kind");
}
- gdbpy_ref<> ptid_obj (gdbpy_create_ptid_object (ptid));
+ gdbpy_ref<> ptid_obj = gdbpy_create_ptid_object (ptid);
if (ptid_obj == NULL)
return NULL;
diff --git a/gdb/python/py-infthread.c b/gdb/python/py-infthread.c
index 4f1f8d4..08533fe 100644
--- a/gdb/python/py-infthread.c
+++ b/gdb/python/py-infthread.c
@@ -190,7 +190,7 @@ thpy_get_ptid (PyObject *self, void *closure)
THPY_REQUIRE_VALID (thread_obj);
- return gdbpy_create_ptid_object (thread_obj->thread->ptid);
+ return gdbpy_create_ptid_object (thread_obj->thread->ptid).release ();
}
/* Implement gdb.InferiorThread.ptid_string attribute. */
@@ -361,23 +361,14 @@ thpy_repr (PyObject *self)
target_pid_to_str (thr->ptid).c_str ());
}
-/* Return a reference to a new Python object representing a ptid_t.
- The object is a tuple containing (pid, lwp, tid). */
-PyObject *
+/* See python-internal.h. */
+
+gdbpy_ref<>
gdbpy_create_ptid_object (ptid_t ptid)
{
- int pid;
- long lwp;
- ULONGEST tid;
- PyObject *ret;
-
- ret = PyTuple_New (3);
- if (!ret)
- return NULL;
-
- pid = ptid.pid ();
- lwp = ptid.lwp ();
- tid = ptid.tid ();
+ int pid = ptid.pid ();
+ long lwp = ptid.lwp ();
+ ULONGEST tid = ptid.tid ();
gdbpy_ref<> pid_obj = gdb_py_object_from_longest (pid);
if (pid_obj == nullptr)
@@ -389,10 +380,14 @@ gdbpy_create_ptid_object (ptid_t ptid)
if (tid_obj == nullptr)
return nullptr;
+ gdbpy_ref<> ret (PyTuple_New (3));
+ if (ret == nullptr)
+ return nullptr;
+
/* Note that these steal references, hence the use of 'release'. */
- PyTuple_SET_ITEM (ret, 0, pid_obj.release ());
- PyTuple_SET_ITEM (ret, 1, lwp_obj.release ());
- PyTuple_SET_ITEM (ret, 2, tid_obj.release ());
+ PyTuple_SET_ITEM (ret.get (), 0, pid_obj.release ());
+ PyTuple_SET_ITEM (ret.get (), 1, lwp_obj.release ());
+ PyTuple_SET_ITEM (ret.get (), 2, tid_obj.release ());
return ret;
}
diff --git a/gdb/python/py-mi.c b/gdb/python/py-mi.c
index 9b871d4..b2ab4e2 100644
--- a/gdb/python/py-mi.c
+++ b/gdb/python/py-mi.c
@@ -218,11 +218,11 @@ py_object_to_mi_key (PyObject *key_obj)
{
gdb_assert (name != nullptr);
- if (*name == '\0' || !isalpha (*name))
+ if (*name == '\0' || !c_isalpha (*name))
return false;
for (; *name != '\0'; ++name)
- if (!isalnum (*name) && *name != '_' && *name != '-')
+ if (!c_isalnum (*name) && *name != '_' && *name != '-')
return false;
return true;
@@ -363,7 +363,7 @@ gdbpy_notify_mi (PyObject *self, PyObject *args, PyObject *kwargs)
}
for (int i = 0; i < name_len; i++)
{
- if (!isalnum (name[i]) && name[i] != '-')
+ if (!c_isalnum (name[i]) && name[i] != '-')
{
PyErr_Format
(PyExc_ValueError,
diff --git a/gdb/python/py-micmd.c b/gdb/python/py-micmd.c
index e4f07c9..07db0cc 100644
--- a/gdb/python/py-micmd.c
+++ b/gdb/python/py-micmd.c
@@ -350,7 +350,7 @@ micmdpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
PyErr_SetString (PyExc_ValueError, _("MI command name is empty."));
return -1;
}
- else if ((name_len < 2) || (name[0] != '-') || !isalnum (name[1]))
+ else if ((name_len < 2) || (name[0] != '-') || !c_isalnum (name[1]))
{
PyErr_SetString (PyExc_ValueError,
_("MI command name does not start with '-'"
@@ -361,7 +361,7 @@ micmdpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
{
for (int i = 2; i < name_len; i++)
{
- if (!isalnum (name[i]) && name[i] != '-')
+ if (!c_isalnum (name[i]) && name[i] != '-')
{
PyErr_Format
(PyExc_ValueError,
@@ -578,9 +578,7 @@ PyTypeObject micmdpy_object_type = {
0, /* tp_alloc */
};
-void _initialize_py_micmd ();
-void
-_initialize_py_micmd ()
+INIT_GDB_FILE (py_micmd)
{
add_setshow_boolean_cmd
("py-micmd", class_maintenance, &pymicmd_debug,
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index 1c6f569..a9f5754 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -556,7 +556,7 @@ objfpy_build_id_ok (const char *string)
return 0;
for (i = 0; i < n; ++i)
{
- if (!isxdigit (string[i]))
+ if (!c_isxdigit (string[i]))
return 0;
}
return 1;
@@ -619,9 +619,8 @@ gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
struct objfile *objfile = nullptr;
if (by_build_id)
- gdbarch_iterate_over_objfiles_in_search_order
- (current_inferior ()->arch (),
- [&objfile, name] (struct objfile *obj)
+ current_program_space->iterate_over_objfiles_in_search_order
+ ([&objfile, name] (struct objfile *obj)
{
/* Don't return separate debug files. */
if (obj->separate_debug_objfile_backlink != nullptr)
@@ -642,9 +641,8 @@ gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
return 1;
}, gdbpy_current_objfile);
else
- gdbarch_iterate_over_objfiles_in_search_order
- (current_inferior ()->arch (),
- [&objfile, name] (struct objfile *obj)
+ current_program_space->iterate_over_objfiles_in_search_order
+ ([&objfile, name] (struct objfile *obj)
{
/* Don't return separate debug files. */
if (obj->separate_debug_objfile_backlink != nullptr)
diff --git a/gdb/python/py-param.c b/gdb/python/py-param.c
index 763680e..06237b6 100644
--- a/gdb/python/py-param.c
+++ b/gdb/python/py-param.c
@@ -495,7 +495,11 @@ get_doc_string (PyObject *object, enum doc_string_type doc_type,
}
}
- if (result == nullptr)
+ /* For the set/show docs, if these strings are empty then we set then to
+ a non-empty string. This ensures that the command has some sane
+ documentation for its 'help' text. */
+ if (result == nullptr
+ || (doc_type != doc_string_description && *result == '\0'))
{
if (doc_type == doc_string_description)
result.reset (xstrdup (_("This command is not documented.")));
@@ -904,6 +908,18 @@ parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
show_doc = get_doc_string (self, doc_string_show, name);
doc = get_doc_string (self, doc_string_description, cmd_name.get ());
+ /* The set/show docs should always be a non-empty string. */
+ gdb_assert (set_doc != nullptr && *set_doc != '\0');
+ gdb_assert (show_doc != nullptr && *show_doc != '\0');
+
+ /* For the DOC string only, if it is the empty string, then we convert it
+ to NULL. This means GDB will not even display a blank line for this
+ part of the help text, instead the set/show line is all the user will
+ get. */
+ gdb_assert (doc != nullptr);
+ if (*doc == '\0')
+ doc = nullptr;
+
Py_INCREF (self);
try
diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c
index 7e7904b..89c2e77 100644
--- a/gdb/python/py-record.c
+++ b/gdb/python/py-record.c
@@ -696,6 +696,9 @@ gdbpy_current_recording (PyObject *self, PyObject *args)
Py_RETURN_NONE;
ret = PyObject_New (recpy_record_object, &recpy_record_type);
+ if (ret == nullptr)
+ return nullptr;
+
ret->thread = inferior_thread ();
ret->method = target_record_method (ret->thread->ptid);
diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c
index 3028a30..284e385 100644
--- a/gdb/python/py-symbol.c
+++ b/gdb/python/py-symbol.c
@@ -126,7 +126,7 @@ sympy_get_addr_class (PyObject *self, void *closure)
SYMPY_REQUIRE_VALID (self, symbol);
- return gdb_py_object_from_longest (symbol->aclass ()).release ();
+ return gdb_py_object_from_longest (symbol->loc_class ()).release ();
}
/* Implement gdb.Symbol.domain attribute. Return the domain as an
@@ -156,42 +156,39 @@ static PyObject *
sympy_is_constant (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
- enum address_class theclass;
SYMPY_REQUIRE_VALID (self, symbol);
- theclass = symbol->aclass ();
+ location_class loc_class = symbol->loc_class ();
- return PyBool_FromLong (theclass == LOC_CONST || theclass == LOC_CONST_BYTES);
+ return PyBool_FromLong (loc_class == LOC_CONST || loc_class == LOC_CONST_BYTES);
}
static PyObject *
sympy_is_function (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
- enum address_class theclass;
SYMPY_REQUIRE_VALID (self, symbol);
- theclass = symbol->aclass ();
+ location_class loc_class = symbol->loc_class ();
- return PyBool_FromLong (theclass == LOC_BLOCK);
+ return PyBool_FromLong (loc_class == LOC_BLOCK);
}
static PyObject *
sympy_is_variable (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
- enum address_class theclass;
SYMPY_REQUIRE_VALID (self, symbol);
- theclass = symbol->aclass ();
+ location_class loc_class = symbol->loc_class ();
return PyBool_FromLong (!symbol->is_argument ()
- && (theclass == LOC_LOCAL || theclass == LOC_REGISTER
- || theclass == LOC_STATIC || theclass == LOC_COMPUTED
- || theclass == LOC_OPTIMIZED_OUT));
+ && (loc_class == LOC_LOCAL || loc_class == LOC_REGISTER
+ || loc_class == LOC_STATIC || loc_class == LOC_COMPUTED
+ || loc_class == LOC_OPTIMIZED_OUT));
}
/* Implementation of Symbol.is_artificial. */
@@ -279,7 +276,7 @@ sympy_value (PyObject *self, PyObject *args)
}
SYMPY_REQUIRE_VALID (self, symbol);
- if (symbol->aclass () == LOC_TYPEDEF)
+ if (symbol->loc_class () == LOC_TYPEDEF)
{
PyErr_SetString (PyExc_TypeError, "cannot get the value of a typedef");
return NULL;
@@ -605,17 +602,15 @@ gdbpy_lookup_static_symbols (PyObject *self, PyObject *args, PyObject *kw)
/* Expand any symtabs that contain potentially matching symbols. */
lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
- expand_symtabs_matching (NULL, lookup_name, NULL, NULL,
- SEARCH_STATIC_BLOCK, flags);
for (objfile *objfile : current_program_space->objfiles ())
{
- for (compunit_symtab *cust : objfile->compunits ())
+ auto callback = [&] (compunit_symtab *cust)
{
/* Skip included compunits to prevent including compunits from
being searched twice. */
if (cust->user != nullptr)
- continue;
+ return true;
const struct blockvector *bv = cust->blockvector ();
const struct block *block = bv->static_block ();
@@ -628,13 +623,18 @@ gdbpy_lookup_static_symbols (PyObject *self, PyObject *args, PyObject *kw)
if (symbol != nullptr)
{
PyObject *sym_obj = symbol_to_symbol_object (symbol);
- if (sym_obj == nullptr)
- return nullptr;
- if (PyList_Append (return_list.get (), sym_obj) == -1)
- return nullptr;
+ if (sym_obj == nullptr
+ || PyList_Append (return_list.get (), sym_obj) == -1)
+ return false;
}
}
- }
+
+ return true;
+ };
+
+ if (!objfile->search (nullptr, &lookup_name, nullptr, callback,
+ SEARCH_STATIC_BLOCK, flags))
+ return nullptr;
}
}
catch (const gdb_exception &except)
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index f37afde..a2c5939 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -158,7 +158,7 @@ convert_field (struct type *type, int field)
}
else
{
- if (type->field (field).loc_kind () == FIELD_LOC_KIND_DWARF_BLOCK)
+ if (type->field (field).loc_is_dwarf_block ())
arg = gdbpy_ref<>::new_reference (Py_None);
else
arg = gdb_py_object_from_longest (type->field (field).loc_bitpos ());
@@ -1045,9 +1045,9 @@ typy_template_argument (PyObject *self, PyObject *args)
}
sym = TYPE_TEMPLATE_ARGUMENT (type, argno);
- if (sym->aclass () == LOC_TYPEDEF)
+ if (sym->loc_class () == LOC_TYPEDEF)
return type_to_type_object (sym->type ());
- else if (sym->aclass () == LOC_OPTIMIZED_OUT)
+ else if (sym->loc_class () == LOC_OPTIMIZED_OUT)
{
PyErr_Format (PyExc_RuntimeError,
_("Template argument is optimized out"));
@@ -1312,10 +1312,9 @@ static PyObject *
typy_has_key (PyObject *self, PyObject *args)
{
struct type *type = ((type_object *) self)->type;
- const char *field;
- int i;
+ const char *field_name;
- if (!PyArg_ParseTuple (args, "s", &field))
+ if (!PyArg_ParseTuple (args, "s", &field_name))
return NULL;
/* We want just fields of this type, not of base types, so instead of
@@ -1326,11 +1325,11 @@ typy_has_key (PyObject *self, PyObject *args)
if (type == NULL)
return NULL;
- for (i = 0; i < type->num_fields (); i++)
+ for (const auto &field : type->fields ())
{
- const char *t_field_name = type->field (i).name ();
+ const char *t_field_name = field.name ();
- if (t_field_name && (strcmp_iw (t_field_name, field) == 0))
+ if (t_field_name && (strcmp_iw (t_field_name, field_name) == 0))
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index d43d7e9..43125bb 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -287,6 +287,8 @@ pyuw_create_unwind_info (PyObject *pyo_pending_frame,
unwind_info_object *unwind_info
= PyObject_New (unwind_info_object, &unwind_info_object_type);
+ if (unwind_info == nullptr)
+ return nullptr;
unwind_info->frame_id = frame_id;
Py_INCREF (pyo_pending_frame);
@@ -1029,9 +1031,7 @@ gdbpy_initialize_unwind (void)
return 0;
}
-void _initialize_py_unwind ();
-void
-_initialize_py_unwind ()
+INIT_GDB_FILE (py_unwind)
{
add_setshow_boolean_cmd
("py-unwind", class_maintenance, &pyuw_debug,
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 8a2e263..5d8fab9 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -478,6 +478,9 @@ valpy_get_dynamic_type (PyObject *self, void *closure)
type = value_rtti_type (val, NULL, NULL, NULL);
else
type = val->type ();
+
+ if (type == nullptr)
+ type = val->type ();
}
catch (const gdb_exception &except)
{
@@ -1288,6 +1291,30 @@ valpy_get_is_optimized_out (PyObject *self, void *closure)
Py_RETURN_FALSE;
}
+/* Implements gdb.Value.is_unavailable. Return true if any part of the
+ value is unavailable. */
+
+static PyObject *
+valpy_get_is_unavailable (PyObject *self, void *closure)
+{
+ struct value *value = ((value_object *) self)->value;
+ bool entirely_available = false;
+
+ try
+ {
+ entirely_available = value->entirely_available ();
+ }
+ catch (const gdb_exception &except)
+ {
+ return gdbpy_handle_gdb_exception (nullptr, except);
+ }
+
+ if (!entirely_available)
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
+
/* Implements gdb.Value.is_lazy. */
static PyObject *
valpy_get_is_lazy (PyObject *self, void *closure)
@@ -1842,7 +1869,7 @@ valpy_long (PyObject *self)
{
struct value *value = ((value_object *) self)->value;
struct type *type = value->type ();
- LONGEST l = 0;
+ PyObject *result;
try
{
@@ -1858,17 +1885,57 @@ valpy_long (PyObject *self)
&& type->code () != TYPE_CODE_PTR)
error (_("Cannot convert value to long."));
- l = value_as_long (value);
+ gdb::array_view<const gdb_byte> contents = value->contents ();
+#if PY_VERSION_HEX >= 0x030d0000
+ int flags = (type_byte_order (type) == BFD_ENDIAN_BIG
+ ? Py_ASNATIVEBYTES_BIG_ENDIAN
+ : Py_ASNATIVEBYTES_LITTLE_ENDIAN);
+ if (type->is_unsigned ())
+ flags |= Py_ASNATIVEBYTES_UNSIGNED_BUFFER;
+ result = PyLong_FromNativeBytes (contents.data (), contents.size (),
+ flags);
+#else
+ /* Here we construct a call to "int.from_bytes", passing in the
+ appropriate arguments. We need a somewhat roundabout
+ approach because int.from_bytes requires "signed" to be a
+ keyword arg. */
+
+ /* PyObject_Call requires a tuple argument. */
+ gdbpy_ref<> empty_tuple (PyTuple_New (0));
+ if (empty_tuple == nullptr)
+ return nullptr;
+
+ /* Since we need a dictionary anyway, we pass all arguments as
+ keywords, building the dictionary here. */
+ gdbpy_ref<> args
+ (Py_BuildValue ("{sy#sssO}",
+ "bytes", contents.data (),
+ (Py_ssize_t) contents.size (),
+ "byteorder",
+ (type_byte_order (type) == BFD_ENDIAN_BIG
+ ? "big" : "little"),
+ "signed",
+ type->is_unsigned ()
+ ? Py_False : Py_True));
+ if (args == nullptr)
+ return nullptr;
+
+ /* Find the "int.from_bytes" callable. */
+ gdbpy_ref<> callable (PyObject_GetAttrString ((PyObject *) &PyLong_Type,
+ "from_bytes"));
+ if (callable == nullptr)
+ return nullptr;
+
+ result = PyObject_Call (callable.get (), empty_tuple.get (),
+ args.get ());
+#endif
}
catch (const gdb_exception &except)
{
return gdbpy_handle_gdb_exception (nullptr, except);
}
- if (type->is_unsigned ())
- return gdb_py_object_from_ulongest (l).release ();
- else
- return gdb_py_object_from_longest (l).release ();
+ return result;
}
/* Implements conversion to float. */
@@ -2194,6 +2261,9 @@ static gdb_PyGetSetDef value_object_getset[] = {
"Boolean telling whether the value is optimized "
"out (i.e., not available).",
NULL },
+ { "is_unavailable", valpy_get_is_unavailable, nullptr,
+ "Boolean telling whether the value is unavailable.",
+ nullptr },
{ "type", valpy_get_type, NULL, "Type of the value.", NULL },
{ "dynamic_type", valpy_get_dynamic_type, NULL,
"Dynamic type of the value.", NULL },
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 5262d76..f61a175 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -88,6 +88,8 @@
#include <frameobject.h>
#include "py-ref.h"
+static_assert (PY_VERSION_HEX >= 0x03040000);
+
#define Py_TPFLAGS_CHECKTYPES 0
/* If Python.h does not define WITH_THREAD, then the various
@@ -135,17 +137,6 @@ typedef unsigned long gdb_py_ulongest;
#endif /* HAVE_LONG_LONG */
-#if PY_VERSION_HEX < 0x03020000
-typedef long Py_hash_t;
-#endif
-
-/* PyMem_RawMalloc appeared in Python 3.4. For earlier versions, we can just
- fall back to PyMem_Malloc. */
-
-#if PY_VERSION_HEX < 0x03040000
-#define PyMem_RawMalloc PyMem_Malloc
-#endif
-
/* A template variable holding the format character (as for
Py_BuildValue) for a given type. */
template<typename T>
@@ -512,14 +503,20 @@ PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
const char *encoding,
struct type *type);
PyObject *gdbpy_inferiors (PyObject *unused, PyObject *unused2);
-PyObject *gdbpy_create_ptid_object (ptid_t ptid);
+
+/* Return a reference to a new Python Tuple object representing a ptid_t.
+ The object is a tuple containing (pid, lwp, tid). */
+
+extern gdbpy_ref<> gdbpy_create_ptid_object (ptid_t ptid);
+
PyObject *gdbpy_selected_thread (PyObject *self, PyObject *args);
PyObject *gdbpy_selected_inferior (PyObject *self, PyObject *args);
PyObject *gdbpy_string_to_argv (PyObject *self, PyObject *args);
PyObject *gdbpy_parameter_value (const setting &var);
gdb::unique_xmalloc_ptr<char> gdbpy_parse_command_name
(const char *name, struct cmd_list_element ***base_list,
- struct cmd_list_element **start_list);
+ struct cmd_list_element **start_list,
+ struct cmd_list_element **prefix_cmd = nullptr);
PyObject *gdbpy_register_tui_window (PyObject *self, PyObject *args,
PyObject *kw);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 24cb511..740b196 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -31,7 +31,6 @@
#include "python.h"
#include "extension-priv.h"
#include "cli/cli-utils.h"
-#include <ctype.h>
#include "location.h"
#include "run-on-main-thread.h"
#include "observable.h"
@@ -1202,15 +1201,22 @@ gdbpy_post_event (PyObject *self, PyObject *args)
static PyObject *
gdbpy_interrupt (PyObject *self, PyObject *args)
{
+#ifdef __MINGW32__
{
- /* Make sure the interrupt isn't delivered immediately somehow.
- This probably is not truly needed, but at the same time it
- seems more clear to be explicit about the intent. */
gdbpy_allow_threads temporarily_exit_python;
scoped_disable_cooperative_sigint_handling no_python_sigint;
set_quit_flag ();
}
+#else
+ {
+ /* For targets with support kill() just send SIGINT. This will be
+ handled as if the user hit Ctrl+C. This isn't exactly the same as
+ the above, which directly sets the quit flag. Consider, for
+ example, every place that install_sigint_handler is called. */
+ kill (getpid (), SIGINT);
+ }
+#endif
Py_RETURN_NONE;
}
@@ -1570,21 +1576,21 @@ gdbpy_write (PyObject *self, PyObject *args, PyObject *kw)
try
{
+ ui_file *stream;
switch (stream_type)
{
case 1:
- {
- gdb_printf (gdb_stderr, "%s", arg);
- break;
- }
+ stream = gdb_stderr;
+ break;
case 2:
- {
- gdb_printf (gdb_stdlog, "%s", arg);
- break;
- }
+ stream = gdb_stdlog;
+ break;
default:
- gdb_printf (gdb_stdout, "%s", arg);
+ stream = gdb_stdout;
+ break;
}
+
+ gdb_puts (arg, stream);
}
catch (const gdb_exception &except)
{
@@ -1630,6 +1636,40 @@ gdbpy_flush (PyObject *self, PyObject *args, PyObject *kw)
Py_RETURN_NONE;
}
+/* Implement gdb.warning(). Takes a single text string argument and emit a
+ warning using GDB's 'warning' function. The input text string must not
+ be empty. */
+
+static PyObject *
+gdbpy_warning (PyObject *self, PyObject *args, PyObject *kw)
+{
+ const char *text;
+ static const char *keywords[] = { "text", nullptr };
+
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s", keywords, &text))
+ return nullptr;
+
+ if (strlen (text) == 0)
+ {
+ PyErr_SetString (PyExc_ValueError,
+ _("Empty text string passed to gdb.warning"));
+ return nullptr;
+ }
+
+ try
+ {
+ warning ("%s", text);
+ }
+ catch (const gdb_exception &ex)
+ {
+ /* The warning() call probably cannot throw an exception. But just
+ in case it ever does. */
+ return gdbpy_handle_gdb_exception (nullptr, ex);
+ }
+
+ Py_RETURN_NONE;
+}
+
/* Return non-zero if print-stack is not "none". */
int
@@ -2446,7 +2486,7 @@ py_initialize ()
/foo/lib/pythonX.Y/...
This must be done before calling Py_Initialize. */
gdb::unique_xmalloc_ptr<char> progname
- (concat (ldirname (python_libdir.c_str ()).c_str (), SLASH_STRING, "bin",
+ (concat (gdb_ldirname (python_libdir.c_str ()).c_str (), SLASH_STRING, "bin",
SLASH_STRING, "python", (char *) NULL));
{
@@ -2683,9 +2723,7 @@ test_python ()
/* See python.h. */
cmd_list_element *python_cmd_element = nullptr;
-void _initialize_python ();
-void
-_initialize_python ()
+INIT_GDB_FILE (python)
{
cmd_list_element *python_interactive_cmd
= add_com ("python-interactive", class_obscure,
@@ -3124,6 +3162,12 @@ Return the current print options." },
METH_VARARGS | METH_KEYWORDS,
"notify_mi (name, data) -> None\n\
Output async record to MI channels if any." },
+
+ { "warning", (PyCFunction) gdbpy_warning,
+ METH_VARARGS | METH_KEYWORDS,
+ "warning (text) -> None\n\
+Print a warning." },
+
{NULL, NULL, 0, NULL}
};
diff --git a/gdb/quick-symbol.h b/gdb/quick-symbol.h
index 9db1f18..b5308dc 100644
--- a/gdb/quick-symbol.h
+++ b/gdb/quick-symbol.h
@@ -37,30 +37,29 @@ DEF_ENUM_FLAGS_TYPE (enum block_search_flag_values, block_search_flags);
using symbol_filename_listener
= gdb::function_view<void (const char *filename, const char *fullname)>;
-/* Callback for quick_symbol_functions::expand_symtabs_matching
- to match a file name. */
+/* Callback for quick_symbol_functions::search to match a file
+ name. */
-using expand_symtabs_file_matcher
+using search_symtabs_file_matcher
= gdb::function_view<bool (const char *filename, bool basenames)>;
-/* Callback for quick_symbol_functions::expand_symtabs_matching
- to match a symbol name. */
+/* Callback for quick_symbol_functions::search to match a symbol
+ name. */
-using expand_symtabs_symbol_matcher
+using search_symtabs_symbol_matcher
= gdb::function_view<bool (const char *name)>;
-/* Callback for quick_symbol_functions::expand_symtabs_matching
- to match a language. */
+/* Callback for quick_symbol_functions::search to match a
+ language. */
-using expand_symtabs_lang_matcher
+using search_symtabs_lang_matcher
= gdb::function_view<bool (enum language lang)>;
-/* Callback for quick_symbol_functions::expand_symtabs_matching
- to be called after a symtab has been expanded. If this returns
- true, more symtabs are checked; if it returns false, iteration
- stops. */
+/* Callback for quick_symbol_functions::search to be called when
+ symtab matches (perhaps expanding it first). If this returns true,
+ more symtabs are checked; if it returns false, iteration stops. */
-using expand_symtabs_expansion_listener
+using search_symtabs_expansion_listener
= gdb::function_view<bool (compunit_symtab *symtab)>;
/* The "quick" symbol functions exist so that symbol readers can
@@ -71,13 +70,6 @@ using expand_symtabs_expansion_listener
The quick symbol functions are generally opaque: the underlying
representation is hidden from the caller.
- In general, these functions should only look at whatever special
- index the symbol reader creates -- looking through the symbol
- tables themselves is handled by generic code. If a function is
- defined as returning a "symbol table", this means that the function
- should only return a newly-created symbol table; it should not
- examine pre-existing ones.
-
The exact list of functions here was determined in an ad hoc way
based on gdb's history. */
@@ -130,11 +122,11 @@ struct quick_symbol_functions
/* Read all symbol tables associated with OBJFILE. */
virtual void expand_all_symtabs (struct objfile *objfile) = 0;
- /* Expand all symbol tables in OBJFILE matching some criteria.
+ /* Search all symbol tables in OBJFILE matching some criteria.
- If LANG_MATCHER returns false, expansion of the symbol table may be
- skipped. It may also not be skipped, which the caller needs to take into
- account.
+ If LANG_MATCHER returns false, search of the symbol table may be
+ skipped. It may also not be skipped, which the caller needs to
+ take into account.
FILE_MATCHER is called for each file in OBJFILE. The file name
is passed to it. If the matcher returns false, the file is
@@ -144,7 +136,7 @@ struct quick_symbol_functions
part).
If the file is not skipped, and SYMBOL_MATCHER and LOOKUP_NAME are NULL,
- the symbol table is expanded.
+ the symbol table is searched.
Otherwise, individual symbols are considered.
@@ -156,19 +148,23 @@ struct quick_symbol_functions
Note that if SYMBOL_MATCHER is non-NULL, then LOOKUP_NAME must
also be provided.
- Otherwise, the symbol's symbol table is expanded and EXPANSION_NOTIFY is
- called. If EXPANSION_NOTIFY returns false, execution stops and this method
- returns false. Otherwise, more files are considered. This method returns
- true if all calls to EXPANSION_NOTIFY return true. */
- virtual bool expand_symtabs_matching
+ Otherwise, the symbol's symbol table is expanded if needed.
+
+ Then (regardless of whether the symbol table was already
+ expanded, or just expanded in response to this search), LISTENER
+ is called. If LISTENER returns false, execution stops and this
+ method returns false. Otherwise, more files are considered.
+ This method returns true if all calls to LISTENER return
+ true. */
+ virtual bool search
(struct objfile *objfile,
- expand_symtabs_file_matcher file_matcher,
+ search_symtabs_file_matcher file_matcher,
const lookup_name_info *lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
+ search_symtabs_symbol_matcher symbol_matcher,
+ search_symtabs_expansion_listener listener,
block_search_flags search_flags,
domain_search_flags domain,
- expand_symtabs_lang_matcher lang_matcher = nullptr) = 0;
+ search_symtabs_lang_matcher lang_matcher = nullptr) = 0;
/* Return the comp unit from OBJFILE that contains PC and
SECTION. Return NULL if there is no such compunit. This
diff --git a/gdb/ravenscar-thread.c b/gdb/ravenscar-thread.c
index 13258c4..4d79b3d 100644
--- a/gdb/ravenscar-thread.c
+++ b/gdb/ravenscar-thread.c
@@ -503,7 +503,7 @@ ravenscar_thread_target::pid_to_str (ptid_t ptid)
return beneath ()->pid_to_str (ptid);
return string_printf ("Ravenscar Thread 0x%s",
- phex_nz (ptid.tid (), sizeof (ULONGEST)));
+ phex_nz (ptid.tid ()));
}
CORE_ADDR
@@ -921,9 +921,7 @@ Support for Ravenscar task/thread switching is disabled\n"));
/* Module startup initialization function, automagically called by
init.c. */
-void _initialize_ravenscar ();
-void
-_initialize_ravenscar ()
+INIT_GDB_FILE (ravenscar)
{
/* Notice when the inferior is created in order to push the
ravenscar ops if needed. */
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 2d71b72..d789992 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -132,10 +132,7 @@ public:
bool can_execute_reverse () override;
bool stopped_by_sw_breakpoint () override;
- bool supports_stopped_by_sw_breakpoint () override;
-
bool stopped_by_hw_breakpoint () override;
- bool supports_stopped_by_hw_breakpoint () override;
enum exec_direction_kind execution_direction () override;
void prepare_to_generate_core () override;
@@ -2581,7 +2578,7 @@ record_btrace_maybe_mark_async_event
const std::vector<thread_info *> &no_history)
{
bool more_moving = !moving.empty ();
- bool more_no_history = !no_history.empty ();;
+ bool more_no_history = !no_history.empty ();
if (!more_moving && !more_no_history)
return;
@@ -2773,18 +2770,6 @@ record_btrace_target::stopped_by_sw_breakpoint ()
return this->beneath ()->stopped_by_sw_breakpoint ();
}
-/* The supports_stopped_by_sw_breakpoint method of target
- record-btrace. */
-
-bool
-record_btrace_target::supports_stopped_by_sw_breakpoint ()
-{
- if (record_is_replaying (minus_one_ptid))
- return true;
-
- return this->beneath ()->supports_stopped_by_sw_breakpoint ();
-}
-
/* The stopped_by_sw_breakpoint method of target record-btrace. */
bool
@@ -2800,18 +2785,6 @@ record_btrace_target::stopped_by_hw_breakpoint ()
return this->beneath ()->stopped_by_hw_breakpoint ();
}
-/* The supports_stopped_by_hw_breakpoint method of target
- record-btrace. */
-
-bool
-record_btrace_target::supports_stopped_by_hw_breakpoint ()
-{
- if (record_is_replaying (minus_one_ptid))
- return true;
-
- return this->beneath ()->supports_stopped_by_hw_breakpoint ();
-}
-
/* The update_thread_list method of target record-btrace. */
void
@@ -3213,9 +3186,7 @@ set_record_pt_event_tracing_value (const char *args, int from_tty,
/* Initialize btrace commands. */
-void _initialize_record_btrace ();
-void
-_initialize_record_btrace ()
+INIT_GDB_FILE (record_btrace)
{
cmd_list_element *record_btrace_cmd
= add_prefix_cmd ("btrace", class_obscure, cmd_record_btrace_start,
diff --git a/gdb/record-full.c b/gdb/record-full.c
index b52fb06..2fbdf3b 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -908,7 +908,7 @@ record_full_exec_insn (struct regcache *regcache,
}
}
-static void record_full_restore (void);
+static void record_full_restore (struct bfd &cbfd);
/* Asynchronous signal handle registered as event loop source for when
we have pending events ready to be passed to the core. */
@@ -921,10 +921,11 @@ record_full_async_inferior_event_handler (gdb_client_data data)
inferior_event_handler (INF_REG_EVENT);
}
-/* Open the process record target for 'core' files. */
+/* Open the process record target for 'core' files. CBFD is the core file
+ containing the record information. */
static void
-record_full_core_open_1 ()
+record_full_core_open_1 (struct bfd &cbfd)
{
regcache *regcache = get_thread_regcache (inferior_thread ());
int regnum = gdbarch_num_regs (regcache->arch ());
@@ -937,11 +938,10 @@ record_full_core_open_1 ()
for (i = 0; i < regnum; i ++)
record_full_core_regbuf->raw_supply (i, *regcache);
- record_full_core_sections
- = build_section_table (current_program_space->core_bfd ());
+ record_full_core_sections = build_section_table (&cbfd);
current_inferior ()->push_target (&record_full_core_ops);
- record_full_restore ();
+ record_full_restore (cbfd);
}
/* Open the process record target for 'live' processes. */
@@ -987,8 +987,8 @@ record_full_open (const char *args, int from_tty)
record_full_list = &record_full_first;
record_full_list->next = NULL;
- if (current_program_space->core_bfd ())
- record_full_core_open_1 ();
+ if (current_program_space->core_bfd () != nullptr)
+ record_full_core_open_1 (*current_program_space->core_bfd ());
else
record_full_open_1 ();
@@ -1091,7 +1091,7 @@ record_full_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
if (!step)
{
/* This is not hard single step. */
- if (!gdbarch_software_single_step_p (gdbarch))
+ if (!gdbarch_get_next_pcs_p (gdbarch))
{
/* This is a normal continue. */
step = 1;
@@ -1266,7 +1266,7 @@ record_full_wait_1 (struct target_ops *ops,
process_stratum_target *proc_target
= current_inferior ()->process_target ();
- if (gdbarch_software_single_step_p (gdbarch))
+ if (gdbarch_get_next_pcs_p (gdbarch))
{
/* Try to insert the software single step breakpoint.
If insert success, set step to 0. */
@@ -2332,9 +2332,10 @@ netorder32 (uint32_t input)
return ret;
}
-/* Restore the execution log from a core_bfd file. */
+/* Restore the execution log from core file CBFD. */
+
static void
-record_full_restore (void)
+record_full_restore (struct bfd &cbfd)
{
uint32_t magic;
struct record_full_entry *rec;
@@ -2342,11 +2343,6 @@ record_full_restore (void)
uint32_t osec_size;
int bfd_offset = 0;
- /* We restore the execution log from the open core bfd,
- if there is one. */
- if (current_program_space->core_bfd () == nullptr)
- return;
-
/* "record_full_restore" can only be called when record list is empty. */
gdb_assert (record_full_first.next == NULL);
@@ -2354,7 +2350,7 @@ record_full_restore (void)
gdb_printf (gdb_stdlog, "Restoring recording from core file.\n");
/* Now need to find our special note section. */
- osec = bfd_get_section_by_name (current_program_space->core_bfd (), "null0");
+ osec = bfd_get_section_by_name (&cbfd, "null0");
if (record_debug)
gdb_printf (gdb_stdlog, "Find precord section %s.\n",
osec ? "succeeded" : "failed");
@@ -2365,11 +2361,10 @@ record_full_restore (void)
gdb_printf (gdb_stdlog, "%s", bfd_section_name (osec));
/* Check the magic code. */
- bfdcore_read (current_program_space->core_bfd (), osec, &magic,
- sizeof (magic), &bfd_offset);
+ bfdcore_read (&cbfd, osec, &magic, sizeof (magic), &bfd_offset);
if (magic != RECORD_FULL_FILE_MAGIC)
error (_("Version mismatch or file format error in core file %s."),
- bfd_get_filename (current_program_space->core_bfd ()));
+ bfd_get_filename (&cbfd));
if (record_debug)
gdb_printf (gdb_stdlog,
" Reading 4-byte magic cookie "
@@ -2395,23 +2390,21 @@ record_full_restore (void)
/* We are finished when offset reaches osec_size. */
if (bfd_offset >= osec_size)
break;
- bfdcore_read (current_program_space->core_bfd (), osec, &rectype,
- sizeof (rectype), &bfd_offset);
+ bfdcore_read (&cbfd, osec, &rectype, sizeof (rectype), &bfd_offset);
switch (rectype)
{
case record_full_reg: /* reg */
/* Get register number to regnum. */
- bfdcore_read (current_program_space->core_bfd (), osec, &regnum,
- sizeof (regnum), &bfd_offset);
+ bfdcore_read (&cbfd, osec, &regnum, sizeof (regnum),
+ &bfd_offset);
regnum = netorder32 (regnum);
rec = record_full_reg_alloc (regcache, regnum);
/* Get val. */
- bfdcore_read (current_program_space->core_bfd (), osec,
- record_full_get_loc (rec), rec->u.reg.len,
- &bfd_offset);
+ bfdcore_read (&cbfd, osec, record_full_get_loc (rec),
+ rec->u.reg.len, &bfd_offset);
if (record_debug)
gdb_printf (gdb_stdlog,
@@ -2424,21 +2417,18 @@ record_full_restore (void)
case record_full_mem: /* mem */
/* Get len. */
- bfdcore_read (current_program_space->core_bfd (), osec, &len,
- sizeof (len), &bfd_offset);
+ bfdcore_read (&cbfd, osec, &len, sizeof (len), &bfd_offset);
len = netorder32 (len);
/* Get addr. */
- bfdcore_read (current_program_space->core_bfd (), osec, &addr,
- sizeof (addr), &bfd_offset);
+ bfdcore_read (&cbfd, osec, &addr, sizeof (addr), &bfd_offset);
addr = netorder64 (addr);
rec = record_full_mem_alloc (addr, len);
/* Get val. */
- bfdcore_read (current_program_space->core_bfd (), osec,
- record_full_get_loc (rec), rec->u.mem.len,
- &bfd_offset);
+ bfdcore_read (&cbfd, osec, record_full_get_loc (rec),
+ rec->u.mem.len, &bfd_offset);
if (record_debug)
gdb_printf (gdb_stdlog,
@@ -2456,14 +2446,13 @@ record_full_restore (void)
record_full_insn_num ++;
/* Get signal value. */
- bfdcore_read (current_program_space->core_bfd (), osec, &signal,
- sizeof (signal), &bfd_offset);
+ bfdcore_read (&cbfd, osec, &signal, sizeof (signal),
+ &bfd_offset);
signal = netorder32 (signal);
rec->u.end.sigval = (enum gdb_signal) signal;
/* Get insn count. */
- bfdcore_read (current_program_space->core_bfd (), osec, &count,
- sizeof (count), &bfd_offset);
+ bfdcore_read (&cbfd, osec, &count, sizeof (count), &bfd_offset);
count = netorder32 (count);
rec->u.end.insn_num = count;
record_full_insn_count = count + 1;
@@ -2479,7 +2468,7 @@ record_full_restore (void)
default:
error (_("Bad entry type in core file %s."),
- bfd_get_filename (current_program_space->core_bfd ()));
+ bfd_get_filename (&cbfd));
break;
}
@@ -2509,7 +2498,7 @@ record_full_restore (void)
/* Succeeded. */
gdb_printf (_("Restored records from core file %s.\n"),
- bfd_get_filename (current_program_space->core_bfd ()));
+ bfd_get_filename (&cbfd));
print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
}
@@ -2877,9 +2866,7 @@ maintenance_print_record_instruction (const char *args, int from_tty)
}
}
-void _initialize_record_full ();
-void
-_initialize_record_full ()
+INIT_GDB_FILE (record_full)
{
struct cmd_list_element *c;
diff --git a/gdb/record.c b/gdb/record.c
index 440c5e9..de1a7a8 100644
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -28,7 +28,6 @@
#include "interps.h"
#include "top.h"
-#include <ctype.h>
/* This is the debug switch for process record. */
unsigned int record_debug = 0;
@@ -423,7 +422,7 @@ get_insn_number (const char **arg)
begin = *arg;
pos = skip_spaces (begin);
- if (!isdigit (*pos))
+ if (!c_isdigit (*pos))
error (_("Expected positive number, got: %s."), pos);
number = strtoulst (pos, &end, 10);
@@ -443,7 +442,7 @@ get_context_size (const char **arg)
pos = skip_spaces (*arg);
- if (!isdigit (*pos))
+ if (!c_isdigit (*pos))
error (_("Expected positive number, got: %s."), pos);
long result = strtol (pos, &end, 10);
@@ -483,7 +482,7 @@ get_insn_history_modifiers (const char **arg)
for (; *args; ++args)
{
- if (isspace (*args))
+ if (c_isspace (*args))
break;
if (*args == '/')
@@ -627,7 +626,7 @@ get_call_history_modifiers (const char **arg)
for (; *args; ++args)
{
- if (isspace (*args))
+ if (c_isspace (*args))
break;
if (*args == '/')
@@ -769,9 +768,7 @@ set_record_call_history_size (const char *args, int from_tty,
&record_call_history_size);
}
-void _initialize_record ();
-void
-_initialize_record ()
+INIT_GDB_FILE (record)
{
struct cmd_list_element *c;
diff --git a/gdb/regcache-dump.c b/gdb/regcache-dump.c
index 39dd8c5..c6ef552 100644
--- a/gdb/regcache-dump.c
+++ b/gdb/regcache-dump.c
@@ -346,9 +346,7 @@ maintenance_print_remote_registers (const char *args, int from_tty)
"maintenance print remote-registers");
}
-void _initialize_regcache_dump ();
-void
-_initialize_regcache_dump ()
+INIT_GDB_FILE (regcache_dump)
{
add_cmd ("registers", class_maintenance, maintenance_print_registers,
_("Print the internal register configuration.\n"
diff --git a/gdb/regcache.c b/gdb/regcache.c
index e3d435f..cf4c5dd 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -1841,9 +1841,10 @@ reg_buffer_raw_compare_zero_len_test ()
const regcache *regcache
= get_thread_arch_regcache (&inf, ptid_t (1, 1), inf.arch ());
- /* The buffer address is irrelevant since we end up comparing 0 bytes, we just
- need to pass something. */
- gdb_byte buf;
+ /* The buffer address is irrelevant since we end up comparing 0 bytes, we
+ just need to pass something. The variable needs to be initialized to
+ avoid compiler warnings about uninitialized values. */
+ gdb_byte buf = 0;
SELF_CHECK (regcache->raw_compare (0, &buf, register_size (inf.arch (), 0)));
}
@@ -2213,9 +2214,7 @@ regcache_thread_ptid_changed ()
} /* namespace selftests */
#endif /* GDB_SELF_TEST */
-void _initialize_regcache ();
-void
-_initialize_regcache ()
+INIT_GDB_FILE (regcache)
{
struct cmd_list_element *c;
diff --git a/gdb/reggroups.c b/gdb/reggroups.c
index c931434..596b336 100644
--- a/gdb/reggroups.c
+++ b/gdb/reggroups.c
@@ -259,9 +259,7 @@ const reggroup *const all_reggroup = &all_group;
const reggroup *const save_reggroup = &save_group;
const reggroup *const restore_reggroup = &restore_group;
-void _initialize_reggroup ();
-void
-_initialize_reggroup ()
+INIT_GDB_FILE (reggroup)
{
add_cmd ("reggroups", class_maintenance,
maintenance_print_reggroups, _("\
diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c
index 053591c..da1b578 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -234,9 +234,7 @@ remote_notif_state::~remote_notif_state ()
delete_async_event_handler (&get_pending_events_token);
}
-void _initialize_notif ();
-void
-_initialize_notif ()
+INIT_GDB_FILE (notif)
{
add_setshow_boolean_cmd ("notification", no_class, &notif_debug,
_("\
diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
index fc2c900..a325ffa 100644
--- a/gdb/remote-sim.c
+++ b/gdb/remote-sim.c
@@ -25,7 +25,6 @@
#include "inferior.h"
#include "infrun.h"
#include "value.h"
-#include <ctype.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>
@@ -1284,9 +1283,7 @@ gdbsim_target::memory_map ()
return result;
}
-void _initialize_remote_sim ();
-void
-_initialize_remote_sim ()
+INIT_GDB_FILE (remote_sim)
{
struct cmd_list_element *c;
diff --git a/gdb/remote.c b/gdb/remote.c
index 73dc426..aa7e6e4 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -19,9 +19,9 @@
/* See the GDB User Guide for details of the GDB remote protocol. */
-#include <ctype.h>
#include <fcntl.h>
#include "exceptions.h"
+#include "gdbsupport/common-inferior.h"
#include "inferior.h"
#include "infrun.h"
#include "bfd.h"
@@ -251,6 +251,7 @@ enum {
PACKET_vFile_readlink,
PACKET_vFile_fstat,
PACKET_vFile_stat,
+ PACKET_vFile_lstat,
PACKET_qXfer_auxv,
PACKET_qXfer_features,
PACKET_qXfer_exec_file,
@@ -400,6 +401,10 @@ enum {
errors, and so they should not need to check for this feature. */
PACKET_accept_error_message,
+ /* Not really a packet; this indicates support for sending the vRun
+ inferior arguments as a single string. */
+ PACKET_vRun_single_argument,
+
PACKET_MAX
};
@@ -825,6 +830,11 @@ struct remote_features
bool remote_memory_tagging_p () const
{ return packet_support (PACKET_memory_tagging_feature) == PACKET_ENABLE; }
+ /* Returns true if there is support for sending vRun inferior arguments
+ as a single string. */
+ bool remote_vrun_single_arg_p () const
+ { return packet_support (PACKET_vRun_single_argument) == PACKET_ENABLE; }
+
/* Reset all packets back to "unknown support". Called when opening a
new connection to a remote target. */
void reset_all_packet_configs_support ();
@@ -1023,8 +1033,8 @@ public:
int fileio_fstat (int fd, struct stat *sb, fileio_error *target_errno) override;
- int fileio_stat (struct inferior *inf, const char *filename,
- struct stat *sb, fileio_error *target_errno) override;
+ int fileio_lstat (struct inferior *inf, const char *filename,
+ struct stat *sb, fileio_error *target_errno) override;
int fileio_close (int fd, fileio_error *target_errno) override;
@@ -2557,7 +2567,7 @@ packet_check_result (const char *buf)
/* The stub recognized the packet request. Check that the
operation succeeded. */
if (buf[0] == 'E'
- && isxdigit (buf[1]) && isxdigit (buf[2])
+ && c_isxdigit (buf[1]) && c_isxdigit (buf[2])
&& buf[3] == '\0')
/* "Enn" - definitely an error. */
return packet_result::make_numeric_error (buf + 1);
@@ -2902,6 +2912,10 @@ remote_target::remote_add_inferior (bool fake_pid_p, int pid, int attached,
inf = add_inferior_with_spaces ();
}
switch_to_inferior_no_thread (inf);
+
+ /* Clear any data left by previous executions. */
+ target_pre_inferior ();
+
inf->push_target (this);
inferior_appeared (inf, pid);
}
@@ -3027,6 +3041,12 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, bool executing)
inf = remote_add_inferior (fake_pid_p,
currthread.pid (), -1, 1);
+
+ /* Fetch the target description for this inferior. Make sure to
+ leave the currently selected inferior unchanged. */
+ scoped_restore_current_thread restore_thread;
+ switch_to_inferior_no_thread (inf);
+ target_find_description ();
}
/* This is really a new thread. Add it. */
@@ -4657,8 +4677,6 @@ remote_target::get_offsets ()
if (bss_addr != data_addr)
warning (_("Target reported unsupported offsets: %s"), buf);
}
- else
- lose = 1;
}
else if (startswith (ptr, "TextSeg="))
{
@@ -4867,7 +4885,11 @@ remote_target::add_current_inferior_and_thread (const char *wait_status)
fake_pid_p = true;
}
- remote_add_inferior (fake_pid_p, curr_ptid.pid (), -1, 1);
+ const auto inf = remote_add_inferior (fake_pid_p, curr_ptid.pid (), -1, 1);
+ switch_to_inferior_no_thread (inf);
+
+ /* Fetch the target description for this inferior. */
+ target_find_description ();
/* Add the main thread and switch to it. Don't try reading
registers yet, since we haven't fetched the target description
@@ -5006,6 +5028,24 @@ remote_target::process_initial_stop_replies (int from_tty)
the inferiors. */
if (!non_stop)
{
+ /* Ensure changes to the thread state are propagated to the
+ frontend. In non-stop mode only the current inferior will be
+ stopped, but in all-stop mode, all inferiors will change, and
+ the frontend will need updating. */
+ process_stratum_target *finish_target;
+ ptid_t finish_ptid;
+ if (non_stop)
+ {
+ finish_target = current_inferior ()->process_target ();
+ finish_ptid = ptid_t (current_inferior ()->pid);
+ }
+ else
+ {
+ finish_target = nullptr;
+ finish_ptid = minus_one_ptid;
+ }
+ scoped_finish_thread_state finish_state (finish_target, finish_ptid);
+
{
/* At this point, the remote target is not async. It needs to be for
the poll in stop_all_threads to consider events from it, so enable
@@ -5863,6 +5903,8 @@ static const struct protocol_feature remote_protocol_features[] = {
{ "error-message", PACKET_ENABLE, remote_supported_packet,
PACKET_accept_error_message },
{ "binary-upload", PACKET_DISABLE, remote_supported_packet, PACKET_x },
+ { "single-inf-arg", PACKET_DISABLE, remote_supported_packet,
+ PACKET_vRun_single_argument },
};
static char *remote_support_xml;
@@ -5974,6 +6016,10 @@ remote_target::remote_query_supported ()
!= AUTO_BOOLEAN_FALSE)
remote_query_supported_append (&q, "memory-tagging+");
+ if (m_features.packet_set_cmd_state (PACKET_vRun_single_argument)
+ != AUTO_BOOLEAN_FALSE)
+ remote_query_supported_append (&q, "single-inf-arg+");
+
/* Keep this one last to work around a gdbserver <= 7.10 bug in
the qSupported:xmlRegisters=i386 handling. */
if (remote_support_xml != NULL
@@ -6165,6 +6211,7 @@ remote_unpush_target (remote_target *target)
/* We have to unpush the target from all inferiors, even those that
aren't running. */
scoped_restore_current_inferior restore_current_inferior;
+ scoped_restore_current_program_space restore_program_space;
for (inferior *inf : all_inferiors (target))
{
@@ -10836,7 +10883,11 @@ remote_target::extended_remote_run (const std::string &args)
if (!args.empty ())
{
- std::vector<std::string> split_args = gdb::remote_args::split (args);
+ std::vector<std::string> split_args;
+ if (!m_features.remote_vrun_single_arg_p ())
+ split_args = gdb::remote_args::split (args);
+ else
+ split_args.push_back (args);
for (const auto &a : split_args)
{
@@ -11650,7 +11701,7 @@ remote_target::remote_write_qxfer (const char *object_name,
i = snprintf (rs->buf.data (), max_size,
"qXfer:%s:write:%s:%s:",
object_name, annex ? annex : "",
- phex_nz (offset, sizeof offset));
+ phex_nz (offset));
max_size -= (i + 1);
/* Escape as much data as fits into rs->buf. */
@@ -11715,8 +11766,8 @@ remote_target::remote_read_qxfer (const char *object_name,
snprintf (rs->buf.data (), get_remote_packet_size () - 4,
"qXfer:%s:read:%s:%s,%s",
object_name, annex ? annex : "",
- phex_nz (offset, sizeof offset),
- phex_nz (n, sizeof n));
+ phex_nz (offset),
+ phex_nz (n));
i = putpkt (rs->buf);
if (i < 0)
return TARGET_XFER_E_IO;
@@ -11935,7 +11986,7 @@ remote_target::xfer_partial (enum target_object object,
while (annex[i] && (i < (get_remote_packet_size () - 8)))
{
/* Bad caller may have sent forbidden characters. */
- gdb_assert (isprint (annex[i]) && annex[i] != '$' && annex[i] != '#');
+ gdb_assert (c_isprint (annex[i]) && annex[i] != '$' && annex[i] != '#');
*p2++ = annex[i];
i++;
}
@@ -12014,7 +12065,7 @@ remote_target::search_memory (CORE_ADDR start_addr, ULONGEST search_space_len,
i = snprintf (rs->buf.data (), max_size,
"qSearch:memory:%s;%s;",
phex_nz (start_addr, addr_size),
- phex_nz (search_space_len, sizeof (search_space_len)));
+ phex_nz (search_space_len));
max_size -= (i + 1);
/* Escape as much data as fits into rs->buf. */
@@ -12185,7 +12236,7 @@ private:
for (int i = 0; i < buf.size (); ++i)
{
gdb_byte c = buf[i];
- if (isprint (c))
+ if (c_isprint (c))
gdb_putc (c, &stb);
else
gdb_printf (&stb, "\\x%02x", (unsigned char) c);
@@ -13149,7 +13200,7 @@ remote_target::fileio_readlink (struct inferior *inf, const char *filename,
return ret;
}
-/* Helper function to handle ::fileio_fstat and ::fileio_stat result
+/* Helper function to handle ::fileio_fstat and ::fileio_lstat result
processing. When this function is called the remote syscall has been
performed and we know we didn't get an error back.
@@ -13160,10 +13211,10 @@ remote_target::fileio_readlink (struct inferior *inf, const char *filename,
data) is to be placed in ST. */
static int
-fileio_process_fstat_and_stat_reply (const char *attachment,
- int attachment_len,
- int expected_len,
- struct stat *st)
+fileio_process_fstat_and_lstat_reply (const char *attachment,
+ int attachment_len,
+ int expected_len,
+ struct stat *st)
{
struct fio_stat fst;
@@ -13225,15 +13276,15 @@ remote_target::fileio_fstat (int fd, struct stat *st, fileio_error *remote_errno
return 0;
}
- return fileio_process_fstat_and_stat_reply (attachment, attachment_len,
- ret, st);
+ return fileio_process_fstat_and_lstat_reply (attachment, attachment_len,
+ ret, st);
}
-/* Implementation of to_fileio_stat. */
+/* Implementation of to_fileio_lstat. */
int
-remote_target::fileio_stat (struct inferior *inf, const char *filename,
- struct stat *st, fileio_error *remote_errno)
+remote_target::fileio_lstat (struct inferior *inf, const char *filename,
+ struct stat *st, fileio_error *remote_errno)
{
struct remote_state *rs = get_remote_state ();
char *p = rs->buf.data ();
@@ -13242,14 +13293,14 @@ remote_target::fileio_stat (struct inferior *inf, const char *filename,
if (remote_hostio_set_filesystem (inf, remote_errno) != 0)
return {};
- remote_buffer_add_string (&p, &left, "vFile:stat:");
+ remote_buffer_add_string (&p, &left, "vFile:lstat:");
remote_buffer_add_bytes (&p, &left, (const gdb_byte *) filename,
strlen (filename));
int attachment_len;
const char *attachment;
- int ret = remote_hostio_send_command (p - rs->buf.data (), PACKET_vFile_stat,
+ int ret = remote_hostio_send_command (p - rs->buf.data (), PACKET_vFile_lstat,
remote_errno, &attachment,
&attachment_len);
@@ -13258,8 +13309,8 @@ remote_target::fileio_stat (struct inferior *inf, const char *filename,
if (ret < 0)
return ret;
- return fileio_process_fstat_and_stat_reply (attachment, attachment_len,
- ret, st);
+ return fileio_process_fstat_and_lstat_reply (attachment, attachment_len,
+ ret, st);
}
/* Implementation of to_filesystem_is_local. */
@@ -13763,7 +13814,7 @@ remote_target::download_tracepoint (struct bp_location *loc)
encode_actions_rsp (loc, &tdp_actions, &stepping_actions);
tpaddr = loc->address;
- strcpy (addrbuf, phex (tpaddr, sizeof (CORE_ADDR)));
+ strcpy (addrbuf, phex (tpaddr));
ret = snprintf (buf.data (), buf.size (), "QTDP:%x:%s:%c:%lx:%x",
b->number, addrbuf, /* address */
(b->enable_state == bp_enabled ? 'E' : 'D'),
@@ -14027,7 +14078,7 @@ remote_target::enable_tracepoint (struct bp_location *location)
xsnprintf (rs->buf.data (), get_remote_packet_size (), "QTEnable:%x:%s",
location->owner->number,
- phex (location->address, sizeof (CORE_ADDR)));
+ phex (location->address));
putpkt (rs->buf);
remote_get_noisy_reply ();
if (rs->buf[0] == '\0')
@@ -14043,7 +14094,7 @@ remote_target::disable_tracepoint (struct bp_location *location)
xsnprintf (rs->buf.data (), get_remote_packet_size (), "QTDisable:%x:%s",
location->owner->number,
- phex (location->address, sizeof (CORE_ADDR)));
+ phex (location->address));
putpkt (rs->buf);
remote_get_noisy_reply ();
if (rs->buf[0] == '\0')
@@ -15569,7 +15620,7 @@ remote_target::commit_requested_thread_options ()
*obuf_p++ = ';';
obuf_p += xsnprintf (obuf_p, obuf_endp - obuf_p, "%s",
- phex_nz (options, sizeof (options)));
+ phex_nz (options));
if (tp->ptid != magic_null_ptid)
{
*obuf_p++ = ':';
@@ -15808,8 +15859,8 @@ create_fetch_memtags_request (gdb::char_vector &packet, CORE_ADDR address,
std::string request = string_printf ("qMemTags:%s,%s:%s",
phex_nz (address, addr_size),
- phex_nz (len, sizeof (len)),
- phex_nz (type, sizeof (type)));
+ phex_nz (len),
+ phex_nz (type));
strcpy (packet.data (), request.c_str ());
}
@@ -15843,8 +15894,8 @@ create_store_memtags_request (gdb::char_vector &packet, CORE_ADDR address,
/* Put together the main packet, address and length. */
std::string request = string_printf ("QMemTags:%s,%s:%s:",
phex_nz (address, addr_size),
- phex_nz (len, sizeof (len)),
- phex_nz (type, sizeof (type)));
+ phex_nz (len),
+ phex_nz (type));
request += bin2hex (tags.data (), tags.size ());
/* Check if we have exceeded the maximum packet size. */
@@ -16161,9 +16212,7 @@ test_packet_check_result ()
} /* namespace selftests */
#endif /* GDB_SELF_TEST */
-void _initialize_remote ();
-void
-_initialize_remote ()
+INIT_GDB_FILE (remote)
{
add_target (remote_target_info, remote_target::open);
add_target (extended_remote_target_info, extended_remote_target::open);
@@ -16422,6 +16471,8 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
add_packet_config_cmd (PACKET_vFile_stat, "vFile:stat", "hostio-stat", 0);
+ add_packet_config_cmd (PACKET_vFile_lstat, "vFile:lstat", "hostio-lstat", 0);
+
add_packet_config_cmd (PACKET_vAttach, "vAttach", "attach", 0);
add_packet_config_cmd (PACKET_vRun, "vRun", "run", 0);
@@ -16539,6 +16590,10 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
add_packet_config_cmd (PACKET_accept_error_message,
"error-message", "error-message", 0);
+ add_packet_config_cmd (PACKET_vRun_single_argument,
+ "single-inferior-argument-feature",
+ "single-inferior-argument-feature", 0);
+
/* Assert that we've registered "set remote foo-packet" commands
for all packet configs. */
{
diff --git a/gdb/reverse.c b/gdb/reverse.c
index 2c9ed72..dc35bca 100644
--- a/gdb/reverse.c
+++ b/gdb/reverse.c
@@ -277,9 +277,7 @@ info_bookmarks_command (const char *args, int from_tty)
}
}
-void _initialize_reverse ();
-void
-_initialize_reverse ()
+INIT_GDB_FILE (reverse)
{
cmd_list_element *reverse_step_cmd
= add_com ("reverse-step", class_run, reverse_step, _("\
diff --git a/gdb/riscv-fbsd-nat.c b/gdb/riscv-fbsd-nat.c
index df7cc6a..2908d9f 100644
--- a/gdb/riscv-fbsd-nat.c
+++ b/gdb/riscv-fbsd-nat.c
@@ -65,9 +65,7 @@ riscv_fbsd_nat_target::store_registers (struct regcache *regcache,
PT_SETFPREGS, &riscv_fbsd_fpregset);
}
-void _initialize_riscv_fbsd_nat ();
-void
-_initialize_riscv_fbsd_nat ()
+INIT_GDB_FILE (riscv_fbsd_nat)
{
add_inf_child_target (&the_riscv_fbsd_nat_target);
}
diff --git a/gdb/riscv-fbsd-tdep.c b/gdb/riscv-fbsd-tdep.c
index fcb91ca..7999bd3 100644
--- a/gdb/riscv-fbsd-tdep.c
+++ b/gdb/riscv-fbsd-tdep.c
@@ -189,12 +189,11 @@ riscv_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Generic FreeBSD support. */
fbsd_init_abi (info, gdbarch);
- set_gdbarch_software_single_step (gdbarch, riscv_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, riscv_software_single_step);
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- (riscv_isa_xlen (gdbarch) == 4
- ? svr4_ilp32_fetch_link_map_offsets
- : svr4_lp64_fetch_link_map_offsets));
+ set_solib_svr4_ops (gdbarch, (riscv_isa_xlen (gdbarch) == 4
+ ? make_svr4_ilp32_solib_ops
+ : make_svr4_lp64_solib_ops));
tramp_frame_prepend_unwinder (gdbarch, &riscv_fbsd_sigframe);
@@ -207,9 +206,7 @@ riscv_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
riscv_fbsd_get_thread_local_address);
}
-void _initialize_riscv_fbsd_tdep ();
-void
-_initialize_riscv_fbsd_tdep ()
+INIT_GDB_FILE (riscv_fbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_riscv, 0, GDB_OSABI_FREEBSD,
riscv_fbsd_init_abi);
diff --git a/gdb/riscv-linux-nat.c b/gdb/riscv-linux-nat.c
index 8846329..89f1ddc 100644
--- a/gdb/riscv-linux-nat.c
+++ b/gdb/riscv-linux-nat.c
@@ -329,9 +329,7 @@ riscv_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
/* Initialize RISC-V Linux native support. */
-void _initialize_riscv_linux_nat ();
-void
-_initialize_riscv_linux_nat ()
+INIT_GDB_FILE (riscv_linux_nat)
{
/* Register the target. */
linux_target = &the_riscv_linux_nat_target;
diff --git a/gdb/riscv-linux-tdep.c b/gdb/riscv-linux-tdep.c
index e1ea615..982273a 100644
--- a/gdb/riscv-linux-tdep.c
+++ b/gdb/riscv-linux-tdep.c
@@ -20,6 +20,7 @@
#include "osabi.h"
#include "glibc-tdep.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "svr4-tls-tdep.h"
#include "solib-svr4.h"
#include "regset.h"
@@ -510,12 +511,11 @@ riscv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
linux_init_abi (info, gdbarch, 0);
- set_gdbarch_software_single_step (gdbarch, riscv_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, riscv_software_single_step);
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- (riscv_isa_xlen (gdbarch) == 4
- ? linux_ilp32_fetch_link_map_offsets
- : linux_lp64_fetch_link_map_offsets));
+ set_solib_svr4_ops (gdbarch, (riscv_isa_xlen (gdbarch) == 4
+ ? make_linux_ilp32_svr4_solib_ops
+ : make_linux_lp64_svr4_solib_ops));
/* GNU/Linux uses SVR4-style shared libraries. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
@@ -544,9 +544,7 @@ riscv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Initialize RISC-V Linux target support. */
-void _initialize_riscv_linux_tdep ();
-void
-_initialize_riscv_linux_tdep ()
+INIT_GDB_FILE (riscv_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_riscv, 0, GDB_OSABI_LINUX,
riscv_linux_init_abi);
diff --git a/gdb/riscv-none-tdep.c b/gdb/riscv-none-tdep.c
index 7303f54..ad32057 100644
--- a/gdb/riscv-none-tdep.c
+++ b/gdb/riscv-none-tdep.c
@@ -163,9 +163,7 @@ riscv_none_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Initialize RISC-V bare-metal target support. */
-void _initialize_riscv_none_tdep ();
-void
-_initialize_riscv_none_tdep ()
+INIT_GDB_FILE (riscv_none_tdep)
{
gdbarch_register_osabi (bfd_arch_riscv, 0, GDB_OSABI_NONE,
riscv_none_init_abi);
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 8998a29..6fd7c61 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -56,7 +56,6 @@
#include "arch/riscv.h"
#include "record-full.h"
#include "riscv-ravenscar-thread.h"
-#include "gdbsupport/gdb-safe-ctype.h"
#include <vector>
@@ -4163,15 +4162,29 @@ riscv_gnu_triplet_regexp (struct gdbarch *gdbarch)
return "riscv(32|64)?";
}
+/* Implement the "print_insn" gdbarch method. */
+
+static int
+riscv_print_insn (bfd_vma addr, struct disassemble_info *info)
+{
+ /* Initialize the BFD section to enable ISA string detection depending on the
+ object in scope. */
+ struct obj_section *s = find_pc_section (addr);
+ if (s != nullptr)
+ info->section = s->the_bfd_section;
+
+ return default_print_insn (addr, info);
+}
+
/* Implementation of `gdbarch_stap_is_single_operand', as defined in
gdbarch.h. */
static int
riscv_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
{
- return (ISDIGIT (*s) /* Literal number. */
+ return (c_isdigit (*s) /* Literal number. */
|| *s == '(' /* Register indirection. */
- || ISALPHA (*s)); /* Register value. */
+ || c_isalpha (*s)); /* Register value. */
}
/* String that appears before a register name in a SystemTap register
@@ -4429,6 +4442,9 @@ riscv_gdbarch_init (struct gdbarch_info info,
disassembler_options_riscv ());
set_gdbarch_disassembler_options (gdbarch, &riscv_disassembler_options);
+ /* Disassembler print_insn. */
+ set_gdbarch_print_insn (gdbarch, riscv_print_insn);
+
/* SystemTap Support. */
set_gdbarch_stap_is_single_operand (gdbarch, riscv_stap_is_single_operand);
set_gdbarch_stap_register_indirection_prefixes
@@ -4778,9 +4794,7 @@ riscv_supply_regset (const struct regset *regset,
}
}
-void _initialize_riscv_tdep ();
-void
-_initialize_riscv_tdep ()
+INIT_GDB_FILE (riscv_tdep)
{
riscv_init_reggroups ();
@@ -4909,6 +4923,8 @@ public:
/* Corner cases. */
ECALL,
EBREAK,
+ SRET,
+ MRET,
};
private:
@@ -4993,6 +5009,14 @@ private:
return (ival >> OP_SH_CSR) & OP_MASK_CSR;
}
+ /* Set any record type. Always returns true. */
+ bool
+ set_record_type (record_type type) noexcept
+ {
+ m_record_type = type;
+ return true;
+ }
+
/* Set ordinary record type. Always returns true. */
bool
set_ordinary_record_type () noexcept
@@ -5051,7 +5075,8 @@ private:
return (is_beq_insn (ival) || is_bne_insn (ival) || is_blt_insn (ival)
|| is_bge_insn (ival) || is_bltu_insn (ival) || is_bgeu_insn (ival)
|| is_fence_insn (ival) || is_pause_insn (ival)
- || is_fence_i_insn (ival));
+ || is_fence_i_insn (ival) || is_wfi_insn (ival)
+ || is_sfence_vma_insn (ival));
}
/* Returns true if instruction is classified. */
@@ -5158,7 +5183,7 @@ private:
{
return (is_csrrw_insn (ival) || is_csrrs_insn (ival) || is_csrrc_insn (ival)
|| is_csrrwi_insn (ival) || is_csrrsi_insn (ival)
- || is_csrrc_insn (ival));
+ || is_csrrci_insn (ival));
}
/* Returns true if instruction is classified. This function can set
@@ -5255,14 +5280,26 @@ private:
if (is_ecall_insn (ival))
{
- m_record_type = record_type::ECALL;
- return true;
+ return set_record_type (record_type::ECALL);
}
if (is_ebreak_insn (ival))
{
- m_record_type = record_type::EBREAK;
- return true;
+ return set_record_type (record_type::EBREAK);
+ }
+
+ if (is_sret_insn (ival))
+ {
+ return (!save_reg (RISCV_CSR_SSTATUS_REGNUM)
+ || !save_reg (RISCV_CSR_MEPC_REGNUM)
+ || set_record_type (record_type::SRET));
+ }
+
+ if (is_mret_insn (ival))
+ {
+ return (!save_reg (RISCV_CSR_MSTATUS_REGNUM)
+ || !save_reg (RISCV_CSR_MEPC_REGNUM)
+ || set_record_type (record_type::MRET));
}
if (try_save_pc (ival) || try_save_pc_rd (ival) || try_save_pc_fprd (ival)
@@ -5356,8 +5393,7 @@ private:
if (is_c_ebreak_insn (ival))
{
- m_record_type = record_type::EBREAK;
- return true;
+ return set_record_type (record_type::EBREAK);
}
if (is_c_jalr_insn (ival))
@@ -5399,8 +5435,20 @@ public:
gdb_assert (regcache != nullptr);
int m_length = 0;
+ ULONGEST ival = 0;
m_xlen = riscv_isa_xlen (gdbarch);
- ULONGEST ival = riscv_insn::fetch_instruction (gdbarch, addr, &m_length);
+
+ /* Since fetch_instruction can throw an exception,
+ it must be wrapped in a try-catch block. */
+ try
+ {
+ ival = riscv_insn::fetch_instruction (gdbarch, addr, &m_length);
+ }
+ catch (const gdb_exception_error &ex)
+ {
+ warning ("%s", ex.what ());
+ return false;
+ }
if (!save_reg (RISCV_PC_REGNUM))
return false;
@@ -5494,6 +5542,9 @@ riscv_record_insn_details (struct gdbarch *gdbarch, struct regcache *regcache,
switch (insn.get_record_type ())
{
case riscv_recorded_insn::record_type::ORDINARY:
+ case riscv_recorded_insn::record_type::EBREAK:
+ case riscv_recorded_insn::record_type::SRET:
+ case riscv_recorded_insn::record_type::MRET:
break;
case riscv_recorded_insn::record_type::ECALL:
@@ -5509,9 +5560,6 @@ riscv_record_insn_details (struct gdbarch *gdbarch, struct regcache *regcache,
return tdep->riscv_syscall_record (regcache, reg_val);
}
- case riscv_recorded_insn::record_type::EBREAK:
- break;
-
default:
return -1;
}
diff --git a/gdb/rl78-tdep.c b/gdb/rl78-tdep.c
index f325f41..5c49d1f 100644
--- a/gdb/rl78-tdep.c
+++ b/gdb/rl78-tdep.c
@@ -1488,9 +1488,7 @@ rl78_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Register the above initialization routine. */
-void _initialize_rl78_tdep ();
-void
-_initialize_rl78_tdep ()
+INIT_GDB_FILE (rl78_tdep)
{
gdbarch_register (bfd_arch_rl78, rl78_gdbarch_init);
}
diff --git a/gdb/rs6000-aix-nat.c b/gdb/rs6000-aix-nat.c
index 225d1b8..213f197 100644
--- a/gdb/rs6000-aix-nat.c
+++ b/gdb/rs6000-aix-nat.c
@@ -1062,9 +1062,7 @@ rs6000_nat_target::xfer_shared_libraries
}
}
-void _initialize_rs6000_nat ();
-void
-_initialize_rs6000_nat ()
+INIT_GDB_FILE (rs6000_nat)
{
add_inf_child_target (&the_rs6000_nat_target);
}
diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c
index ab9feb3..536f647 100644
--- a/gdb/rs6000-aix-tdep.c
+++ b/gdb/rs6000-aix-tdep.c
@@ -1330,6 +1330,7 @@ rs6000_aix_ld_info_to_xml (struct gdbarch *gdbarch, const gdb_byte *ldi_buf,
static ULONGEST
rs6000_aix_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch,
+ struct bfd &cbfd,
gdb_byte *readbuf,
ULONGEST offset,
ULONGEST len)
@@ -1337,8 +1338,7 @@ rs6000_aix_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch,
struct bfd_section *ldinfo_sec;
int ldinfo_size;
- ldinfo_sec = bfd_get_section_by_name (current_program_space->core_bfd (),
- ".ldinfo");
+ ldinfo_sec = bfd_get_section_by_name (&cbfd, ".ldinfo");
if (ldinfo_sec == NULL)
error (_("cannot find .ldinfo section from core file: %s"),
bfd_errmsg (bfd_get_error ()));
@@ -1346,8 +1346,7 @@ rs6000_aix_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch,
gdb::byte_vector ldinfo_buf (ldinfo_size);
- if (! bfd_get_section_contents (current_program_space->core_bfd (),
- ldinfo_sec, ldinfo_buf.data (), 0,
+ if (! bfd_get_section_contents (&cbfd, ldinfo_sec, ldinfo_buf.data (), 0,
ldinfo_size))
error (_("unable to read .ldinfo section from core file: %s"),
bfd_errmsg (bfd_get_error ()));
@@ -1362,7 +1361,7 @@ rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
/* RS6000/AIX does not support PT_STEP. Has to be simulated. */
- set_gdbarch_software_single_step (gdbarch, rs6000_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, rs6000_software_single_step);
/* Displaced stepping is currently not supported in combination with
software single-stepping. These override the values set by
@@ -1411,13 +1410,11 @@ rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_wchar_signed (gdbarch, 0);
set_gdbarch_auto_wide_charset (gdbarch, rs6000_aix_auto_wide_charset);
- set_gdbarch_so_ops (gdbarch, &solib_aix_so_ops);
+ set_gdbarch_make_solib_ops (gdbarch, make_aix_solib_ops);
frame_unwind_append_unwinder (gdbarch, &aix_sighandle_frame_unwind);
}
-void _initialize_rs6000_aix_tdep ();
-void
-_initialize_rs6000_aix_tdep ()
+INIT_GDB_FILE (rs6000_aix_tdep)
{
gdbarch_register_osabi_sniffer (bfd_arch_rs6000,
bfd_target_xcoff_flavour,
diff --git a/gdb/rs6000-lynx178-tdep.c b/gdb/rs6000-lynx178-tdep.c
index 38af2ac..d0d9a53 100644
--- a/gdb/rs6000-lynx178-tdep.c
+++ b/gdb/rs6000-lynx178-tdep.c
@@ -407,9 +407,7 @@ rs6000_lynx178_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
}
-void _initialize_rs6000_lynx178_tdep ();
-void
-_initialize_rs6000_lynx178_tdep ()
+INIT_GDB_FILE (rs6000_lynx178_tdep)
{
gdbarch_register_osabi_sniffer (bfd_arch_rs6000,
bfd_target_xcoff_flavour,
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 23ccd92..75079b9 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -8458,7 +8458,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_sofun_address_maybe_missing (gdbarch, 1);
/* Handles single stepping of atomic sequences. */
- set_gdbarch_software_single_step (gdbarch, ppc_deal_with_atomic_sequence);
+ set_gdbarch_get_next_pcs (gdbarch, ppc_deal_with_atomic_sequence);
/* Not sure on this. FIXMEmgo */
set_gdbarch_frame_args_skip (gdbarch, 8);
@@ -8722,9 +8722,7 @@ ppc_insn_prefix_dform (unsigned int insn1, unsigned int insn2)
/* Initialization code. */
-void _initialize_rs6000_tdep ();
-void
-_initialize_rs6000_tdep ()
+INIT_GDB_FILE (rs6000_tdep)
{
gdbarch_register (bfd_arch_rs6000, rs6000_gdbarch_init, rs6000_dump_tdep);
gdbarch_register (bfd_arch_powerpc, rs6000_gdbarch_init, rs6000_dump_tdep);
diff --git a/gdb/run-on-main-thread.c b/gdb/run-on-main-thread.c
index edaab08..bf53163 100644
--- a/gdb/run-on-main-thread.c
+++ b/gdb/run-on-main-thread.c
@@ -22,6 +22,7 @@
#include <thread>
#include <mutex>
#endif
+#include "gdbsupport/cleanups.h"
#include "gdbsupport/event-loop.h"
/* The serial event used when posting runnables. */
@@ -130,9 +131,7 @@ is_main_thread ()
#endif
}
-void _initialize_run_on_main_thread ();
-void
-_initialize_run_on_main_thread ()
+INIT_GDB_FILE (run_on_main_thread)
{
#if CXX_STD_THREAD
/* The variable main_thread_id should be initialized when entering main, or
diff --git a/gdb/rust-exp.h b/gdb/rust-exp.h
index 73654f6..3185242 100644
--- a/gdb/rust-exp.h
+++ b/gdb/rust-exp.h
@@ -33,14 +33,6 @@ extern struct value *eval_op_rust_array (struct type *expect_type,
enum exp_opcode opcode,
struct value *ncopies,
struct value *elt);
-extern struct value *rust_subscript (struct type *expect_type,
- struct expression *exp,
- enum noside noside, bool for_addr,
- struct value *lhs, struct value *rhs);
-extern struct value *rust_range (struct type *expect_type,
- struct expression *exp,
- enum noside noside, enum range_flag kind,
- struct value *low, struct value *high);
namespace expr
{
@@ -75,22 +67,26 @@ public:
struct expression *exp,
enum noside noside) override
{
- value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
- value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
- return rust_subscript (expect_type, exp, noside, false, arg1, arg2);
+ return subscript (exp, noside, false);
}
value *slice (struct type *expect_type,
struct expression *exp,
enum noside noside)
{
- value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
- value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
- return rust_subscript (expect_type, exp, noside, true, arg1, arg2);
+ return subscript (exp, noside, true);
}
enum exp_opcode opcode () const override
{ return BINOP_SUBSCRIPT; }
+
+private:
+
+ /* Helper function that does the work of evaluation. FOR_ADDR is
+ true if we're evaluating a slice. */
+ value *subscript (struct expression *exp, enum noside noside,
+ bool for_addr);
+
};
class rust_unop_addr_operation
@@ -126,17 +122,7 @@ public:
value *evaluate (struct type *expect_type,
struct expression *exp,
- enum noside noside) override
- {
- auto kind = std::get<0> (m_storage);
- value *low = nullptr;
- if (std::get<1> (m_storage) != nullptr)
- low = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
- value *high = nullptr;
- if (std::get<2> (m_storage) != nullptr)
- high = std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
- return rust_range (expect_type, exp, noside, kind, low, high);
- }
+ enum noside noside) override;
enum exp_opcode opcode () const override
{ return OP_RANGE; }
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index 1bb14db..4626685 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -18,7 +18,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include <ctype.h>
#include "block.h"
#include "c-lang.h"
@@ -126,15 +125,15 @@ rust_underscore_fields (struct type *type)
if (type->code () != TYPE_CODE_STRUCT)
return false;
- for (int i = 0; i < type->num_fields (); ++i)
+ for (const auto &field : type->fields ())
{
- if (!type->field (i).is_static ())
+ if (!field.is_static ())
{
char buf[20];
xsnprintf (buf, sizeof (buf), "%d", field_number);
- const char *field_name = type->field (i).name ();
+ const char *field_name = field.name ();
if (startswith (field_name, "__"))
field_name += 2;
if (strcmp (buf, field_name) != 0)
@@ -376,11 +375,11 @@ rust_array_like_element_type (struct type *type)
{
/* Caller must check this. */
gdb_assert (rust_slice_type_p (type));
- for (int i = 0; i < type->num_fields (); ++i)
+ for (const auto &field : type->fields ())
{
- if (strcmp (type->field (i).name (), "data_ptr") == 0)
+ if (strcmp (field.name (), "data_ptr") == 0)
{
- struct type *base_type = type->field (i).type ()->target_type ();
+ struct type *base_type = field.type ()->target_type ();
if (rewrite_slice_type (base_type, nullptr, 0, nullptr))
return nullptr;
return base_type;
@@ -1017,9 +1016,9 @@ rust_internal_print_type (struct type *type, const char *varstring,
}
gdb_puts ("{\n", stream);
- for (int i = 0; i < type->num_fields (); ++i)
+ for (const auto &field : type->fields ())
{
- const char *name = type->field (i).name ();
+ const char *name = field.name ();
QUIT;
@@ -1142,13 +1141,22 @@ rust_slice_type (const char *name, struct type *elt_type,
-/* A helper for rust_evaluate_subexp that handles OP_RANGE. */
+namespace expr
+{
struct value *
-rust_range (struct type *expect_type, struct expression *exp,
- enum noside noside, enum range_flag kind,
- struct value *low, struct value *high)
+rust_range_operation::evaluate (struct type *expect_type,
+ struct expression *exp,
+ enum noside noside)
{
+ auto kind = std::get<0> (m_storage);
+ value *low = nullptr;
+ if (std::get<1> (m_storage) != nullptr)
+ low = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+ value *high = nullptr;
+ if (std::get<2> (m_storage) != nullptr)
+ high = std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
+
struct value *addrval, *result;
CORE_ADDR addr;
struct type *range_type;
@@ -1225,6 +1233,8 @@ rust_range (struct type *expect_type, struct expression *exp,
return result;
}
+} /* namespace expr */
+
/* A helper function to compute the range and kind given a range
value. TYPE is the type of the range value. RANGE is the range
value. LOW, HIGH, and KIND are out parameters. The LOW and HIGH
@@ -1266,13 +1276,16 @@ rust_compute_range (struct type *type, struct value *range,
}
}
-/* A helper for rust_evaluate_subexp that handles BINOP_SUBSCRIPT. */
+namespace expr
+{
struct value *
-rust_subscript (struct type *expect_type, struct expression *exp,
- enum noside noside, bool for_addr,
- struct value *lhs, struct value *rhs)
+rust_subscript_operation::subscript (struct expression *exp,
+ enum noside noside, bool for_addr)
{
+ value *lhs = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+ value *rhs = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+
struct value *result;
struct type *rhstype;
LONGEST low, high_bound;
@@ -1413,9 +1426,6 @@ rust_subscript (struct type *expect_type, struct expression *exp,
return result;
}
-namespace expr
-{
-
struct value *
rust_unop_ind_operation::evaluate (struct type *expect_type,
struct expression *exp,
@@ -1777,7 +1787,7 @@ rust_language::emitchar (int ch, struct type *chtype,
gdb_puts ("\\t", stream);
else if (ch == '\0')
gdb_puts ("\\0", stream);
- else if (ch >= 32 && ch <= 127 && isprint (ch))
+ else if (ch >= 32 && ch <= 127 && c_isprint (ch))
gdb_putc (ch, stream);
else if (ch <= 255)
gdb_printf (stream, "\\x%02x", ch);
diff --git a/gdb/rust-parse.c b/gdb/rust-parse.c
index ef64005..6ad6542 100644
--- a/gdb/rust-parse.c
+++ b/gdb/rust-parse.c
@@ -335,7 +335,7 @@ struct rust_parser
return std::string (current_string_val.ptr, current_string_val.length);
}
- /* A pointer to this is installed globally. */
+ /* Storage for use while parsing. */
auto_obstack obstack;
/* The parser state gdb gave us. */
@@ -1232,14 +1232,14 @@ rust_parser::name_to_operation (const std::string &name)
struct block_symbol sym = lookup_symbol (name.c_str (),
pstate->expression_context_block,
SEARCH_VFT);
- if (sym.symbol != nullptr && sym.symbol->aclass () != LOC_TYPEDEF)
+ if (sym.symbol != nullptr && sym.symbol->loc_class () != LOC_TYPEDEF)
return make_operation<var_value_operation> (sym);
struct type *type = nullptr;
if (sym.symbol != nullptr)
{
- gdb_assert (sym.symbol->aclass () == LOC_TYPEDEF);
+ gdb_assert (sym.symbol->loc_class () == LOC_TYPEDEF);
type = sym.symbol->type ();
}
if (type == nullptr)
@@ -2421,9 +2421,7 @@ rust_lex_tests (void)
-void _initialize_rust_exp ();
-void
-_initialize_rust_exp ()
+INIT_GDB_FILE (rust_exp)
{
int code = regcomp (&number_regex, number_regex_text, REG_EXTENDED);
/* If the regular expression was incorrect, it was a programming
diff --git a/gdb/rx-tdep.c b/gdb/rx-tdep.c
index f767666..7b110ce 100644
--- a/gdb/rx-tdep.c
+++ b/gdb/rx-tdep.c
@@ -1063,9 +1063,7 @@ rx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Register the above initialization routine. */
-void _initialize_rx_tdep ();
-void
-_initialize_rx_tdep ()
+INIT_GDB_FILE (rx_tdep)
{
gdbarch_register (bfd_arch_rx, rx_gdbarch_init);
initialize_tdesc_rx ();
diff --git a/gdb/s12z-tdep.c b/gdb/s12z-tdep.c
index 70f8598..0d49f98 100644
--- a/gdb/s12z-tdep.c
+++ b/gdb/s12z-tdep.c
@@ -516,7 +516,7 @@ s12z_print_ccw_info (struct gdbarch *gdbarch,
gdb_putc (ccw_bits[b], file);
}
else
- gdb_putc (tolower (ccw_bits[b]), file);
+ gdb_putc (c_tolower (ccw_bits[b]), file);
}
gdb_putc ('\n', file);
}
@@ -662,9 +662,7 @@ s12z_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_s12z_tdep ();
-void
-_initialize_s12z_tdep ()
+INIT_GDB_FILE (s12z_tdep)
{
gdbarch_register (bfd_arch_s12z, s12z_gdbarch_init, NULL);
}
diff --git a/gdb/s390-linux-nat.c b/gdb/s390-linux-nat.c
index d5964e2..5b723b1 100644
--- a/gdb/s390-linux-nat.c
+++ b/gdb/s390-linux-nat.c
@@ -1051,9 +1051,7 @@ s390_linux_nat_target::read_description ()
tdesc_s390_linux32);
}
-void _initialize_s390_nat ();
-void
-_initialize_s390_nat ()
+INIT_GDB_FILE (s390_nat)
{
/* Register the target. */
linux_target = &the_s390_linux_nat_target;
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index bd1f42c..66e571d 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -29,6 +29,7 @@
#include "gdbcore.h"
#include "linux-record.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "svr4-tls-tdep.h"
#include "objfiles.h"
#include "osabi.h"
@@ -1214,8 +1215,7 @@ s390_linux_init_abi_31 (struct gdbarch_info info, struct gdbarch *gdbarch)
s390_linux_init_abi_any (info, gdbarch);
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_S390);
}
@@ -1230,14 +1230,11 @@ s390_linux_init_abi_64 (struct gdbarch_info info, struct gdbarch *gdbarch)
s390_linux_init_abi_any (info, gdbarch);
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- linux_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_lp64_svr4_solib_ops);
set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_S390X);
}
-void _initialize_s390_linux_tdep ();
-void
-_initialize_s390_linux_tdep ()
+INIT_GDB_FILE (s390_linux_tdep)
{
/* Hook us into the OSABI mechanism. */
gdbarch_register_osabi (bfd_arch_s390, bfd_mach_s390_31, GDB_OSABI_LINUX,
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
index a3b7658..0cef5f4 100644
--- a/gdb/s390-tdep.c
+++ b/gdb/s390-tdep.c
@@ -7057,10 +7057,10 @@ s390_gnu_triplet_regexp (struct gdbarch *gdbarch)
static int
s390_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
{
- return ((isdigit (*s) && s[1] == '(' && s[2] == '%') /* Displacement
+ return ((c_isdigit (*s) && s[1] == '(' && s[2] == '%') /* Displacement
or indirection. */
|| *s == '%' /* Register access. */
- || isdigit (*s)); /* Literal number. */
+ || c_isdigit (*s)); /* Literal number. */
}
/* gdbarch init. */
@@ -7300,7 +7300,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
s390_displaced_step_copy_insn);
set_gdbarch_displaced_step_fixup (gdbarch, s390_displaced_step_fixup);
set_gdbarch_displaced_step_hw_singlestep (gdbarch, s390_displaced_step_hw_singlestep);
- set_gdbarch_software_single_step (gdbarch, s390_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, s390_software_single_step);
set_gdbarch_max_insn_length (gdbarch, S390_MAX_INSTR_SIZE);
/* Prologue analysis. */
@@ -7515,9 +7515,7 @@ disassemble_s390x ()
#endif /* GDB_SELF_TEST */
-void _initialize_s390_tdep ();
-void
-_initialize_s390_tdep ()
+INIT_GDB_FILE (s390_tdep)
{
/* Hook us into the gdbarch mechanism. */
gdbarch_register (bfd_arch_s390, s390_gdbarch_init);
diff --git a/gdb/ser-go32.c b/gdb/ser-go32.c
index c6b34ab..6e60569 100644
--- a/gdb/ser-go32.c
+++ b/gdb/ser-go32.c
@@ -914,9 +914,7 @@ info_serial_command (const char *arg, int from_tty)
#endif
}
-void _initialize_ser_dos ();
-void
-_initialize_ser_dos ()
+INIT_GDB_FILE (ser_dos)
{
serial_add_interface (&dos_ops);
diff --git a/gdb/ser-mingw.c b/gdb/ser-mingw.c
index db733c3..086919a 100644
--- a/gdb/ser-mingw.c
+++ b/gdb/ser-mingw.c
@@ -1338,9 +1338,7 @@ static const struct serial_ops tcp_ops =
net_windows_done_wait_handle
};
-void _initialize_ser_windows ();
-void
-_initialize_ser_windows ()
+INIT_GDB_FILE (ser_windows)
{
WSADATA wsa_data;
diff --git a/gdb/ser-pipe.c b/gdb/ser-pipe.c
index 16f7419..bdf3602 100644
--- a/gdb/ser-pipe.c
+++ b/gdb/ser-pipe.c
@@ -236,9 +236,7 @@ static const struct serial_ops pipe_ops =
ser_unix_write_prim
};
-void _initialize_ser_pipe ();
-void
-_initialize_ser_pipe ()
+INIT_GDB_FILE (ser_pipe)
{
serial_add_interface (&pipe_ops);
}
diff --git a/gdb/ser-tcp.c b/gdb/ser-tcp.c
index 122b913..589b23d 100644
--- a/gdb/ser-tcp.c
+++ b/gdb/ser-tcp.c
@@ -465,9 +465,7 @@ static const struct serial_ops tcp_ops =
#endif /* USE_WIN32API */
-void _initialize_ser_tcp ();
-void
-_initialize_ser_tcp ()
+INIT_GDB_FILE (ser_tcp)
{
#ifdef USE_WIN32API
/* Do nothing; the TCP serial operations will be initialized in
diff --git a/gdb/ser-uds.c b/gdb/ser-uds.c
index 64e1599..2a45a90 100644
--- a/gdb/ser-uds.c
+++ b/gdb/ser-uds.c
@@ -110,9 +110,7 @@ static const struct serial_ops uds_ops =
uds_write_prim
};
-void _initialize_ser_socket ();
-void
-_initialize_ser_socket ()
+INIT_GDB_FILE (ser_socket)
{
serial_add_interface (&uds_ops);
}
diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c
index cb803a5..553220e 100644
--- a/gdb/ser-unix.c
+++ b/gdb/ser-unix.c
@@ -30,9 +30,33 @@
#include "gdbsupport/gdb_select.h"
#include "cli/cli-cmds.h"
#include "gdbsupport/filestuff.h"
-#include <termios.h>
+
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+
+#if HAVE_IOKIT_SERIAL_IOSS_H
+# include <IOKit/serial/ioss.h>
+#endif
+
+#if HAVE_ASM_TERMIOS_H
+/* Workaround to resolve conflicting declarations of termios
+ in <asm/termbits.h> and <termios.h>. */
+# define termios asmtermios
+# include <asm/termbits.h>
+# undef termios
+#endif
+
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+#endif
+
#include "gdbsupport/scoped_ignore_sigttou.h"
+#if defined(HAVE_SYS_IOCTL_H) && (defined(BOTHER) || defined(IOSSIOSPEED))
+# define HAVE_CUSTOM_BAUDRATE_SUPPORT 1
+#endif
+
struct hardwire_ttystate
{
struct termios termios;
@@ -289,14 +313,32 @@ baudtab[] =
4800, B4800
}
,
+#ifdef B7200
+ {
+ 7200, B7200
+ }
+ ,
+#endif
{
9600, B9600
}
,
+#ifdef B14400
+ {
+ 14400, B14400
+ }
+ ,
+#endif
{
19200, B19200
}
,
+#ifdef B28800
+ {
+ 28800, B28800
+ }
+ ,
+#endif
{
38400, B38400
}
@@ -307,6 +349,12 @@ baudtab[] =
}
,
#endif
+#ifdef B76800
+ {
+ 76800, B76800
+ }
+ ,
+#endif
#ifdef B115200
{
115200, B115200
@@ -412,6 +460,7 @@ rate_to_code (int rate)
/* check if it is in between valid values. */
if (rate < baudtab[i].rate)
{
+#if !HAVE_CUSTOM_BAUDRATE_SUPPORT
if (i)
{
error (_("Invalid baud rate %d. "
@@ -423,29 +472,126 @@ rate_to_code (int rate)
error (_("Invalid baud rate %d. Minimum value is %d."),
rate, baudtab[0].rate);
}
+#else
+ return -1;
+#endif
}
}
}
-
+
+#if !HAVE_CUSTOM_BAUDRATE_SUPPORT
/* The requested speed was too large. */
error (_("Invalid baud rate %d. Maximum value is %d."),
rate, baudtab[i - 1].rate);
+#else
+ return -1;
+#endif
}
+/* Set baud rate using B_code from termios.h. */
+
static void
-hardwire_setbaudrate (struct serial *scb, int rate)
+set_baudcode_baudrate (struct serial *scb, int baud_code)
{
struct hardwire_ttystate state;
- int baud_code = rate_to_code (rate);
-
+
if (get_tty_state (scb, &state))
- perror_with_name ("could not get tty state");
+ perror_with_name (_("could not get tty state"));
cfsetospeed (&state.termios, baud_code);
cfsetispeed (&state.termios, baud_code);
if (set_tty_state (scb, &state))
- perror_with_name ("could not set tty state");
+ perror_with_name (_("could not set tty state"));
+}
+
+#if HAVE_CUSTOM_BAUDRATE_SUPPORT && defined(BOTHER)
+
+/* Set a custom baud rate using the termios BOTHER. */
+
+static void
+set_custom_baudrate_linux (int fd, int rate)
+{
+#ifdef TCGETS2
+ struct termios2 tio;
+ const unsigned long req_get = TCGETS2;
+ const unsigned long req_set = TCSETS2;
+#else
+ struct termios tio;
+ const unsigned long req_get = TCGETS;
+ const unsigned long req_set = TCSETS;
+#endif
+
+ if (ioctl (fd, req_get, &tio) < 0)
+ perror_with_name (_("Can not get current baud rate"));
+
+ /* Clear the current output baud rate and fill a new value. */
+ tio.c_cflag &= ~CBAUD;
+ tio.c_cflag |= BOTHER;
+ tio.c_ospeed = rate;
+
+ /* Clear the current input baud rate and fill a new value. */
+ tio.c_cflag &= ~(CBAUD << IBSHIFT);
+ tio.c_cflag |= BOTHER << IBSHIFT;
+ tio.c_ispeed = rate;
+
+ if (ioctl (fd, req_set, &tio) < 0)
+ perror_with_name (_("Can not set custom baud rate"));
+}
+
+#elif HAVE_CUSTOM_BAUDRATE_SUPPORT && defined(IOSSIOSPEED)
+
+/* Set a custom baud rate using the IOSSIOSPEED ioctl call. */
+
+static void
+set_custom_baudrate_darwin (int fd, int rate)
+{
+
+ if (ioctl (fd, IOSSIOSPEED, &rate) < 0)
+ perror_with_name (_("Can not set custom baud rate"));
+}
+
+#endif /* HAVE_CUSTOM_BAUDRATE_SUPPORT
+ && (defined(BOTHER) || defined(IOSSIOSPEED)) */
+
+#if HAVE_CUSTOM_BAUDRATE_SUPPORT
+
+/* Set a baud rate that differs from the OS B_codes.
+ This is possible if one of the following macros is available:
+ - BOTHER (Linux).
+ - IOSSIOSPEED (Darwin). */
+
+static void
+set_custom_baudrate (int fd, int rate)
+{
+#if defined(BOTHER)
+ set_custom_baudrate_linux (fd, rate);
+#elif defined(IOSSIOSPEED)
+ set_custom_baudrate_darwin (fd, rate);
+#endif
+}
+
+#endif /* HAVE_CUSTOM_BAUDRATE_SUPPORT */
+
+/* Set the baud rate for the serial communication. */
+
+static void
+hardwire_setbaudrate (struct serial *scb, int rate)
+{
+ int baud_code = rate_to_code (rate);
+
+ if (baud_code < 0)
+ {
+#if HAVE_CUSTOM_BAUDRATE_SUPPORT
+ set_custom_baudrate (scb->fd, rate);
+#else
+ /* An error should already have been thrown by rate_to_code().
+ Add an additional error in case execution somehow reaches this line. */
+ gdb_assert_not_reached ("Serial baud rate was not found in B_codes");
+#endif
+ }
+ else
+ set_baudcode_baudrate (scb, baud_code);
}
static int
@@ -551,9 +697,7 @@ static const struct serial_ops hardwire_ops =
ser_unix_write_prim
};
-void _initialize_ser_hardwire ();
-void
-_initialize_ser_hardwire ()
+INIT_GDB_FILE (ser_hardwire)
{
serial_add_interface (&hardwire_ops);
diff --git a/gdb/serial.c b/gdb/serial.c
index bab8480..d047fdf 100644
--- a/gdb/serial.c
+++ b/gdb/serial.c
@@ -17,7 +17,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include <ctype.h>
#include "serial.h"
#include "cli/cli-cmds.h"
#include "cli/cli-utils.h"
@@ -116,7 +115,7 @@ serial_logchar (struct ui_file *stream, int ch_type, int ch, int timeout)
break;
default:
gdb_printf (stream,
- isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF);
+ c_isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF);
break;
}
}
@@ -642,9 +641,7 @@ set_parity (const char *ignore_args, int from_tty, struct cmd_list_element *c)
serial_parity = GDBPARITY_NONE;
}
-void _initialize_serial ();
-void
-_initialize_serial ()
+INIT_GDB_FILE (serial)
{
#if 0
add_com ("connect", class_obscure, connect_command, _("\
diff --git a/gdb/sh-linux-tdep.c b/gdb/sh-linux-tdep.c
index f0b35d3..2578192 100644
--- a/gdb/sh-linux-tdep.c
+++ b/gdb/sh-linux-tdep.c
@@ -28,6 +28,7 @@
#include "glibc-tdep.h"
#include "sh-tdep.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "gdbarch.h"
#define REGSx16(base) \
@@ -187,8 +188,7 @@ sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* GNU/Linux uses SVR4-style shared libraries. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
set_gdbarch_fetch_tls_load_module_address (gdbarch,
@@ -207,9 +207,7 @@ sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tramp_frame_prepend_unwinder (gdbarch, &sh_linux_rt_sigreturn_tramp_frame);
}
-void _initialize_sh_linux_tdep ();
-void
-_initialize_sh_linux_tdep ()
+INIT_GDB_FILE (sh_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_LINUX, sh_linux_init_abi);
}
diff --git a/gdb/sh-netbsd-nat.c b/gdb/sh-netbsd-nat.c
index 25aafe1..d36dba5 100644
--- a/gdb/sh-netbsd-nat.c
+++ b/gdb/sh-netbsd-nat.c
@@ -98,9 +98,7 @@ sh_nbsd_nat_target::store_registers (struct regcache *regcache, int regno)
}
}
-void _initialize_shnbsd_nat ();
-void
-_initialize_shnbsd_nat ()
+INIT_GDB_FILE (shnbsd_nat)
{
add_inf_child_target (&the_sh_nbsd_nat_target);
}
diff --git a/gdb/sh-netbsd-tdep.c b/gdb/sh-netbsd-tdep.c
index f99566f..4b0181b 100644
--- a/gdb/sh-netbsd-tdep.c
+++ b/gdb/sh-netbsd-tdep.c
@@ -68,13 +68,10 @@ shnbsd_init_abi (struct gdbarch_info info,
tdep->core_gregmap = (struct sh_corefile_regmap *)regmap;
tdep->sizeof_gregset = 84;
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
}
-void _initialize_shnbsd_tdep ();
-void
-_initialize_shnbsd_tdep ()
+INIT_GDB_FILE (shnbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_NETBSD,
shnbsd_init_abi);
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
index 59a67bf..6bd4fd3 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -2394,9 +2394,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_sh_tdep ();
-void
-_initialize_sh_tdep ()
+INIT_GDB_FILE (sh_tdep)
{
gdbarch_register (bfd_arch_sh, sh_gdbarch_init, NULL);
diff --git a/gdb/skip.c b/gdb/skip.c
index a077241..a9ee223 100644
--- a/gdb/skip.c
+++ b/gdb/skip.c
@@ -657,9 +657,7 @@ complete_skip_number (cmd_list_element *cmd,
}
}
-void _initialize_step_skip ();
-void
-_initialize_step_skip ()
+INIT_GDB_FILE (step_skip)
{
static struct cmd_list_element *skiplist = NULL;
struct cmd_list_element *c;
diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c
index ae1e5c0..55e1d3e 100644
--- a/gdb/sol-thread.c
+++ b/gdb/sol-thread.c
@@ -1111,19 +1111,21 @@ info_solthreads (const char *args, int from_tty)
ptid_t
sol_thread_target::get_ada_task_ptid (long lwp, ULONGEST thread)
{
- struct thread_info *thread_info
- = iterate_over_threads ([&] (struct thread_info *thread)
+ auto thread_db_find_thread_from_tid
+ = [&] (struct thread_info *iter)
{
- return thread->ptid.tid () == thread;
- });
+ return iter->ptid.tid () == thread;
+ };
+
+ struct thread_info *thread_info
+ = iterate_over_threads (thread_db_find_thread_from_tid);
if (thread_info == NULL)
{
/* The list of threads is probably not up to date. Find any
thread that is missing from the list, and try again. */
update_thread_list ();
- thread_info = iterate_over_threads (thread_db_find_thread_from_tid,
- &thread);
+ thread_info = iterate_over_threads (thread_db_find_thread_from_tid);
}
gdb_assert (thread_info != NULL);
@@ -1131,9 +1133,7 @@ sol_thread_target::get_ada_task_ptid (long lwp, ULONGEST thread)
return (thread_info->ptid);
}
-void _initialize_sol_thread ();
-void
-_initialize_sol_thread ()
+INIT_GDB_FILE (sol_thread)
{
void *dlhandle;
diff --git a/gdb/solib-aix.c b/gdb/solib-aix.c
index 0ad25f1..6859092 100644
--- a/gdb/solib-aix.c
+++ b/gdb/solib-aix.c
@@ -17,7 +17,6 @@
#include "solib-aix.h"
#include "solib.h"
-#include "solist.h"
#include "inferior.h"
#include "gdb_bfd.h"
#include "objfiles.h"
@@ -25,6 +24,26 @@
#include "xcoffread.h"
#include "observable.h"
+/* solib_ops for AIX systems. */
+
+struct aix_solib_ops : public solib_ops
+{
+ using solib_ops::solib_ops;
+
+ void relocate_section_addresses (solib &so, target_section *) const override;
+ void create_inferior_hook (int from_tty) const override;
+ owning_intrusive_list<solib> current_sos () const override;
+ gdb_bfd_ref_ptr bfd_open (const char *pathname) const override;
+};
+
+/* See solib-aix.h. */
+
+solib_ops_up
+make_aix_solib_ops (program_space *pspace)
+{
+ return std::make_unique<aix_solib_ops> (pspace);
+}
+
/* Our private data in struct solib. */
struct lm_info_aix final : public lm_info
@@ -307,10 +326,9 @@ solib_aix_bss_data_overlap (bfd *abfd)
return 0;
}
-/* Implement the "relocate_section_addresses" solib_ops method. */
-
-static void
-solib_aix_relocate_section_addresses (solib &so, target_section *sec)
+void
+aix_solib_ops::relocate_section_addresses (solib &so,
+ target_section *sec) const
{
struct bfd_section *bfd_sect = sec->the_bfd_section;
bfd *abfd = bfd_sect->owner;
@@ -411,10 +429,8 @@ solib_aix_get_section_offsets (struct objfile *objfile,
return offsets;
}
-/* Implement the "solib_create_inferior_hook" solib_ops method. */
-
-static void
-solib_aix_solib_create_inferior_hook (int from_tty)
+void
+aix_solib_ops::create_inferior_hook (int from_tty) const
{
const char *warning_msg = "unable to relocate main executable";
@@ -442,10 +458,8 @@ solib_aix_solib_create_inferior_hook (int from_tty)
}
}
-/* Implement the "current_sos" solib_ops method. */
-
-static owning_intrusive_list<solib>
-solib_aix_current_sos ()
+owning_intrusive_list<solib>
+aix_solib_ops::current_sos () const
{
std::optional<std::vector<lm_info_aix>> &library_list
= solib_aix_get_library_list (current_inferior (), NULL);
@@ -481,35 +495,17 @@ solib_aix_current_sos ()
}
/* Add it to the list. */
- auto &new_solib = sos.emplace_back ();
- new_solib.so_original_name = so_name;
- new_solib.so_name = so_name;
+ auto &new_solib = sos.emplace_back (*this);
+ new_solib.original_name = so_name;
+ new_solib.name = so_name;
new_solib.lm_info = std::make_unique<lm_info_aix> (info);
}
return sos;
}
-/* Implement the "open_symbol_file_object" solib_ops method. */
-
-static int
-solib_aix_open_symbol_file_object (int from_tty)
-{
- return 0;
-}
-
-/* Implement the "in_dynsym_resolve_code" solib_ops method. */
-
-static int
-solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
-{
- return 0;
-}
-
-/* Implement the "bfd_open" solib_ops method. */
-
-static gdb_bfd_ref_ptr
-solib_aix_bfd_open (const char *pathname)
+gdb_bfd_ref_ptr
+aix_solib_ops::bfd_open (const char *pathname) const
{
/* The pathname is actually a synthetic filename with the following
form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
@@ -523,7 +519,7 @@ solib_aix_bfd_open (const char *pathname)
int found_file;
if (pathname[path_len - 1] != ')')
- return solib_bfd_open (pathname);
+ return solib_ops::bfd_open (pathname);
/* Search for the associated parens. */
sep = strrchr (pathname, '(');
@@ -533,7 +529,7 @@ solib_aix_bfd_open (const char *pathname)
to open pathname without decoding, possibly leading to
a failure), rather than triggering an assert failure). */
warning (_("missing '(' in shared object pathname: %s"), pathname);
- return solib_bfd_open (pathname);
+ return solib_ops::bfd_open (pathname);
}
filename_len = sep - pathname;
@@ -626,9 +622,9 @@ solib_aix_bfd_open (const char *pathname)
static struct obj_section *
data_obj_section_from_objfile (struct objfile *objfile)
{
- for (obj_section *osect : objfile->sections ())
- if (strcmp (bfd_section_name (osect->the_bfd_section), ".data") == 0)
- return osect;
+ for (obj_section &osect : objfile->sections ())
+ if (strcmp (bfd_section_name (osect.the_bfd_section), ".data") == 0)
+ return &osect;
return NULL;
}
@@ -676,27 +672,7 @@ solib_aix_normal_stop_observer (struct bpstat *unused_1, int unused_2)
data->library_list.reset ();
}
-/* The solib_ops for AIX targets. */
-const solib_ops solib_aix_so_ops =
-{
- solib_aix_relocate_section_addresses,
- nullptr,
- nullptr,
- solib_aix_solib_create_inferior_hook,
- solib_aix_current_sos,
- solib_aix_open_symbol_file_object,
- solib_aix_in_dynsym_resolve_code,
- solib_aix_bfd_open,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- default_find_solib_addr,
-};
-
-void _initialize_solib_aix ();
-void
-_initialize_solib_aix ()
+INIT_GDB_FILE (solib_aix)
{
gdb::observers::normal_stop.attach (solib_aix_normal_stop_observer,
"solib-aix");
diff --git a/gdb/solib-aix.h b/gdb/solib-aix.h
index 7a1bc7b..887487d 100644
--- a/gdb/solib-aix.h
+++ b/gdb/solib-aix.h
@@ -18,9 +18,12 @@
#ifndef GDB_SOLIB_AIX_H
#define GDB_SOLIB_AIX_H
-struct solib_ops;
-extern const solib_ops solib_aix_so_ops;
+#include "solib.h"
extern CORE_ADDR solib_aix_get_toc_value (CORE_ADDR pc);
+/* Return a new solib_ops for AIX systems. */
+
+solib_ops_up make_aix_solib_ops (program_space *pspace);
+
#endif /* GDB_SOLIB_AIX_H */
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index 368f401..6212697 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -27,12 +27,33 @@
#include "regcache.h"
#include "gdb_bfd.h"
-#include "solist.h"
+#include "solib.h"
#include "solib-darwin.h"
#include "mach-o.h"
#include "mach-o/external.h"
+/* solib_ops for Darwin systems. */
+
+struct darwin_solib_ops : public solib_ops
+{
+ using solib_ops::solib_ops;
+
+ void relocate_section_addresses (solib &so, target_section *) const override;
+ void clear_solib (program_space *pspace) const override;
+ void create_inferior_hook (int from_tty) const override;
+ owning_intrusive_list<solib> current_sos () const override;
+ gdb_bfd_ref_ptr bfd_open (const char *pathname) const override;
+};
+
+/* See solib-darwin.h. */
+
+solib_ops_up
+make_darwin_solib_ops (program_space *pspace)
+{
+ return std::make_unique<darwin_solib_ops> (pspace);
+}
+
struct gdb_dyld_image_info
{
/* Base address (which corresponds to the Mach-O header). */
@@ -133,7 +154,7 @@ darwin_load_image_infos (struct darwin_info *info)
(buf + 8 + ptr_type->length (), ptr_type);
}
-/* Link map info to include in an allocated so_list entry. */
+/* Link map info to include in an allocated solib entry. */
struct lm_info_darwin final : public lm_info
{
@@ -188,20 +209,8 @@ find_program_interpreter (void)
return buf;
}
-/* Not used. I don't see how the main symbol file can be found: the
- interpreter name is needed and it is known from the executable file.
- Note that darwin-nat.c implements pid_to_exec_file. */
-
-static int
-open_symbol_file_object (int from_tty)
-{
- return 0;
-}
-
-/* Build a list of currently loaded shared objects. See solib-svr4.c. */
-
-static owning_intrusive_list<solib>
-darwin_current_sos ()
+owning_intrusive_list<solib>
+darwin_solib_ops::current_sos () const
{
type *ptr_type
= builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
@@ -260,12 +269,12 @@ darwin_current_sos ()
break;
/* Create and fill the new struct solib element. */
- auto &newobj = sos.emplace_back ();
+ auto &newobj = sos.emplace_back (*this);
auto li = std::make_unique<lm_info_darwin> ();
- newobj.so_name = file_path.get ();
- newobj.so_original_name = newobj.so_name;
+ newobj.name = file_path.get ();
+ newobj.original_name = newobj.name;
li->lm_addr = load_addr;
newobj.lm_info = std::move (li);
@@ -363,15 +372,6 @@ darwin_read_exec_load_addr_at_init (struct darwin_info *info)
return darwin_validate_exec_header (load_addr);
}
-/* Return 1 if PC lies in the dynamic symbol resolution code of the
- run time loader. */
-
-static int
-darwin_in_dynsym_resolve_code (CORE_ADDR pc)
-{
- return 0;
-}
-
/* A wrapper for bfd_mach_o_fat_extract that handles reference
counting properly. This will either return NULL, or return a new
reference to a BFD. */
@@ -476,10 +476,8 @@ darwin_solib_read_all_image_info_addr (struct darwin_info *info)
info->all_image_addr = extract_unsigned_integer (buf, len, BFD_ENDIAN_BIG);
}
-/* Shared library startup support. See documentation in solib-svr4.c. */
-
-static void
-darwin_solib_create_inferior_hook (int from_tty)
+void
+darwin_solib_ops::create_inferior_hook (int from_tty) const
{
/* Everything below only makes sense if we have a running inferior. */
if (!target_has_execution ())
@@ -579,8 +577,8 @@ darwin_solib_create_inferior_hook (int from_tty)
create_solib_event_breakpoint (current_inferior ()->arch (), notifier);
}
-static void
-darwin_clear_solib (program_space *pspace)
+void
+darwin_solib_ops::clear_solib (program_space *pspace) const
{
darwin_info *info = get_darwin_info (pspace);
@@ -591,8 +589,9 @@ darwin_clear_solib (program_space *pspace)
/* The section table is built from bfd sections using bfd VMAs.
Relocate these VMAs according to solib info. */
-static void
-darwin_relocate_section_addresses (solib &so, target_section *sec)
+void
+darwin_solib_ops::relocate_section_addresses (solib &so,
+ target_section *sec) const
{
auto *li = gdb::checked_static_cast<lm_info_darwin *> (so.lm_info.get ());
@@ -611,9 +610,9 @@ darwin_relocate_section_addresses (solib &so, target_section *sec)
if (sec->addr < so.addr_low)
so.addr_low = sec->addr;
}
-
-static gdb_bfd_ref_ptr
-darwin_bfd_open (const char *pathname)
+
+gdb_bfd_ref_ptr
+darwin_solib_ops::bfd_open (const char *pathname) const
{
int found_file;
@@ -641,20 +640,3 @@ darwin_bfd_open (const char *pathname)
return res;
}
-
-const solib_ops darwin_so_ops =
-{
- darwin_relocate_section_addresses,
- nullptr,
- darwin_clear_solib,
- darwin_solib_create_inferior_hook,
- darwin_current_sos,
- open_symbol_file_object,
- darwin_in_dynsym_resolve_code,
- darwin_bfd_open,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- default_find_solib_addr,
-};
diff --git a/gdb/solib-darwin.h b/gdb/solib-darwin.h
index b96e744..fc28b2c 100644
--- a/gdb/solib-darwin.h
+++ b/gdb/solib-darwin.h
@@ -20,8 +20,10 @@
#ifndef GDB_SOLIB_DARWIN_H
#define GDB_SOLIB_DARWIN_H
-struct solib_ops;
+#include "solib.h"
-extern const solib_ops darwin_so_ops;
+/* Return a new solib_ops for Darwin systems. */
+
+extern solib_ops_up make_darwin_solib_ops (program_space *pspace);
#endif /* GDB_SOLIB_DARWIN_H */
diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c
index 3832a7a..6b5b646 100644
--- a/gdb/solib-dsbt.c
+++ b/gdb/solib-dsbt.c
@@ -19,9 +19,7 @@
#include "extract-store-integer.h"
#include "inferior.h"
-#include "gdbcore.h"
#include "solib.h"
-#include "solist.h"
#include "objfiles.h"
#include "symtab.h"
#include "command.h"
@@ -121,7 +119,28 @@ struct dbst_ext_link_map
ext_ptr l_next, l_prev; /* struct link_map *l_next, *l_prev; */
};
-/* Link map info to include in an allocated so_list entry */
+/* solib_ops for DSBT systems. */
+
+struct dsbt_solib_ops : public solib_ops
+{
+ using solib_ops::solib_ops;
+
+ void relocate_section_addresses (solib &so, target_section *) const override;
+ void clear_solib (program_space *pspace) const override;
+ void create_inferior_hook (int from_tty) const override;
+ owning_intrusive_list<solib> current_sos () const override;
+ bool in_dynsym_resolve_code (CORE_ADDR pc) const override;
+};
+
+/* See solib-dsbt.h. */
+
+solib_ops_up
+make_dsbt_solib_ops (program_space *pspace)
+{
+ return std::make_unique<dsbt_solib_ops> (pspace);
+}
+
+/* Link map info to include in an allocated solib entry */
struct lm_info_dsbt final : public lm_info
{
@@ -393,15 +412,6 @@ fetch_loadmap (CORE_ADDR ldmaddr)
static void dsbt_relocate_main_executable (void);
static int enable_break (void);
-/* See solist.h. */
-
-static int
-open_symbol_file_object (int from_tty)
-{
- /* Unimplemented. */
- return 0;
-}
-
/* Given a loadmap and an address, return the displacement needed
to relocate the address. */
@@ -512,8 +522,8 @@ lm_base (void)
themselves. The declaration of `struct solib' says which fields
we provide values for. */
-static owning_intrusive_list<solib>
-dsbt_current_sos (void)
+owning_intrusive_list<solib>
+dsbt_solib_ops::current_sos () const
{
bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
CORE_ADDR lm_addr;
@@ -594,7 +604,7 @@ dsbt_current_sos (void)
break;
}
- auto &sop = sos.emplace_back ();
+ auto &sop = sos.emplace_back (*this);
auto li = std::make_unique<lm_info_dsbt> ();
li->map = loadmap;
/* Fetch the name. */
@@ -612,8 +622,8 @@ dsbt_current_sos (void)
gdb_printf (gdb_stdlog, "current_sos: name = %s\n",
name_buf.get ());
- sop.so_name = name_buf.get ();
- sop.so_original_name = sop.so_name;
+ sop.name = name_buf.get ();
+ sop.original_name = sop.name;
}
sop.lm_info = std::move (li);
@@ -630,11 +640,11 @@ dsbt_current_sos (void)
return sos;
}
-/* Return 1 if PC lies in the dynamic symbol resolution code of the
+/* Return true if PC lies in the dynamic symbol resolution code of the
run time loader. */
-static int
-dsbt_in_dynsym_resolve_code (CORE_ADDR pc)
+bool
+dsbt_solib_ops::in_dynsym_resolve_code (CORE_ADDR pc) const
{
dsbt_info *info = get_dsbt_info (current_program_space);
@@ -806,16 +816,16 @@ dsbt_relocate_main_executable (void)
section_offsets new_offsets (objf->section_offsets.size ());
changed = 0;
- for (obj_section *osect : objf->sections ())
+ for (obj_section &osect : objf->sections ())
{
CORE_ADDR orig_addr, addr, offset;
int osect_idx;
int seg;
- osect_idx = osect - objf->sections_start;
+ osect_idx = &osect - objf->sections_start;
/* Current address of section. */
- addr = osect->addr ();
+ addr = osect.addr ();
/* Offset from where this section started. */
offset = objf->section_offsets[osect_idx];
/* Original address prior to any past relocations. */
@@ -850,8 +860,8 @@ dsbt_relocate_main_executable (void)
For the DSBT shared library, the main executable needs to be relocated.
The shared library breakpoints also need to be enabled. */
-static void
-dsbt_solib_create_inferior_hook (int from_tty)
+void
+dsbt_solib_ops::create_inferior_hook (int from_tty) const
{
/* Relocate main executable. */
dsbt_relocate_main_executable ();
@@ -864,8 +874,8 @@ dsbt_solib_create_inferior_hook (int from_tty)
}
}
-static void
-dsbt_clear_solib (program_space *pspace)
+void
+dsbt_solib_ops::clear_solib (program_space *pspace) const
{
dsbt_info *info = get_dsbt_info (pspace);
@@ -876,8 +886,9 @@ dsbt_clear_solib (program_space *pspace)
info->main_executable_lm_info = NULL;
}
-static void
-dsbt_relocate_section_addresses (solib &so, target_section *sec)
+void
+dsbt_solib_ops::relocate_section_addresses (solib &so,
+ target_section *sec) const
{
int seg;
auto *li = gdb::checked_static_cast<lm_info_dsbt *> (so.lm_info.get ());
@@ -903,26 +914,7 @@ show_dsbt_debug (struct ui_file *file, int from_tty,
gdb_printf (file, _("solib-dsbt debugging is %s.\n"), value);
}
-const solib_ops dsbt_so_ops =
-{
- dsbt_relocate_section_addresses,
- nullptr,
- dsbt_clear_solib,
- dsbt_solib_create_inferior_hook,
- dsbt_current_sos,
- open_symbol_file_object,
- dsbt_in_dynsym_resolve_code,
- solib_bfd_open,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- default_find_solib_addr,
-};
-
-void _initialize_dsbt_solib ();
-void
-_initialize_dsbt_solib ()
+INIT_GDB_FILE (dsbt_solib)
{
/* Debug this file's internals. */
add_setshow_zuinteger_cmd ("solib-dsbt", class_maintenance,
diff --git a/gdb/solib-dsbt.h b/gdb/solib-dsbt.h
index d5c52c6..00f7791 100644
--- a/gdb/solib-dsbt.h
+++ b/gdb/solib-dsbt.h
@@ -20,8 +20,10 @@
#ifndef GDB_SOLIB_DSBT_H
#define GDB_SOLIB_DSBT_H
-struct solib_ops;
+#include "solib.h"
-extern const solib_ops dsbt_so_ops;
+/* Return a new solib_ops for DSBT systems. */
+
+solib_ops_up make_dsbt_solib_ops (program_space *pspace);
#endif /* GDB_SOLIB_DSBT_H */
diff --git a/gdb/solib-frv.c b/gdb/solib-frv.c
index bf13d36..e6499f4 100644
--- a/gdb/solib-frv.c
+++ b/gdb/solib-frv.c
@@ -18,15 +18,35 @@
#include "extract-store-integer.h"
-#include "gdbcore.h"
#include "solib.h"
-#include "solist.h"
#include "frv-tdep.h"
#include "objfiles.h"
#include "symtab.h"
#include "elf/frv.h"
#include "gdb_bfd.h"
#include "inferior.h"
+#include "solib-frv.h"
+
+/* solib_ops for FR-V systems. */
+
+struct frv_solib_ops : public solib_ops
+{
+ using solib_ops::solib_ops;
+
+ void relocate_section_addresses (solib &so, target_section *) const override;
+ void clear_solib (program_space *pspace) const override;
+ void create_inferior_hook (int from_tty) const override;
+ owning_intrusive_list<solib> current_sos () const override;
+ bool in_dynsym_resolve_code (CORE_ADDR pc) const override;
+};
+
+/* See solib-frv.h. */
+
+solib_ops_up
+make_frv_solib_ops (program_space *pspace)
+{
+ return std::make_unique<frv_solib_ops> (pspace);
+}
/* FR-V pointers are four bytes wide. */
enum { FRV_PTR_SIZE = 4 };
@@ -194,7 +214,7 @@ struct ext_link_map
ext_ptr l_next, l_prev; /* struct link_map *l_next, *l_prev; */
};
-/* Link map info to include in an allocated so_list entry. */
+/* Link map info to include in an allocated solib entry. */
struct lm_info_frv final : public lm_info
{
@@ -237,15 +257,6 @@ static void frv_relocate_main_executable (void);
static CORE_ADDR main_got (void);
static int enable_break2 (void);
-/* Implement the "open_symbol_file_object" solib_ops method. */
-
-static int
-open_symbol_file_object (int from_tty)
-{
- /* Unimplemented. */
- return 0;
-}
-
/* Cached value for lm_base(), below. */
static CORE_ADDR lm_base_cache = 0;
@@ -303,11 +314,8 @@ lm_base (void)
return lm_base_cache;
}
-
-/* Implement the "current_sos" solib_ops method. */
-
-static owning_intrusive_list<solib>
-frv_current_sos ()
+owning_intrusive_list<solib>
+frv_solib_ops::current_sos () const
{
bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
CORE_ADDR lm_addr, mgot;
@@ -377,7 +385,7 @@ frv_current_sos ()
break;
}
- auto &sop = sos.emplace_back ();
+ auto &sop = sos.emplace_back (*this);
auto li = std::make_unique<lm_info_frv> ();
li->map = loadmap;
li->got_value = got_addr;
@@ -397,8 +405,8 @@ frv_current_sos ()
warning (_("Can't read pathname for link map entry."));
else
{
- sop.so_name = name_buf.get ();
- sop.so_original_name = sop.so_name;
+ sop.name = name_buf.get ();
+ sop.original_name = sop.name;
}
}
else
@@ -424,8 +432,8 @@ static CORE_ADDR interp_text_sect_high;
static CORE_ADDR interp_plt_sect_low;
static CORE_ADDR interp_plt_sect_high;
-static int
-frv_in_dynsym_resolve_code (CORE_ADDR pc)
+bool
+frv_solib_ops::in_dynsym_resolve_code (CORE_ADDR pc) const
{
return ((pc >= interp_text_sect_low && pc < interp_text_sect_high)
|| (pc >= interp_plt_sect_low && pc < interp_plt_sect_high)
@@ -742,16 +750,16 @@ frv_relocate_main_executable (void)
section_offsets new_offsets (objf->section_offsets.size ());
changed = 0;
- for (obj_section *osect : objf->sections ())
+ for (obj_section &osect : objf->sections ())
{
CORE_ADDR orig_addr, addr, offset;
int osect_idx;
int seg;
-
- osect_idx = osect - objf->sections_start;
+
+ osect_idx = &osect - objf->sections_start;
/* Current address of section. */
- addr = osect->addr ();
+ addr = osect.addr ();
/* Offset from where this section started. */
offset = objf->section_offsets[osect_idx];
/* Original address prior to any past relocations. */
@@ -786,8 +794,8 @@ frv_relocate_main_executable (void)
to be relocated. The shared library breakpoints also need to be
enabled. */
-static void
-frv_solib_create_inferior_hook (int from_tty)
+void
+frv_solib_ops::create_inferior_hook (int from_tty) const
{
/* Relocate main executable. */
frv_relocate_main_executable ();
@@ -800,8 +808,8 @@ frv_solib_create_inferior_hook (int from_tty)
}
}
-static void
-frv_clear_solib (program_space *pspace)
+void
+frv_solib_ops::clear_solib (program_space *pspace) const
{
lm_base_cache = 0;
enable_break2_done = 0;
@@ -811,8 +819,9 @@ frv_clear_solib (program_space *pspace)
main_executable_lm_info = NULL;
}
-static void
-frv_relocate_section_addresses (solib &so, target_section *sec)
+void
+frv_solib_ops::relocate_section_addresses (solib &so,
+ target_section *sec) const
{
int seg;
auto *li = gdb::checked_static_cast<lm_info_frv *> (so.lm_info.get ());
@@ -1073,20 +1082,3 @@ frv_fetch_objfile_link_map (struct objfile *objfile)
/* Not found! */
return 0;
}
-
-const solib_ops frv_so_ops =
-{
- frv_relocate_section_addresses,
- nullptr,
- frv_clear_solib,
- frv_solib_create_inferior_hook,
- frv_current_sos,
- open_symbol_file_object,
- frv_in_dynsym_resolve_code,
- solib_bfd_open,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- default_find_solib_addr,
-};
diff --git a/gdb/solib-frv.h b/gdb/solib-frv.h
new file mode 100644
index 0000000..33d156c
--- /dev/null
+++ b/gdb/solib-frv.h
@@ -0,0 +1,28 @@
+/* Handle FR-V (FDPIC) shared libraries for GDB, the GNU Debugger.
+ Copyright (C) 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/>. */
+
+#ifndef GDB_SOLIB_FRV_H
+#define GDB_SOLIB_FRV_H
+
+#include "solib.h"
+
+/* Return a new solib_ops for FR-V systems. */
+
+solib_ops_up make_frv_solib_ops (program_space *pspace);
+
+#endif /* GDB_SOLIB_FRV_H */
diff --git a/gdb/solib-rocm.c b/gdb/solib-rocm.c
index 27b404c..c3c2e44 100644
--- a/gdb/solib-rocm.c
+++ b/gdb/solib-rocm.c
@@ -26,10 +26,10 @@
#include "event-top.h"
#include "gdbsupport/fileio.h"
#include "inferior.h"
+#include "linux-tdep.h"
#include "observable.h"
#include "solib.h"
#include "solib-svr4.h"
-#include "solist.h"
#include "symfile.h"
#include <unordered_map>
@@ -154,7 +154,77 @@ struct solib_info
/* Per-inferior data key. */
static const registry<inferior>::key<solib_info> rocm_solib_data;
-static solib_ops rocm_solib_ops;
+/* solib_ops for ROCm systems. */
+
+struct rocm_solib_ops : public solib_ops
+{
+ /* HOST_OPS is the host solib_ops that rocm_solib_ops hijacks / wraps,
+ in order to provide support for ROCm code objects. */
+ explicit rocm_solib_ops (program_space *pspace, solib_ops_up host_ops)
+ : solib_ops (pspace), m_host_ops (std::move (host_ops))
+ {
+ }
+
+ /* The methods implemented by rocm_solib_ops. */
+ owning_intrusive_list<solib> current_sos () const override;
+ void create_inferior_hook (int from_tty) const override;
+ gdb_bfd_ref_ptr bfd_open (const char *pathname) const override;
+ void relocate_section_addresses (solib &so, target_section *) const override;
+ void handle_event () const override;
+
+ /* Implement the following methods just to forward the calls to the host
+ solib_ops. We currently need to implement all the methods that
+ svr4_solib_ops implements. */
+ void clear_so (const solib &so) const override
+ { return m_host_ops->clear_so (so); }
+
+ void clear_solib (program_space *pspace) const override
+ { return m_host_ops->clear_solib (pspace); }
+
+ bool open_symbol_file_object (int from_tty) const override
+ { return m_host_ops->open_symbol_file_object (from_tty); }
+
+ bool in_dynsym_resolve_code (CORE_ADDR pc) const override
+ { return m_host_ops->in_dynsym_resolve_code (pc); }
+
+ bool same (const solib &gdb, const solib &inferior) const override
+ { return m_host_ops->same (gdb, inferior); }
+
+ bool keep_data_in_core (CORE_ADDR vaddr, unsigned long size) const override
+ { return m_host_ops->keep_data_in_core (vaddr, size); }
+
+ void update_breakpoints () const override
+ { return m_host_ops->update_breakpoints (); }
+
+ std::optional<CORE_ADDR> find_solib_addr (solib &so) const override
+ { return m_host_ops->find_solib_addr (so); }
+
+ bool supports_namespaces () const override
+ { return true; }
+
+ int find_solib_ns (const solib &so) const override
+ { return m_host_ops->find_solib_ns (so); }
+
+ int num_active_namespaces () const override
+ { return m_host_ops->num_active_namespaces (); }
+
+ std::vector<const solib *> get_solibs_in_ns (int nsid) const override
+ { return m_host_ops->get_solibs_in_ns (nsid); }
+
+ void iterate_over_objfiles_in_search_order
+ (iterate_over_objfiles_in_search_order_cb_ftype cb,
+ objfile *current_objfile) const override
+ {
+ return m_host_ops->iterate_over_objfiles_in_search_order
+ (cb, current_objfile);
+ }
+
+private:
+ owning_intrusive_list<solib>
+ solibs_from_rocm_sos (const std::vector<rocm_so> &sos) const;
+
+ solib_ops_up m_host_ops;
+};
/* Fetch the solib_info data for INF. */
@@ -171,13 +241,13 @@ get_solib_info (inferior *inf)
/* Relocate section addresses. */
-static void
-rocm_solib_relocate_section_addresses (solib &so,
- struct target_section *sec)
+void
+rocm_solib_ops::relocate_section_addresses (solib &so,
+ struct target_section *sec) const
{
if (!is_amdgpu_arch (gdbarch_from_bfd (so.abfd.get ())))
{
- svr4_so_ops.relocate_section_addresses (so, sec);
+ m_host_ops->relocate_section_addresses (so, sec);
return;
}
@@ -188,34 +258,34 @@ rocm_solib_relocate_section_addresses (solib &so,
static void rocm_update_solib_list ();
-static void
-rocm_solib_handle_event ()
+void
+rocm_solib_ops::handle_event () const
{
- /* Since we sit on top of svr4_so_ops, we might get called following an event
- concerning host libraries. We must therefore forward the call. If the
- event was for a ROCm code object, it will be a no-op. On the other hand,
+ /* Since we sit on top of a host solib_ops, we might get called following an
+ event concerning host libraries. We must therefore forward the call. If
+ the event was for a ROCm code object, it will be a no-op. On the other hand
if the event was for host libraries, rocm_update_solib_list will be
essentially be a no-op (it will reload the same code object list as was
previously loaded). */
- svr4_so_ops.handle_event ();
+ m_host_ops->handle_event ();
rocm_update_solib_list ();
}
-/* Create so_list objects from rocm_so objects in SOS. */
+/* Create solib objects from rocm_so objects in SOS. */
-static owning_intrusive_list<solib>
-so_list_from_rocm_sos (const std::vector<rocm_so> &sos)
+owning_intrusive_list<solib>
+rocm_solib_ops::solibs_from_rocm_sos (const std::vector<rocm_so> &sos) const
{
owning_intrusive_list<solib> dst;
for (const rocm_so &so : sos)
{
- auto &newobj = dst.emplace_back ();
+ auto &newobj = dst.emplace_back (*this);
newobj.lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
- newobj.so_name = so.name;
- newobj.so_original_name = so.unique_name;
+ newobj.name = so.name;
+ newobj.original_name = so.unique_name;
}
return dst;
@@ -224,11 +294,11 @@ so_list_from_rocm_sos (const std::vector<rocm_so> &sos)
/* Build a list of `struct solib' objects describing the shared
objects currently loaded in the inferior. */
-static owning_intrusive_list<solib>
-rocm_solib_current_sos ()
+owning_intrusive_list<solib>
+rocm_solib_ops::current_sos () const
{
/* First, retrieve the host-side shared library list. */
- owning_intrusive_list<solib> sos = svr4_so_ops.current_sos ();
+ owning_intrusive_list<solib> sos = m_host_ops->current_sos ();
/* Then, the device-side shared library list. */
std::vector<rocm_so> &dev_sos = get_solib_info (current_inferior ())->solib_list;
@@ -236,13 +306,13 @@ rocm_solib_current_sos ()
if (dev_sos.empty ())
return sos;
- owning_intrusive_list<solib> dev_so_list = so_list_from_rocm_sos (dev_sos);
+ owning_intrusive_list<solib> dev_solibs = solibs_from_rocm_sos (dev_sos);
if (sos.empty ())
- return dev_so_list;
+ return dev_solibs;
/* Append our libraries to the end of the list. */
- sos.splice (std::move (dev_so_list));
+ sos.splice (std::move (dev_solibs));
return sos;
}
@@ -441,7 +511,7 @@ rocm_bfd_iovec_open (bfd *abfd, inferior *inferior)
protocol_end += protocol_delim.length ();
std::transform (protocol.begin (), protocol.end (), protocol.begin (),
- [] (unsigned char c) { return std::tolower (c); });
+ [] (unsigned char c) { return c_tolower (c); });
std::string_view path;
size_t path_end = uri.find_first_of ("#?", protocol_end);
@@ -456,8 +526,8 @@ rocm_bfd_iovec_open (bfd *abfd, inferior *inferior)
for (size_t i = 0; i < path.length (); ++i)
if (path[i] == '%'
&& i < path.length () - 2
- && std::isxdigit (path[i + 1])
- && std::isxdigit (path[i + 2]))
+ && c_isxdigit (path[i + 1])
+ && c_isxdigit (path[i + 2]))
{
std::string_view hex_digits = path.substr (i + 1, 2);
decoded_path += std::stoi (std::string (hex_digits), 0, 16);
@@ -580,12 +650,12 @@ rocm_bfd_iovec_open (bfd *abfd, inferior *inferior)
}
}
-static gdb_bfd_ref_ptr
-rocm_solib_bfd_open (const char *pathname)
+gdb_bfd_ref_ptr
+rocm_solib_ops::bfd_open (const char *pathname) const
{
/* Handle regular files with SVR4 open. */
if (strstr (pathname, "://") == nullptr)
- return svr4_so_ops.bfd_open (pathname);
+ return m_host_ops->bfd_open (pathname);
auto open = [] (bfd *nbfd) -> gdb_bfd_iovec_base *
{
@@ -669,12 +739,12 @@ rocm_solib_bfd_open (const char *pathname)
return abfd;
}
-static void
-rocm_solib_create_inferior_hook (int from_tty)
+void
+rocm_solib_ops::create_inferior_hook (int from_tty) const
{
get_solib_info (current_inferior ())->solib_list.clear ();
- svr4_so_ops.solib_create_inferior_hook (from_tty);
+ m_host_ops->create_inferior_hook (from_tty);
}
static void
@@ -704,6 +774,9 @@ rocm_update_solib_list ()
return;
}
+ gdb::unique_xmalloc_ptr<amd_dbgapi_code_object_id_t> code_object_list_holder
+ (code_object_list);
+
for (size_t i = 0; i < count; ++i)
{
CORE_ADDR l_addr;
@@ -723,7 +796,8 @@ rocm_update_solib_list ()
gdb::unique_xmalloc_ptr<char> uri_bytes_holder (uri_bytes);
- lm_info_svr4_up li = std::make_unique<lm_info_svr4> ();
+ /* Pass a dummy debug base. */
+ lm_info_svr4_up li = std::make_unique<lm_info_svr4> (-1);
li->l_addr = l_addr;
/* Generate a unique name so that code objects with the same URI but
@@ -734,24 +808,6 @@ rocm_update_solib_list ()
sos.emplace_back (uri_bytes, std::move (unique_name), std::move (li));
}
-
- xfree (code_object_list);
-
- if (rocm_solib_ops.current_sos == NULL)
- {
- /* Override what we need to. */
- rocm_solib_ops = svr4_so_ops;
- rocm_solib_ops.current_sos = rocm_solib_current_sos;
- rocm_solib_ops.solib_create_inferior_hook
- = rocm_solib_create_inferior_hook;
- rocm_solib_ops.bfd_open = rocm_solib_bfd_open;
- rocm_solib_ops.relocate_section_addresses
- = rocm_solib_relocate_section_addresses;
- rocm_solib_ops.handle_event = rocm_solib_handle_event;
-
- /* Engage the ROCm so_ops. */
- set_gdbarch_so_ops (current_inferior ()->arch (), &rocm_solib_ops);
- }
}
static void
@@ -759,6 +815,11 @@ rocm_solib_target_inferior_created (inferior *inf)
{
get_solib_info (inf)->solib_list.clear ();
+ auto prev_ops = inf->pspace->release_solib_ops ();
+ auto rocm_ops
+ = std::make_unique<rocm_solib_ops> (inf->pspace, std::move (prev_ops));
+ inf->pspace->set_solib_ops (std::move (rocm_ops));
+
rocm_update_solib_list ();
/* Force GDB to reload the solibs. */
@@ -766,11 +827,24 @@ rocm_solib_target_inferior_created (inferior *inf)
solib_add (nullptr, 0, auto_solib_add);
}
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_rocm_solib;
+static void
+rocm_solib_target_inferior_execd (inferior *exec_inf, inferior *follow_inf)
+{
+ /* Engage the ROCm so_ops, but only if dbgapi is attached to the inferior
+ (avoiding remote inferiors and core file debugging). */
+ if (get_amd_dbgapi_process_id (follow_inf) == AMD_DBGAPI_PROCESS_NONE)
+ return;
-void
-_initialize_rocm_solib ()
+ auto pspace = follow_inf->pspace;
+ auto prev_ops = pspace->release_solib_ops ();
+ auto rocm_ops
+ = std::make_unique<rocm_solib_ops> (pspace, std::move (prev_ops));
+ pspace->set_solib_ops (std::move (rocm_ops));
+
+ get_solib_info (exec_inf)->solib_list.clear ();
+}
+
+INIT_GDB_FILE (rocm_solib)
{
/* The dependency on the amd-dbgapi exists because solib-rocm's
inferior_created observer needs amd-dbgapi to have attached the process,
@@ -779,4 +853,8 @@ _initialize_rocm_solib ()
(rocm_solib_target_inferior_created,
"solib-rocm",
{ &get_amd_dbgapi_target_inferior_created_observer_token () });
+
+ gdb::observers::inferior_execd.attach
+ (rocm_solib_target_inferior_execd, "solib-rocm",
+ { &get_amd_dbgapi_target_inferior_execd_observer_token () });
}
diff --git a/gdb/solib-svr4-linux.c b/gdb/solib-svr4-linux.c
new file mode 100644
index 0000000..fe82e5d
--- /dev/null
+++ b/gdb/solib-svr4-linux.c
@@ -0,0 +1,98 @@
+/* Target-dependent code for GNU/Linux using SVR4-style libraries.
+
+ Copyright (C) 2025 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "solib-svr4-linux.h"
+
+/* See solib-svr4-linux.h. */
+
+solib_ops_up
+make_linux_ilp32_svr4_solib_ops (program_space *pspace)
+{
+ return std::make_unique<linux_ilp32_svr4_solib_ops> (pspace);
+}
+
+/* See solib-svr4-linux.h. */
+
+link_map_offsets *
+linux_ilp32_svr4_solib_ops::fetch_link_map_offsets () const
+{
+ static link_map_offsets lmo;
+ static link_map_offsets *lmp = nullptr;
+
+ if (lmp == nullptr)
+ {
+ lmp = &lmo;
+
+ lmo.r_version_offset = 0;
+ lmo.r_version_size = 4;
+ lmo.r_map_offset = 4;
+ lmo.r_brk_offset = 8;
+ lmo.r_ldsomap_offset = -1;
+ lmo.r_next_offset = 20;
+
+ /* Everything we need is in the first 20 bytes. */
+ lmo.link_map_size = 20;
+ lmo.l_addr_offset = 0;
+ lmo.l_name_offset = 4;
+ lmo.l_ld_offset = 8;
+ lmo.l_next_offset = 12;
+ lmo.l_prev_offset = 16;
+ }
+
+ return lmp;
+}
+
+/* See solib-svr4-linux.h. */
+
+solib_ops_up
+make_linux_lp64_svr4_solib_ops (program_space *pspace)
+{
+ return std::make_unique<linux_lp64_svr4_solib_ops> (pspace);
+}
+
+/* See linux-tdep.h. */
+
+link_map_offsets *
+linux_lp64_svr4_solib_ops::fetch_link_map_offsets () const
+{
+ static link_map_offsets lmo;
+ static link_map_offsets *lmp = nullptr;
+
+ if (lmp == nullptr)
+ {
+ lmp = &lmo;
+
+ lmo.r_version_offset = 0;
+ lmo.r_version_size = 4;
+ lmo.r_map_offset = 8;
+ lmo.r_brk_offset = 16;
+ lmo.r_ldsomap_offset = -1;
+ lmo.r_next_offset = 40;
+
+ /* Everything we need is in the first 40 bytes. */
+ lmo.link_map_size = 40;
+ lmo.l_addr_offset = 0;
+ lmo.l_name_offset = 8;
+ lmo.l_ld_offset = 16;
+ lmo.l_next_offset = 24;
+ lmo.l_prev_offset = 32;
+ }
+
+ return lmp;
+}
diff --git a/gdb/solib-svr4-linux.h b/gdb/solib-svr4-linux.h
new file mode 100644
index 0000000..af040ff
--- /dev/null
+++ b/gdb/solib-svr4-linux.h
@@ -0,0 +1,51 @@
+/* Target-dependent code for GNU/Linux using SVR4-style libraries.
+
+ Copyright (C) 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/>. */
+
+#ifndef GDB_SOLIB_SVR4_LINUX_H
+#define GDB_SOLIB_SVR4_LINUX_H
+
+#include "solib-svr4.h"
+
+/* solib_ops for ILP32 Linux systems. */
+
+struct linux_ilp32_svr4_solib_ops : public svr4_solib_ops
+{
+ using svr4_solib_ops::svr4_solib_ops;
+
+ link_map_offsets *fetch_link_map_offsets () const override;
+};
+
+/* solib_ops for LP64 Linux systems. */
+
+struct linux_lp64_svr4_solib_ops : public svr4_solib_ops
+{
+ using svr4_solib_ops::svr4_solib_ops;
+
+ link_map_offsets *fetch_link_map_offsets () const override;
+};
+
+/* Return a new solib_ops for ILP32 Linux systems. */
+
+extern solib_ops_up make_linux_ilp32_svr4_solib_ops (program_space *pspace);
+
+/* Return a new solib_ops for LP64 Linux systems. */
+
+extern solib_ops_up make_linux_lp64_svr4_solib_ops (program_space *pspace);
+
+#endif /* GDB_SOLIB_SVR4_LINUX_H */
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 458c4ba..58432b6 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -35,7 +35,6 @@
#include "regcache.h"
#include "observable.h"
-#include "solist.h"
#include "solib.h"
#include "solib-svr4.h"
@@ -48,14 +47,8 @@
#include <map>
-static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
-static int svr4_have_link_map_offsets (void);
static void svr4_relocate_main_executable (void);
static void probes_table_remove_objfile_probes (struct objfile *objfile);
-static void svr4_iterate_over_objfiles_in_search_order
- (gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb,
- objfile *current_objfile);
-
/* On SVR4 systems, a list of symbols in the dynamic linker where
GDB can try to place a breakpoint to monitor shared library
@@ -91,27 +84,6 @@ static const char * const main_name_list[] =
NULL
};
-/* What to do when a probe stop occurs. */
-
-enum probe_action
-{
- /* Something went seriously wrong. Stop using probes and
- revert to using the older interface. */
- PROBES_INTERFACE_FAILED,
-
- /* No action is required. The shared object list is still
- valid. */
- DO_NOTHING,
-
- /* The shared object list should be reloaded entirely. */
- FULL_RELOAD,
-
- /* Attempt to incrementally update the shared object list. If
- the update fails or is not possible, fall back to reloading
- the list in full. */
- UPDATE_OR_RELOAD,
-};
-
/* A probe's name and its associated action. */
struct probe_info
@@ -140,11 +112,17 @@ static const struct probe_info probe_info[] =
#define NUM_PROBES ARRAY_SIZE (probe_info)
-/* Return non-zero if GDB_SO_NAME and INFERIOR_SO_NAME represent
- the same shared library. */
+static lm_info_svr4 &
+get_lm_info_svr4 (const solib &solib)
+{
+ return gdb::checked_static_cast<lm_info_svr4 &> (*solib.lm_info);
+}
+
+/* Return true if GDB_SO_NAME and INFERIOR_SO_NAME represent the same shared
+ library. */
-static int
-svr4_same_1 (const char *gdb_so_name, const char *inferior_so_name)
+static bool
+svr4_same_name (const char *gdb_so_name, const char *inferior_so_name)
{
if (strcmp (gdb_so_name, inferior_so_name) == 0)
return 1;
@@ -177,31 +155,35 @@ svr4_same (const char *gdb_name, const char *inferior_name,
const lm_info_svr4 &gdb_lm_info,
const lm_info_svr4 &inferior_lm_info)
{
- if (!svr4_same_1 (gdb_name, inferior_name))
+ /* There may be different instances of the same library, in different
+ namespaces. Each instance is typically loaded at a different address
+ so its relocation offset would be different. */
+ if (gdb_lm_info.l_addr_inferior != inferior_lm_info.l_addr_inferior)
return false;
- /* There may be different instances of the same library, in different
- namespaces. Each instance, however, must have been loaded at a
- different address so its relocation offset would be different. */
- return gdb_lm_info.l_addr_inferior == inferior_lm_info.l_addr_inferior;
+ /* There may be multiple entries for the same dynamic linker instance (at
+ the same address) visible in different namespaces. Those are considered
+ different instances. */
+ if (gdb_lm_info.debug_base != inferior_lm_info.debug_base)
+ return false;
+
+ return svr4_same_name (gdb_name, inferior_name);
}
-static int
-svr4_same (const solib &gdb, const solib &inferior)
+bool
+svr4_solib_ops::same (const solib &gdb, const solib &inferior) const
{
- auto *lmg
- = gdb::checked_static_cast<const lm_info_svr4 *> (gdb.lm_info.get ());
- auto *lmi
- = gdb::checked_static_cast<const lm_info_svr4 *> (inferior.lm_info.get ());
+ auto &lmg = get_lm_info_svr4 (gdb);
+ auto &lmi = get_lm_info_svr4 (inferior);
- return svr4_same (gdb.so_original_name.c_str (),
- inferior.so_original_name.c_str (), *lmg, *lmi);
+ return svr4_same (gdb.original_name.c_str (),
+ inferior.original_name.c_str (), lmg, lmi);
}
-static lm_info_svr4_up
-lm_info_read (CORE_ADDR lm_addr)
+lm_info_svr4_up
+svr4_solib_ops::read_lm_info (CORE_ADDR lm_addr, CORE_ADDR debug_base) const
{
- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+ link_map_offsets *lmo = this->fetch_link_map_offsets ();
lm_info_svr4_up lm_info;
gdb::byte_vector lm (lmo->link_map_size);
@@ -214,7 +196,7 @@ lm_info_read (CORE_ADDR lm_addr)
type *ptr_type
= builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
- lm_info = std::make_unique<lm_info_svr4> ();
+ lm_info = std::make_unique<lm_info_svr4> (debug_base);
lm_info->lm_addr = lm_addr;
lm_info->l_addr_inferior = extract_typed_address (&lm[lmo->l_addr_offset],
@@ -231,30 +213,30 @@ lm_info_read (CORE_ADDR lm_addr)
return lm_info;
}
-static int
-has_lm_dynamic_from_link_map (void)
+int
+svr4_solib_ops::has_lm_dynamic_from_link_map () const
{
- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+ link_map_offsets *lmo = this->fetch_link_map_offsets ();
return lmo->l_ld_offset >= 0;
}
-static CORE_ADDR
-lm_addr_check (const solib &so, bfd *abfd)
+CORE_ADDR
+svr4_solib_ops::lm_addr_check (const solib &so, bfd *abfd) const
{
- auto *li = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
+ auto &li = get_lm_info_svr4 (so);
- if (!li->l_addr_p)
+ if (!li.l_addr_p)
{
struct bfd_section *dyninfo_sect;
CORE_ADDR l_addr, l_dynaddr, dynaddr;
- l_addr = li->l_addr_inferior;
+ l_addr = li.l_addr_inferior;
- if (! abfd || ! has_lm_dynamic_from_link_map ())
+ if (!abfd || !this->has_lm_dynamic_from_link_map ())
goto set_addr;
- l_dynaddr = li->l_ld;
+ l_dynaddr = li.l_ld;
dyninfo_sect = bfd_get_section_by_name (abfd, ".dynamic");
if (dyninfo_sect == NULL)
@@ -317,7 +299,7 @@ lm_addr_check (const solib &so, bfd *abfd)
gdb_printf (_("Using PIC (Position Independent Code) "
"prelink displacement %s for \"%s\".\n"),
paddress (current_inferior ()->arch (), l_addr),
- so.so_name.c_str ());
+ so.name.c_str ());
}
else
{
@@ -333,16 +315,16 @@ lm_addr_check (const solib &so, bfd *abfd)
warning (_(".dynamic section for \"%s\" "
"is not at the expected address "
"(wrong library or version mismatch?)"),
- so.so_name.c_str ());
+ so.name.c_str ());
}
}
set_addr:
- li->l_addr = l_addr;
- li->l_addr_p = 1;
+ li.l_addr = l_addr;
+ li.l_addr_p = 1;
}
- return li->l_addr;
+ return li.l_addr;
}
struct svr4_so
@@ -359,8 +341,11 @@ struct svr4_so
struct svr4_info
{
- /* Base of dynamic linker structures in default namespace. */
- CORE_ADDR debug_base = 0;
+ /* Base of dynamic linker structures in default namespace.
+
+ The value is fetched from the inferior every time we need it. This field
+ represents the last known value. */
+ CORE_ADDR default_debug_base = 0;
/* Validity flag for debug_loader_offset. */
int debug_loader_offset_p = 0;
@@ -369,7 +354,7 @@ struct svr4_info
CORE_ADDR debug_loader_offset = 0;
/* Name of the dynamic linker, valid if debug_loader_offset_p. */
- char *debug_loader_name = nullptr;
+ std::string debug_loader_name;
/* Load map address for the main executable in default namespace. */
CORE_ADDR main_lm_addr = 0;
@@ -459,12 +444,6 @@ svr4_maybe_add_namespace (svr4_info *info, CORE_ADDR lmid)
info->namespace_id.push_back (lmid);
info->active_namespaces.insert (i);
-
- /* Create or update the convenience variable "active_namespaces".
- It only needs to be updated here, as this only changes when a
- dlmopen or dlclose call happens. */
- set_internalvar_integer (lookup_internalvar ("_active_linker_namespaces"),
- info->active_namespaces.size ());
}
/* Return whether DEBUG_BASE is the default namespace of INFO. */
@@ -472,13 +451,13 @@ svr4_maybe_add_namespace (svr4_info *info, CORE_ADDR lmid)
static bool
svr4_is_default_namespace (const svr4_info *info, CORE_ADDR debug_base)
{
- return (debug_base == info->debug_base);
+ return debug_base == info->default_debug_base;
}
/* Free the probes table. */
-static void
-free_probes_table (struct svr4_info *info)
+void
+svr4_solib_ops::free_probes_table (svr4_info *info) const
{
info->probes_table.reset (nullptr);
}
@@ -737,8 +716,8 @@ scan_dyntag_auxv (const int desired_dyntag, CORE_ADDR *ptr,
return 0;
}
-/* Locate the base address of dynamic linker structs for SVR4 elf
- targets.
+/* Locate the base address the dynamic linker structure for the default
+ namespace.
For SVR4 elf targets the address of the dynamic linker's runtime
structure is contained within the dynamic info section in the
@@ -747,16 +726,16 @@ scan_dyntag_auxv (const int desired_dyntag, CORE_ADDR *ptr,
real address before starting the inferior, we have to read in the
dynamic info section from the inferior address space.
If there are any errors while trying to find the address, we
- silently return 0, otherwise the found address is returned. */
+ silently return 0, otherwise the found address is returned.
+
+ If we try to read the address before the dynamic linker had a change to
+ fill in the real address, this will also typically return 0. */
static CORE_ADDR
-elf_locate_base (void)
+locate_default_debug_base ()
{
CORE_ADDR dyn_ptr, dyn_ptr_addr;
- if (!svr4_have_link_map_offsets ())
- return 0;
-
/* Look for DT_MIPS_RLD_MAP first. MIPS executables use this
instead of DT_DEBUG, although they sometimes contain an unused
DT_DEBUG. */
@@ -817,6 +796,38 @@ elf_locate_base (void)
return 0;
}
+/* See solib-svr4.h. */
+
+CORE_ADDR
+svr4_solib_ops::default_debug_base (svr4_info *info, bool *changed) const
+{
+ CORE_ADDR default_debug_base = locate_default_debug_base ();
+
+ if (changed != nullptr)
+ *changed = default_debug_base != info->default_debug_base;
+
+ if (default_debug_base != info->default_debug_base)
+ {
+ /* Update the debug base value for existing solibs. The only known case
+ where this is required is when a struct solib was created for the
+ dynamic linker itself by svr4_solib_ops::default_sos, before the
+ default debug base was known. */
+ for (const auto &solib : m_pspace->solibs ())
+ {
+ if (&solib.ops () != this)
+ continue;
+
+ if (auto &li = get_lm_info_svr4 (solib);
+ li.debug_base == info->default_debug_base)
+ li.debug_base = default_debug_base;
+ }
+
+ info->default_debug_base = default_debug_base;
+ }
+
+ return info->default_debug_base;
+}
+
/* Find the first element in the inferior's dynamic link map, and
return its address in the inferior. Return zero if the address
could not be determined.
@@ -825,10 +836,10 @@ elf_locate_base (void)
checking r_version for a known version number, or r_state for
RT_CONSISTENT. */
-static CORE_ADDR
-solib_svr4_r_map (CORE_ADDR debug_base)
+CORE_ADDR
+svr4_solib_ops::read_r_map (CORE_ADDR debug_base) const
{
- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+ link_map_offsets *lmo = this->fetch_link_map_offsets ();
type *ptr_type
= builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
CORE_ADDR addr = 0;
@@ -848,35 +859,40 @@ solib_svr4_r_map (CORE_ADDR debug_base)
/* Find r_brk from the inferior's debug base. */
-static CORE_ADDR
-solib_svr4_r_brk (struct svr4_info *info)
+CORE_ADDR
+svr4_solib_ops::find_r_brk (svr4_info *info) const
{
- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+ link_map_offsets *lmo = this->fetch_link_map_offsets ();
type *ptr_type
= builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
- return read_memory_typed_address (info->debug_base + lmo->r_brk_offset,
- ptr_type);
+ gdb_assert (info->default_debug_base != 0);
+
+ return read_memory_typed_address ((info->default_debug_base
+ + lmo->r_brk_offset), ptr_type);
}
/* Find the link map for the dynamic linker (if it is not in the
normal list of loaded shared objects). */
-static CORE_ADDR
-solib_svr4_r_ldsomap (struct svr4_info *info)
+CORE_ADDR
+svr4_solib_ops::find_r_ldsomap (svr4_info *info) const
{
- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+ link_map_offsets *lmo = this->fetch_link_map_offsets ();
type *ptr_type
= builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
enum bfd_endian byte_order = type_byte_order (ptr_type);
ULONGEST version = 0;
+ gdb_assert (info->default_debug_base != 0);
+
try
{
/* Check version, and return zero if `struct r_debug' doesn't have
the r_ldsomap member. */
version
- = read_memory_unsigned_integer (info->debug_base + lmo->r_version_offset,
+ = read_memory_unsigned_integer ((info->default_debug_base
+ + lmo->r_version_offset),
lmo->r_version_size, byte_order);
}
catch (const gdb_exception_error &ex)
@@ -887,16 +903,17 @@ solib_svr4_r_ldsomap (struct svr4_info *info)
if (version < 2 || lmo->r_ldsomap_offset == -1)
return 0;
- return read_memory_typed_address (info->debug_base + lmo->r_ldsomap_offset,
+ return read_memory_typed_address ((info->default_debug_base
+ + lmo->r_ldsomap_offset),
ptr_type);
}
/* Find the next namespace from the r_next field. */
-static CORE_ADDR
-solib_svr4_r_next (CORE_ADDR debug_base)
+CORE_ADDR
+svr4_solib_ops::read_r_next (CORE_ADDR debug_base) const
{
- link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+ link_map_offsets *lmo = this->fetch_link_map_offsets ();
type *ptr_type
= builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
bfd_endian byte_order = type_byte_order (ptr_type);
@@ -928,36 +945,37 @@ solib_svr4_r_next (CORE_ADDR debug_base)
memory areas containing the l_name string are saved in the core
file. */
-static int
-svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
+bool
+svr4_solib_ops::keep_data_in_core (CORE_ADDR vaddr, unsigned long size) const
{
struct svr4_info *info;
CORE_ADDR ldsomap;
CORE_ADDR name_lm;
info = get_svr4_info (current_program_space);
+ CORE_ADDR default_debug_base = this->default_debug_base (info);
- info->debug_base = elf_locate_base ();
- if (info->debug_base == 0)
- return 0;
+ if (default_debug_base == 0)
+ return false;
- ldsomap = solib_svr4_r_ldsomap (info);
+ ldsomap = this->find_r_ldsomap (info);
if (!ldsomap)
- return 0;
+ return false;
- std::unique_ptr<lm_info_svr4> li = lm_info_read (ldsomap);
+ std::unique_ptr<lm_info_svr4> li
+ = this->read_lm_info (ldsomap, info->default_debug_base);
name_lm = li != NULL ? li->l_name : 0;
return (name_lm >= vaddr && name_lm < vaddr + size);
}
-/* See solist.h. */
+/* See solib.h. */
-static int
-open_symbol_file_object (int from_tty)
+bool
+svr4_solib_ops::open_symbol_file_object (int from_tty) const
{
CORE_ADDR lm, l_name;
- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+ link_map_offsets *lmo = this->fetch_link_map_offsets ();
type *ptr_type
= builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
int l_name_size = ptr_type->length ();
@@ -970,17 +988,17 @@ open_symbol_file_object (int from_tty)
if (current_program_space->symfile_object_file)
if (!query (_("Attempt to reload symbols from process? ")))
- return 0;
+ return false;
- /* Always locate the debug struct, in case it has moved. */
- info->debug_base = elf_locate_base ();
- if (info->debug_base == 0)
- return 0; /* failed somehow... */
+ CORE_ADDR default_debug_base = this->default_debug_base (info);
+
+ if (default_debug_base == 0)
+ return false; /* failed somehow... */
/* First link map member should be the executable. */
- lm = solib_svr4_r_map (info->debug_base);
+ lm = this->read_r_map (default_debug_base);
if (lm == 0)
- return 0; /* failed somehow... */
+ return false; /* failed somehow... */
/* Read address of name from target memory to GDB. */
read_memory (lm + lmo->l_name_offset, l_name_buf.data (), l_name_size);
@@ -989,7 +1007,7 @@ open_symbol_file_object (int from_tty)
l_name = extract_typed_address (l_name_buf.data (), ptr_type);
if (l_name == 0)
- return 0; /* No filename. */
+ return false; /* No filename. */
/* Now fetch the filename from target memory. */
gdb::unique_xmalloc_ptr<char> filename
@@ -998,13 +1016,13 @@ open_symbol_file_object (int from_tty)
if (filename == nullptr)
{
warning (_("failed to read exec filename from attached file"));
- return 0;
+ return false;
}
/* Have a pathname: read the symbol file. */
symbol_file_add_main (filename.get (), add_flags);
- return 1;
+ return true;
}
/* Data exchange structure for the XML parser as returned by
@@ -1037,28 +1055,25 @@ svr4_free_objfile_observer (struct objfile *objfile)
/* Implement solib_ops.clear_so. */
-static void
-svr4_clear_so (const solib &so)
+void
+svr4_solib_ops::clear_so (const solib &so) const
{
- auto *li = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
-
- if (li != NULL)
- li->l_addr_p = 0;
+ get_lm_info_svr4 (so).l_addr_p = 0;
}
-/* Create the so_list objects equivalent to the svr4_sos in SOS. */
+/* Create the solib objects equivalent to the svr4_sos in SOS. */
-static owning_intrusive_list<solib>
-so_list_from_svr4_sos (const std::vector<svr4_so> &sos)
+owning_intrusive_list<solib>
+svr4_solib_ops::solibs_from_svr4_sos (const std::vector<svr4_so> &sos) const
{
owning_intrusive_list<solib> dst;
for (const svr4_so &so : sos)
{
- auto &newobj = dst.emplace_back ();
+ auto &newobj = dst.emplace_back (*this);
- newobj.so_name = so.name;
- newobj.so_original_name = so.name;
+ newobj.name = so.name;
+ newobj.original_name = so.name;
newobj.lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
}
@@ -1088,28 +1103,33 @@ library_list_start_library (struct gdb_xml_parser *parser,
ULONGEST *l_ldp
= (ULONGEST *) xml_find_attribute (attributes, "l_ld")->value.get ();
- lm_info_svr4_up li = std::make_unique<lm_info_svr4> ();
- li->lm_addr = *lmp;
- li->l_addr_inferior = *l_addrp;
- li->l_ld = *l_ldp;
-
std::vector<svr4_so> *solist;
/* Older versions did not supply lmid. Put the element into the flat
list of the special namespace zero in that case. */
gdb_xml_value *at_lmid = xml_find_attribute (attributes, "lmid");
svr4_info *info = get_svr4_info (current_program_space);
+ ULONGEST lmid;
+
if (at_lmid == nullptr)
{
solist = list->cur_list;
svr4_maybe_add_namespace (info, 0);
+ lmid = 0;
}
else
{
- ULONGEST lmid = *(ULONGEST *) at_lmid->value.get ();
+ lmid = *(ULONGEST *) at_lmid->value.get ();
solist = &list->solib_lists[lmid];
svr4_maybe_add_namespace (info, lmid);
}
+
+ lm_info_svr4_up li = std::make_unique<lm_info_svr4> (lmid);
+
+ li->lm_addr = *lmp;
+ li->l_addr_inferior = *l_addrp;
+ li->l_ld = *l_ldp;
+
solist->emplace_back (name, std::move (li));
}
@@ -1148,7 +1168,7 @@ static const struct gdb_xml_attribute svr4_library_attributes[] =
{ "lm", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
{ "l_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
{ "l_ld", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
- { "lmid", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { "lmid", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
@@ -1176,11 +1196,10 @@ static const struct gdb_xml_element svr4_library_list_elements[] =
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
-/* Parse qXfer:libraries:read packet into *SO_LIST_RETURN. Return 1 if
+/* Parse qXfer:libraries:read packet into *LIST.
- Return 0 if packet not supported, *SO_LIST_RETURN is not modified in such
- case. Return 1 if *SO_LIST_RETURN contains the library list, it may be
- empty, caller is responsible for freeing all its entries. */
+ Return 0 if packet not supported, *LIST is not modified in such case.
+ Return 1 if *LIST contains the library list. */
static int
svr4_parse_libraries (const char *document, struct svr4_library_list *list)
@@ -1202,11 +1221,11 @@ svr4_parse_libraries (const char *document, struct svr4_library_list *list)
return 0;
}
-/* Attempt to get so_list from target via qXfer:libraries-svr4:read packet.
+/* Attempt to get the shared object list from target via
+ qXfer:libraries-svr4:read packet.
- Return 0 if packet not supported, *SO_LIST_RETURN is not modified in such
- case. Return 1 if *SO_LIST_RETURN contains the library list, it may be
- empty, caller is responsible for freeing all its entries.
+ Return 0 if packet not supported, *LIST is not modified in such case.
+ Return 1 if *LIST contains the library list.
Note that ANNEX must be NULL if the remote does not explicitly allow
qXfer:libraries-svr4:read packets with non-empty annexes. Support for
@@ -1243,24 +1262,24 @@ svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list,
/* If no shared library information is available from the dynamic
linker, build a fallback list from other sources. */
-static owning_intrusive_list<solib>
-svr4_default_sos (svr4_info *info)
+owning_intrusive_list<solib>
+svr4_solib_ops::default_sos (svr4_info *info) const
{
if (!info->debug_loader_offset_p)
return {};
- auto li = std::make_unique<lm_info_svr4> ();
+ auto li = std::make_unique<lm_info_svr4> (0);
/* Nothing will ever check the other fields if we set l_addr_p. */
li->l_addr = li->l_addr_inferior = info->debug_loader_offset;
li->l_addr_p = 1;
owning_intrusive_list<solib> sos;
- auto &newobj = sos.emplace_back ();
+ auto &newobj = sos.emplace_back (*this);
newobj.lm_info = std::move (li);
- newobj.so_name = info->debug_loader_name;
- newobj.so_original_name = newobj.so_name;
+ newobj.name = info->debug_loader_name;
+ newobj.original_name = newobj.name;
return sos;
}
@@ -1272,16 +1291,17 @@ svr4_default_sos (svr4_info *info)
is returned the entries stored to LINK_PTR_PTR are still valid although they may
represent only part of the inferior library list. */
-static int
-svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
- std::vector<svr4_so> &sos, int ignore_first)
+int
+svr4_solib_ops::read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
+ CORE_ADDR debug_base, std::vector<svr4_so> &sos,
+ int ignore_first) const
{
CORE_ADDR first_l_name = 0;
CORE_ADDR next_lm;
for (; lm != 0; prev_lm = lm, lm = next_lm)
{
- lm_info_svr4_up li = lm_info_read (lm);
+ lm_info_svr4_up li = this->read_lm_info (lm, debug_base);
if (li == NULL)
return 0;
@@ -1337,8 +1357,8 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
stored by the probes interface. Handle special cases relating
to the first elements of the list in default namespace. */
-static void
-svr4_current_sos_direct (struct svr4_info *info)
+void
+svr4_solib_ops::current_sos_direct (svr4_info *info) const
{
CORE_ADDR lm;
bool ignore_first;
@@ -1382,8 +1402,9 @@ svr4_current_sos_direct (struct svr4_info *info)
/* If we can't find the dynamic linker's base structure, this
must not be a dynamically linked executable. Hmm. */
- info->debug_base = elf_locate_base ();
- if (info->debug_base == 0)
+ CORE_ADDR default_debug_base = this->default_debug_base (info);
+
+ if (default_debug_base == 0)
return;
/* Assume that everything is a library if the dynamic loader was loaded
@@ -1402,17 +1423,18 @@ svr4_current_sos_direct (struct svr4_info *info)
});
/* Collect the sos in each namespace. */
- CORE_ADDR debug_base = info->debug_base;
+ CORE_ADDR debug_base = default_debug_base;
+
for (; debug_base != 0;
- ignore_first = false, debug_base = solib_svr4_r_next (debug_base))
+ ignore_first = false, debug_base = this->read_r_next (debug_base))
{
/* Walk the inferior's link map list, and build our so_list list. */
- lm = solib_svr4_r_map (debug_base);
+ lm = this->read_r_map (debug_base);
if (lm != 0)
{
svr4_maybe_add_namespace (info, debug_base);
- svr4_read_so_list (info, lm, 0, info->solib_lists[debug_base],
- ignore_first);
+ this->read_so_list (info, lm, 0, debug_base,
+ info->solib_lists[debug_base], ignore_first);
}
}
@@ -1425,15 +1447,15 @@ svr4_current_sos_direct (struct svr4_info *info)
r_debug object. If we added it to the default namespace (as it was),
we would probably run into inconsistencies with the load map's
prev/next links (I wonder if we did). */
- debug_base = solib_svr4_r_ldsomap (info);
+ debug_base = this->find_r_ldsomap (info);
if (debug_base != 0)
{
/* Add the dynamic linker's namespace unless we already did. */
if (info->solib_lists.find (debug_base) == info->solib_lists.end ())
{
svr4_maybe_add_namespace (info, debug_base);
- svr4_read_so_list (info, debug_base, 0, info->solib_lists[debug_base],
- 0);
+ this->read_so_list (info, debug_base, 0, debug_base,
+ info->solib_lists[debug_base], 0);
}
}
@@ -1442,15 +1464,15 @@ svr4_current_sos_direct (struct svr4_info *info)
/* Collect sos read and stored by the probes interface. */
-static owning_intrusive_list<solib>
-svr4_collect_probes_sos (svr4_info *info)
+owning_intrusive_list<solib>
+svr4_solib_ops::collect_probes_sos (svr4_info *info) const
{
owning_intrusive_list<solib> res;
for (const auto &tuple : info->solib_lists)
{
const std::vector<svr4_so> &sos = tuple.second;
- res.splice (so_list_from_svr4_sos (sos));
+ res.splice (this->solibs_from_svr4_sos (sos));
}
return res;
@@ -1459,26 +1481,26 @@ svr4_collect_probes_sos (svr4_info *info)
/* Implement the main part of the "current_sos" solib_ops
method. */
-static owning_intrusive_list<solib>
-svr4_current_sos_1 (svr4_info *info)
+owning_intrusive_list<solib>
+svr4_solib_ops::current_sos_1 (svr4_info *info) const
{
owning_intrusive_list<solib> sos;
/* If we're using the probes interface, we can use the cache as it will
be maintained by probe update/reload actions. */
if (info->probes_table != nullptr)
- sos = svr4_collect_probes_sos (info);
+ sos = this->collect_probes_sos (info);
/* If we're not using the probes interface or if we didn't cache
anything, read the sos to fill the cache, then collect them from the
cache. */
if (sos.empty ())
{
- svr4_current_sos_direct (info);
+ this->current_sos_direct (info);
- sos = svr4_collect_probes_sos (info);
+ sos = this->collect_probes_sos (info);
if (sos.empty ())
- sos = svr4_default_sos (info);
+ sos = this->default_sos (info);
}
return sos;
@@ -1486,11 +1508,20 @@ svr4_current_sos_1 (svr4_info *info)
/* Implement the "current_sos" solib_ops method. */
-static owning_intrusive_list<solib>
-svr4_current_sos ()
+owning_intrusive_list<solib>
+svr4_solib_ops::current_sos () const
{
svr4_info *info = get_svr4_info (current_program_space);
- owning_intrusive_list<solib> sos = svr4_current_sos_1 (info);
+
+ /* Call this for the side-effect of updating the debug base in existing
+ solibs' lm_info_svr4, if needed. It is possible for the core to have
+ an solib with a stale lm_info_svr4::debug_base. In that case, we are
+ about to return the same solib, but with an updated debug_base. If we
+ didn't do this call, then it would appear as two different libraries to
+ the core, and it would appear as a spurious unload / load. */
+ this->default_debug_base (info);
+
+ owning_intrusive_list<solib> sos = this->current_sos_1 (info);
struct mem_range vsyscall_range;
/* Filter out the vDSO module, if present. Its symbol file would
@@ -1543,9 +1574,9 @@ svr4_current_sos ()
[ 9] .dynamic DYNAMIC ffffffffff700580 000580 0000f0
*/
- auto *li = gdb::checked_static_cast<lm_info_svr4 *> (so->lm_info.get ());
+ const auto &li = get_lm_info_svr4 (*so);
- if (vsyscall_range.contains (li->l_ld))
+ if (vsyscall_range.contains (li.l_ld))
{
so = sos.erase (so);
break;
@@ -1577,12 +1608,7 @@ svr4_fetch_objfile_link_map (struct objfile *objfile)
of shared libraries. */
for (const solib &so : current_program_space->solibs ())
if (so.objfile == objfile)
- {
- auto *li
- = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
-
- return li->lm_addr;
- }
+ return get_lm_info_svr4 (so).lm_addr;
/* Not found! */
return 0;
@@ -1605,8 +1631,8 @@ is_thread_local_section (struct bfd_section *bfd_sect)
static bool
has_thread_local_section (const objfile *objf)
{
- for (obj_section *objsec : objf->sections ())
- if (is_thread_local_section (objsec->the_bfd_section))
+ for (obj_section &objsec : objf->sections ())
+ if (is_thread_local_section (objsec.the_bfd_section))
return true;
return false;
}
@@ -1666,8 +1692,9 @@ musl_link_map_to_tls_module_id (CORE_ADDR lm_addr)
if (has_thread_local_section (so))
mod_id++;
- auto *li = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
- if (li->lm_addr == lm_addr)
+ const auto &li = get_lm_info_svr4 (so);
+
+ if (li.lm_addr == lm_addr)
return mod_id;
}
return 0;
@@ -1728,12 +1755,20 @@ glibc_link_map_to_tls_module_id (CORE_ADDR lm_addr)
static void
tls_maybe_fill_slot (solib &so)
{
+ auto *li = dynamic_cast<lm_info_svr4 *> (so.lm_info.get ());
+ if (li == nullptr)
+ return;
+
struct svr4_info *info = get_svr4_info (current_program_space);
if (!info->glibc_tls_slots_inited)
{
/* Cause svr4_current_sos() to be run if it hasn't been already. */
if (info->main_lm_addr == 0)
- svr4_current_sos_direct (info);
+ {
+ auto &ops
+ = gdb::checked_static_cast<const svr4_solib_ops &> (so.ops ());
+ ops.current_sos_direct (info);
+ }
/* Quit early when main_lm_addr is still 0. */
if (info->main_lm_addr == 0)
@@ -1753,7 +1788,6 @@ tls_maybe_fill_slot (solib &so)
auto it = std::find (info->glibc_tls_slots.begin (),
info->glibc_tls_slots.end (),
0);
- auto *li = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
if (it == info->glibc_tls_slots.end ())
info->glibc_tls_slots.push_back (li->lm_addr);
else
@@ -1771,8 +1805,11 @@ tls_maybe_erase_slot (program_space *pspace, const solib &so,
if (still_in_use)
return;
+ auto *li = dynamic_cast<lm_info_svr4 *> (so.lm_info.get ());
+ if (li == nullptr)
+ return;
+
struct svr4_info *info = get_svr4_info (pspace);
- auto *li = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
auto it = std::find (info->glibc_tls_slots.begin (),
info->glibc_tls_slots.end (),
li->lm_addr);
@@ -1798,11 +1835,11 @@ match_main (const char *soname)
return (0);
}
-/* Return 1 if PC lies in the dynamic symbol resolution code of the
+/* Return true if PC lies in the dynamic symbol resolution code of the
SVR4 run time loader. */
-int
-svr4_in_dynsym_resolve_code (CORE_ADDR pc)
+bool
+svr4_solib_ops::in_dynsym_resolve_code (CORE_ADDR pc) const
{
struct svr4_info *info = get_svr4_info (current_program_space);
@@ -2001,12 +2038,10 @@ solib_event_probe_action (struct probe_and_action *pa)
shared objects from the inferior. Handle special cases relating
to the first elements of the list. Returns nonzero on success. */
-static int
-solist_update_full (struct svr4_info *info)
+void
+svr4_solib_ops::update_full (svr4_info *info) const
{
- svr4_current_sos_direct (info);
-
- return 1;
+ this->current_sos_direct (info);
}
/* Update the shared object list starting from the link-map entry
@@ -2014,9 +2049,9 @@ solist_update_full (struct svr4_info *info)
nonzero if the list was successfully updated, or zero to indicate
failure. */
-static int
-solist_update_incremental (svr4_info *info, CORE_ADDR debug_base,
- CORE_ADDR lm)
+int
+svr4_solib_ops::update_incremental (svr4_info *info, CORE_ADDR debug_base,
+ CORE_ADDR lm) const
{
/* Fall back to a full update if we are using a remote target
that does not support incremental transfers. */
@@ -2058,9 +2093,9 @@ solist_update_incremental (svr4_info *info, CORE_ADDR debug_base,
/* Unknown key=value pairs are ignored by the gdbstub. */
xsnprintf (annex, sizeof (annex), "lmid=%s;start=%s;prev=%s",
- phex_nz (debug_base, sizeof (debug_base)),
- phex_nz (lm, sizeof (lm)),
- phex_nz (prev_lm, sizeof (prev_lm)));
+ phex_nz (debug_base),
+ phex_nz (lm),
+ phex_nz (prev_lm));
if (!svr4_current_sos_via_xfer_libraries (&library_list, annex))
return 0;
@@ -2094,7 +2129,7 @@ solist_update_incremental (svr4_info *info, CORE_ADDR debug_base,
above check and deferral to solist_update_full ensures
that this call to svr4_read_so_list will never see the
first element. */
- if (!svr4_read_so_list (info, lm, prev_lm, solist, 0))
+ if (!this->read_so_list (info, lm, prev_lm, debug_base, solist, 0))
return 0;
}
@@ -2105,8 +2140,8 @@ solist_update_incremental (svr4_info *info, CORE_ADDR debug_base,
original interface. We don't reset the breakpoints as the
ones set up for the probes-based interface are adequate. */
-static void
-disable_probes_interface (svr4_info *info)
+void
+svr4_solib_ops::disable_probes_interface (svr4_info *info) const
{
warning (_("Probes-based dynamic linker interface failed.\n"
"Reverting to original interface."));
@@ -2121,8 +2156,8 @@ disable_probes_interface (svr4_info *info)
probes-based linker interface. Do nothing if using the
standard interface. */
-static void
-svr4_handle_solib_event (void)
+void
+svr4_solib_ops::handle_event () const
{
struct svr4_info *info = get_svr4_info (current_program_space);
struct probe_and_action *pa;
@@ -2147,9 +2182,9 @@ svr4_handle_solib_event (void)
/* If anything goes wrong we revert to the original linker
interface. */
- auto cleanup = make_scope_exit ([info] ()
+ auto cleanup = make_scope_exit ([this, info] ()
{
- disable_probes_interface (info);
+ this->disable_probes_interface (info);
});
action = solib_event_probe_action (pa);
@@ -2193,17 +2228,14 @@ svr4_handle_solib_event (void)
if (debug_base == 0)
return;
- /* If the global _r_debug object moved, we need to reload everything
- since we cannot identify namespaces (by the location of their
- r_debug_ext object) anymore. */
- CORE_ADDR global_debug_base = elf_locate_base ();
- if (global_debug_base != info->debug_base)
- {
- info->debug_base = global_debug_base;
- action = FULL_RELOAD;
- }
+ bool default_debug_base_changed;
+ CORE_ADDR default_debug_base
+ = this->default_debug_base (info, &default_debug_base_changed);
+
+ if (default_debug_base_changed)
+ action = FULL_RELOAD;
- if (info->debug_base == 0)
+ if (default_debug_base == 0)
{
/* It's possible for the reloc_complete probe to be triggered before
the linker has set the DT_DEBUG pointer (for example, when the
@@ -2251,15 +2283,12 @@ svr4_handle_solib_event (void)
if (action == UPDATE_OR_RELOAD)
{
- if (!solist_update_incremental (info, debug_base, lm))
+ if (!this->update_incremental (info, debug_base, lm))
action = FULL_RELOAD;
}
if (action == FULL_RELOAD)
- {
- if (!solist_update_full (info))
- return;
- }
+ this->update_full (info);
cleanup.release ();
}
@@ -2306,8 +2335,8 @@ svr4_update_solib_event_breakpoint (struct breakpoint *b)
/* Enable or disable optional solib event breakpoints as appropriate.
Called whenever stop_on_solib_events is changed. */
-static void
-svr4_update_solib_event_breakpoints (void)
+void
+svr4_solib_ops::update_breakpoints () const
{
for (breakpoint &bp : all_breakpoints_safe ())
svr4_update_solib_event_breakpoint (&bp);
@@ -2318,10 +2347,10 @@ svr4_update_solib_event_breakpoints (void)
solib event breakpoint will be created and registered for each
probe. */
-static void
-svr4_create_probe_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
- const std::vector<probe *> *probes,
- struct objfile *objfile)
+void
+svr4_solib_ops::create_probe_breakpoints (svr4_info *info, gdbarch *gdbarch,
+ const std::vector<probe *> *probes,
+ objfile *objfile) const
{
for (int i = 0; i < NUM_PROBES; i++)
{
@@ -2339,17 +2368,17 @@ svr4_create_probe_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
}
}
- svr4_update_solib_event_breakpoints ();
+ this->update_breakpoints ();
}
/* Find all the glibc named probes. Only if all of the probes are found, then
create them and return true. Otherwise return false. If WITH_PREFIX is set
then add "rtld" to the front of the probe names. */
-static bool
-svr4_find_and_create_probe_breakpoints (svr4_info *info,
- struct gdbarch *gdbarch,
- struct obj_section *os,
- bool with_prefix)
+bool
+svr4_solib_ops::find_and_create_probe_breakpoints (svr4_info *info,
+ gdbarch *gdbarch,
+ obj_section *os,
+ bool with_prefix) const
{
SOLIB_SCOPED_DEBUG_START_END ("objfile=%s, with_prefix=%d",
os->objfile->original_name, with_prefix);
@@ -2427,7 +2456,7 @@ svr4_find_and_create_probe_breakpoints (svr4_info *info,
/* All probes found. Now create them. */
solib_debug_printf ("using probes interface");
- svr4_create_probe_breakpoints (info, gdbarch, probes, os->objfile);
+ this->create_probe_breakpoints (info, gdbarch, probes, os->objfile);
return true;
}
@@ -2443,15 +2472,16 @@ svr4_find_and_create_probe_breakpoints (svr4_info *info,
probes aren't found, a single breakpoint is set on the original
marker function. */
-static void
-svr4_create_solib_event_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
- CORE_ADDR address)
+void
+svr4_solib_ops::create_event_breakpoints (svr4_info *info, gdbarch *gdbarch,
+ CORE_ADDR address) const
{
struct obj_section *os = find_pc_section (address);
if (os == nullptr
- || (!svr4_find_and_create_probe_breakpoints (info, gdbarch, os, false)
- && !svr4_find_and_create_probe_breakpoints (info, gdbarch, os, true)))
+ || (!this->find_and_create_probe_breakpoints (info, gdbarch, os, false)
+ && !this->find_and_create_probe_breakpoints (info, gdbarch, os,
+ true)))
{
solib_debug_printf ("falling back to r_brk breakpoint: addr=%s",
paddress (gdbarch, address));
@@ -2491,12 +2521,11 @@ svr4_create_solib_event_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
depending upon whether or not the library is being mapped or unmapped,
and then set to RT_CONSISTENT after the library is mapped/unmapped. */
-static int
-enable_break (struct svr4_info *info, int from_tty)
+int
+svr4_solib_ops::enable_break (svr4_info *info, int from_tty) const
{
const char * const *bkpt_namep;
asection *interp_sect;
- CORE_ADDR sym_addr;
info->interp_text_sect_low = info->interp_text_sect_high = 0;
info->interp_plt_sect_low = info->interp_plt_sect_high = 0;
@@ -2507,9 +2536,12 @@ enable_break (struct svr4_info *info, int from_tty)
is the object containing r_brk. */
solib_add (NULL, from_tty, auto_solib_add);
- sym_addr = 0;
- if (info->debug_base && solib_svr4_r_map (info->debug_base) != 0)
- sym_addr = solib_svr4_r_brk (info);
+
+ CORE_ADDR sym_addr = 0;
+ CORE_ADDR default_debug_base = this->default_debug_base (info);
+
+ if (default_debug_base != 0 && this->read_r_map (default_debug_base) != 0)
+ sym_addr = this->find_r_brk (info);
if (sym_addr != 0)
{
@@ -2568,8 +2600,8 @@ enable_break (struct svr4_info *info, int from_tty)
= info->interp_plt_sect_low + bfd_section_size (interp_sect);
}
- svr4_create_solib_event_breakpoints
- (info, current_inferior ()->arch (), sym_addr);
+ this->create_event_breakpoints (info, current_inferior ()->arch (),
+ sym_addr);
return 1;
}
}
@@ -2617,11 +2649,11 @@ enable_break (struct svr4_info *info, int from_tty)
address from the shared library table. */
for (const solib &so : current_program_space->solibs ())
{
- if (svr4_same_1 (interp_name, so.so_original_name.c_str ()))
+ if (svr4_same_name (interp_name, so.original_name.c_str ()))
{
load_addr_found = 1;
loader_found_in_list = 1;
- load_addr = lm_addr_check (so, tmp_bfd.get ());
+ load_addr = this->lm_addr_check (so, tmp_bfd.get ());
break;
}
}
@@ -2677,7 +2709,7 @@ enable_break (struct svr4_info *info, int from_tty)
if (!loader_found_in_list)
{
- info->debug_loader_name = xstrdup (interp_name);
+ info->debug_loader_name = interp_name;
info->debug_loader_offset_p = 1;
info->debug_loader_offset = load_addr;
solib_add (NULL, from_tty, auto_solib_add);
@@ -2728,9 +2760,8 @@ enable_break (struct svr4_info *info, int from_tty)
if (sym_addr != 0)
{
- svr4_create_solib_event_breakpoints (info,
- current_inferior ()->arch (),
- load_addr + sym_addr);
+ this->create_event_breakpoints (info, current_inferior ()->arch (),
+ load_addr + sym_addr);
return 1;
}
@@ -2738,8 +2769,8 @@ enable_break (struct svr4_info *info, int from_tty)
linker. Warn and drop into the old code. */
bkpt_at_symbol:
warning (_("Unable to find dynamic linker breakpoint function.\n"
- "GDB will be unable to debug shared library initializers\n"
- "and track explicitly loaded dynamic code."));
+ "GDB will be unable to debug shared library initializers\n"
+ "and track explicitly loaded dynamic code."));
}
/* Scan through the lists of symbols, trying to look up the symbol and
@@ -2757,9 +2788,8 @@ enable_break (struct svr4_info *info, int from_tty)
sym_addr = gdbarch_convert_from_func_ptr_addr
(current_inferior ()->arch (), sym_addr,
current_inferior ()->top_target ());
- svr4_create_solib_event_breakpoints (info,
- current_inferior ()->arch (),
- sym_addr);
+ this->create_event_breakpoints (info, current_inferior ()->arch (),
+ sym_addr);
return 1;
}
}
@@ -2777,8 +2807,9 @@ enable_break (struct svr4_info *info, int from_tty)
sym_addr = gdbarch_convert_from_func_ptr_addr
(current_inferior ()->arch (), sym_addr,
current_inferior ()->top_target ());
- svr4_create_solib_event_breakpoints
- (info, current_inferior ()->arch (), sym_addr);
+ this->create_event_breakpoints (info,
+ current_inferior ()->arch (),
+ sym_addr);
return 1;
}
}
@@ -3302,15 +3333,15 @@ svr4_relocate_main_executable (void)
addresses, and saving sufficient information about them to allow
their symbols to be read at a later time. */
-static void
-svr4_solib_create_inferior_hook (int from_tty)
+void
+svr4_solib_ops::create_inferior_hook (int from_tty) const
{
struct svr4_info *info;
info = get_svr4_info (current_program_space);
/* Clear the probes-based interface's state. */
- free_probes_table (info);
+ this->free_probes_table (info);
info->solib_lists.clear ();
info->namespace_id.clear ();
info->active_namespaces.clear ();
@@ -3323,22 +3354,18 @@ svr4_solib_create_inferior_hook (int from_tty)
if (!target_has_execution ())
return;
- if (!svr4_have_link_map_offsets ())
- return;
-
- if (!enable_break (info, from_tty))
+ if (!this->enable_break (info, from_tty))
return;
}
-static void
-svr4_clear_solib (program_space *pspace)
+void
+svr4_solib_ops::clear_solib (program_space *pspace) const
{
svr4_info *info = get_svr4_info (pspace);
- info->debug_base = 0;
+ info->default_debug_base = 0;
info->debug_loader_offset_p = 0;
info->debug_loader_offset = 0;
- xfree (info->debug_loader_name);
- info->debug_loader_name = NULL;
+ info->debug_loader_name.clear ();
}
/* Clear any bits of ADDR that wouldn't fit in a target-format
@@ -3395,15 +3422,15 @@ find_loadable_elf_internal_phdr (bfd *abfd, bfd_section *asect)
return nullptr;
}
-/* Implement solib_ops::relocate_section_addresses() for svr4 targets. */
-
-static void
-svr4_relocate_section_addresses (solib &so, target_section *sec)
+void
+svr4_solib_ops::relocate_section_addresses (solib &so,
+ target_section *sec) const
{
bfd *abfd = sec->the_bfd_section->owner;
- sec->addr = svr4_truncate_ptr (sec->addr + lm_addr_check (so, abfd));
- sec->endaddr = svr4_truncate_ptr (sec->endaddr + lm_addr_check (so, abfd));
+ sec->addr = svr4_truncate_ptr (sec->addr + this->lm_addr_check (so, abfd));
+ sec->endaddr
+ = svr4_truncate_ptr (sec->endaddr + this->lm_addr_check (so, abfd));
struct bfd_section *asect = sec->the_bfd_section;
gdb_assert (asect != nullptr);
@@ -3473,68 +3500,22 @@ svr4_relocate_section_addresses (solib &so, target_section *sec)
}
}
}
-
-
-/* Architecture-specific operations. */
-
-struct solib_svr4_ops
-{
- /* Return a description of the layout of `struct link_map'. */
- struct link_map_offsets *(*fetch_link_map_offsets)(void) = nullptr;
-};
-
-/* Per-architecture data key. */
-static const registry<gdbarch>::key<struct solib_svr4_ops> solib_svr4_data;
-
-/* Return a default for the architecture-specific operations. */
-
-static struct solib_svr4_ops *
-get_ops (struct gdbarch *gdbarch)
-{
- struct solib_svr4_ops *ops = solib_svr4_data.get (gdbarch);
- if (ops == nullptr)
- ops = solib_svr4_data.emplace (gdbarch);
- return ops;
-}
-/* Set the architecture-specific `struct link_map_offsets' fetcher for
- GDBARCH to FLMO. Also, install SVR4 solib_ops into GDBARCH. */
+/* See solib-svr4.h. */
void
-set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
- struct link_map_offsets *(*flmo) (void))
+set_solib_svr4_ops (gdbarch *gdbarch, gdbarch_make_solib_ops_ftype make_solib_ops)
{
- struct solib_svr4_ops *ops = get_ops (gdbarch);
-
- ops->fetch_link_map_offsets = flmo;
-
- set_gdbarch_so_ops (gdbarch, &svr4_so_ops);
- set_gdbarch_iterate_over_objfiles_in_search_order
- (gdbarch, svr4_iterate_over_objfiles_in_search_order);
+ set_gdbarch_make_solib_ops (gdbarch, make_solib_ops);
}
-/* Fetch a link_map_offsets structure using the architecture-specific
- `struct link_map_offsets' fetcher. */
-
-static struct link_map_offsets *
-svr4_fetch_link_map_offsets (void)
-{
- struct solib_svr4_ops *ops = get_ops (current_inferior ()->arch ());
-
- gdb_assert (ops->fetch_link_map_offsets);
- return ops->fetch_link_map_offsets ();
-}
-
-/* Return 1 if a link map offset fetcher has been defined, 0 otherwise. */
+/* See solib-svr4.h. */
-static int
-svr4_have_link_map_offsets (void)
+solib_ops_up
+make_svr4_ilp32_solib_ops (program_space *pspace)
{
- struct solib_svr4_ops *ops = get_ops (current_inferior ()->arch ());
-
- return (ops->fetch_link_map_offsets != NULL);
+ return std::make_unique<ilp32_svr4_solib_ops> (pspace);
}
-
/* Most OS'es that have SVR4-style ELF dynamic libraries define a
`struct r_debug' and a `struct link_map' that are binary compatible
@@ -3543,8 +3524,8 @@ svr4_have_link_map_offsets (void)
/* Fetch (and possibly build) an appropriate `struct link_map_offsets'
for an ILP32 SVR4 system. */
-struct link_map_offsets *
-svr4_ilp32_fetch_link_map_offsets (void)
+link_map_offsets *
+ilp32_svr4_solib_ops::fetch_link_map_offsets () const
{
static struct link_map_offsets lmo;
static struct link_map_offsets *lmp = NULL;
@@ -3572,11 +3553,28 @@ svr4_ilp32_fetch_link_map_offsets (void)
return lmp;
}
+/* solib_ops for LP64 SVR4 systems. */
+
+struct lp64_svr4_solib_ops : public svr4_solib_ops
+{
+ using svr4_solib_ops::svr4_solib_ops;
+
+ link_map_offsets *fetch_link_map_offsets () const override;
+};
+
+/* See solib-svr4.h. */
+
+solib_ops_up
+make_svr4_lp64_solib_ops (program_space *pspace)
+{
+ return std::make_unique<lp64_svr4_solib_ops> (pspace);
+}
+
/* Fetch (and possibly build) an appropriate `struct link_map_offsets'
for an LP64 SVR4 system. */
-struct link_map_offsets *
-svr4_lp64_fetch_link_map_offsets (void)
+link_map_offsets *
+lp64_svr4_solib_ops::fetch_link_map_offsets () const
{
static struct link_map_offsets lmo;
static struct link_map_offsets *lmp = NULL;
@@ -3638,24 +3636,15 @@ find_debug_base_for_solib (const solib *solib)
if (solib == nullptr)
return 0;
- svr4_info *info = get_svr4_info (current_program_space);
- gdb_assert (info != nullptr);
+ /* This is always called for solibs with an associated objfile. */
+ gdb_assert (solib->objfile != nullptr);
- auto *lm_info
- = gdb::checked_static_cast<const lm_info_svr4 *> (solib->lm_info.get ());
-
- for (const auto &tuple : info->solib_lists)
- {
- CORE_ADDR debug_base = tuple.first;
- const std::vector<svr4_so> &sos = tuple.second;
+ svr4_info *info = get_svr4_info (solib->objfile->pspace ());
+ gdb_assert (info != nullptr);
- for (const svr4_so &so : sos)
- if (svr4_same (solib->so_original_name.c_str (), so.name.c_str (),
- *lm_info, *so.lm_info))
- return debug_base;
- }
+ auto &lm_info = get_lm_info_svr4 (*solib);
- return 0;
+ return lm_info.debug_base;
}
/* Search order for ELF DSOs linked with -Bsymbolic. Those DSOs have a
@@ -3664,10 +3653,10 @@ find_debug_base_for_solib (const solib *solib)
stay in the same namespace as that file. Otherwise, we only consider
the initial namespace. */
-static void
-svr4_iterate_over_objfiles_in_search_order
- (gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb,
- objfile *current_objfile)
+void
+svr4_solib_ops::iterate_over_objfiles_in_search_order
+ (iterate_over_objfiles_in_search_order_cb_ftype cb,
+ objfile *current_objfile) const
{
bool checked_current_objfile = false;
if (current_objfile != nullptr)
@@ -3677,11 +3666,14 @@ svr4_iterate_over_objfiles_in_search_order
if (current_objfile->separate_debug_objfile_backlink != nullptr)
current_objfile = current_objfile->separate_debug_objfile_backlink;
- if (current_objfile == current_program_space->symfile_object_file)
- abfd = current_program_space->exec_bfd ();
+ if (current_objfile == m_pspace->symfile_object_file)
+ abfd = m_pspace->exec_bfd ();
else
abfd = current_objfile->obfd.get ();
+ /* gdb_bfd_scan_elf_dyntag relies on the current program space. */
+ gdb_assert (m_pspace == current_program_space);
+
if (abfd != nullptr
&& gdb_bfd_scan_elf_dyntag (DT_SYMBOLIC, abfd, nullptr, nullptr) == 1)
{
@@ -3691,15 +3683,19 @@ svr4_iterate_over_objfiles_in_search_order
}
}
+ /* elf_locate_base relies on the current program space. */
+ gdb_assert (m_pspace == current_program_space);
+
/* The linker namespace to iterate identified by the address of its
r_debug object, defaulting to the initial namespace. */
- CORE_ADDR initial = elf_locate_base ();
+ svr4_info *info = get_svr4_info (current_program_space);
+ CORE_ADDR default_debug_base = this->default_debug_base (info);
const solib *curr_solib = find_solib_for_objfile (current_objfile);
CORE_ADDR debug_base = find_debug_base_for_solib (curr_solib);
if (debug_base == 0)
- debug_base = initial;
+ debug_base = default_debug_base;
- for (objfile *objfile : current_program_space->objfiles ())
+ for (objfile *objfile : m_pspace->objfiles ())
{
if (checked_current_objfile && objfile == current_objfile)
continue;
@@ -3712,7 +3708,7 @@ svr4_iterate_over_objfiles_in_search_order
const solib *solib = find_solib_for_objfile (objfile);
CORE_ADDR solib_base = find_debug_base_for_solib (solib);
if (solib_base == 0)
- solib_base = initial;
+ solib_base = default_debug_base;
/* Ignore objfiles that were added to a different namespace. */
if (solib_base != debug_base)
@@ -3723,19 +3719,14 @@ svr4_iterate_over_objfiles_in_search_order
}
}
-/* See solib_ops::find_solib_addr in solist.h. */
-
-static std::optional<CORE_ADDR>
-svr4_find_solib_addr (solib &so)
+std::optional<CORE_ADDR>
+svr4_solib_ops::find_solib_addr (solib &so) const
{
- auto *li = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
- return li->l_addr_inferior;
+ return get_lm_info_svr4 (so).l_addr_inferior;
}
-/* See solib_ops::find_solib_ns in solist.h. */
-
-static int
-svr4_find_solib_ns (const solib &so)
+int
+svr4_solib_ops::find_solib_ns (const solib &so) const
{
CORE_ADDR debug_base = find_debug_base_for_solib (&so);
svr4_info *info = get_svr4_info (current_program_space);
@@ -3750,17 +3741,15 @@ svr4_find_solib_ns (const solib &so)
error (_("No namespace found"));
}
-/* see solib_ops::num_active_namespaces in solist.h. */
-static int
-svr4_num_active_namespaces ()
+int
+svr4_solib_ops::num_active_namespaces () const
{
svr4_info *info = get_svr4_info (current_program_space);
return info->active_namespaces.size ();
}
-/* See solib_ops::get_solibs_in_ns in solist.h. */
-static std::vector<const solib *>
-svr4_get_solibs_in_ns (int nsid)
+std::vector<const solib *>
+svr4_solib_ops::get_solibs_in_ns (int nsid) const
{
std::vector<const solib*> ns_solibs;
svr4_info *info = get_svr4_info (current_program_space);
@@ -3779,56 +3768,30 @@ svr4_get_solibs_in_ns (int nsid)
CORE_ADDR debug_base = info->namespace_id[nsid];
std::unordered_map<std::string, const lm_info_svr4 *> namespace_solibs;
for (svr4_so &so : info->solib_lists[debug_base])
- {
- namespace_solibs[so.name]
- = gdb::checked_static_cast<const lm_info_svr4 *>
- (so.lm_info.get ());
- }
+ namespace_solibs[so.name] = so.lm_info.get ();
+
for (const solib &so: current_program_space->solibs ())
{
- auto *lm_inferior
- = gdb::checked_static_cast<const lm_info_svr4 *> (so.lm_info.get ());
+ auto &lm_inferior = get_lm_info_svr4 (so);
/* This is inspired by the svr4_same, by finding the svr4_so object
in the map, and then double checking if the lm_info is considered
the same. */
- if (namespace_solibs.count (so.so_original_name) > 0
- && namespace_solibs[so.so_original_name]->l_addr_inferior
- == lm_inferior->l_addr_inferior)
+ if (namespace_solibs.count (so.original_name) > 0
+ && (namespace_solibs[so.original_name]->l_addr_inferior
+ == lm_inferior.l_addr_inferior))
{
ns_solibs.push_back (&so);
/* Remove the SO from the map, so that we don't end up
printing the dynamic linker multiple times. */
- namespace_solibs.erase (so.so_original_name);
+ namespace_solibs.erase (so.original_name);
}
}
return ns_solibs;
}
-const struct solib_ops svr4_so_ops =
-{
- svr4_relocate_section_addresses,
- svr4_clear_so,
- svr4_clear_solib,
- svr4_solib_create_inferior_hook,
- svr4_current_sos,
- open_symbol_file_object,
- svr4_in_dynsym_resolve_code,
- solib_bfd_open,
- svr4_same,
- svr4_keep_data_in_core,
- svr4_update_solib_event_breakpoints,
- svr4_handle_solib_event,
- svr4_find_solib_addr,
- svr4_find_solib_ns,
- svr4_num_active_namespaces,
- svr4_get_solibs_in_ns,
-};
-
-void _initialize_svr4_solib ();
-void
-_initialize_svr4_solib ()
+INIT_GDB_FILE (svr4_solib)
{
gdb::observers::free_objfile.attach (svr4_free_objfile_observer,
"solib-svr4");
diff --git a/gdb/solib-svr4.h b/gdb/solib-svr4.h
index e59c8e4..7b38ff4 100644
--- a/gdb/solib-svr4.h
+++ b/gdb/solib-svr4.h
@@ -20,17 +20,24 @@
#ifndef GDB_SOLIB_SVR4_H
#define GDB_SOLIB_SVR4_H
-#include "solist.h"
+#include "gdbarch.h"
+#include "solib.h"
struct objfile;
-struct solib_ops;
+struct link_map_offsets;
+struct probe_and_action;
+struct svr4_info;
+struct svr4_library_list;
+struct svr4_so;
-extern const solib_ops svr4_so_ops;
-
-/* Link map info to include in an allocated so_list entry. */
+/* Link map info to include in an allocated solib entry. */
struct lm_info_svr4 final : public lm_info
{
+ explicit lm_info_svr4 (CORE_ADDR debug_base)
+ : debug_base (debug_base)
+ {}
+
/* Amount by which addresses in the binary should be relocated to
match the inferior. The direct inferior value is L_ADDR_INFERIOR.
When prelinking is involved and the prelink base address changes,
@@ -46,10 +53,121 @@ struct lm_info_svr4 final : public lm_info
/* Values read in from inferior's fields of the same name. */
CORE_ADDR l_ld = 0, l_next = 0, l_prev = 0, l_name = 0;
+
+ /* The address of the dynamic linker structure (r_debug) this solib comes
+ from. This identifies which namespace this library is in.
+
+ This field can be 0 in the following situations:
+
+ - we receive the libraries through XML from an old gdbserver that
+ doesn't include the "lmid" field
+ - the default debug base is not yet known
+
+ In other cases, this field should have a sensible value. */
+ CORE_ADDR debug_base;
};
using lm_info_svr4_up = std::unique_ptr<lm_info_svr4>;
+/* What to do when a probe stop occurs. */
+
+enum probe_action
+{
+ /* Something went seriously wrong. Stop using probes and
+ revert to using the older interface. */
+ PROBES_INTERFACE_FAILED,
+
+ /* No action is required. The shared object list is still
+ valid. */
+ DO_NOTHING,
+
+ /* The shared object list should be reloaded entirely. */
+ FULL_RELOAD,
+
+ /* Attempt to incrementally update the shared object list. If
+ the update fails or is not possible, fall back to reloading
+ the list in full. */
+ UPDATE_OR_RELOAD,
+};
+
+/* solib_ops for SVR4 systems. */
+
+struct svr4_solib_ops : public solib_ops
+{
+ using solib_ops::solib_ops;
+
+ void relocate_section_addresses (solib &so, target_section *) const override;
+ void clear_so (const solib &so) const override;
+ void clear_solib (program_space *pspace) const override;
+ void create_inferior_hook (int from_tty) const override;
+ owning_intrusive_list<solib> current_sos () const override;
+ bool open_symbol_file_object (int from_tty) const override;
+ bool in_dynsym_resolve_code (CORE_ADDR pc) const override;
+ bool same (const solib &gdb, const solib &inferior) const override;
+ bool keep_data_in_core (CORE_ADDR vaddr, unsigned long size) const override;
+ void update_breakpoints () const override;
+ void handle_event () const override;
+ std::optional<CORE_ADDR> find_solib_addr (solib &so) const override;
+ bool supports_namespaces () const override { return true; }
+ int find_solib_ns (const solib &so) const override;
+ int num_active_namespaces () const override;
+ std::vector<const solib *> get_solibs_in_ns (int nsid) const override;
+ void iterate_over_objfiles_in_search_order
+ (iterate_over_objfiles_in_search_order_cb_ftype cb,
+ objfile *current_objfile) const override;
+
+ /* Return the appropriate link map offsets table for the architecture. */
+ virtual link_map_offsets *fetch_link_map_offsets () const = 0;
+
+ /* This needs to be public because it's accessed from an observer. */
+ void current_sos_direct (svr4_info *info) const;
+
+private:
+ void create_probe_breakpoints (svr4_info *info, gdbarch *gdbarch,
+ const std::vector<probe *> *probes,
+ objfile *objfile) const;
+ bool find_and_create_probe_breakpoints (svr4_info *info, gdbarch *gdbarch,
+ obj_section *os,
+ bool with_prefix) const;
+ void create_event_breakpoints (svr4_info *info, gdbarch *gdbarch,
+ CORE_ADDR address) const;
+ int enable_break (svr4_info *info, int from_tty) const;
+ void free_probes_table (svr4_info *info) const;
+ CORE_ADDR find_r_brk (svr4_info *info) const;
+ CORE_ADDR find_r_ldsomap (svr4_info *info) const;
+ owning_intrusive_list<solib> default_sos (svr4_info *info) const;
+ int read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
+ CORE_ADDR debug_base, std::vector<svr4_so> &sos,
+ int ignore_first) const;
+ lm_info_svr4_up read_lm_info (CORE_ADDR lm_addr, CORE_ADDR debug_base) const;
+ int has_lm_dynamic_from_link_map () const;
+ CORE_ADDR lm_addr_check (const solib &so, bfd *abfd) const;
+ CORE_ADDR read_r_next (CORE_ADDR debug_base) const;
+ CORE_ADDR read_r_map (CORE_ADDR debug_base) const;
+ owning_intrusive_list<solib> collect_probes_sos (svr4_info *info) const;
+ owning_intrusive_list<solib> current_sos_1 (svr4_info *info) const;
+ owning_intrusive_list<solib> solibs_from_svr4_sos
+ (const std::vector<svr4_so> &sos) const;
+ void disable_probes_interface (svr4_info *info) const;
+ void update_full (svr4_info *info) const;
+ int update_incremental (svr4_info *info, CORE_ADDR debug_base,
+ CORE_ADDR lm) const;
+ bool update_event_breakpoint (breakpoint *b) const;
+
+ /* Return the base address of the dynamic linker structure for the default
+ namespace. */
+ CORE_ADDR default_debug_base (svr4_info *info, bool *changed = nullptr) const;
+};
+
+/* solib_ops for ILP32 SVR4 systems. */
+
+struct ilp32_svr4_solib_ops : public svr4_solib_ops
+{
+ using svr4_solib_ops::svr4_solib_ops;
+
+ link_map_offsets *fetch_link_map_offsets () const override;
+};
+
/* Critical offsets and sizes which describe struct r_debug and
struct link_map on SVR4-like targets. All offsets and sizes are
in bytes unless otherwise specified. */
@@ -91,26 +209,22 @@ struct link_map_offsets
int l_name_offset;
};
-/* set_solib_svr4_fetch_link_map_offsets() is intended to be called by
- a <arch>_gdbarch_init() function. It is used to establish an
- architecture specific link_map_offsets fetcher for the architecture
- being defined. */
+/* Set the gdbarch methods for SVR4 systems. */
-extern void set_solib_svr4_fetch_link_map_offsets
- (struct gdbarch *gdbarch, struct link_map_offsets *(*func) (void));
+extern void set_solib_svr4_ops (gdbarch *gdbarch,
+ gdbarch_make_solib_ops_ftype make_solib_ops);
/* This function is called by thread_db.c. Return the address of the
link map for the given objfile. */
extern CORE_ADDR svr4_fetch_objfile_link_map (struct objfile *objfile);
-/* Fetch (and possibly build) an appropriate `struct link_map_offsets'
- for ILP32 and LP64 SVR4 systems. */
-extern struct link_map_offsets *svr4_ilp32_fetch_link_map_offsets (void);
-extern struct link_map_offsets *svr4_lp64_fetch_link_map_offsets (void);
+/* Return a new solib_ops for ILP32 SVR4 systems. */
+
+extern solib_ops_up make_svr4_ilp32_solib_ops (program_space *pspace);
+
+/* Return a new solib_ops for LP64 SVR4 systems. */
-/* Return 1 if PC lies in the dynamic symbol resolution code of the
- SVR4 run time loader. */
-int svr4_in_dynsym_resolve_code (CORE_ADDR pc);
+extern solib_ops_up make_svr4_lp64_solib_ops (program_space *pspace);
/* For the MUSL C library, given link map address LM_ADDR, return the
corresponding TLS module id, or 0 if not found. */
diff --git a/gdb/solib-target.c b/gdb/solib-target.c
index f304431..f20332a 100644
--- a/gdb/solib-target.c
+++ b/gdb/solib-target.c
@@ -18,7 +18,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "objfiles.h"
-#include "solist.h"
+#include "solib.h"
#include "symtab.h"
#include "symfile.h"
#include "target.h"
@@ -30,7 +30,7 @@
struct lm_info_target final : public lm_info
{
/* The library's name. The name is normally kept in the struct
- so_list; it is only here during XML parsing. */
+ solib; it is only here during XML parsing. */
std::string name;
/* The target can either specify segment bases or section bases, not
@@ -226,8 +226,8 @@ solib_target_parse_libraries (const char *library)
}
#endif
-static owning_intrusive_list<solib>
-solib_target_current_sos (void)
+owning_intrusive_list<solib>
+target_solib_ops::current_sos () const
{
owning_intrusive_list<solib> sos;
@@ -245,25 +245,20 @@ solib_target_current_sos (void)
/* Build a struct solib for each entry on the list. */
for (lm_info_target_up &info : library_list)
{
- auto &new_solib = sos.emplace_back ();
+ auto &new_solib = sos.emplace_back (*this);
/* We don't need a copy of the name in INFO anymore. */
- new_solib.so_name = std::move (info->name);
- new_solib.so_original_name = new_solib.so_name;
+ new_solib.name = std::move (info->name);
+ new_solib.original_name = new_solib.name;
new_solib.lm_info = std::move (info);
}
return sos;
}
-static void
-solib_target_solib_create_inferior_hook (int from_tty)
-{
- /* Nothing needed. */
-}
-
-static void
-solib_target_relocate_section_addresses (solib &so, target_section *sec)
+void
+target_solib_ops::relocate_section_addresses (solib &so,
+ target_section *sec) const
{
CORE_ADDR offset;
auto *li = gdb::checked_static_cast<lm_info_target *> (so.lm_info.get ());
@@ -291,7 +286,7 @@ solib_target_relocate_section_addresses (solib &so, target_section *sec)
if (num_alloc_sections != li->section_bases.size ())
warning (_("\
Could not relocate shared library \"%s\": wrong number of ALLOC sections"),
- so.so_name.c_str ());
+ so.name.c_str ());
else
{
int bases_index = 0;
@@ -334,7 +329,7 @@ Could not relocate shared library \"%s\": wrong number of ALLOC sections"),
if (data == NULL)
warning (_("\
-Could not relocate shared library \"%s\": no segments"), so.so_name.c_str ());
+Could not relocate shared library \"%s\": no segments"), so.name.c_str ());
else
{
ULONGEST orig_delta;
@@ -345,7 +340,7 @@ Could not relocate shared library \"%s\": no segments"), so.so_name.c_str ());
li->segment_bases.size (),
li->segment_bases.data ()))
warning (_("\
-Could not relocate shared library \"%s\": bad offsets"), so.so_name.c_str ());
+Could not relocate shared library \"%s\": bad offsets"), so.name.c_str ());
/* Find the range of addresses to report for this library in
"info sharedlibrary". Report any consecutive segments
@@ -382,16 +377,8 @@ Could not relocate shared library \"%s\": bad offsets"), so.so_name.c_str ());
sec->endaddr += offset;
}
-static int
-solib_target_open_symbol_file_object (int from_tty)
-{
- /* We can't locate the main symbol file based on the target's
- knowledge; the user has to specify it. */
- return 0;
-}
-
-static int
-solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
+bool
+target_solib_ops::in_dynsym_resolve_code (CORE_ADDR pc) const
{
/* We don't have a range of addresses for the dynamic linker; there
may not be one in the program's address space. So only report
@@ -399,19 +386,10 @@ solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
return in_plt_section (pc);
}
-const solib_ops solib_target_so_ops =
+/* See solib-target.h. */
+
+solib_ops_up
+make_target_solib_ops (program_space *pspace)
{
- solib_target_relocate_section_addresses,
- nullptr,
- nullptr,
- solib_target_solib_create_inferior_hook,
- solib_target_current_sos,
- solib_target_open_symbol_file_object,
- solib_target_in_dynsym_resolve_code,
- solib_bfd_open,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- default_find_solib_addr,
-};
+ return std::make_unique<target_solib_ops> (pspace);
+}
diff --git a/gdb/solib-target.h b/gdb/solib-target.h
index f8a22fd..4b8f2d6 100644
--- a/gdb/solib-target.h
+++ b/gdb/solib-target.h
@@ -20,7 +20,21 @@
#ifndef GDB_SOLIB_TARGET_H
#define GDB_SOLIB_TARGET_H
-struct solib_ops;
-extern const solib_ops solib_target_so_ops;
+#include "solib.h"
+
+/* solib_ops for systems fetching solibs from the target. */
+
+struct target_solib_ops : solib_ops
+{
+ using solib_ops::solib_ops;
+
+ void relocate_section_addresses (solib &so, target_section *) const override;
+ owning_intrusive_list<solib> current_sos () const override;
+ bool in_dynsym_resolve_code (CORE_ADDR pc) const override;
+};
+
+/* Return a new solib_ops for systems fetching solibs from the target. */
+
+solib_ops_up make_target_solib_ops (program_space *pspace);
#endif /* GDB_SOLIB_TARGET_H */
diff --git a/gdb/solib.c b/gdb/solib.c
index 85ec6bb..9a2ef12 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -37,7 +37,6 @@
#include "elf/common.h"
#include "filenames.h"
#include "exec.h"
-#include "solist.h"
#include "observable.h"
#include "readline/tilde.h"
#include "solib.h"
@@ -63,8 +62,8 @@ show_solib_search_path (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
gdb_printf (file,
- _ ("The search path for loading non-absolute "
- "shared library symbol files is %s.\n"),
+ _("The search path for loading non-absolute "
+ "shared library symbol files is %s.\n"),
value);
}
@@ -421,7 +420,7 @@ solib_bfd_fopen (const char *pathname, int fd)
if (abfd == NULL)
{
/* Arrange to free PATHNAME when the error is thrown. */
- error (_ ("Could not open `%s' as an executable file: %s"), pathname,
+ error (_("Could not open `%s' as an executable file: %s"), pathname,
bfd_errmsg (bfd_get_error ()));
}
@@ -454,20 +453,38 @@ solib_bfd_open (const char *pathname)
/* Check bfd format. */
if (!bfd_check_format (abfd.get (), bfd_object))
- error (_ ("`%s': not in executable format: %s"),
+ error (_("`%s': not in executable format: %s"),
bfd_get_filename (abfd.get ()), bfd_errmsg (bfd_get_error ()));
/* Check bfd arch. */
b = gdbarch_bfd_arch_info (current_inferior ()->arch ());
if (!b->compatible (b, bfd_get_arch_info (abfd.get ())))
- error (_ ("`%s': Shared library architecture %s is not compatible "
- "with target architecture %s."),
+ error (_("`%s': Shared library architecture %s is not compatible "
+ "with target architecture %s."),
bfd_get_filename (abfd.get ()),
bfd_get_arch_info (abfd.get ())->printable_name, b->printable_name);
return abfd;
}
+gdb_bfd_ref_ptr
+solib_ops::bfd_open (const char *pathname) const
+{
+ return solib_bfd_open (pathname);
+}
+
+/* See solib.h. */
+
+void
+solib_ops::iterate_over_objfiles_in_search_order
+ (iterate_over_objfiles_in_search_order_cb_ftype cb,
+ objfile *current_objfile) const
+{
+ for (objfile *objfile : m_pspace->objfiles ())
+ if (cb (objfile))
+ return;
+}
+
/* Given a pointer to one of the shared objects in our list of mapped
objects, use the recorded name to open a bfd descriptor for the
object, build a section table, relocate all the section addresses
@@ -483,10 +500,8 @@ solib_bfd_open (const char *pathname)
static int
solib_map_sections (solib &so)
{
- const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
-
- gdb::unique_xmalloc_ptr<char> filename (tilde_expand (so.so_name.c_str ()));
- gdb_bfd_ref_ptr abfd (ops->bfd_open (filename.get ()));
+ gdb::unique_xmalloc_ptr<char> filename (tilde_expand (so.name.c_str ()));
+ gdb_bfd_ref_ptr abfd (so.ops ().bfd_open (filename.get ()));
/* If we have a core target then the core target might have some helpful
information (i.e. build-ids) about the shared libraries we are trying
@@ -496,9 +511,9 @@ solib_map_sections (solib &so)
If we don't have a core target then this will return an empty struct
with no hint information, we then lookup the shared library based on
its filename. */
- std::optional<CORE_ADDR> solib_addr = ops->find_solib_addr (so);
+ std::optional<CORE_ADDR> solib_addr = so.ops ().find_solib_addr (so);
std::optional <const core_target_mapped_file_info> mapped_file_info
- = core_target_find_mapped_file (so.so_name.c_str (), solib_addr);
+ = core_target_find_mapped_file (so.name.c_str (), solib_addr);
/* If we already know the build-id of this solib from a core file, verify
it matches ABFD's build-id. If there is a mismatch or the solib wasn't
@@ -520,18 +535,18 @@ solib_map_sections (solib &so)
However, if it was good enough during the mapped file
processing, we assume it's good enough now. */
if (!mapped_file_info->filename ().empty ())
- abfd = ops->bfd_open (mapped_file_info->filename ().c_str ());
+ abfd = so.ops ().bfd_open (mapped_file_info->filename ().c_str ());
else
abfd = nullptr;
if (abfd == nullptr)
abfd = find_objfile_by_build_id (current_program_space,
mapped_file_info->build_id (),
- so.so_name.c_str ());
+ so.name.c_str ());
if (abfd == nullptr && mismatch)
{
- warning (_ ("Build-id of %ps does not match core file."),
+ warning (_("Build-id of %ps does not match core file."),
styled_string (file_name_style.style (),
filename.get ()));
abfd = nullptr;
@@ -545,14 +560,14 @@ solib_map_sections (solib &so)
/* Leave bfd open, core_xfer_memory and "info files" need it. */
so.abfd = std::move (abfd);
- /* Copy the full path name into so_name, allowing symbol_file_add
+ /* Copy the full path name into `so.name`, allowing symbol_file_add
to find it later. This also affects the =library-loaded GDB/MI
event, and in particular the part of that notification providing
the library's host-side path. If we let the target dictate
that objfile's path, and the target is different from the host,
GDB/MI will not provide the correct host-side path. */
- so.so_name = bfd_get_filename (so.abfd.get ());
+ so.name = bfd_get_filename (so.abfd.get ());
so.sections = build_section_table (so.abfd.get ());
for (target_section &p : so.sections)
@@ -560,7 +575,7 @@ solib_map_sections (solib &so)
/* Relocate the section binding addresses as recorded in the shared
object's file by the base address to which the object was actually
mapped. */
- ops->relocate_section_addresses (so, &p);
+ so.ops ().relocate_section_addresses (so, &p);
/* If the target didn't provide information about the address
range of the shared object, assume we want the location of
@@ -582,13 +597,11 @@ solib_map_sections (solib &so)
return 1;
}
-/* See solist.h. */
+/* See solib.h. */
void
solib::clear ()
{
- const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
-
this->sections.clear ();
this->abfd = nullptr;
@@ -600,11 +613,10 @@ solib::clear ()
/* Restore the target-supplied file name. SO_NAME may be the path
of the symbol file. */
- this->so_name = this->so_original_name;
+ this->name = this->original_name;
/* Do the same for target-specific data. */
- if (ops->clear_so != NULL)
- ops->clear_so (*this);
+ this->ops ().clear_so (*this);
}
lm_info::~lm_info () = default;
@@ -633,22 +645,19 @@ solib_read_symbols (solib &so, symfile_add_flags flags)
/* Have we already loaded this shared object? */
so.objfile = nullptr;
for (objfile *objfile : current_program_space->objfiles ())
- {
- if (filename_cmp (objfile_name (objfile), so.so_name.c_str ())
- == 0
- && objfile->addr_low == so.addr_low)
- {
- so.objfile = objfile;
- break;
- }
- }
+ if (objfile->addr_low == so.addr_low)
+ {
+ so.objfile = objfile;
+ break;
+ }
+
if (so.objfile == NULL)
{
section_addr_info sap
= build_section_addr_info_from_section_table (so.sections);
gdb_bfd_ref_ptr tmp_bfd = so.abfd;
so.objfile
- = symbol_file_add_from_bfd (tmp_bfd, so.so_name.c_str (),
+ = symbol_file_add_from_bfd (tmp_bfd, so.name.c_str (),
flags, &sap, OBJF_SHARED, nullptr);
so.objfile->addr_low = so.addr_low;
}
@@ -658,9 +667,9 @@ solib_read_symbols (solib &so, symfile_add_flags flags)
catch (const gdb_exception_error &e)
{
exception_fprintf (gdb_stderr, e,
- _ ("Error while reading shared"
- " library symbols for %s:\n"),
- so.so_name.c_str ());
+ _("Error while reading shared"
+ " library symbols for %s:\n"),
+ so.name.c_str ());
}
return true;
@@ -712,7 +721,10 @@ notify_solib_unloaded (program_space *pspace, const solib &so,
void
update_solib_list (int from_tty)
{
- const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
+ const solib_ops *ops = current_program_space->solib_ops ();
+
+ if (ops == nullptr)
+ return;
/* We can reach here due to changing solib-search-path or the
sysroot, before having any inferior. */
@@ -724,7 +736,7 @@ update_solib_list (int from_tty)
have not opened a symbol file, we may be able to get its
symbols now! */
if (inf->attach_flag
- && current_program_space->symfile_object_file == NULL)
+ && current_program_space->symfile_object_file == nullptr)
{
try
{
@@ -765,27 +777,16 @@ update_solib_list (int from_tty)
owning_intrusive_list<solib> inferior = ops->current_sos ();
owning_intrusive_list<solib>::iterator gdb_iter
- = current_program_space->so_list.begin ();
- while (gdb_iter != current_program_space->so_list.end ())
+ = current_program_space->solibs ().begin ();
+ while (gdb_iter != current_program_space->solibs ().end ())
{
intrusive_list<solib>::iterator inferior_iter = inferior.begin ();
/* Check to see whether the shared object *gdb also appears in
the inferior's current list. */
for (; inferior_iter != inferior.end (); ++inferior_iter)
- {
- if (ops->same)
- {
- if (ops->same (*gdb_iter, *inferior_iter))
- break;
- }
- else
- {
- if (!filename_cmp (gdb_iter->so_original_name.c_str (),
- inferior_iter->so_original_name.c_str ()))
- break;
- }
- }
+ if (ops->same (*gdb_iter, *inferior_iter))
+ break;
/* If the shared object appears on the inferior's list too, then
it's still loaded, so we don't need to do anything. Delete
@@ -814,13 +815,13 @@ update_solib_list (int from_tty)
&& !still_in_use)
gdb_iter->objfile->unlink ();
- current_program_space->deleted_solibs.push_back (gdb_iter->so_name);
+ current_program_space->deleted_solibs.push_back (gdb_iter->name);
/* Some targets' section tables might be referring to
sections from so.abfd; remove them. */
current_program_space->remove_target_sections (&*gdb_iter);
- gdb_iter = current_program_space->so_list.erase (gdb_iter);
+ gdb_iter = current_program_space->solibs ().erase (gdb_iter);
}
}
@@ -844,15 +845,15 @@ update_solib_list (int from_tty)
{
not_found++;
if (not_found_filename == NULL)
- not_found_filename = new_so.so_original_name.c_str ();
+ not_found_filename = new_so.original_name.c_str ();
}
}
catch (const gdb_exception_error &e)
{
exception_fprintf (gdb_stderr, e,
- _ ("Error while mapping shared "
- "library sections:\n"));
+ _("Error while mapping shared "
+ "library sections:\n"));
}
/* Notify any observer that the shared object has been
@@ -861,7 +862,7 @@ update_solib_list (int from_tty)
}
/* Add the new shared objects to GDB's list. */
- current_program_space->so_list.splice (std::move (inferior));
+ current_program_space->solibs ().splice (std::move (inferior));
/* If a library was not found, issue an appropriate warning
message. We have to use a single call to warning in case the
@@ -871,15 +872,15 @@ update_solib_list (int from_tty)
stand out well. */
if (not_found == 1)
- warning (_ ("Could not load shared library symbols for %ps.\n"
- "Do you need \"%ps\" or \"%ps\"?"),
+ warning (_("Could not load shared library symbols for %ps.\n"
+ "Do you need \"%ps\" or \"%ps\"?"),
styled_string (file_name_style.style (),
not_found_filename),
styled_string (command_style.style (),
"set solib-search-path"),
styled_string (command_style.style (), "set sysroot"));
else if (not_found > 1)
- warning (_ ("\
+ warning (_("\
Could not load shared library symbols for %d libraries, e.g. %ps.\n\
Use the \"%ps\" command to see the complete listing.\n\
Do you need \"%ps\" or \"%ps\"?"),
@@ -918,7 +919,7 @@ libpthread_name_p (const char *name)
static bool
libpthread_solib_p (const solib &so)
{
- return libpthread_name_p (so.so_name.c_str ());
+ return libpthread_name_p (so.name.c_str ());
}
/* Read in symbolic information for any shared objects whose names
@@ -937,11 +938,11 @@ solib_add (const char *pattern, int from_tty, int readsyms)
{
if (pattern != NULL)
{
- gdb_printf (_ ("Loading symbols for shared libraries: %s\n"),
+ gdb_printf (_("Loading symbols for shared libraries: %s\n"),
pattern);
}
else
- gdb_printf (_ ("Loading symbols for shared libraries.\n"));
+ gdb_printf (_("Loading symbols for shared libraries.\n"));
}
current_program_space->solib_add_generation++;
@@ -951,7 +952,7 @@ solib_add (const char *pattern, int from_tty, int readsyms)
char *re_err = re_comp (pattern);
if (re_err)
- error (_ ("Invalid regexp: %s"), re_err);
+ error (_("Invalid regexp: %s"), re_err);
}
update_solib_list (from_tty);
@@ -968,7 +969,7 @@ solib_add (const char *pattern, int from_tty, int readsyms)
add_flags |= SYMFILE_VERBOSE;
for (solib &gdb : current_program_space->solibs ())
- if (!pattern || re_exec (gdb.so_name.c_str ()))
+ if (!pattern || re_exec (gdb.name.c_str ()))
{
/* Normally, we would read the symbols from that library
only if READSYMS is set. However, we're making a small
@@ -985,9 +986,9 @@ solib_add (const char *pattern, int from_tty, int readsyms)
/* If no pattern was given, be quiet for shared
libraries we have already loaded. */
if (pattern && (from_tty || info_verbose))
- gdb_printf (_ ("Symbols already loaded for %ps\n"),
+ gdb_printf (_("Symbols already loaded for %ps\n"),
styled_string (file_name_style.style (),
- gdb.so_name.c_str ()));
+ gdb.name.c_str ()));
}
else if (solib_read_symbols (gdb, add_flags))
loaded_any_symbols = true;
@@ -1025,16 +1026,21 @@ print_solib_list_table (std::vector<const solib *> solib_list,
gdbarch *gdbarch = current_inferior ()->arch ();
/* "0x", a little whitespace, and two hex digits per byte of pointers. */
int addr_width = 4 + (gdbarch_ptr_bit (gdbarch) / 4);
- const solib_ops *ops = gdbarch_so_ops (gdbarch);
+ const solib_ops *ops = current_program_space->solib_ops ();
struct ui_out *uiout = current_uiout;
bool so_missing_debug_info = false;
+ if (ops == nullptr)
+ return;
+
/* There are 3 conditions for this command to print solib namespaces,
first PRINT_NAMESPACE has to be true, second the solib_ops has to
support multiple namespaces, and third there must be more than one
active namespace. Fold all these into the PRINT_NAMESPACE condition. */
- print_namespace = print_namespace && ops->num_active_namespaces != nullptr
- && ops->num_active_namespaces () > 1;
+ print_namespace = (print_namespace
+ && ops != nullptr
+ && ops->supports_namespaces ()
+ && ops->num_active_namespaces () > 1);
int num_cols = 4;
if (print_namespace)
@@ -1048,7 +1054,7 @@ print_solib_list_table (std::vector<const solib *> solib_list,
uiout->table_header (addr_width - 1, ui_left, "from", "From");
uiout->table_header (addr_width - 1, ui_left, "to", "To");
if (print_namespace)
- uiout->table_header (5, ui_left, "namespace", "NS");
+ uiout->table_header (9, ui_left, "namespace", "Linker NS");
uiout->table_header (12 - 1, ui_left, "syms-read", "Syms Read");
uiout->table_header (0, ui_noalign, "name", "Shared Object Library");
@@ -1056,7 +1062,7 @@ print_solib_list_table (std::vector<const solib *> solib_list,
for (const solib *so : solib_list)
{
- if (so->so_name.empty ())
+ if (so->name.empty ())
continue;
ui_out_emit_tuple tuple_emitter (uiout, "lib");
@@ -1076,7 +1082,7 @@ print_solib_list_table (std::vector<const solib *> solib_list,
{
try
{
- uiout->field_fmt ("namespace", "[[%d]]", ops->find_solib_ns (*so));
+ uiout->field_fmt ("namespace", "%d", ops->find_solib_ns (*so));
}
catch (const gdb_exception_error &er)
{
@@ -1085,7 +1091,7 @@ print_solib_list_table (std::vector<const solib *> solib_list,
}
if (!top_level_interpreter ()->interp_ui_out ()->is_mi_like_p ()
- && so->symbols_loaded && !objfile_has_symbols (so->objfile))
+ && so->symbols_loaded && !so->objfile->has_symbols ())
{
so_missing_debug_info = true;
uiout->field_string ("syms-read", "Yes (*)");
@@ -1093,15 +1099,15 @@ print_solib_list_table (std::vector<const solib *> solib_list,
else
uiout->field_string ("syms-read", so->symbols_loaded ? "Yes" : "No");
- uiout->field_string ("name", so->so_name, file_name_style.style ());
+ uiout->field_string ("name", so->name, file_name_style.style ());
uiout->text ("\n");
}
}
if (so_missing_debug_info)
- uiout->message (_ ("(*): Shared library is missing "
- "debugging information.\n"));
+ uiout->message (_("(*): Shared library is missing "
+ "debugging information.\n"));
}
/* Implement the "info sharedlibrary" command. Walk through the
@@ -1119,7 +1125,7 @@ info_sharedlibrary_command (const char *pattern, int from_tty)
char *re_err = re_comp (pattern);
if (re_err)
- error (_ ("Invalid regexp: %s"), re_err);
+ error (_("Invalid regexp: %s"), re_err);
}
update_solib_list (from_tty);
@@ -1130,9 +1136,9 @@ info_sharedlibrary_command (const char *pattern, int from_tty)
std::vector<const solib *> print_libs;
for (const solib &so : current_program_space->solibs ())
{
- if (!so.so_name.empty ())
+ if (!so.name.empty ())
{
- if (pattern && !re_exec (so.so_name.c_str ()))
+ if (pattern && !re_exec (so.name.c_str ()))
continue;
print_libs.push_back (&so);
}
@@ -1143,9 +1149,9 @@ info_sharedlibrary_command (const char *pattern, int from_tty)
if (print_libs.size () == 0)
{
if (pattern)
- uiout->message (_ ("No shared libraries matched.\n"));
+ uiout->message (_("No shared libraries matched.\n"));
else
- uiout->message (_ ("No shared libraries loaded at this time.\n"));
+ uiout->message (_("No shared libraries loaded at this time.\n"));
}
}
@@ -1159,23 +1165,22 @@ info_sharedlibrary_command (const char *pattern, int from_tty)
static void
info_linker_namespace_command (const char *pattern, int from_tty)
{
- const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
+ const solib_ops *ops = current_program_space->solib_ops ();
+
/* This command only really makes sense for inferiors that support
linker namespaces, so we can leave early. */
- if (ops->num_active_namespaces == nullptr)
- error (_("Current inferior does not support linker namespaces." \
- "Use \"info sharedlibrary\" instead"));
+ if (ops == nullptr || !ops->supports_namespaces ())
+ error (_("Current inferior does not support linker namespaces. "
+ "Use \"info sharedlibrary\" instead."));
struct ui_out *uiout = current_uiout;
std::vector<std::pair<int, std::vector<const solib *>>> all_solibs_to_print;
- if (pattern != nullptr)
- while (*pattern == ' ')
- pattern++;
+ pattern = skip_spaces (pattern);
if (pattern == nullptr || pattern[0] == '\0')
{
- uiout->message (_ ("There are %d linker namespaces loaded\n"),
+ uiout->message (_("There are %d linker namespaces loaded.\n"),
ops->num_active_namespaces ());
int printed = 0;
@@ -1199,41 +1204,39 @@ info_linker_namespace_command (const char *pattern, int from_tty)
escape sequence must be doubled to survive the compiler pass. */
re_comp ("^\\[\\[[0-9]\\+\\]\\]$");
if (re_exec (pattern))
- ns = strtol (pattern+2, nullptr, 10);
+ ns = strtol (pattern + 2, nullptr, 10);
else
{
- char * end = nullptr;
+ char *end = nullptr;
ns = strtol (pattern, &end, 10);
if (end[0] != '\0')
- error (_ ("Invalid linker namespace identifier: %s"), pattern);
+ error (_("Invalid linker namespace identifier: %s"), pattern);
}
all_solibs_to_print.push_back
(std::make_pair (ns, ops->get_solibs_in_ns (ns)));
}
- bool ns_separator = false;
-
- for (auto &solibs_pair : all_solibs_to_print)
+ for (const auto &[ns, solibs_to_print] : all_solibs_to_print)
{
- if (ns_separator)
- uiout->message ("\n\n");
- else
- ns_separator = true;
- int ns = solibs_pair.first;
- std::vector<const solib *> solibs_to_print = solibs_pair.second;
+ uiout->message ("\n");
+
if (solibs_to_print.size () == 0)
{
- uiout->message (_("Linker namespace [[%d]] is not active.\n"), ns);
+ uiout->message (_("Linker namespace %d is not active.\n"), ns);
/* If we got here, a specific namespace was requested, so there
will only be one vector. We can leave early. */
break;
}
- uiout->message
- (_ ("There are %zu libraries loaded in linker namespace [[%d]]\n"),
- solibs_to_print.size (), ns);
- uiout->message
- (_ ("Displaying libraries for linker namespace [[%d]]:\n"), ns);
+
+ if (solibs_to_print.size () == 1)
+ uiout->message
+ (_("1 library loaded in linker namespace %d:\n"), ns);
+ else
+ uiout->message
+ (_("%zu libraries loaded in linker namespace %d:\n"),
+ solibs_to_print.size (), ns);
+
print_solib_list_table (solibs_to_print, false);
}
@@ -1265,24 +1268,28 @@ solib_contains_address_p (const solib &solib, CORE_ADDR address)
const char *
solib_name_from_address (struct program_space *pspace, CORE_ADDR address)
{
- for (const solib &so : pspace->so_list)
+ for (const solib &so : pspace->solibs ())
if (solib_contains_address_p (so, address))
- return so.so_name.c_str ();
+ return so.name.c_str ();
return nullptr;
}
+bool
+solib_ops::same (const solib &a, const solib &b) const
+{
+ return (filename_cmp (a.original_name.c_str (), b.original_name.c_str ())
+ == 0);
+}
+
/* See solib.h. */
bool
solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
{
- const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
+ const solib_ops *ops = current_program_space->solib_ops ();
- if (ops->keep_data_in_core)
- return ops->keep_data_in_core (vaddr, size) != 0;
- else
- return false;
+ return ops != nullptr && ops->keep_data_in_core (vaddr, size);
}
/* See solib.h. */
@@ -1290,9 +1297,7 @@ solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
void
clear_solib (program_space *pspace)
{
- const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
-
- for (solib &so : pspace->so_list)
+ for (solib &so : pspace->solibs ())
{
bool still_in_use
= (so.objfile != nullptr && solib_used (pspace, so));
@@ -1301,9 +1306,10 @@ clear_solib (program_space *pspace)
pspace->remove_target_sections (&so);
};
- pspace->so_list.clear ();
+ pspace->solibs ().clear ();
- if (ops->clear_solib != nullptr)
+ if (const solib_ops *ops = pspace->solib_ops ();
+ ops != nullptr)
ops->clear_solib (pspace);
}
@@ -1315,9 +1321,9 @@ clear_solib (program_space *pspace)
void
solib_create_inferior_hook (int from_tty)
{
- const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
-
- ops->solib_create_inferior_hook (from_tty);
+ if (const solib_ops *ops = current_program_space->solib_ops ();
+ ops != nullptr)
+ ops->create_inferior_hook (from_tty);
}
/* See solib.h. */
@@ -1325,9 +1331,9 @@ solib_create_inferior_hook (int from_tty)
bool
in_solib_dynsym_resolve_code (CORE_ADDR pc)
{
- const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
+ const solib_ops *ops = current_program_space->solib_ops ();
- return ops->in_dynsym_resolve_code (pc) != 0;
+ return ops != nullptr && ops->in_dynsym_resolve_code (pc);
}
/* Implements the "sharedlibrary" command. */
@@ -1369,9 +1375,9 @@ no_shared_libraries_command (const char *ignored, int from_tty)
void
update_solib_breakpoints (void)
{
- const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
+ const solib_ops *ops = current_program_space->solib_ops ();
- if (ops->update_breakpoints != NULL)
+ if (ops != nullptr)
ops->update_breakpoints ();
}
@@ -1380,9 +1386,8 @@ update_solib_breakpoints (void)
void
handle_solib_event (void)
{
- const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
-
- if (ops->handle_event != NULL)
+ if (const solib_ops *ops = current_program_space->solib_ops ();
+ ops != nullptr)
ops->handle_event ();
current_inferior ()->pspace->clear_solib_cache ();
@@ -1402,7 +1407,7 @@ static void
reload_shared_libraries_1 (int from_tty)
{
if (print_symbol_loading_p (from_tty, 0, 0))
- gdb_printf (_ ("Loading symbols for shared libraries.\n"));
+ gdb_printf (_("Loading symbols for shared libraries.\n"));
for (solib &so : current_program_space->solibs ())
{
@@ -1414,8 +1419,9 @@ reload_shared_libraries_1 (int from_tty)
add_flags |= SYMFILE_VERBOSE;
gdb::unique_xmalloc_ptr<char> filename (
- tilde_expand (so.so_original_name.c_str ()));
- gdb_bfd_ref_ptr abfd (solib_bfd_open (filename.get ()));
+ tilde_expand (so.original_name.c_str ()));
+
+ gdb_bfd_ref_ptr abfd = so.ops ().bfd_open (filename.get ());
if (abfd != NULL)
found_pathname = bfd_get_filename (abfd.get ());
@@ -1423,7 +1429,7 @@ reload_shared_libraries_1 (int from_tty)
symbol file, close that. */
if ((found_pathname == NULL && was_loaded)
|| (found_pathname != NULL
- && filename_cmp (found_pathname, so.so_name.c_str ()) != 0))
+ && filename_cmp (found_pathname, so.name.c_str ()) != 0))
{
if (so.objfile && !(so.objfile->flags & OBJF_USERLOADED)
&& !solib_used (current_program_space, so))
@@ -1436,7 +1442,7 @@ reload_shared_libraries_1 (int from_tty)
file, open it. */
if (found_pathname != NULL
&& (!was_loaded
- || filename_cmp (found_pathname, so.so_name.c_str ()) != 0))
+ || filename_cmp (found_pathname, so.name.c_str ()) != 0))
{
bool got_error = false;
@@ -1448,8 +1454,8 @@ reload_shared_libraries_1 (int from_tty)
catch (const gdb_exception_error &e)
{
exception_fprintf (gdb_stderr, e,
- _ ("Error while mapping "
- "shared library sections:\n"));
+ _("Error while mapping "
+ "shared library sections:\n"));
got_error = true;
}
@@ -1466,8 +1472,6 @@ reload_shared_libraries (const char *ignored, int from_tty,
{
reload_shared_libraries_1 (from_tty);
- const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
-
/* Creating inferior hooks here has two purposes. First, if we reload
shared libraries then the address of solib breakpoint we've computed
previously might be no longer valid. For example, if we forgot to set
@@ -1480,8 +1484,9 @@ reload_shared_libraries (const char *ignored, int from_tty,
if (target_has_execution ())
{
/* Reset or free private data structures not associated with
- so_list entries. */
- if (ops->clear_solib != nullptr)
+ solib entries. */
+ if (const solib_ops *ops = current_program_space->solib_ops ();
+ ops != nullptr)
ops->clear_solib (current_program_space);
/* Remove any previous solib event breakpoint. This is usually
@@ -1530,9 +1535,9 @@ gdb_sysroot_changed (const char *ignored, int from_tty,
if (!warning_issued)
{
- warning (_ ("\"%s\" is deprecated, use \"%s\" instead."), old_prefix,
+ warning (_("\"%s\" is deprecated, use \"%s\" instead."), old_prefix,
new_prefix);
- warning (_ ("sysroot set to \"%s\"."), gdb_sysroot.c_str ());
+ warning (_("sysroot set to \"%s\"."), gdb_sysroot.c_str ());
warning_issued = true;
}
@@ -1545,7 +1550,7 @@ static void
show_auto_solib_add (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- gdb_printf (file, _ ("Autoloading of shared library symbols is %s.\n"),
+ gdb_printf (file, _("Autoloading of shared library symbols is %s.\n"),
value);
}
@@ -1743,8 +1748,8 @@ gdb_bfd_read_elf_soname (const char *filename)
if symbol is not found. */
static CORE_ADDR
-bfd_lookup_symbol_from_dyn_symtab (
- bfd *abfd, gdb::function_view<bool (const asymbol *)> match_sym)
+bfd_lookup_symbol_from_dyn_symtab
+ (bfd *abfd, gdb::function_view<bool (const asymbol *)> match_sym)
{
long storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd);
CORE_ADDR symaddr = 0;
@@ -1808,56 +1813,71 @@ remove_user_added_objfile (struct objfile *objfile)
}
}
-/* See solist.h. */
+/* See solib.h. */
-std::optional<CORE_ADDR>
-default_find_solib_addr (solib &so)
+int
+solib_linker_namespace_count (program_space *pspace)
{
- return {};
+ if (const auto ops = pspace->solib_ops (); ops != nullptr
+ && ops->supports_namespaces ())
+ return ops->num_active_namespaces ();
+
+ return 0;
}
-/* Implementation of the current_linker_namespace convenience variable.
+/* Implementation of the linker_namespace convenience variable.
+
This returns the GDB internal identifier of the linker namespace,
- for the current frame, in the form '[[<number>]]'. If the inferior
- doesn't support linker namespaces, this always returns [[0]]. */
+ for the selected frame, as an integer. If the inferior doesn't support
+ linker namespaces, this always returns 0. */
static value *
-current_linker_namespace_make_value (gdbarch *gdbarch, internalvar *var,
+linker_namespace_make_value (gdbarch *gdbarch, internalvar *var,
void *ignore)
{
- const solib_ops *ops = gdbarch_so_ops (gdbarch);
- const language_defn *lang = language_def (get_frame_language
- (get_current_frame ()));
- std::string nsid = "[[0]]";
- if (ops->find_solib_ns != nullptr)
- {
- CORE_ADDR curr_pc = get_frame_pc (get_current_frame ());
- for (const solib &so : current_program_space->solibs ())
- if (solib_contains_address_p (so, curr_pc))
- {
- nsid = string_printf ("[[%d]]", ops->find_solib_ns (so));
- break;
- }
- }
+ int nsid = 0;
+ CORE_ADDR curr_pc = get_frame_pc (get_selected_frame ());
+ for (const solib &so : current_program_space->solibs ())
+ if (solib_contains_address_p (so, curr_pc))
+ {
+ if (so.ops ().supports_namespaces ())
+ nsid = so.ops ().find_solib_ns (so);
+
+ break;
+ }
/* If the PC is not in an SO, or the solib_ops doesn't support
linker namespaces, the inferior is in the default namespace. */
- return lang->value_string (gdbarch, nsid.c_str (), nsid.length ());
+ return value_from_longest (builtin_type (gdbarch)->builtin_int, nsid);
}
-/* Implementation of `$_current_linker_namespace' variable. */
+/* Implementation of `$_linker_namespace' variable. */
-static const struct internalvar_funcs current_linker_namespace_funcs =
+static const struct internalvar_funcs linker_namespace_funcs =
{
- current_linker_namespace_make_value,
+ linker_namespace_make_value,
nullptr,
};
-void _initialize_solib ();
+static value *
+linker_namespace_count_make_value (gdbarch *gdbarch, internalvar *var,
+ void *ignore)
+{
+ return value_from_longest
+ (builtin_type (gdbarch)->builtin_int,
+ solib_linker_namespace_count (current_program_space));
+}
-void
-_initialize_solib ()
+/* Implementation of `$_linker_namespace_count' variable. */
+
+static const struct internalvar_funcs linker_namespace_count_funcs =
+{
+ linker_namespace_count_make_value,
+ nullptr,
+};
+
+INIT_GDB_FILE (solib)
{
gdb::observers::free_objfile.attach (remove_user_added_objfile, "solib");
gdb::observers::inferior_execd.attach (
@@ -1869,29 +1889,30 @@ _initialize_solib ()
/* Convenience variables for debugging linker namespaces. These are
set here, even if the solib_ops doesn't support them,
for consistency. */
- create_internalvar_type_lazy ("_current_linker_namespace",
- &current_linker_namespace_funcs, nullptr);
- set_internalvar_integer (lookup_internalvar ("_active_linker_namespaces"), 1);
+ create_internalvar_type_lazy ("_linker_namespace",
+ &linker_namespace_funcs, nullptr);
+ create_internalvar_type_lazy ("_linker_namespace_count",
+ &linker_namespace_count_funcs, nullptr);
add_com (
"sharedlibrary", class_files, sharedlibrary_command,
- _ ("Load shared object library symbols for files matching REGEXP."));
+ _("Load shared object library symbols for files matching REGEXP."));
cmd_list_element *info_sharedlibrary_cmd
= add_info ("sharedlibrary", info_sharedlibrary_command,
- _ ("Status of loaded shared object libraries."));
+ _("Status of loaded shared object libraries."));
add_info_alias ("dll", info_sharedlibrary_cmd, 1);
add_com ("nosharedlibrary", class_files, no_shared_libraries_command,
- _ ("Unload all shared object library symbols."));
+ _("Unload all shared object library symbols."));
add_info ("linker-namespaces", info_linker_namespace_command,
- _ ("Get information about linker namespaces in the inferior."));
+ _("Get information about linker namespaces in the inferior."));
add_setshow_boolean_cmd ("auto-solib-add", class_support, &auto_solib_add,
- _ ("\
+ _("\
Set autoloading of shared library symbols."),
- _ ("\
+ _("\
Show autoloading of shared library symbols."),
- _ ("\
+ _("\
If \"on\", symbols from all shared object libraries will be loaded\n\
automatically when the inferior begins execution, when the dynamic linker\n\
informs gdb that a new library has been loaded, or when attaching to the\n\
@@ -1901,11 +1922,11 @@ inferior. Otherwise, symbols must be loaded manually, using \
set_show_commands sysroot_cmds
= add_setshow_optional_filename_cmd ("sysroot", class_support,
- &gdb_sysroot, _ ("\
+ &gdb_sysroot, _("\
Set an alternate system root."),
- _ ("\
+ _("\
Show the current system root."),
- _ ("\
+ _("\
The system root is used to load absolute shared library symbol files.\n\
For other (relative) files, you can add directories using\n\
`set solib-search-path'."),
@@ -1918,22 +1939,22 @@ For other (relative) files, you can add directories using\n\
&showlist);
add_setshow_optional_filename_cmd ("solib-search-path", class_support,
- &solib_search_path, _ ("\
+ &solib_search_path, _("\
Set the search path for loading non-absolute shared library symbol files."),
- _ ("\
+ _("\
Show the search path for loading non-absolute shared library symbol files."),
- _ ("\
+ _("\
This takes precedence over the environment variables \
PATH and LD_LIBRARY_PATH."),
reload_shared_libraries,
show_solib_search_path, &setlist,
&showlist);
- add_setshow_boolean_cmd ("solib", class_maintenance, &debug_solib, _ ("\
+ add_setshow_boolean_cmd ("solib", class_maintenance, &debug_solib, _("\
Set solib debugging."),
- _ ("\
+ _("\
Show solib debugging."),
- _ ("\
+ _("\
When true, solib-related debugging output is enabled."),
nullptr, nullptr, &setdebuglist, &showdebuglist);
}
diff --git a/gdb/solib.h b/gdb/solib.h
index 360b6ef..eb8bafe 100644
--- a/gdb/solib.h
+++ b/gdb/solib.h
@@ -20,15 +20,14 @@
#ifndef GDB_SOLIB_H
#define GDB_SOLIB_H
-/* Forward decl's for prototypes */
-struct solib;
-struct target_ops;
-struct solib_ops;
-struct program_space;
-
#include "gdb_bfd.h"
-#include "symfile-add-flags.h"
#include "gdbsupport/function-view.h"
+#include "gdbsupport/intrusive_list.h"
+#include "gdbsupport/owning_intrusive_list.h"
+#include "symfile-add-flags.h"
+#include "target-section.h"
+
+struct program_space;
/* Value of the 'set debug solib' configuration variable. */
@@ -42,6 +41,269 @@ extern bool debug_solib;
#define SOLIB_SCOPED_DEBUG_START_END(fmt, ...) \
scoped_debug_start_end (debug_solib, "solib", fmt, ##__VA_ARGS__)
+#define SO_NAME_MAX_PATH_SIZE 512 /* FIXME: Should be dynamic */
+
+/* Base class for target-specific link map information. */
+
+struct lm_info
+{
+ lm_info () = default;
+ lm_info (const lm_info &) = default;
+ virtual ~lm_info () = 0;
+};
+
+using lm_info_up = std::unique_ptr<lm_info>;
+
+struct solib_ops;
+
+struct solib : intrusive_list_node<solib>
+{
+ /* Constructor
+
+ OPS is the solib_ops implementation providing this solib. */
+ explicit solib (const solib_ops &ops) : m_ops (&ops) {}
+
+ /* Return the solib_ops implementation providing this solib. */
+ const solib_ops &ops () const
+ { return *m_ops; }
+
+ /* Free symbol-file related contents of SO and reset for possible reloading
+ of SO. If we have opened a BFD for SO, close it. If we have placed SO's
+ sections in some target's section table, the caller is responsible for
+ removing them.
+
+ This function doesn't mess with objfiles at all. If there is an
+ objfile associated with SO that needs to be removed, the caller is
+ responsible for taking care of that. */
+ void clear () ;
+
+ /* The following fields of the structure come directly from the
+ dynamic linker's tables in the inferior, and are initialized by
+ current_sos. */
+
+ /* A pointer to target specific link map information. Often this
+ will be a copy of struct link_map from the user process, but
+ it need not be; it can be any collection of data needed to
+ traverse the dynamic linker's data structures. */
+ lm_info_up lm_info;
+
+ /* Shared object file name, exactly as it appears in the
+ inferior's link map. This may be a relative path, or something
+ which needs to be looked up in LD_LIBRARY_PATH, etc. We use it
+ to tell which entries in the inferior's dynamic linker's link
+ map we've already loaded. */
+ std::string original_name;
+
+ /* Shared object file name, expanded to something GDB can open. */
+ std::string name;
+
+ /* The following fields of the structure are built from
+ information gathered from the shared object file itself, and
+ are set when we actually add it to our symbol tables.
+
+ current_sos must initialize these fields to 0. */
+
+ gdb_bfd_ref_ptr abfd;
+
+ /* True if symbols have been read in. */
+ bool symbols_loaded = false;
+
+ /* objfile with symbols for a loaded library. Target memory is read from
+ ABFD. OBJFILE may be NULL either before symbols have been loaded, if
+ the file cannot be found or after the command "nosharedlibrary". */
+ struct objfile *objfile = nullptr;
+
+ std::vector<target_section> sections;
+
+ /* Record the range of addresses belonging to this shared library.
+ There may not be just one (e.g. if two segments are relocated
+ differently). This is used for "info sharedlibrary" and
+ the MI command "-file-list-shared-libraries". The latter has a format
+ that supports outputting multiple segments once the related code
+ supports them. */
+ CORE_ADDR addr_low = 0, addr_high = 0;
+
+private:
+ /* The solib_ops responsible for this solib. */
+ const solib_ops *m_ops;
+};
+
+/* A unique pointer to an solib. */
+using solib_up = std::unique_ptr<solib>;
+
+/* Callback type for the 'iterate_over_objfiles_in_search_order'
+ methods. */
+
+using iterate_over_objfiles_in_search_order_cb_ftype
+ = gdb::function_view<bool (objfile *)>;
+
+struct solib_ops
+{
+ explicit solib_ops (program_space *pspace)
+ : m_pspace (pspace)
+ {}
+
+ virtual ~solib_ops () = default;
+
+ /* Adjust the section binding addresses by the base address at
+ which the object was actually mapped. */
+ virtual void relocate_section_addresses (solib &so, target_section *) const
+ = 0;
+
+ /* Reset private data structures associated with SO.
+ This is called when SO is about to be reloaded.
+ It is also called when SO is about to be freed.
+
+ Defaults to no-op. */
+ virtual void clear_so (const solib &so) const {}
+
+ /* Free private data structures associated to PSPACE. This method
+ should not free resources associated to individual solib entries,
+ those are cleared by the clear_so method.
+
+ Defaults to no-op. */
+ virtual void clear_solib (program_space *pspace) const {}
+
+ /* Target dependent code to run after child process fork.
+
+ Defaults to no-op. */
+ virtual void create_inferior_hook (int from_tty) const {};
+
+ /* Construct a list of the currently loaded shared objects. This
+ list does not include an entry for the main executable file.
+
+ Note that we only gather information directly available from the
+ inferior --- we don't examine any of the shared library files
+ themselves. The declaration of `struct solib' says which fields
+ we provide values for. */
+ virtual owning_intrusive_list<solib> current_sos () const = 0;
+
+ /* Find, open, and read the symbols for the main executable. If
+ FROM_TTY is non-zero, allow messages to be printed.
+
+ Return true if this was done successfully. Defaults to false. */
+ virtual bool open_symbol_file_object (int from_tty) const { return false; }
+
+ /* Determine if PC lies in the dynamic symbol resolution code of
+ the run time loader.
+
+ Defaults to false. */
+ virtual bool in_dynsym_resolve_code (CORE_ADDR pc) const
+ { return false; };
+
+ /* Find and open shared library binary file. */
+ virtual gdb_bfd_ref_ptr bfd_open (const char *pathname) const;
+
+ /* Given two solib objects, GDB from the GDB thread list and INFERIOR from the
+ list returned by current_sos, return true if they represent the same library.
+
+ Defaults to comparing the solib original names using filename_cmp. */
+ virtual bool same (const solib &gdb, const solib &inferior) const;
+
+ /* Return whether a region of memory must be kept in a core file
+ for shared libraries loaded before "gcore" is used to be
+ handled correctly when the core file is loaded. This only
+ applies when the section would otherwise not be kept in the
+ core file (in particular, for readonly sections).
+
+ Defaults to false. */
+ virtual bool keep_data_in_core (CORE_ADDR vaddr, unsigned long size) const
+ { return false; };
+
+ /* Enable or disable optional solib event breakpoints as appropriate. This
+ should be called whenever stop_on_solib_events is changed.
+
+ Defaults to no-op. */
+ virtual void update_breakpoints () const {};
+
+ /* Target-specific processing of solib events that will be performed before
+ solib_add is called.
+
+ Defaults to no-op. */
+ virtual void handle_event () const {};
+
+ /* Return an address within the inferior's address space which is known
+ to be part of SO. If there is no such address, or GDB doesn't know
+ how to figure out such an address then an empty optional is
+ returned.
+
+ The returned address can be used when loading the shared libraries
+ for a core file. GDB knows the build-ids for (some) files mapped
+ into the inferior's address space, and knows the address ranges which
+ those mapped files cover. If GDB can figure out a representative
+ address for the library then this can be used to match a library to a
+ mapped file, and thus to a build-id. GDB can then use this
+ information to help locate the shared library objfile, if the objfile
+ is not in the expected place (as defined by the shared libraries file
+ name).
+
+ The default implementation of returns an empty option, indicating GDB is
+ unable to find an address within the library SO. */
+ virtual std::optional<CORE_ADDR> find_solib_addr (solib &so) const
+ { return {}; };
+
+ /* Return true if the linker or libc supports linkage namespaces.
+
+ Defaults to false. */
+ virtual bool supports_namespaces () const { return false; }
+
+ /* Return which linker namespace contains SO.
+
+ The supports_namespaces method must return true for this to be
+ called.
+
+ Throw an error if the namespace can not be determined (such as when we're
+ stepping though the dynamic linker). */
+ virtual int find_solib_ns (const solib &so) const
+ { gdb_assert_not_reached ("namespaces not supported"); }
+
+ /* Returns the number of active namespaces in the inferior.
+
+ The supports_namespaces method must return true for this to be called. */
+ virtual int num_active_namespaces () const
+ { gdb_assert_not_reached ("namespaces not supported"); }
+
+ /* Returns all solibs for a given namespace. If the namespace is not
+ active, returns an empty vector.
+
+ The supports_namespaces method must return true for this to be called. */
+ virtual std::vector<const solib *> get_solibs_in_ns (int ns) const
+ { gdb_assert_not_reached ("namespaces not supported"); }
+
+ /* Iterate over all objfiles of the program space in the order that makes the
+ most sense for the architecture to make global symbol searches.
+
+ CB is a callback function passed an objfile to be searched. The iteration
+ stops if this function returns true.
+
+ If not nullptr, CURRENT_OBJFILE corresponds to the objfile being inspected
+ when the symbol search was requested. */
+ virtual void iterate_over_objfiles_in_search_order
+ (iterate_over_objfiles_in_search_order_cb_ftype cb,
+ objfile *current_objfile) const;
+
+protected:
+ /* The program space for which this solib_ops was created. */
+ program_space *m_pspace;
+};
+
+/* A unique pointer to an solib_ops. */
+using solib_ops_up = std::unique_ptr<solib_ops>;
+
+/* Find main executable binary file. */
+extern gdb::unique_xmalloc_ptr<char> exec_file_find (const char *in_pathname,
+ int *fd);
+
+/* Find shared library binary file. */
+extern gdb::unique_xmalloc_ptr<char> solib_find (const char *in_pathname,
+ int *fd);
+
+/* Open BFD for shared library file. */
+extern gdb_bfd_ref_ptr solib_bfd_fopen (const char *pathname, int fd);
+
+/* Find solib binary file and open it. */
+extern gdb_bfd_ref_ptr solib_bfd_open (const char *in_pathname);
+
/* Called when we free all symtabs of PSPACE, to free the shared library
information as well. */
@@ -89,7 +351,8 @@ extern void no_shared_libraries (program_space *pspace);
Extract the list of currently loaded shared objects from the
inferior, and compare it with the list of shared objects in the
current program space's list of shared libraries. Edit
- so_list_head to bring it in sync with the inferior's new list.
+ the current program space's solib list to bring it in sync with the
+ inferior's new list.
If we notice that the inferior has unloaded some shared objects,
free any symbolic info GDB had read about those shared objects.
@@ -136,4 +399,8 @@ extern void update_solib_breakpoints (void);
extern void handle_solib_event (void);
+/* Calculate the number of linker namespaces active in PSPACE. */
+
+extern int solib_linker_namespace_count (program_space *pspace);
+
#endif /* GDB_SOLIB_H */
diff --git a/gdb/solist.h b/gdb/solist.h
deleted file mode 100644
index 6ab5a06..0000000
--- a/gdb/solist.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/* Shared library declarations for GDB, the GNU Debugger.
- Copyright (C) 1990-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/>. */
-
-#ifndef GDB_SOLIST_H
-#define GDB_SOLIST_H
-
-#define SO_NAME_MAX_PATH_SIZE 512 /* FIXME: Should be dynamic */
-
-/* For domain_enum domain. */
-#include "symtab.h"
-#include "gdb_bfd.h"
-#include "gdbsupport/owning_intrusive_list.h"
-#include "target-section.h"
-
-/* Base class for target-specific link map information. */
-
-struct lm_info
-{
- lm_info () = default;
- lm_info (const lm_info &) = default;
- virtual ~lm_info () = 0;
-};
-
-using lm_info_up = std::unique_ptr<lm_info>;
-
-struct solib : intrusive_list_node<solib>
-{
- /* Free symbol-file related contents of SO and reset for possible reloading
- of SO. If we have opened a BFD for SO, close it. If we have placed SO's
- sections in some target's section table, the caller is responsible for
- removing them.
-
- This function doesn't mess with objfiles at all. If there is an
- objfile associated with SO that needs to be removed, the caller is
- responsible for taking care of that. */
- void clear () ;
-
- /* The following fields of the structure come directly from the
- dynamic linker's tables in the inferior, and are initialized by
- current_sos. */
-
- /* A pointer to target specific link map information. Often this
- will be a copy of struct link_map from the user process, but
- it need not be; it can be any collection of data needed to
- traverse the dynamic linker's data structures. */
- lm_info_up lm_info;
-
- /* Shared object file name, exactly as it appears in the
- inferior's link map. This may be a relative path, or something
- which needs to be looked up in LD_LIBRARY_PATH, etc. We use it
- to tell which entries in the inferior's dynamic linker's link
- map we've already loaded. */
- std::string so_original_name;
-
- /* Shared object file name, expanded to something GDB can open. */
- std::string so_name;
-
- /* The following fields of the structure are built from
- information gathered from the shared object file itself, and
- are set when we actually add it to our symbol tables.
-
- current_sos must initialize these fields to 0. */
-
- gdb_bfd_ref_ptr abfd;
-
- /* True if symbols have been read in. */
- bool symbols_loaded = false;
-
- /* objfile with symbols for a loaded library. Target memory is read from
- ABFD. OBJFILE may be NULL either before symbols have been loaded, if
- the file cannot be found or after the command "nosharedlibrary". */
- struct objfile *objfile = nullptr;
-
- std::vector<target_section> sections;
-
- /* Record the range of addresses belonging to this shared library.
- There may not be just one (e.g. if two segments are relocated
- differently). This is used for "info sharedlibrary" and
- the MI command "-file-list-shared-libraries". The latter has a format
- that supports outputting multiple segments once the related code
- supports them. */
- CORE_ADDR addr_low = 0, addr_high = 0;
-};
-
-struct solib_ops
-{
- /* Adjust the section binding addresses by the base address at
- which the object was actually mapped. */
- void (*relocate_section_addresses) (solib &so, target_section *);
-
- /* Reset private data structures associated with SO.
- This is called when SO is about to be reloaded.
- It is also called when SO is about to be freed. */
- void (*clear_so) (const solib &so);
-
- /* Free private data structures associated to PSPACE. This method
- should not free resources associated to individual so_list entries,
- those are cleared by the clear_so method. */
- void (*clear_solib) (program_space *pspace);
-
- /* Target dependent code to run after child process fork. */
- void (*solib_create_inferior_hook) (int from_tty);
-
- /* Construct a list of the currently loaded shared objects. This
- list does not include an entry for the main executable file.
-
- Note that we only gather information directly available from the
- inferior --- we don't examine any of the shared library files
- themselves. The declaration of `struct solib' says which fields
- we provide values for. */
- owning_intrusive_list<solib> (*current_sos) ();
-
- /* Find, open, and read the symbols for the main executable. If
- FROM_TTY is non-zero, allow messages to be printed. */
- int (*open_symbol_file_object) (int from_ttyp);
-
- /* Determine if PC lies in the dynamic symbol resolution code of
- the run time loader. */
- int (*in_dynsym_resolve_code) (CORE_ADDR pc);
-
- /* Find and open shared library binary file. */
- gdb_bfd_ref_ptr (*bfd_open) (const char *pathname);
-
- /* Given two so_list objects, one from the GDB thread list
- and another from the list returned by current_sos, return 1
- if they represent the same library.
- Falls back to using strcmp on so_original_name field when set
- to NULL. */
- int (*same) (const solib &gdb, const solib &inferior);
-
- /* Return whether a region of memory must be kept in a core file
- for shared libraries loaded before "gcore" is used to be
- handled correctly when the core file is loaded. This only
- applies when the section would otherwise not be kept in the
- core file (in particular, for readonly sections). */
- int (*keep_data_in_core) (CORE_ADDR vaddr,
- unsigned long size);
-
- /* Enable or disable optional solib event breakpoints as
- appropriate. This should be called whenever
- stop_on_solib_events is changed. This pointer can be
- NULL, in which case no enabling or disabling is necessary
- for this target. */
- void (*update_breakpoints) (void);
-
- /* Target-specific processing of solib events that will be
- performed before solib_add is called. This pointer can be
- NULL, in which case no specific preprocessing is necessary
- for this target. */
- void (*handle_event) (void);
-
- /* Return an address within the inferior's address space which is known
- to be part of SO. If there is no such address, or GDB doesn't know
- how to figure out such an address then an empty optional is
- returned.
-
- The returned address can be used when loading the shared libraries
- for a core file. GDB knows the build-ids for (some) files mapped
- into the inferior's address space, and knows the address ranges which
- those mapped files cover. If GDB can figure out a representative
- address for the library then this can be used to match a library to a
- mapped file, and thus to a build-id. GDB can then use this
- information to help locate the shared library objfile, if the objfile
- is not in the expected place (as defined by the shared libraries file
- name). */
-
- std::optional<CORE_ADDR> (*find_solib_addr) (solib &so);
-
- /* Return which linker namespace contains the current so.
- If the linker or libc does not support linkage namespaces at all
- (which is basically all of them but solib-svr4), this function should
- be set to nullptr, so that "info shared" won't add an unnecessary
- column.
-
- If the namespace can not be determined (such as when we're stepping
- though the dynamic linker), this function should throw a
- gdb_exception_error. */
- int (*find_solib_ns) (const solib &so);
-
- /* Returns the number of active namespaces in the inferior. */
- int (*num_active_namespaces) ();
-
- /* Returns all solibs for a given namespace. If the namespace is not
- active, returns an empty vector. */
- std::vector<const solib *> (*get_solibs_in_ns) (int ns);
-};
-
-/* A unique pointer to a so_list. */
-using solib_up = std::unique_ptr<solib>;
-
-/* Find main executable binary file. */
-extern gdb::unique_xmalloc_ptr<char> exec_file_find (const char *in_pathname,
- int *fd);
-
-/* Find shared library binary file. */
-extern gdb::unique_xmalloc_ptr<char> solib_find (const char *in_pathname,
- int *fd);
-
-/* Open BFD for shared library file. */
-extern gdb_bfd_ref_ptr solib_bfd_fopen (const char *pathname, int fd);
-
-/* Find solib binary file and open it. */
-extern gdb_bfd_ref_ptr solib_bfd_open (const char *in_pathname);
-
-/* A default implementation of the solib_ops::find_solib_addr callback.
- This just returns an empty std::optional<CORE_ADDR> indicating GDB is
- unable to find an address within the library SO. */
-extern std::optional<CORE_ADDR> default_find_solib_addr (solib &so);
-
-#endif /* GDB_SOLIST_H */
diff --git a/gdb/source-cache.c b/gdb/source-cache.c
index ebe451d..9d5151a 100644
--- a/gdb/source-cache.c
+++ b/gdb/source-cache.c
@@ -511,9 +511,7 @@ static void extract_lines_test ()
}
#endif
-void _initialize_source_cache ();
-void
-_initialize_source_cache ()
+INIT_GDB_FILE (source_cache)
{
add_cmd ("source-cache", class_maintenance, source_cache_flush_command,
_("Force gdb to flush its source code cache."),
diff --git a/gdb/source.c b/gdb/source.c
index 13cb8d6..8cb5c36 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -1312,14 +1312,12 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
int nlines = stopline - line;
struct ui_out *uiout = current_uiout;
- /* Regardless of whether we can open the file, set current_source_symtab. */
+ /* Regardless of whether we can open the file, we'll want to set
+ current_source_symtab, but not if throw an error, or return without
+ printing any source lines. */
current_source_location *loc
= get_source_location (current_program_space);
- loc->set (s, line);
- first_line_listed = line;
- last_line_listed = line;
-
/* If printing of source lines is disabled, just print file and line
number. */
if (uiout->test_flags (ui_source_list) && source_open)
@@ -1380,6 +1378,10 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
uiout->text ("\n");
}
+ loc->set (s, line);
+ first_line_listed = line;
+ last_line_listed = line;
+
return;
}
@@ -1399,12 +1401,9 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
}
const char *iter = lines.c_str ();
- int new_lineno = loc->line ();
- while (nlines-- > 0 && *iter != '\0')
+ int new_lineno = line;
+ for (; nlines-- > 0 && *iter != '\0'; ++new_lineno)
{
- char buf[20];
-
- last_line_listed = loc->line ();
if (flags & PRINT_SOURCE_LINES_FILENAME)
{
uiout->message ("%ps",
@@ -1415,7 +1414,6 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
uiout->message ("%ps\t", styled_string (line_number_style.style (),
pulongest (new_lineno)));
- ++new_lineno;
while (*iter != '\0')
{
@@ -1457,6 +1455,8 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
}
else if (*iter > 0 && *iter < 040)
{
+ char buf[20];
+
xsnprintf (buf, sizeof (buf), "^%c", *iter + 0100);
uiout->text (buf);
++iter;
@@ -1470,7 +1470,11 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
uiout->text ("\n");
}
- loc->set (loc->symtab (), new_lineno);
+ /* As NEW_LINENO was incremented after displaying the last source line,
+ the last line shown was the one before NEW_LINENO. */
+ first_line_listed = line;
+ last_line_listed = new_lineno - 1;
+ loc->set (s, new_lineno);
}
@@ -1910,9 +1914,7 @@ source_lines_range::source_lines_range (int startline,
}
-void _initialize_source ();
-void
-_initialize_source ()
+INIT_GDB_FILE (source)
{
init_source_path ();
diff --git a/gdb/sparc-linux-nat.c b/gdb/sparc-linux-nat.c
index 8dccce9..18db599 100644
--- a/gdb/sparc-linux-nat.c
+++ b/gdb/sparc-linux-nat.c
@@ -65,9 +65,7 @@ fill_fpregset (const struct regcache *regcache,
sparc32_collect_fpregset (sparc_fpregmap, regcache, regnum, fpregs);
}
-void _initialize_sparc_linux_nat ();
-void
-_initialize_sparc_linux_nat ()
+INIT_GDB_FILE (sparc_linux_nat)
{
sparc_fpregmap = &sparc32_bsd_fpregmap;
diff --git a/gdb/sparc-linux-tdep.c b/gdb/sparc-linux-tdep.c
index 27706b7..6e23fdd 100644
--- a/gdb/sparc-linux-tdep.c
+++ b/gdb/sparc-linux-tdep.c
@@ -33,6 +33,7 @@
#include "tramp-frame.h"
#include "xml-syscall.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
/* The syscall's XML filename for sparc 32-bit. */
#define XML_SYSCALL_FILENAME_SPARC32 "syscalls/sparc-linux.xml"
@@ -436,8 +437,7 @@ sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* GNU/Linux has SVR4-style shared libraries... */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
/* ...which means that we need some special handling when doing
prologue analysis. */
@@ -466,9 +466,7 @@ sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
sparc32_linux_gdb_signal_to_target);
}
-void _initialize_sparc_linux_tdep ();
-void
-_initialize_sparc_linux_tdep ()
+INIT_GDB_FILE (sparc_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_LINUX,
sparc32_linux_init_abi);
diff --git a/gdb/sparc-nat.c b/gdb/sparc-nat.c
index c2d3833..1219612 100644
--- a/gdb/sparc-nat.c
+++ b/gdb/sparc-nat.c
@@ -309,9 +309,7 @@ sparc_xfer_wcookie (enum target_object object,
}
-void _initialize_sparc_nat ();
-void
-_initialize_sparc_nat ()
+INIT_GDB_FILE (sparc_nat)
{
/* Default to using SunOS 4 register sets. */
if (sparc_gregmap == NULL)
diff --git a/gdb/sparc-netbsd-nat.c b/gdb/sparc-netbsd-nat.c
index 8eee741..54cba0b 100644
--- a/gdb/sparc-netbsd-nat.c
+++ b/gdb/sparc-netbsd-nat.c
@@ -56,9 +56,7 @@ sparc32nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
static sparc_target<inf_ptrace_target> the_sparc_nbsd_nat_target;
-void _initialize_sparcnbsd_nat ();
-void
-_initialize_sparcnbsd_nat ()
+INIT_GDB_FILE (sparcnbsd_nat)
{
sparc_gregmap = &sparc32nbsd_gregmap;
sparc_fpregmap = &sparc32_bsd_fpregmap;
diff --git a/gdb/sparc-netbsd-tdep.c b/gdb/sparc-netbsd-tdep.c
index 84e3a97..8e8a1ba 100644
--- a/gdb/sparc-netbsd-tdep.c
+++ b/gdb/sparc-netbsd-tdep.c
@@ -313,13 +313,10 @@ sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
frame_unwind_append_unwinder (gdbarch, &sparc32nbsd_sigcontext_frame_unwind);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
}
-void _initialize_sparcnbsd_tdep ();
-void
-_initialize_sparcnbsd_tdep ()
+INIT_GDB_FILE (sparcnbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD,
sparc32nbsd_init_abi);
diff --git a/gdb/sparc-obsd-tdep.c b/gdb/sparc-obsd-tdep.c
index 3486799..ff6e915 100644
--- a/gdb/sparc-obsd-tdep.c
+++ b/gdb/sparc-obsd-tdep.c
@@ -254,9 +254,7 @@ sparc32obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
bsd_uthread_set_collect_uthread (gdbarch, sparc32obsd_collect_uthread);
}
-void _initialize_sparc32obsd_tdep ();
-void
-_initialize_sparc32obsd_tdep ()
+INIT_GDB_FILE (sparc32obsd_tdep)
{
gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_OPENBSD,
sparc32obsd_init_abi);
diff --git a/gdb/sparc-sol2-tdep.c b/gdb/sparc-sol2-tdep.c
index 5c6085a..8de7439 100644
--- a/gdb/sparc-sol2-tdep.c
+++ b/gdb/sparc-sol2-tdep.c
@@ -207,22 +207,19 @@ sparc32_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Solaris has SVR4-style shared libraries... */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
/* ...which means that we need some special handling when doing
prologue analysis. */
tdep->plt_entry_size = 12;
/* Solaris has kernel-assisted single-stepping support. */
- set_gdbarch_software_single_step (gdbarch, NULL);
+ set_gdbarch_get_next_pcs (gdbarch, NULL);
frame_unwind_append_unwinder (gdbarch, &sparc32_sol2_sigtramp_frame_unwind);
}
-void _initialize_sparc_sol2_tdep ();
-void
-_initialize_sparc_sol2_tdep ()
+INIT_GDB_FILE (sparc_sol2_tdep)
{
gdbarch_register_osabi (bfd_arch_sparc, 0,
GDB_OSABI_SOLARIS, sparc32_sol2_init_abi);
diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
index 80914d9..914a568 100644
--- a/gdb/sparc-tdep.c
+++ b/gdb/sparc-tdep.c
@@ -1874,7 +1874,7 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_frame_args_skip (gdbarch, 8);
- set_gdbarch_software_single_step (gdbarch, sparc_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, sparc_software_single_step);
set_gdbarch_write_pc (gdbarch, sparc_write_pc);
set_gdbarch_dummy_id (gdbarch, sparc_dummy_id);
@@ -2264,9 +2264,7 @@ const struct sparc_fpregmap sparc32_bsd_fpregmap =
32 * 4, /* %fsr */
};
-void _initialize_sparc_tdep ();
-void
-_initialize_sparc_tdep ()
+INIT_GDB_FILE (sparc_tdep)
{
gdbarch_register (bfd_arch_sparc, sparc32_gdbarch_init);
}
diff --git a/gdb/sparc64-fbsd-nat.c b/gdb/sparc64-fbsd-nat.c
index 4848c77..d697841 100644
--- a/gdb/sparc64-fbsd-nat.c
+++ b/gdb/sparc64-fbsd-nat.c
@@ -61,9 +61,7 @@ sparc64fbsd_kvm_supply_pcb (struct regcache *regcache, struct pcb *pcb)
/* Add some extra features to the generic SPARC target. */
static sparc_target<fbsd_nat_target> the_sparc64_fbsd_nat_target;
-void _initialize_sparc64fbsd_nat ();
-void
-_initialize_sparc64fbsd_nat ()
+INIT_GDB_FILE (sparc64fbsd_nat)
{
add_inf_child_target (&the_sparc64_fbsd_nat_target);
diff --git a/gdb/sparc64-fbsd-tdep.c b/gdb/sparc64-fbsd-tdep.c
index 738c3d1..ba04a71 100644
--- a/gdb/sparc64-fbsd-tdep.c
+++ b/gdb/sparc64-fbsd-tdep.c
@@ -238,13 +238,10 @@ sparc64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* FreeBSD/sparc64 has SVR4-style shared libraries. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
}
-void _initialize_sparc64fbsd_tdep ();
-void
-_initialize_sparc64fbsd_tdep ()
+INIT_GDB_FILE (sparc64fbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
GDB_OSABI_FREEBSD, sparc64fbsd_init_abi);
diff --git a/gdb/sparc64-linux-nat.c b/gdb/sparc64-linux-nat.c
index 9a4b228..2884faa 100644
--- a/gdb/sparc64-linux-nat.c
+++ b/gdb/sparc64-linux-nat.c
@@ -87,9 +87,7 @@ fill_fpregset (const struct regcache *regcache,
sparc64_collect_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs);
}
-void _initialize_sparc64_linux_nat ();
-void
-_initialize_sparc64_linux_nat ()
+INIT_GDB_FILE (sparc64_linux_nat)
{
sparc_fpregmap = &sparc64_bsd_fpregmap;
diff --git a/gdb/sparc64-linux-tdep.c b/gdb/sparc64-linux-tdep.c
index 6e7281c..373dfb6 100644
--- a/gdb/sparc64-linux-tdep.c
+++ b/gdb/sparc64-linux-tdep.c
@@ -32,6 +32,7 @@
#include "tramp-frame.h"
#include "xml-syscall.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
/* ADI specific si_code */
#ifndef SEGV_ACCADI
@@ -383,8 +384,7 @@ sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* GNU/Linux has SVR4-style shared libraries... */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_lp64_svr4_solib_ops);
/* ...which means that we need some special handling when doing
prologue analysis. */
@@ -409,9 +409,7 @@ sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_report_signal_info (gdbarch, sparc64_linux_report_signal_info);
}
-void _initialize_sparc64_linux_tdep ();
-void
-_initialize_sparc64_linux_tdep ()
+INIT_GDB_FILE (sparc64_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
GDB_OSABI_LINUX, sparc64_linux_init_abi);
diff --git a/gdb/sparc64-nat.c b/gdb/sparc64-nat.c
index 6bb37d8..66451a0 100644
--- a/gdb/sparc64-nat.c
+++ b/gdb/sparc64-nat.c
@@ -68,9 +68,7 @@ sparc64_fpregset_supplies_p (struct gdbarch *gdbarch, int regnum)
return 0;
}
-void _initialize_sparc64_nat ();
-void
-_initialize_sparc64_nat ()
+INIT_GDB_FILE (sparc64_nat)
{
sparc_supply_gregset = sparc64_supply_gregset;
sparc_collect_gregset = sparc64_collect_gregset;
diff --git a/gdb/sparc64-netbsd-nat.c b/gdb/sparc64-netbsd-nat.c
index c4bec4c..1036160 100644
--- a/gdb/sparc64-netbsd-nat.c
+++ b/gdb/sparc64-netbsd-nat.c
@@ -169,9 +169,7 @@ sparc64nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
/* We've got nothing to add to the generic SPARC target. */
static sparc_target<inf_ptrace_target> the_sparc64_nbsd_nat_target;
-void _initialize_sparc64nbsd_nat ();
-void
-_initialize_sparc64nbsd_nat ()
+INIT_GDB_FILE (sparc64nbsd_nat)
{
sparc_supply_gregset = sparc64nbsd_supply_gregset;
sparc_collect_gregset = sparc64nbsd_collect_gregset;
diff --git a/gdb/sparc64-netbsd-tdep.c b/gdb/sparc64-netbsd-tdep.c
index 1919598..0227ec4 100644
--- a/gdb/sparc64-netbsd-tdep.c
+++ b/gdb/sparc64-netbsd-tdep.c
@@ -266,13 +266,10 @@ sparc64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* NetBSD/sparc64 has SVR4-style shared libraries. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
}
-void _initialize_sparc64nbsd_tdep ();
-void
-_initialize_sparc64nbsd_tdep ()
+INIT_GDB_FILE (sparc64nbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
GDB_OSABI_NETBSD, sparc64nbsd_init_abi);
diff --git a/gdb/sparc64-obsd-nat.c b/gdb/sparc64-obsd-nat.c
index 5f9bd46..60dd188 100644
--- a/gdb/sparc64-obsd-nat.c
+++ b/gdb/sparc64-obsd-nat.c
@@ -108,9 +108,7 @@ sparc64obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
/* Add some extra features to the generic SPARC target. */
static sparc_target<obsd_nat_target> the_sparc64_obsd_nat_target;
-void _initialize_sparc64obsd_nat ();
-void
-_initialize_sparc64obsd_nat ()
+INIT_GDB_FILE (sparc64obsd_nat)
{
sparc_supply_gregset = sparc64_supply_gregset;
sparc_collect_gregset = sparc64_collect_gregset;
diff --git a/gdb/sparc64-obsd-tdep.c b/gdb/sparc64-obsd-tdep.c
index 657f548..83cc9c0 100644
--- a/gdb/sparc64-obsd-tdep.c
+++ b/gdb/sparc64-obsd-tdep.c
@@ -440,8 +440,7 @@ sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
obsd_init_abi (info, gdbarch);
/* OpenBSD/sparc64 has SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
/* OpenBSD provides a user-level threads implementation. */
@@ -449,9 +448,7 @@ sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
bsd_uthread_set_collect_uthread (gdbarch, sparc64obsd_collect_uthread);
}
-void _initialize_sparc64obsd_tdep ();
-void
-_initialize_sparc64obsd_tdep ()
+INIT_GDB_FILE (sparc64obsd_tdep)
{
gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
GDB_OSABI_OPENBSD, sparc64obsd_init_abi);
diff --git a/gdb/sparc64-sol2-tdep.c b/gdb/sparc64-sol2-tdep.c
index 72a07ec..cb3ba6b 100644
--- a/gdb/sparc64-sol2-tdep.c
+++ b/gdb/sparc64-sol2-tdep.c
@@ -214,20 +214,17 @@ sparc64_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Solaris has SVR4-style shared libraries... */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_lp64_solib_ops);
/* ...which means that we need some special handling when doing
prologue analysis. */
tdep->plt_entry_size = 16;
/* Solaris has kernel-assisted single-stepping support. */
- set_gdbarch_software_single_step (gdbarch, NULL);
+ set_gdbarch_get_next_pcs (gdbarch, NULL);
}
-void _initialize_sparc64_sol2_tdep ();
-void
-_initialize_sparc64_sol2_tdep ()
+INIT_GDB_FILE (sparc64_sol2_tdep)
{
gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
GDB_OSABI_SOLARIS, sparc64_sol2_init_abi);
diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c
index ee7d7ed..6846421 100644
--- a/gdb/sparc64-tdep.c
+++ b/gdb/sparc64-tdep.c
@@ -529,9 +529,7 @@ adi_assign_command (const char *args, int from_tty)
do_assign (next_address, cnt, version);
}
-void _initialize_sparc64_adi_tdep ();
-void
-_initialize_sparc64_adi_tdep ()
+INIT_GDB_FILE (sparc64_adi_tdep)
{
add_basic_prefix_cmd ("adi", class_support,
_("ADI version related commands."),
diff --git a/gdb/stabsread.c b/gdb/stabsread.c
index 409f303..733fc9e 100644
--- a/gdb/stabsread.c
+++ b/gdb/stabsread.c
@@ -46,7 +46,6 @@
#include "c-lang.h"
#include "cp-abi.h"
#include "cp-support.h"
-#include <ctype.h>
#include "block.h"
#include "filenames.h"
@@ -472,7 +471,7 @@ patch_block_stabs (struct pending *symbols, struct pending_stabs *stabs,
a N_GSYM stab for it, but no regular (C_EXT) symbol. */
sym = new (&objfile->objfile_obstack) symbol;
sym->set_domain (VAR_DOMAIN);
- sym->set_aclass_index (LOC_OPTIMIZED_OUT);
+ sym->set_loc_class_index (LOC_OPTIMIZED_OUT);
sym->set_linkage_name
(obstack_strndup (&objfile->objfile_obstack, name, pp - name));
pp += 2;
@@ -3067,7 +3066,7 @@ process_reference (const char **string)
p = *string + 1;
/* Read number as reference id. */
- while (*p && isdigit (*p))
+ while (*p && c_isdigit (*p))
{
refnum = refnum * 10 + *p - '0';
p++;
@@ -3123,7 +3122,7 @@ static const struct symbol_register_ops stab_register_funcs = {
stab_reg_to_regnum
};
-/* The "aclass" indices for computed symbols. */
+/* The "loc_class" indices for computed symbols. */
static int stab_register_index;
static int stab_regparm_index;
@@ -3251,7 +3250,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
deftypes we know how to handle is a local. */
if (!strchr ("cfFGpPrStTvVXCR", *p))
#else
- if (isdigit (*p) || *p == '(' || *p == '-')
+ if (c_isdigit (*p) || *p == '(' || *p == '-')
#endif
deftype = 'l';
else
@@ -3268,7 +3267,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
(where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
if (*p != '=')
{
- sym->set_aclass_index (LOC_CONST);
+ sym->set_loc_class_index (LOC_CONST);
sym->set_type (error_type (&p, objfile));
sym->set_domain (VAR_DOMAIN);
add_symbol_to_list (sym, get_file_symbols ());
@@ -3291,7 +3290,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
sym->set_type (dbl_type);
sym->set_value_bytes (dbl_valu);
- sym->set_aclass_index (LOC_CONST_BYTES);
+ sym->set_loc_class_index (LOC_CONST_BYTES);
}
break;
case 'i':
@@ -3305,7 +3304,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
sym->set_type (builtin_type (objfile)->builtin_long);
sym->set_value_longest (atoi (p));
- sym->set_aclass_index (LOC_CONST);
+ sym->set_loc_class_index (LOC_CONST);
}
break;
@@ -3313,7 +3312,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
{
sym->set_type (builtin_type (objfile)->builtin_char);
sym->set_value_longest (atoi (p));
- sym->set_aclass_index (LOC_CONST);
+ sym->set_loc_class_index (LOC_CONST);
}
break;
@@ -3327,7 +3326,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
if (quote != '\'' && quote != '"')
{
- sym->set_aclass_index (LOC_CONST);
+ sym->set_loc_class_index (LOC_CONST);
sym->set_type (error_type (&p, objfile));
sym->set_domain (VAR_DOMAIN);
add_symbol_to_list (sym, get_file_symbols ());
@@ -3352,7 +3351,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
}
if (*p != quote)
{
- sym->set_aclass_index (LOC_CONST);
+ sym->set_loc_class_index (LOC_CONST);
sym->set_type (error_type (&p, objfile));
sym->set_domain (VAR_DOMAIN);
add_symbol_to_list (sym, get_file_symbols ());
@@ -3375,7 +3374,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
p++;
sym->set_value_bytes (string_value);
- sym->set_aclass_index (LOC_CONST_BYTES);
+ sym->set_loc_class_index (LOC_CONST_BYTES);
}
break;
@@ -3385,7 +3384,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
e.g. "b:c=e6,0" for "const b = blob1"
(where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
{
- sym->set_aclass_index (LOC_CONST);
+ sym->set_loc_class_index (LOC_CONST);
sym->set_type (read_type (&p, objfile));
if (*p != ',')
@@ -3406,7 +3405,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
break;
default:
{
- sym->set_aclass_index (LOC_CONST);
+ sym->set_loc_class_index (LOC_CONST);
sym->set_type (error_type (&p, objfile));
}
}
@@ -3417,7 +3416,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
case 'C':
/* The name of a caught exception. */
sym->set_type (read_type (&p, objfile));
- sym->set_aclass_index (LOC_LABEL);
+ sym->set_loc_class_index (LOC_LABEL);
sym->set_domain (VAR_DOMAIN);
sym->set_value_address (valu);
add_symbol_to_list (sym, get_local_symbols ());
@@ -3426,7 +3425,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
case 'f':
/* A static function definition. */
sym->set_type (read_type (&p, objfile));
- sym->set_aclass_index (LOC_BLOCK);
+ sym->set_loc_class_index (LOC_BLOCK);
sym->set_domain (FUNCTION_DOMAIN);
add_symbol_to_list (sym, get_file_symbols ());
/* fall into process_function_types. */
@@ -3497,7 +3496,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
case 'F':
/* A global function definition. */
sym->set_type (read_type (&p, objfile));
- sym->set_aclass_index (LOC_BLOCK);
+ sym->set_loc_class_index (LOC_BLOCK);
sym->set_domain (FUNCTION_DOMAIN);
add_symbol_to_list (sym, get_global_symbols ());
goto process_function_types;
@@ -3508,7 +3507,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
corresponding linker definition to find the value.
These definitions appear at the end of the namelist. */
sym->set_type (read_type (&p, objfile));
- sym->set_aclass_index (LOC_STATIC);
+ sym->set_loc_class_index (LOC_STATIC);
sym->set_domain (VAR_DOMAIN);
/* Don't add symbol references to global_sym_chain.
Symbol references don't have valid names and won't match up with
@@ -3529,7 +3528,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
case 's':
case 'l':
sym->set_type (read_type (&p, objfile));
- sym->set_aclass_index (LOC_LOCAL);
+ sym->set_loc_class_index (LOC_LOCAL);
sym->set_value_longest (valu);
sym->set_domain (VAR_DOMAIN);
add_symbol_to_list (sym, get_local_symbols ());
@@ -3549,7 +3548,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
else
sym->set_type (read_type (&p, objfile));
- sym->set_aclass_index (LOC_ARG);
+ sym->set_loc_class_index (LOC_ARG);
sym->set_value_longest (valu);
sym->set_domain (VAR_DOMAIN);
sym->set_is_argument (1);
@@ -3598,7 +3597,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
case 'R':
/* Parameter which is in a register. */
sym->set_type (read_type (&p, objfile));
- sym->set_aclass_index (stab_register_index);
+ sym->set_loc_class_index (stab_register_index);
sym->set_is_argument (1);
sym->set_value_longest (valu);
sym->set_domain (VAR_DOMAIN);
@@ -3608,7 +3607,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
case 'r':
/* Register variable (either global or local). */
sym->set_type (read_type (&p, objfile));
- sym->set_aclass_index (stab_register_index);
+ sym->set_loc_class_index (stab_register_index);
sym->set_value_longest (valu);
sym->set_domain (VAR_DOMAIN);
if (within_function)
@@ -3640,12 +3639,12 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
struct symbol *prev_sym;
prev_sym = local_symbols->symbol[local_symbols->nsyms - 1];
- if ((prev_sym->aclass () == LOC_REF_ARG
- || prev_sym->aclass () == LOC_ARG)
+ if ((prev_sym->loc_class () == LOC_REF_ARG
+ || prev_sym->loc_class () == LOC_ARG)
&& strcmp (prev_sym->linkage_name (),
sym->linkage_name ()) == 0)
{
- prev_sym->set_aclass_index (stab_register_index);
+ prev_sym->set_loc_class_index (stab_register_index);
/* Use the type from the LOC_REGISTER; that is the type
that is actually in that register. */
prev_sym->set_type (sym->type ());
@@ -3663,7 +3662,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
case 'S':
/* Static symbol at top level of file. */
sym->set_type (read_type (&p, objfile));
- sym->set_aclass_index (LOC_STATIC);
+ sym->set_loc_class_index (LOC_STATIC);
sym->set_value_address (valu);
sym->set_domain (VAR_DOMAIN);
add_symbol_to_list (sym, get_file_symbols ());
@@ -3694,7 +3693,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
if (nameless)
return NULL;
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_value_longest (valu);
sym->set_domain (TYPE_DOMAIN);
/* C++ vagaries: we may have a type which is derived from
@@ -3771,7 +3770,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
struct symbol *struct_sym = new (&objfile->objfile_obstack) symbol;
*struct_sym = *sym;
- struct_sym->set_aclass_index (LOC_TYPEDEF);
+ struct_sym->set_loc_class_index (LOC_TYPEDEF);
struct_sym->set_value_longest (valu);
struct_sym->set_domain (STRUCT_DOMAIN);
if (sym->type ()->name () == 0)
@@ -3798,7 +3797,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
if (nameless)
return NULL;
- sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_loc_class_index (LOC_TYPEDEF);
sym->set_value_longest (valu);
sym->set_domain (STRUCT_DOMAIN);
if (sym->type ()->name () == 0)
@@ -3813,7 +3812,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
struct symbol *typedef_sym = new (&objfile->objfile_obstack) symbol;
*typedef_sym = *sym;
- typedef_sym->set_aclass_index (LOC_TYPEDEF);
+ typedef_sym->set_loc_class_index (LOC_TYPEDEF);
typedef_sym->set_value_longest (valu);
typedef_sym->set_domain (TYPE_DOMAIN);
if (sym->type ()->name () == 0)
@@ -3827,7 +3826,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
case 'V':
/* Static symbol of local scope. */
sym->set_type (read_type (&p, objfile));
- sym->set_aclass_index (LOC_STATIC);
+ sym->set_loc_class_index (LOC_STATIC);
sym->set_value_address (valu);
sym->set_domain (VAR_DOMAIN);
add_symbol_to_list (sym, get_local_symbols ());
@@ -3836,7 +3835,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
case 'v':
/* Reference parameter */
sym->set_type (read_type (&p, objfile));
- sym->set_aclass_index (LOC_REF_ARG);
+ sym->set_loc_class_index (LOC_REF_ARG);
sym->set_is_argument (1);
sym->set_value_longest (valu);
sym->set_domain (VAR_DOMAIN);
@@ -3846,7 +3845,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
case 'a':
/* Reference parameter which is in a register. */
sym->set_type (read_type (&p, objfile));
- sym->set_aclass_index (stab_regparm_index);
+ sym->set_loc_class_index (stab_regparm_index);
sym->set_is_argument (1);
sym->set_value_longest (valu);
sym->set_domain (VAR_DOMAIN);
@@ -3859,7 +3858,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
that Pascal uses it too, but when I tried it Pascal used
"x:3" (local symbol) instead. */
sym->set_type (read_type (&p, objfile));
- sym->set_aclass_index (LOC_LOCAL);
+ sym->set_loc_class_index (LOC_LOCAL);
sym->set_value_longest (valu);
sym->set_domain (VAR_DOMAIN);
add_symbol_to_list (sym, get_local_symbols ());
@@ -3867,7 +3866,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
default:
sym->set_type (error_type (&p, objfile));
- sym->set_aclass_index (LOC_CONST);
+ sym->set_loc_class_index (LOC_CONST);
sym->set_value_longest (0);
sym->set_domain (VAR_DOMAIN);
add_symbol_to_list (sym, get_file_symbols ());
@@ -3883,12 +3882,12 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
{
/* We have to convert LOC_REGISTER to LOC_REGPARM_ADDR (for
variables passed in a register). */
- if (sym->aclass () == LOC_REGISTER)
- sym->set_aclass_index (LOC_REGPARM_ADDR);
+ if (sym->loc_class () == LOC_REGISTER)
+ sym->set_loc_class_index (LOC_REGPARM_ADDR);
/* Likewise for converting LOC_ARG to LOC_REF_ARG (for the 7th
and subsequent arguments on SPARC, for example). */
- else if (sym->aclass () == LOC_ARG)
- sym->set_aclass_index (LOC_REF_ARG);
+ else if (sym->loc_class () == LOC_ARG)
+ sym->set_loc_class_index (LOC_REF_ARG);
}
return sym;
@@ -4139,7 +4138,7 @@ again:
{
struct symbol *sym = ppt->symbol[i];
- if (sym->aclass () == LOC_TYPEDEF
+ if (sym->loc_class () == LOC_TYPEDEF
&& sym->domain () == STRUCT_DOMAIN
&& (sym->type ()->code () == code)
&& strcmp (sym->linkage_name (), type_name) == 0)
@@ -4340,7 +4339,7 @@ again:
break;
case '@':
- if (isdigit (**pp) || **pp == '(' || **pp == '-')
+ if (c_isdigit (**pp) || **pp == '(' || **pp == '-')
{ /* Member (class & variable) type */
/* FIXME -- we should be doing smash_to_XXX types here. */
@@ -4431,8 +4430,9 @@ again:
if (args == NULL)
return error_type (pp, objfile);
type = dbx_alloc_type (typenums, objfile);
- smash_to_method_type (type, domain, return_type, args,
- nargs, varargs);
+ smash_to_method_type (type, domain, return_type,
+ gdb::make_array_view (args, nargs),
+ varargs);
}
break;
@@ -6059,7 +6059,7 @@ read_enum_type (const char **pp, struct type *type,
sym->set_linkage_name (name);
sym->set_language (get_current_subfile ()->language,
&objfile->objfile_obstack);
- sym->set_aclass_index (LOC_CONST);
+ sym->set_loc_class_index (LOC_CONST);
sym->set_domain (VAR_DOMAIN);
sym->set_value_longest (n);
if (n < 0)
@@ -6726,7 +6726,7 @@ common_block_end (struct objfile *objfile)
sym = new (&objfile->objfile_obstack) symbol;
/* Note: common_block_name already saved on objfile_obstack. */
sym->set_linkage_name (common_block_name);
- sym->set_aclass_index (LOC_BLOCK);
+ sym->set_loc_class_index (LOC_BLOCK);
/* Now we copy all the symbols which have been defined since the BCOMM. */
@@ -6934,7 +6934,7 @@ cleanup_undefined_types_1 (void)
{
struct symbol *sym = ppt->symbol[i];
- if (sym->aclass () == LOC_TYPEDEF
+ if (sym->loc_class () == LOC_TYPEDEF
&& sym->domain () == STRUCT_DOMAIN
&& (sym->type ()->code () == (*type)->code ())
&& ((*type)->instance_flags ()
@@ -7044,7 +7044,7 @@ scan_file_globals (struct objfile *objfile)
the same symbol if there are multiple references. */
if (sym)
{
- if (sym->aclass () == LOC_BLOCK)
+ if (sym->loc_class () == LOC_BLOCK)
fix_common_block
(sym, msymbol->value_address (resolve_objfile),
msymbol->section_index ());
@@ -7090,8 +7090,8 @@ scan_file_globals (struct objfile *objfile)
prev->set_value_address (0);
/* Complain about unresolved common block symbols. */
- if (prev->aclass () == LOC_STATIC)
- prev->set_aclass_index (LOC_UNRESOLVED);
+ if (prev->loc_class () == LOC_STATIC)
+ prev->set_loc_class_index (LOC_UNRESOLVED);
else
complaint (_("%s: common block `%s' from "
"global_sym_chain unresolved"),
@@ -7200,9 +7200,7 @@ hashname (const char *name)
/* Initializer for this module. */
-void _initialize_stabsread ();
-void
-_initialize_stabsread ()
+INIT_GDB_FILE (stabsread)
{
undef_types_allocated = 20;
undef_types_length = 0;
diff --git a/gdb/stack.c b/gdb/stack.c
index 6542840..add1c54 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -758,7 +758,7 @@ print_frame_args (const frame_print_options &fp_opts,
break;
}
- switch (sym->aclass ())
+ switch (sym->loc_class ())
{
case LOC_ARG:
case LOC_REF_ARG:
@@ -813,7 +813,7 @@ print_frame_args (const frame_print_options &fp_opts,
nsym = lookup_symbol_search_name (sym->search_name (),
b, SEARCH_VAR_DOMAIN).symbol;
gdb_assert (nsym != NULL);
- if (nsym->aclass () == LOC_REGISTER
+ if (nsym->loc_class () == LOC_REGISTER
&& !nsym->is_argument ())
{
/* There is a LOC_ARG/LOC_REGISTER pair. This means
@@ -1165,10 +1165,10 @@ do_print_frame_info (struct ui_out *uiout, const frame_print_options &fp_opts,
if (set_current_sal)
{
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
- if (get_frame_pc_if_available (frame, &pc))
- last_displayed_symtab_info.set (sal.pspace, pc, sal.symtab, sal.line);
+ if ((pc = get_frame_pc_if_available (frame)))
+ last_displayed_symtab_info.set (sal.pspace, *pc, sal.symtab, sal.line);
else
last_displayed_symtab_info.invalidate ();
}
@@ -1325,16 +1325,15 @@ print_frame (struct ui_out *uiout,
enum language funlang = language_unknown;
struct value_print_options opts;
struct symbol *func;
- CORE_ADDR pc = 0;
- int pc_p;
+ std::optional <CORE_ADDR> pc;
- pc_p = get_frame_pc_if_available (frame, &pc);
+ pc = get_frame_pc_if_available (frame);
gdb::unique_xmalloc_ptr<char> funname
= find_frame_funname (frame, &funlang, &func);
annotate_frame_begin (print_level ? frame_relative_level (frame) : 0,
- gdbarch, pc);
+ gdbarch, pc.value_or (0));
{
ui_out_emit_tuple tuple_emitter (uiout, "frame");
@@ -1352,8 +1351,8 @@ print_frame (struct ui_out *uiout,
|| print_what == LOC_AND_ADDRESS)
{
annotate_frame_address ();
- if (pc_p)
- print_pc (uiout, gdbarch, frame, pc);
+ if (pc.has_value ())
+ print_pc (uiout, gdbarch, frame, *pc);
else
uiout->field_string ("addr", "<unavailable>",
metadata_style.style ());
@@ -1422,7 +1421,7 @@ print_frame (struct ui_out *uiout,
}
if (print_what != SHORT_LOCATION
- && pc_p && (funname == NULL || sal.symtab == NULL))
+ && pc.has_value () && (funname == NULL || sal.symtab == NULL))
{
const char *lib
= solib_name_from_address (get_frame_program_space (frame),
@@ -1481,8 +1480,7 @@ info_frame_command_core (const frame_info_ptr &fi, bool selected_frame_p)
enum language funlang = language_unknown;
const char *pc_regname;
struct gdbarch *gdbarch;
- CORE_ADDR frame_pc;
- int frame_pc_p;
+ std::optional<CORE_ADDR> frame_pc;
/* Initialize it to avoid "may be used uninitialized" warning. */
CORE_ADDR caller_pc = 0;
int caller_pc_p = 0;
@@ -1503,7 +1501,7 @@ info_frame_command_core (const frame_info_ptr &fi, bool selected_frame_p)
get_frame_pc(). */
pc_regname = "pc";
- frame_pc_p = get_frame_pc_if_available (fi, &frame_pc);
+ frame_pc = get_frame_pc_if_available (fi);
func = get_frame_function (fi);
symtab_and_line sal = find_frame_sal (fi);
s = sal.symtab;
@@ -1525,9 +1523,9 @@ info_frame_command_core (const frame_info_ptr &fi, bool selected_frame_p)
funname = func_only.get ();
}
}
- else if (frame_pc_p)
+ else if (frame_pc.has_value ())
{
- bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (frame_pc);
+ bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (*frame_pc);
if (msymbol.minsym != NULL)
{
funname = msymbol.minsym->print_name ();
@@ -1548,7 +1546,7 @@ info_frame_command_core (const frame_info_ptr &fi, bool selected_frame_p)
gdb_puts (paddress (gdbarch, get_frame_base (fi)));
gdb_printf (":\n");
gdb_printf (" %s = ", pc_regname);
- if (frame_pc_p)
+ if (frame_pc.has_value ())
gdb_puts (paddress (gdbarch, get_frame_pc (fi)));
else
fputs_styled ("<unavailable>", metadata_style.style (), gdb_stdout);
@@ -2218,7 +2216,7 @@ iterate_over_block_locals (const struct block *b,
{
for (struct symbol *sym : block_iterator_range (b))
{
- switch (sym->aclass ())
+ switch (sym->loc_class ())
{
case LOC_CONST:
case LOC_CONST_BYTES:
@@ -2337,9 +2335,9 @@ print_frame_local_vars (const frame_info_ptr &frame,
{
struct print_variable_and_value_data cb_data;
const struct block *block;
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
- if (!get_frame_pc_if_available (frame, &pc))
+ if (!(pc = get_frame_pc_if_available (frame)))
{
if (!quiet)
gdb_printf (stream,
@@ -2499,11 +2497,11 @@ print_frame_arg_vars (const frame_info_ptr &frame,
{
struct print_variable_and_value_data cb_data;
struct symbol *func;
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
std::optional<compiled_regex> preg;
std::optional<compiled_regex> treg;
- if (!get_frame_pc_if_available (frame, &pc))
+ if (!(pc = get_frame_pc_if_available (frame)))
{
if (!quiet)
gdb_printf (stream,
@@ -3066,7 +3064,7 @@ frame_apply_level_cmd_completer (struct cmd_list_element *ignore,
/* Check if we're past a valid LEVEL already. */
if (levels.finished ()
- && cmd > text && !isspace (cmd[-1]))
+ && cmd > text && !c_isspace (cmd[-1]))
return;
/* We're past LEVELs, advance word point. */
@@ -3100,7 +3098,7 @@ frame_apply_cmd_completer (struct cmd_list_element *ignore,
return;
/* Check if we're past a valid COUNT already. */
- if (cmd > text && !isspace (cmd[-1]))
+ if (cmd > text && !c_isspace (cmd[-1]))
return;
/* We're past COUNT, advance word point. */
@@ -3262,9 +3260,7 @@ static struct cmd_list_element *select_frame_cmd_list = NULL;
/* Commands with a prefix of `info frame'. */
static struct cmd_list_element *info_frame_cmd_list = NULL;
-void _initialize_stack ();
-void
-_initialize_stack ()
+INIT_GDB_FILE (stack)
{
struct cmd_list_element *cmd;
diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
index 8cc7599..6c15bce 100644
--- a/gdb/stap-probe.c
+++ b/gdb/stap-probe.c
@@ -39,7 +39,6 @@
#include "expop.h"
#include "gdbsupport/unordered_map.h"
-#include <ctype.h>
/* The name of the SystemTap section where we will find information about
the probes. */
@@ -575,14 +574,14 @@ stap_is_integer_prefix (struct gdbarch *gdbarch, const char *s,
if (r != NULL)
*r = "";
- return isdigit (*s) > 0;
+ return c_isdigit (*s) > 0;
}
for (p = t; *p != NULL; ++p)
{
size_t len = strlen (*p);
- if ((len == 0 && isdigit (*s))
+ if ((len == 0 && c_isdigit (*s))
|| (len > 0 && strncasecmp (s, *p, len) == 0))
{
/* Integers may or may not have a prefix. The "len == 0"
@@ -732,7 +731,7 @@ stap_parse_register_operand (struct stap_parse_info *p)
struct type *long_type = builtin_type (gdbarch)->builtin_long;
operation_up disp_op;
- if (isdigit (*p->arg))
+ if (c_isdigit (*p->arg))
{
/* The value of the displacement. */
long displacement;
@@ -767,14 +766,14 @@ stap_parse_register_operand (struct stap_parse_info *p)
start = p->arg;
/* We assume the register name is composed by letters and numbers. */
- while (isalnum (*p->arg))
+ while (c_isalnum (*p->arg))
++p->arg;
std::string regname (start, p->arg - start);
/* We only add the GDB's register prefix/suffix if we are dealing with
a numeric register. */
- if (isdigit (*start))
+ if (c_isdigit (*start))
{
if (gdb_reg_prefix != NULL)
regname = gdb_reg_prefix + regname;
@@ -921,7 +920,7 @@ stap_parse_single_operand (struct stap_parse_info *p)
if (p->inside_paren_p)
tmp = skip_spaces (tmp);
- while (isdigit (*tmp))
+ while (c_isdigit (*tmp))
{
/* We skip the digit here because we are only interested in
knowing what kind of unary operation this is. The digit
@@ -959,7 +958,7 @@ stap_parse_single_operand (struct stap_parse_info *p)
(std::move (result)));
}
}
- else if (isdigit (*p->arg))
+ else if (c_isdigit (*p->arg))
{
/* A temporary variable, needed for lookahead. */
const char *tmp = p->arg;
@@ -1042,7 +1041,7 @@ stap_parse_argument_conditionally (struct stap_parse_info *p)
expr::operation_up result;
if (*p->arg == '-' || *p->arg == '~' || *p->arg == '+' || *p->arg == '!'
- || isdigit (*p->arg)
+ || c_isdigit (*p->arg)
|| gdbarch_stap_is_single_operand (p->gdbarch, p->arg))
result = stap_parse_single_operand (p);
else if (*p->arg == '(')
@@ -1111,7 +1110,7 @@ stap_parse_argument_1 (struct stap_parse_info *p,
This loop shall continue until we run out of characters in the input,
or until we find a close-parenthesis, which means that we've reached
the end of a sub-expression. */
- while (*p->arg != '\0' && *p->arg != ')' && !isspace (*p->arg))
+ while (*p->arg != '\0' && *p->arg != ')' && !c_isspace (*p->arg))
{
const char *tmp_exp_buf;
enum exp_opcode opcode;
@@ -1270,8 +1269,8 @@ stap_probe::parse_arguments (struct gdbarch *gdbarch)
Where `N' can be [+,-][1,2,4,8]. This is not mandatory, so
we check it here. If we don't find it, go to the next
state. */
- if ((cur[0] == '-' && isdigit (cur[1]) && cur[2] == '@')
- || (isdigit (cur[0]) && cur[1] == '@'))
+ if ((cur[0] == '-' && c_isdigit (cur[1]) && cur[2] == '@')
+ || (c_isdigit (cur[0]) && cur[1] == '@'))
{
if (*cur == '-')
{
@@ -1748,9 +1747,7 @@ info_probes_stap_command (const char *arg, int from_tty)
info_probes_for_spops (arg, from_tty, &stap_static_probe_ops);
}
-void _initialize_stap_probe ();
-void
-_initialize_stap_probe ()
+INIT_GDB_FILE (stap_probe)
{
all_static_probe_ops.push_back (&stap_static_probe_ops);
diff --git a/gdb/std-regs.c b/gdb/std-regs.c
index 2a3f93d..9940cb0 100644
--- a/gdb/std-regs.c
+++ b/gdb/std-regs.c
@@ -93,9 +93,7 @@ value_of_builtin_frame_ps_reg (const frame_info_ptr &frame, const void *baton)
error (_("Standard register ``$ps'' is not available for this target"));
}
-void _initialize_frame_reg ();
-void
-_initialize_frame_reg ()
+INIT_GDB_FILE (frame_reg)
{
/* Frame based $fp, $pc, $sp and $ps. These only come into play
when the target does not define its own version of these
diff --git a/gdb/svr4-tls-tdep.c b/gdb/svr4-tls-tdep.c
index 56e1470..1f36d57 100644
--- a/gdb/svr4-tls-tdep.c
+++ b/gdb/svr4-tls-tdep.c
@@ -1,6 +1,6 @@
/* Target-dependent code for GNU/Linux, architecture independent.
- Copyright (C) 2009-2024 Free Software Foundation, Inc.
+ Copyright (C) 2009-2025 Free Software Foundation, Inc.
This file is part of GDB.
@@ -233,9 +233,7 @@ svr4_tls_register_tls_methods (struct gdbarch_info info, struct gdbarch *gdbarch
gdbarch_data->get_tls_dtp_offset = get_tls_dtp_offset;
}
-void _initialize_svr4_tls_tdep ();
-void
-_initialize_svr4_tls_tdep ()
+INIT_GDB_FILE (svr4_tls_tdep)
{
add_setshow_boolean_cmd ("force-internal-tls-address-lookup", class_obscure,
&force_internal_tls_address_lookup, _("\
diff --git a/gdb/symfile-debug.c b/gdb/symfile-debug.c
index 9c5ce85..705d8f7 100644
--- a/gdb/symfile-debug.c
+++ b/gdb/symfile-debug.c
@@ -193,7 +193,7 @@ objfile::map_symtabs_matching_filename
{
/* The callback to iterate_over_some_symtabs returns false to keep
going and true to continue, so we have to invert the result
- here, for expand_symtabs_matching. */
+ here, for search. */
bool result = !iterate_over_some_symtabs (name, real_path,
this->compunit_symtabs,
last_made,
@@ -204,14 +204,10 @@ objfile::map_symtabs_matching_filename
for (const auto &iter : qf)
{
- if (!iter->expand_symtabs_matching (this,
- match_one_filename,
- nullptr,
- nullptr,
- on_expansion,
- (SEARCH_GLOBAL_BLOCK
- | SEARCH_STATIC_BLOCK),
- SEARCH_ALL_DOMAINS))
+ if (!iter->search (this, match_one_filename, nullptr, nullptr,
+ on_expansion,
+ SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
+ SEARCH_ALL_DOMAINS))
{
retval = false;
break;
@@ -267,15 +263,11 @@ objfile::lookup_symbol (block_enum kind, const lookup_name_info &name,
for (const auto &iter : qf)
{
- if (!iter->expand_symtabs_matching (this,
- nullptr,
- &name,
- nullptr,
- search_one_symtab,
- kind == GLOBAL_BLOCK
- ? SEARCH_GLOBAL_BLOCK
- : SEARCH_STATIC_BLOCK,
- domain))
+ if (!iter->search (this, nullptr, &name, nullptr, search_one_symtab,
+ kind == GLOBAL_BLOCK
+ ? SEARCH_GLOBAL_BLOCK
+ : SEARCH_STATIC_BLOCK,
+ domain))
break;
}
@@ -311,28 +303,6 @@ objfile::dump ()
}
void
-objfile::expand_symtabs_for_function (const char *func_name)
-{
- if (debug_symfile)
- gdb_printf (gdb_stdlog,
- "qf->expand_symtabs_for_function (%s, \"%s\")\n",
- objfile_debug_name (this), func_name);
-
- lookup_name_info base_lookup (func_name, symbol_name_match_type::FULL);
- lookup_name_info lookup_name = base_lookup.make_ignore_params ();
-
- for (const auto &iter : qf)
- iter->expand_symtabs_matching (this,
- nullptr,
- &lookup_name,
- nullptr,
- nullptr,
- (SEARCH_GLOBAL_BLOCK
- | SEARCH_STATIC_BLOCK),
- SEARCH_FUNCTION_DOMAIN);
-}
-
-void
objfile::expand_all_symtabs ()
{
if (debug_symfile)
@@ -358,43 +328,35 @@ objfile::expand_symtabs_with_fullname (const char *fullname)
};
for (const auto &iter : qf)
- iter->expand_symtabs_matching (this,
- file_matcher,
- nullptr,
- nullptr,
- nullptr,
- (SEARCH_GLOBAL_BLOCK
- | SEARCH_STATIC_BLOCK),
- SEARCH_ALL_DOMAINS);
+ iter->search (this, file_matcher, nullptr, nullptr, nullptr,
+ SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
+ SEARCH_ALL_DOMAINS);
}
bool
-objfile::expand_symtabs_matching
- (expand_symtabs_file_matcher file_matcher,
- const lookup_name_info *lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
- block_search_flags search_flags,
- domain_search_flags domain,
- expand_symtabs_lang_matcher lang_matcher)
-{
- /* This invariant is documented in quick-functions.h. */
+objfile::search (search_symtabs_file_matcher file_matcher,
+ const lookup_name_info *lookup_name,
+ search_symtabs_symbol_matcher symbol_matcher,
+ search_symtabs_expansion_listener listener,
+ block_search_flags search_flags,
+ domain_search_flags domain,
+ search_symtabs_lang_matcher lang_matcher)
+{
+ /* This invariant is documented in quick-symbol.h. */
gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
if (debug_symfile)
gdb_printf (gdb_stdlog,
- "qf->expand_symtabs_matching (%s, %s, %s, %s, %s)\n",
+ "qf->search (%s, %s, %s, %s, %s)\n",
objfile_debug_name (this),
host_address_to_string (&file_matcher),
host_address_to_string (&symbol_matcher),
- host_address_to_string (&expansion_notify),
+ host_address_to_string (&listener),
domain_name (domain).c_str ());
for (const auto &iter : qf)
- if (!iter->expand_symtabs_matching (this, file_matcher, lookup_name,
- symbol_matcher, expansion_notify,
- search_flags, domain,
- lang_matcher))
+ if (!iter->search (this, file_matcher, lookup_name, symbol_matcher,
+ listener, search_flags, domain, lang_matcher))
return false;
return true;
}
@@ -895,9 +857,7 @@ show_debug_symfile (struct ui_file *file, int from_tty,
gdb_printf (file, _("Symfile debugging is %s.\n"), value);
}
-void _initialize_symfile_debug ();
-void
-_initialize_symfile_debug ()
+INIT_GDB_FILE (symfile_debug)
{
add_setshow_boolean_cmd ("symfile", no_class, &debug_symfile, _("\
Set debugging of the symfile functions."), _("\
diff --git a/gdb/symfile-mem.c b/gdb/symfile-mem.c
index 92672d7..274dc0f 100644
--- a/gdb/symfile-mem.c
+++ b/gdb/symfile-mem.c
@@ -204,9 +204,7 @@ add_vsyscall_page (inferior *inf)
}
}
-void _initialize_symfile_mem ();
-void
-_initialize_symfile_mem ()
+INIT_GDB_FILE (symfile_mem)
{
add_cmd ("add-symbol-file-from-memory", class_files,
add_symbol_file_from_memory_command,
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 9a6322d..98cb637 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -58,7 +58,6 @@
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
-#include <ctype.h>
#include <chrono>
#include <algorithm>
@@ -835,9 +834,9 @@ init_entry_point_info (struct objfile *objfile)
= gdbarch_addr_bits_remove (objfile->arch (), entry_point);
found = 0;
- for (obj_section *osect : objfile->sections ())
+ for (obj_section &osect : objfile->sections ())
{
- struct bfd_section *sect = osect->the_bfd_section;
+ struct bfd_section *sect = osect.the_bfd_section;
if (entry_point >= bfd_section_vma (sect)
&& entry_point < (bfd_section_vma (sect)
@@ -1101,7 +1100,7 @@ symbol_file_add_with_addrs (const gdb_bfd_ref_ptr &abfd, const char *name,
no separate debug file. If there is a separate debug file which
does not have symbols, we'll have emitted this message for that
file, and so printing it twice is just redundant. */
- if (should_print && !objfile_has_symbols (objfile)
+ if (should_print && !objfile->has_symbols ()
&& objfile->separate_debug_objfile == nullptr)
gdb_printf (_("(No debugging symbols found in %ps)\n"),
styled_string (file_name_style.style (), name));
@@ -2323,7 +2322,7 @@ add_symbol_file_command (const char *args, int from_tty)
objf = symbol_file_add (filename.get (), add_flags, &section_addrs,
flags);
- if (!objfile_has_symbols (objf) && objf->per_bfd->minimal_symbol_count <= 0)
+ if (!objf->has_symbols () && objf->per_bfd->minimal_symbol_count <= 0)
warning (_("newly-added symbol file \"%ps\" does not provide any symbols"),
styled_string (file_name_style.style (), filename.get ()));
@@ -2662,7 +2661,7 @@ reread_symbols (int from_tty)
objfile->expand_all_symtabs ();
}
- if (!objfile_has_symbols (objfile))
+ if (!objfile->has_symbols ())
{
gdb_stdout->wrap_here (0);
gdb_printf (_("(no debugging symbols found)\n"));
@@ -2748,7 +2747,7 @@ set_ext_lang_command (const char *args,
error (_("'%s': Filename extension must begin with '.'"), ext_args.c_str ());
/* Find end of first arg. */
- while (*end != '\0' && !isspace (*end))
+ while (*end != '\0' && !c_isspace (*end))
end++;
if (*end == '\0')
@@ -3007,9 +3006,9 @@ static void
overlay_invalidate_all (program_space *pspace)
{
for (objfile *objfile : pspace->objfiles ())
- for (obj_section *sect : objfile->sections ())
- if (section_is_overlay (sect))
- sect->ovly_mapped = -1;
+ for (obj_section &sect : objfile->sections ())
+ if (section_is_overlay (&sect))
+ sect.ovly_mapped = -1;
}
/* Function: section_is_mapped (SECTION)
@@ -3183,18 +3182,18 @@ find_pc_overlay (CORE_ADDR pc)
if (overlay_debugging)
{
for (objfile *objfile : current_program_space->objfiles ())
- for (obj_section *osect : objfile->sections ())
- if (section_is_overlay (osect))
+ for (obj_section &osect : objfile->sections ())
+ if (section_is_overlay (&osect))
{
- if (pc_in_mapped_range (pc, osect))
+ if (pc_in_mapped_range (pc, &osect))
{
- if (section_is_mapped (osect))
- return osect;
+ if (section_is_mapped (&osect))
+ return &osect;
else
- best_match = osect;
+ best_match = &osect;
}
- else if (pc_in_unmapped_range (pc, osect))
- best_match = osect;
+ else if (pc_in_unmapped_range (pc, &osect))
+ best_match = &osect;
}
}
return best_match;
@@ -3210,9 +3209,9 @@ find_pc_mapped_section (CORE_ADDR pc)
if (overlay_debugging)
{
for (objfile *objfile : current_program_space->objfiles ())
- for (obj_section *osect : objfile->sections ())
- if (pc_in_mapped_range (pc, osect) && section_is_mapped (osect))
- return osect;
+ for (obj_section &osect : objfile->sections ())
+ if (pc_in_mapped_range (pc, &osect) && section_is_mapped (&osect))
+ return &osect;
}
return NULL;
@@ -3229,18 +3228,18 @@ list_overlays_command (const char *args, int from_tty)
if (overlay_debugging)
{
for (objfile *objfile : current_program_space->objfiles ())
- for (obj_section *osect : objfile->sections ())
- if (section_is_mapped (osect))
+ for (obj_section &osect : objfile->sections ())
+ if (section_is_mapped (&osect))
{
struct gdbarch *gdbarch = objfile->arch ();
const char *name;
bfd_vma lma, vma;
int size;
- vma = bfd_section_vma (osect->the_bfd_section);
- lma = bfd_section_lma (osect->the_bfd_section);
- size = bfd_section_size (osect->the_bfd_section);
- name = bfd_section_name (osect->the_bfd_section);
+ vma = bfd_section_vma (osect.the_bfd_section);
+ lma = bfd_section_lma (osect.the_bfd_section);
+ size = bfd_section_size (osect.the_bfd_section);
+ name = bfd_section_name (osect.the_bfd_section);
gdb_printf ("Section %s, loaded at ", name);
gdb_puts (paddress (gdbarch, lma));
@@ -3275,27 +3274,27 @@ map_overlay_command (const char *args, int from_tty)
/* First, find a section matching the user supplied argument. */
for (objfile *obj_file : current_program_space->objfiles ())
- for (obj_section *sec : obj_file->sections ())
- if (!strcmp (bfd_section_name (sec->the_bfd_section), args))
+ for (obj_section &sec : obj_file->sections ())
+ if (!strcmp (bfd_section_name (sec.the_bfd_section), args))
{
/* Now, check to see if the section is an overlay. */
- if (!section_is_overlay (sec))
+ if (!section_is_overlay (&sec))
continue; /* not an overlay section */
/* Mark the overlay as "mapped". */
- sec->ovly_mapped = 1;
+ sec.ovly_mapped = 1;
/* Next, make a pass and unmap any sections that are
overlapped by this new section: */
for (objfile *objfile2 : current_program_space->objfiles ())
- for (obj_section *sec2 : objfile2->sections ())
- if (sec2->ovly_mapped && sec != sec2 && sections_overlap (sec,
- sec2))
+ for (obj_section &sec2 : objfile2->sections ())
+ if (sec2.ovly_mapped && &sec != &sec2 && sections_overlap (&sec,
+ &sec2))
{
if (info_verbose)
gdb_printf (_("Note: section %s unmapped by overlap\n"),
- bfd_section_name (sec2->the_bfd_section));
- sec2->ovly_mapped = 0; /* sec2 overlaps sec: unmap sec2. */
+ bfd_section_name (sec2.the_bfd_section));
+ sec2.ovly_mapped = 0; /* sec2 overlaps sec: unmap sec2. */
}
return;
}
@@ -3319,12 +3318,12 @@ unmap_overlay_command (const char *args, int from_tty)
/* First, find a section matching the user supplied argument. */
for (objfile *objfile : current_program_space->objfiles ())
- for (obj_section *sec : objfile->sections ())
- if (!strcmp (bfd_section_name (sec->the_bfd_section), args))
+ for (obj_section &sec : objfile->sections ())
+ if (!strcmp (bfd_section_name (sec.the_bfd_section), args))
{
- if (!sec->ovly_mapped)
+ if (!sec.ovly_mapped)
error (_("Section %s is not mapped"), args);
- sec->ovly_mapped = 0;
+ sec.ovly_mapped = 0;
return;
}
error (_("No overlay section called %s"), args);
@@ -3578,17 +3577,17 @@ simple_overlay_update (struct obj_section *osect)
/* Now may as well update all sections, even if only one was requested. */
for (objfile *objfile : current_program_space->objfiles ())
- for (obj_section *sect : objfile->sections ())
- if (section_is_overlay (sect))
+ for (obj_section &sect : objfile->sections ())
+ if (section_is_overlay (&sect))
{
int i;
- asection *bsect = sect->the_bfd_section;
+ asection *bsect = sect.the_bfd_section;
for (i = 0; i < cache_novlys; i++)
if (cache_ovly_table[i][VMA] == bfd_section_vma (bsect)
&& cache_ovly_table[i][LMA] == bfd_section_lma (bsect))
{ /* obj_section matches i'th entry in ovly_table. */
- sect->ovly_mapped = cache_ovly_table[i][MAPPED];
+ sect.ovly_mapped = cache_ovly_table[i][MAPPED];
break; /* finished with inner for loop: break out. */
}
}
@@ -3756,31 +3755,6 @@ symfile_free_objfile (struct objfile *objfile)
objfile->pspace ()->remove_target_sections (objfile);
}
-/* Wrapper around the quick_symbol_functions expand_symtabs_matching "method".
- Expand all symtabs that match the specified criteria.
- See quick_symbol_functions.expand_symtabs_matching for details. */
-
-bool
-expand_symtabs_matching (expand_symtabs_file_matcher file_matcher,
- const lookup_name_info &lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
- block_search_flags search_flags,
- domain_search_flags domain,
- expand_symtabs_lang_matcher lang_matcher)
-{
- for (objfile *objfile : current_program_space->objfiles ())
- if (!objfile->expand_symtabs_matching (file_matcher,
- &lookup_name,
- symbol_matcher,
- expansion_notify,
- search_flags,
- domain,
- lang_matcher))
- return false;
- return true;
-}
-
/* Wrapper around the quick_symbol_functions map_symbol_filenames "method".
Map function FUN over every file.
See quick_symbol_functions.map_symbol_filenames for details. */
@@ -3849,9 +3823,7 @@ test_set_ext_lang_command ()
#endif /* GDB_SELF_TEST */
-void _initialize_symfile ();
-void
-_initialize_symfile ()
+INIT_GDB_FILE (symfile)
{
struct cmd_list_element *c;
diff --git a/gdb/symfile.h b/gdb/symfile.h
index ee9bc11..06509a6 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -345,15 +345,6 @@ symfile_segment_data_up get_symfile_segment_data (bfd *abfd);
extern scoped_restore_tmpl<int> increment_reading_symtab (void);
-bool expand_symtabs_matching
- (expand_symtabs_file_matcher file_matcher,
- const lookup_name_info &lookup_name,
- expand_symtabs_symbol_matcher symbol_matcher,
- expand_symtabs_expansion_listener expansion_notify,
- block_search_flags search_flags,
- domain_search_flags kind,
- expand_symtabs_lang_matcher lang_matcher = nullptr);
-
void map_symbol_filenames (symbol_filename_listener fun, bool need_fullname);
/* Target-agnostic function to load the sections of an executable into memory.
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
index 8a95958..e43fafa 100644
--- a/gdb/symmisc.c
+++ b/gdb/symmisc.c
@@ -537,7 +537,7 @@ print_symbol (struct gdbarch *gdbarch, struct symbol *symbol,
}
else
{
- if (symbol->aclass () == LOC_TYPEDEF)
+ if (symbol->loc_class () == LOC_TYPEDEF)
gdb_printf (outfile, "typedef ");
if (symbol->type ())
{
@@ -552,7 +552,7 @@ print_symbol (struct gdbarch *gdbarch, struct symbol *symbol,
else
gdb_printf (outfile, "%s ", symbol->print_name ());
- switch (symbol->aclass ())
+ switch (symbol->loc_class ())
{
case LOC_CONST:
gdb_printf (outfile, "const %s (%s)",
@@ -646,7 +646,7 @@ print_symbol (struct gdbarch *gdbarch, struct symbol *symbol,
default:
gdb_printf (outfile, "botched symbol class %x",
- symbol->aclass ());
+ symbol->loc_class ());
break;
}
}
@@ -918,7 +918,7 @@ maintenance_expand_symtabs (const char *args, int from_tty)
for (struct program_space *pspace : program_spaces)
for (objfile *objfile : pspace->objfiles ())
- objfile->expand_symtabs_matching
+ objfile->search
([&] (const char *filename, bool basenames)
{
/* KISS: Only apply the regexp to the complete file name. */
@@ -1051,9 +1051,7 @@ maintenance_info_line_tables (const char *regexp, int from_tty)
/* Do early runtime initializations. */
-void _initialize_symmisc ();
-void
-_initialize_symmisc ()
+INIT_GDB_FILE (symmisc)
{
add_cmd ("symbols", class_maintenance, maintenance_print_symbols, _("\
Print dump of current symbol definitions.\n\
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 5147aee..896b81d 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -56,11 +56,9 @@
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
-#include <ctype.h>
#include "cp-abi.h"
#include "cp-support.h"
#include "observable.h"
-#include "solist.h"
#include "macrotab.h"
#include "macroscope.h"
@@ -124,41 +122,6 @@ struct main_info
static const registry<program_space>::key<main_info> main_progspace_key;
-/* Symbol lookup is not reentrant (though this is not an intrinsic
- restriction). Keep track of whether a symbol lookup is active, to be able
- to detect reentrancy. */
-static bool in_symbol_lookup;
-
-/* Struct to mark that a symbol lookup is active for the duration of its
- lifetime. */
-
-struct enter_symbol_lookup
-{
- enter_symbol_lookup ()
- {
- /* Ensure that the current language has been set. Normally the
- language is set lazily. However, when performing a symbol lookup,
- this could result in a recursive call into the lookup code in some
- cases. Set it now to ensure that this does not happen. */
- get_current_language ();
-
- /* Detect symbol lookup reentrance. */
- gdb_assert (!in_symbol_lookup);
-
- in_symbol_lookup = true;
- }
-
- ~enter_symbol_lookup ()
- {
- /* Sanity check. */
- gdb_assert (in_symbol_lookup);
-
- in_symbol_lookup = false;
- }
-
- DISABLE_COPY_AND_ASSIGN (enter_symbol_lookup);
-};
-
/* The default symbol cache size.
There is no extra cpu cost for large N (except when flushing the cache,
which is rare). The value here is just a first attempt. A better default
@@ -1781,7 +1744,7 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
index without doing the check that is done by the wrapper macros
like SECT_OFF_TEXT. */
int fallback;
- switch (sym->aclass ())
+ switch (sym->loc_class ())
{
case LOC_STATIC:
fallback = objfile->sect_index_data;
@@ -1847,18 +1810,18 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
this reason, we still attempt a lookup by name prior to doing
a search of the section table. */
- for (obj_section *s : objfile->sections ())
+ for (obj_section &s : objfile->sections ())
{
- if ((bfd_section_flags (s->the_bfd_section) & SEC_ALLOC) == 0)
+ if ((bfd_section_flags (s.the_bfd_section) & SEC_ALLOC) == 0)
continue;
- int idx = s - objfile->sections_start;
+ int idx = &s - objfile->sections_start;
CORE_ADDR offset = objfile->section_offsets[idx];
if (fallback == -1)
fallback = idx;
- if (s->addr () - offset <= addr && addr < s->endaddr () - offset)
+ if (s.addr () - offset <= addr && addr < s.endaddr () - offset)
{
sym->set_section_index (idx);
return;
@@ -2163,13 +2126,6 @@ lookup_symbol_aux (const char *name, symbol_name_match_type match_type,
domain_name (domain).c_str (), language_str (language));
}
- /* Make sure we do something sensible with is_a_field_of_this, since
- the callers that set this parameter to some non-null value will
- certainly use it later. If we don't set it, the contents of
- is_a_field_of_this are undefined. */
- if (is_a_field_of_this != NULL)
- memset (is_a_field_of_this, 0, sizeof (*is_a_field_of_this));
-
langdef = language_def (language);
/* Search specified block and its superiors. Don't search
@@ -2294,8 +2250,6 @@ lookup_symbol_in_block (const char *name, symbol_name_match_type match_type,
const struct block *block,
const domain_search_flags domain)
{
- enter_symbol_lookup tmp;
-
struct symbol *sym;
if (symbol_lookup_debug)
@@ -2331,8 +2285,6 @@ lookup_global_symbol_from_objfile (struct objfile *main_objfile,
const char *name,
const domain_search_flags domain)
{
- enter_symbol_lookup tmp;
-
gdb_assert (block_index == GLOBAL_BLOCK || block_index == STATIC_BLOCK);
for (objfile *objfile : main_objfile->separate_debug_objfiles ())
@@ -2365,44 +2317,26 @@ lookup_symbol_in_objfile_symtabs (struct objfile *objfile,
block_index == GLOBAL_BLOCK ? "GLOBAL_BLOCK" : "STATIC_BLOCK",
name, domain_name (domain).c_str ());
- struct block_symbol other;
- other.symbol = NULL;
+ lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
+ best_symbol_tracker accum;
for (compunit_symtab *cust : objfile->compunits ())
{
const struct blockvector *bv;
const struct block *block;
- struct block_symbol result;
bv = cust->blockvector ();
block = bv->block (block_index);
- result.symbol = block_lookup_symbol_primary (block, name, domain);
- result.block = block;
- if (result.symbol == NULL)
- continue;
- if (best_symbol (result.symbol, domain))
- {
- other = result;
- break;
- }
- if (result.symbol->matches (domain))
- {
- struct symbol *better
- = better_symbol (other.symbol, result.symbol, domain);
- if (better != other.symbol)
- {
- other.symbol = better;
- other.block = block;
- }
- }
+ if (accum.search (cust, block, lookup_name, domain))
+ break;
}
- if (other.symbol != NULL)
+ if (accum.currently_best.symbol != nullptr)
{
symbol_lookup_debug_printf_v
("lookup_symbol_in_objfile_symtabs (...) = %s (block %s)",
- host_address_to_string (other.symbol),
- host_address_to_string (other.block));
- return other;
+ host_address_to_string (accum.currently_best.symbol),
+ host_address_to_string (accum.currently_best.block));
+ return accum.currently_best;
}
symbol_lookup_debug_printf_v
@@ -2476,11 +2410,6 @@ lookup_symbol_via_quick_fns (struct objfile *objfile,
enum block_enum block_index, const char *name,
const domain_search_flags domain)
{
- struct compunit_symtab *cust;
- const struct blockvector *bv;
- const struct block *block;
- struct block_symbol result;
-
symbol_lookup_debug_printf_v
("lookup_symbol_via_quick_fns (%s, %s, %s, %s)",
objfile_debug_name (objfile),
@@ -2488,27 +2417,36 @@ lookup_symbol_via_quick_fns (struct objfile *objfile,
name, domain_name (domain).c_str ());
lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
- cust = objfile->lookup_symbol (block_index, lookup_name, domain);
- if (cust == NULL)
+ best_symbol_tracker accum;
+ auto searcher = [&] (compunit_symtab *symtab)
+ {
+ const struct blockvector *bv = symtab->blockvector ();
+ const struct block *block = bv->block (block_index);
+ /* If the accumulator finds a best symbol, end the search by
+ returning false; otherwise keep going by returning true. */
+ return !accum.search (symtab, block, lookup_name, domain);
+ };
+
+ objfile->search (nullptr, &lookup_name, nullptr, searcher,
+ block_index == GLOBAL_BLOCK
+ ? SEARCH_GLOBAL_BLOCK
+ : SEARCH_STATIC_BLOCK,
+ domain);
+ if (accum.best_symtab == nullptr)
{
symbol_lookup_debug_printf_v
("lookup_symbol_via_quick_fns (...) = NULL");
return {};
}
-
- bv = cust->blockvector ();
- block = bv->block (block_index);
- result.symbol = block_lookup_symbol (block, lookup_name, domain);
- if (result.symbol == NULL)
- error_in_psymtab_expansion (block_index, name, cust);
+ if (accum.currently_best.symbol == nullptr)
+ error_in_psymtab_expansion (block_index, name, accum.best_symtab);
symbol_lookup_debug_printf_v
("lookup_symbol_via_quick_fns (...) = %s (block %s)",
- host_address_to_string (result.symbol),
- host_address_to_string (block));
+ host_address_to_string (accum.currently_best.symbol),
+ host_address_to_string (accum.currently_best.block));
- result.block = block;
- return result;
+ return accum.currently_best;
}
/* See language.h. */
@@ -2608,24 +2546,12 @@ lookup_symbol_in_objfile (struct objfile *objfile, enum block_enum block_index,
? "GLOBAL_BLOCK" : "STATIC_BLOCK",
name, domain_name (domain).c_str ());
- result = lookup_symbol_in_objfile_symtabs (objfile, block_index,
- name, domain);
- if (result.symbol != NULL)
- {
- symbol_lookup_debug_printf
- ("lookup_symbol_in_objfile (...) = %s (in symtabs)",
- host_address_to_string (result.symbol));
- return result;
- }
-
result = lookup_symbol_via_quick_fns (objfile, block_index,
name, domain);
- symbol_lookup_debug_printf ("lookup_symbol_in_objfile (...) = %s%s",
+ symbol_lookup_debug_printf ("lookup_symbol_in_objfile (...) = %s",
result.symbol != NULL
? host_address_to_string (result.symbol)
- : "NULL",
- result.symbol != NULL ? " (via quick fns)"
- : "");
+ : "NULL");
return result;
}
@@ -2658,13 +2584,10 @@ lookup_global_or_static_symbol (const char *name,
return result;
}
- enter_symbol_lookup tmp;
-
/* Do a global search (of global blocks, heh). */
if (result.symbol == NULL)
- gdbarch_iterate_over_objfiles_in_search_order
- (objfile != NULL ? objfile->arch () : current_inferior ()->arch (),
- [&result, block_index, name, domain] (struct objfile *objfile_iter)
+ current_program_space->iterate_over_objfiles_in_search_order
+ ([&result, block_index, name, domain] (struct objfile *objfile_iter)
{
result = lookup_symbol_in_objfile (objfile_iter, block_index,
name, domain);
@@ -2776,35 +2699,6 @@ basic_lookup_transparent_type_quick (struct objfile *objfile,
return sym->type ();
}
-/* Subroutine of basic_lookup_transparent_type to simplify it.
- Look up the non-opaque definition of NAME in BLOCK_INDEX of OBJFILE.
- BLOCK_INDEX is either GLOBAL_BLOCK or STATIC_BLOCK. */
-
-static struct type *
-basic_lookup_transparent_type_1 (struct objfile *objfile,
- enum block_enum block_index,
- domain_search_flags flags,
- const lookup_name_info &name)
-{
- const struct blockvector *bv;
- const struct block *block;
- const struct symbol *sym;
-
- for (compunit_symtab *cust : objfile->compunits ())
- {
- bv = cust->blockvector ();
- block = bv->block (block_index);
- sym = block_find_symbol (block, name, flags, nullptr);
- if (sym != nullptr)
- {
- gdb_assert (!TYPE_IS_OPAQUE (sym->type ()));
- return sym->type ();
- }
- }
-
- return NULL;
-}
-
/* The standard implementation of lookup_transparent_type. This code
was modeled on lookup_symbol -- the parts not relevant to looking
up types were just left out. In particular it's assumed here that
@@ -2818,19 +2712,7 @@ basic_lookup_transparent_type (const char *name, domain_search_flags flags)
lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
- /* Now search all the global symbols. Do the symtab's first, then
- check the psymtab's. If a psymtab indicates the existence
- of the desired name as a global, then do psymtab-to-symtab
- conversion on the fly and return the found symbol. */
-
- for (objfile *objfile : current_program_space->objfiles ())
- {
- t = basic_lookup_transparent_type_1 (objfile, GLOBAL_BLOCK,
- flags, lookup_name);
- if (t)
- return t;
- }
-
+ /* Search all the global symbols. */
for (objfile *objfile : current_program_space->objfiles ())
{
t = basic_lookup_transparent_type_quick (objfile, GLOBAL_BLOCK,
@@ -2839,21 +2721,8 @@ basic_lookup_transparent_type (const char *name, domain_search_flags flags)
return t;
}
- /* Now search the static file-level symbols.
- Not strictly correct, but more useful than an error.
- Do the symtab's first, then
- check the psymtab's. If a psymtab indicates the existence
- of the desired name as a file-level static, then do psymtab-to-symtab
- conversion on the fly and return the found symbol. */
-
- for (objfile *objfile : current_program_space->objfiles ())
- {
- t = basic_lookup_transparent_type_1 (objfile, STATIC_BLOCK,
- flags, lookup_name);
- if (t)
- return t;
- }
-
+ /* Now search the static file-level symbols. Not strictly correct,
+ but more useful than an error. */
for (objfile *objfile : current_program_space->objfiles ())
{
t = basic_lookup_transparent_type_quick (objfile, STATIC_BLOCK,
@@ -3046,7 +2915,7 @@ find_symbol_at_address (CORE_ADDR address)
for (struct symbol *sym : block_iterator_range (b))
{
- if (sym->aclass () == LOC_STATIC
+ if (sym->loc_class () == LOC_STATIC
&& sym->value_address () == addr)
return sym;
}
@@ -4318,7 +4187,7 @@ find_function_alias_target (bound_minimal_symbol msymbol)
symbol *sym = find_pc_function (func_addr);
if (sym != NULL
- && sym->aclass () == LOC_BLOCK
+ && sym->loc_class () == LOC_BLOCK
&& sym->value_block ()->entry_pc () == func_addr)
return sym;
@@ -4341,7 +4210,7 @@ operator_chars (const char *p, const char **end)
/* Don't get faked out by `operator' being part of a longer
identifier. */
- if (isalpha (*p) || *p == '_' || *p == '$' || *p == '\0')
+ if (c_isalpha (*p) || *p == '_' || *p == '$' || *p == '\0')
return *end;
/* Allow some whitespace between `operator' and the operator symbol. */
@@ -4350,11 +4219,11 @@ operator_chars (const char *p, const char **end)
/* Recognize 'operator TYPENAME'. */
- if (isalpha (*p) || *p == '_' || *p == '$')
+ if (c_isalpha (*p) || *p == '_' || *p == '$')
{
const char *q = p + 1;
- while (isalnum (*q) || *q == '_' || *q == '$')
+ while (c_isalnum (*q) || *q == '_' || *q == '$')
q++;
*end = q;
return p;
@@ -4499,7 +4368,7 @@ info_sources_filter::matches (const char *fullname) const
switch (m_match_type)
{
case match_on::DIRNAME:
- dirname = ldirname (fullname);
+ dirname = gdb_ldirname (fullname);
to_match = dirname.c_str ();
break;
case match_on::BASENAME:
@@ -4714,7 +4583,7 @@ info_sources_worker (struct ui_out *uiout,
if (uiout->is_mi_like_p ())
{
const char *debug_info_state;
- if (objfile_has_symbols (objfile))
+ if (objfile->has_symbols ())
{
if (debug_fully_readin)
debug_info_state = "fully-read";
@@ -4730,7 +4599,7 @@ info_sources_worker (struct ui_out *uiout,
if (!debug_fully_readin)
uiout->text ("(Full debug information has not yet been read "
"for this file.)\n");
- if (!objfile_has_symbols (objfile))
+ if (!objfile->has_symbols ())
uiout->text ("(Objfile has no debug information.)\n");
uiout->text ("\n");
}
@@ -4910,11 +4779,11 @@ global_symbol_searcher::expand_symtabs
{
return file_matches (filename, m_filenames, basenames);
};
- expand_symtabs_file_matcher file_matcher = nullptr;
+ search_symtabs_file_matcher file_matcher = nullptr;
if (!m_filenames.empty ())
file_matcher = do_file_match;
- objfile->expand_symtabs_matching
+ objfile->search
(file_matcher,
&lookup_name_info::match_any (),
[&] (const char *symname)
@@ -5029,12 +4898,12 @@ global_symbol_searcher::add_matching_symbols
if ((kind & SEARCH_VAR_DOMAIN) != 0)
{
- if (sym->aclass () == LOC_UNRESOLVED
+ if (sym->loc_class () == LOC_UNRESOLVED
/* LOC_CONST can be used for more than
just enums, e.g., c++ static const
members. We only want to skip enums
here. */
- || (sym->aclass () == LOC_CONST
+ || (sym->loc_class () == LOC_CONST
&& (sym->type ()->code () == TYPE_CODE_ENUM)))
continue;
}
@@ -5128,7 +4997,7 @@ global_symbol_searcher::search () const
int fix = -1; /* -1 means ok; otherwise number of
spaces needed. */
- if (isalpha (*opname) || *opname == '_' || *opname == '$')
+ if (c_isalpha (*opname) || *opname == '_' || *opname == '$')
{
/* There should 1 space between 'operator' and 'TYPENAME'. */
if (opname[-1] != ' ' || opname[-2] == ' ')
@@ -5242,7 +5111,7 @@ symbol_to_info_string (struct symbol *sym, int block)
string_file tmp_stream;
type_print (sym->type (),
- (sym->aclass () == LOC_TYPEDEF
+ (sym->loc_class () == LOC_TYPEDEF
? "" : sym->print_name ()),
&tmp_stream, 0);
@@ -5610,7 +5479,7 @@ rbreak_command (const char *regexp, int from_tty)
if (colon && *(colon + 1) != ':')
{
int colon_index = colon - regexp;
- while (colon_index > 0 && isspace (regexp[colon_index - 1]))
+ while (colon_index > 0 && c_isspace (regexp[colon_index - 1]))
--colon_index;
file_name = make_unique_xstrndup (regexp, colon_index);
@@ -5761,7 +5630,7 @@ completion_list_add_symbol (completion_tracker &tracker,
the msymbol name and removes the msymbol name from the completion
tracker. */
if (sym->language () == language_cplus
- && sym->aclass () == LOC_BLOCK)
+ && sym->loc_class () == LOC_BLOCK)
{
/* The call to canonicalize returns the empty string if the input
string is already in canonical form, thanks to this we don't
@@ -5862,7 +5731,7 @@ language_search_unquoted_string (const char *text, const char *p)
{
for (; p > text; --p)
{
- if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
+ if (c_isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
continue;
else
{
@@ -5882,7 +5751,7 @@ language_search_unquoted_string (const char *text, const char *p)
Unfortunately we have to find it now to decide. */
while (t > text)
- if (isalnum (t[-1]) || t[-1] == '_' ||
+ if (c_isalnum (t[-1]) || t[-1] == '_' ||
t[-1] == ' ' || t[-1] == ':' ||
t[-1] == '(' || t[-1] == ')')
--t;
@@ -5906,7 +5775,7 @@ completion_list_add_fields (completion_tracker &tracker,
const lookup_name_info &lookup_name,
const char *text, const char *word)
{
- if (sym->aclass () == LOC_TYPEDEF)
+ if (sym->loc_class () == LOC_TYPEDEF)
{
struct type *t = sym->type ();
enum type_code c = t->code ();
@@ -5958,7 +5827,7 @@ symbol_is_function_or_method (minimal_symbol *msymbol)
bound_minimal_symbol
find_gnu_ifunc (const symbol *sym)
{
- if (sym->aclass () != LOC_BLOCK)
+ if (sym->loc_class () != LOC_BLOCK)
return {};
lookup_name_info lookup_name (sym->search_name (),
@@ -6090,7 +5959,7 @@ default_collect_symbol_completion_matches_break_on
which are in symbols. */
while (p > text)
{
- if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0'
+ if (c_isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0'
|| p[-1] == ':' || strchr (break_on, p[-1]) != NULL)
--p;
else
@@ -6130,25 +5999,20 @@ default_collect_symbol_completion_matches_break_on
/* Add completions for all currently loaded symbol tables. */
for (objfile *objfile : current_program_space->objfiles ())
{
- for (compunit_symtab *cust : objfile->compunits ())
- add_symtab_completions (cust, tracker, mode, lookup_name,
- sym_text, word, code);
- }
-
- /* Look through the partial symtabs for all symbols which begin by
- matching SYM_TEXT. Expand all CUs that you find to the list. */
- expand_symtabs_matching (NULL,
- lookup_name,
- NULL,
- [&] (compunit_symtab *symtab) /* expansion notify */
- {
- add_symtab_completions (symtab,
- tracker, mode, lookup_name,
- sym_text, word, code);
- return true;
- },
- SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
- SEARCH_ALL_DOMAINS);
+ /* Look through the partial symtabs for all symbols which begin by
+ matching SYM_TEXT. Expand all CUs that you find to the list. */
+ objfile->search
+ (nullptr, &lookup_name, nullptr,
+ [&] (compunit_symtab *symtab)
+ {
+ add_symtab_completions (symtab,
+ tracker, mode, lookup_name,
+ sym_text, word, code);
+ return true;
+ },
+ SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
+ SEARCH_ALL_DOMAINS);
+ }
/* Search upwards from currently selected frame (so that we can
complete on local vars). Also catch fields of types defined in
@@ -6206,8 +6070,6 @@ default_collect_symbol_completion_matches_break_on
if (current_language->macro_expansion () == macro_expansion_c
&& code == TYPE_CODE_UNDEF)
{
- gdb::unique_xmalloc_ptr<struct macro_scope> scope;
-
/* This adds a macro's name to the current completion list. */
auto add_macro_name = [&] (const char *macro_name,
const macro_definition *,
@@ -6225,10 +6087,9 @@ default_collect_symbol_completion_matches_break_on
resulting expression will be evaluated at "file:line" -- but
at there does not seem to be a way to detect this at
completion time. */
- scope = default_macro_scope ();
- if (scope)
- macro_for_each_in_scope (scope->file, scope->line,
- add_macro_name);
+ macro_scope scope = default_macro_scope ();
+ if (scope.is_valid ())
+ macro_for_each_in_scope (scope.file, scope.line, add_macro_name);
/* User-defined macros are always visible. */
macro_for_each (macro_user_macros, add_macro_name);
@@ -6413,7 +6274,7 @@ add_partial_filename_data::operator() (const char *filename,
program. */
completion_list
-make_source_files_completion_list (const char *text, const char *word)
+make_source_files_completion_list (const char *text)
{
size_t text_len = strlen (text);
completion_list list;
@@ -6439,7 +6300,7 @@ make_source_files_completion_list (const char *text, const char *word)
{
/* This file matches for a completion; add it to the current
list of matches. */
- add_filename_to_list (s->filename, text, word, &list);
+ add_filename_to_list (s->filename, text, text, &list);
}
else
{
@@ -6451,7 +6312,7 @@ make_source_files_completion_list (const char *text, const char *word)
if (base_name != s->filename
&& !filenames_seen.seen (base_name)
&& filename_ncmp (base_name, text, text_len) == 0)
- add_filename_to_list (base_name, text, word, &list);
+ add_filename_to_list (base_name, text, text, &list);
}
}
}
@@ -6459,7 +6320,7 @@ make_source_files_completion_list (const char *text, const char *word)
datum.filename_seen_cache = &filenames_seen;
datum.text = text;
- datum.word = word;
+ datum.word = text;
datum.text_len = text_len;
datum.list = &list;
map_symbol_filenames (datum, false /*need_fullname*/);
@@ -6586,9 +6447,8 @@ find_main_name (void)
/* Try to find language for main in psymtabs. */
bool symbol_found_p = false;
- gdbarch_iterate_over_objfiles_in_search_order
- (current_inferior ()->arch (),
- [&symbol_found_p, pspace] (objfile *obj)
+ current_program_space->iterate_over_objfiles_in_search_order
+ ([&symbol_found_p, pspace] (objfile *obj)
{
language lang
= obj->lookup_global_symbol_language ("main",
@@ -6640,13 +6500,13 @@ main_language (void)
/* The next index to hand out in response to a registration request. */
-static int next_aclass_value = LOC_FINAL_VALUE;
+static int next_loc_class_value = LOC_FINAL_VALUE;
-/* The maximum number of "aclass" registrations we support. This is
+/* The maximum number of "loc_class" registrations we support. This is
constant for convenience. */
#define MAX_SYMBOL_IMPLS (LOC_FINAL_VALUE + 11)
-/* The objects representing the various "aclass" values. The elements
+/* The objects representing the various "loc_class" values. The elements
from 0 up to LOC_FINAL_VALUE-1 represent themselves, and subsequent
elements are those registered at gdb initialization time. */
@@ -6659,22 +6519,22 @@ gdb::array_view<const struct symbol_impl> symbol_impls (symbol_impl);
/* Make sure we saved enough room in struct symbol. */
-static_assert (MAX_SYMBOL_IMPLS <= (1 << SYMBOL_ACLASS_BITS));
+static_assert (MAX_SYMBOL_IMPLS <= (1 << SYMBOL_LOC_CLASS_BITS));
-/* Register a computed symbol type. ACLASS must be LOC_COMPUTED. OPS
+/* Register a computed symbol type. LOC_CLASS must be LOC_COMPUTED. OPS
is the ops vector associated with this index. This returns the new
- index, which should be used as the aclass_index field for symbols
+ index, which should be used as the loc_class_index field for symbols
of this type. */
int
-register_symbol_computed_impl (enum address_class aclass,
+register_symbol_computed_impl (location_class loc_class,
const struct symbol_computed_ops *ops)
{
- int result = next_aclass_value++;
+ int result = next_loc_class_value++;
- gdb_assert (aclass == LOC_COMPUTED);
+ gdb_assert (loc_class == LOC_COMPUTED);
gdb_assert (result < MAX_SYMBOL_IMPLS);
- symbol_impl[result].aclass = aclass;
+ symbol_impl[result].loc_class = loc_class;
symbol_impl[result].ops_computed = ops;
/* Sanity check OPS. */
@@ -6687,20 +6547,20 @@ register_symbol_computed_impl (enum address_class aclass,
return result;
}
-/* Register a function with frame base type. ACLASS must be LOC_BLOCK.
+/* Register a function with frame base type. LOC_CLASS must be LOC_BLOCK.
OPS is the ops vector associated with this index. This returns the
- new index, which should be used as the aclass_index field for symbols
+ new index, which should be used as the loc_class_index field for symbols
of this type. */
int
-register_symbol_block_impl (enum address_class aclass,
+register_symbol_block_impl (location_class loc_class,
const struct symbol_block_ops *ops)
{
- int result = next_aclass_value++;
+ int result = next_loc_class_value++;
- gdb_assert (aclass == LOC_BLOCK);
+ gdb_assert (loc_class == LOC_BLOCK);
gdb_assert (result < MAX_SYMBOL_IMPLS);
- symbol_impl[result].aclass = aclass;
+ symbol_impl[result].loc_class = loc_class;
symbol_impl[result].ops_block = ops;
/* Sanity check OPS. */
@@ -6711,35 +6571,33 @@ register_symbol_block_impl (enum address_class aclass,
return result;
}
-/* Register a register symbol type. ACLASS must be LOC_REGISTER or
+/* Register a register symbol type. LOC_CLASS must be LOC_REGISTER or
LOC_REGPARM_ADDR. OPS is the register ops vector associated with
this index. This returns the new index, which should be used as
- the aclass_index field for symbols of this type. */
+ the loc_class_index field for symbols of this type. */
int
-register_symbol_register_impl (enum address_class aclass,
+register_symbol_register_impl (location_class loc_class,
const struct symbol_register_ops *ops)
{
- int result = next_aclass_value++;
+ int result = next_loc_class_value++;
- gdb_assert (aclass == LOC_REGISTER || aclass == LOC_REGPARM_ADDR);
+ gdb_assert (loc_class == LOC_REGISTER || loc_class == LOC_REGPARM_ADDR);
gdb_assert (result < MAX_SYMBOL_IMPLS);
- symbol_impl[result].aclass = aclass;
+ symbol_impl[result].loc_class = loc_class;
symbol_impl[result].ops_register = ops;
return result;
}
/* Initialize elements of 'symbol_impl' for the constants in enum
- address_class. */
+ location_class. */
static void
initialize_ordinary_address_classes (void)
{
- int i;
-
- for (i = 0; i < LOC_FINAL_VALUE; ++i)
- symbol_impl[i].aclass = (enum address_class) i;
+ for (int i = 0; i < LOC_FINAL_VALUE; ++i)
+ symbol_impl[i].loc_class = static_cast<location_class> (i);
}
@@ -6787,7 +6645,7 @@ CORE_ADDR
symbol::get_maybe_copied_address () const
{
gdb_assert (this->maybe_copied);
- gdb_assert (this->aclass () == LOC_STATIC);
+ gdb_assert (this->loc_class () == LOC_STATIC);
const char *linkage_name = this->linkage_name ();
bound_minimal_symbol minsym
@@ -6997,11 +6855,8 @@ info_module_subcommand (bool quiet, const char *module_regexp,
const char *last_filename = "";
const symbol *last_module_symbol = nullptr;
- for (const module_symbol_search &ms : module_symbols)
+ for (const auto &[p, q] : module_symbols)
{
- const symbol_search &p = ms.first;
- const symbol_search &q = ms.second;
-
gdb_assert (q.symbol != nullptr);
if (last_module_symbol != p.symbol)
@@ -7120,9 +6975,7 @@ info_module_var_func_command_completer (struct cmd_list_element *ignore,
-void _initialize_symtab ();
-void
-_initialize_symtab ()
+INIT_GDB_FILE (symtab)
{
cmd_list_element *c;
diff --git a/gdb/symtab.h b/gdb/symtab.h
index e547d10..09a361d 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -145,7 +145,7 @@ private:
std::string m_encoded_name;
/* The decoded lookup name. This is formed by calling ada_decode
- with both 'operators' and 'wide' set to false. */
+ with 'translate' set to false. */
std::string m_decoded_name;
/* Whether the user-provided lookup name was Ada encoded. If so,
@@ -967,9 +967,9 @@ to_scripting_domain (domain_search_flags val)
Throws an exception if VAL is not one of the allowable values. */
extern domain_search_flags from_scripting_domain (int val);
-/* An address-class says where to find the value of a symbol. */
+/* A location class says where to find the value of a symbol. */
-enum address_class
+enum location_class
{
/* Not used; catches errors. */
@@ -1078,14 +1078,14 @@ enum address_class
LOC_FINAL_VALUE
};
-/* The number of bits needed for values in enum address_class, with some
+/* The number of bits needed for values in enum location_class, with some
padding for reasonable growth, and room for run-time registered address
classes. See symtab.c:MAX_SYMBOL_IMPLS.
This is a #define so that we can have a assertion elsewhere to
verify that we have reserved enough space for synthetic address
classes. */
-#define SYMBOL_ACLASS_BITS 5
-static_assert (LOC_FINAL_VALUE <= (1 << SYMBOL_ACLASS_BITS));
+#define SYMBOL_LOC_CLASS_BITS 5
+static_assert (LOC_FINAL_VALUE <= (1 << SYMBOL_LOC_CLASS_BITS));
/* The methods needed to implement LOC_COMPUTED. These methods can
use the symbol's .aux_value for additional per-symbol information.
@@ -1202,7 +1202,7 @@ struct symbol_register_ops
struct symbol_impl
{
- enum address_class aclass;
+ location_class loc_class;
/* Used with LOC_COMPUTED. */
const struct symbol_computed_ops *ops_computed;
@@ -1238,7 +1238,7 @@ struct symbol : public general_symbol_info, public allocate_on_obstack<symbol>
symbol ()
/* Class-initialization of bitfields is only allowed in C++20. */
: m_domain (UNDEF_DOMAIN),
- m_aclass_index (0),
+ m_loc_class_index (0),
m_is_objfile_owned (1),
m_is_argument (0),
m_is_inlined (0),
@@ -1262,14 +1262,14 @@ struct symbol : public general_symbol_info, public allocate_on_obstack<symbol>
symbol (const symbol &) = default;
symbol &operator= (const symbol &) = default;
- void set_aclass_index (unsigned int aclass_index)
+ void set_loc_class_index (unsigned int loc_class_index)
{
- m_aclass_index = aclass_index;
+ m_loc_class_index = loc_class_index;
}
const symbol_impl &impl () const
{
- return symbol_impls[this->m_aclass_index];
+ return symbol_impls[this->m_loc_class_index];
}
const symbol_block_ops *block_ops () const
@@ -1287,9 +1287,9 @@ struct symbol : public general_symbol_info, public allocate_on_obstack<symbol>
return this->impl ().ops_register;
}
- address_class aclass () const
+ location_class loc_class () const
{
- return this->impl ().aclass;
+ return this->impl ().loc_class;
}
/* Return true if this symbol's domain matches FLAGS. */
@@ -1480,11 +1480,11 @@ struct symbol : public general_symbol_info, public allocate_on_obstack<symbol>
ENUM_BITFIELD(domain_enum) m_domain : SYMBOL_DOMAIN_BITS;
- /* Address class. This holds an index into the 'symbol_impls'
- table. The actual enum address_class value is stored there,
+ /* Location class. This holds an index into the 'symbol_impls'
+ table. The actual location_class value is stored there,
alongside any per-class ops vectors. */
- unsigned int m_aclass_index : SYMBOL_ACLASS_BITS;
+ unsigned int m_loc_class_index : SYMBOL_LOC_CLASS_BITS;
/* If non-zero then symbol is objfile-owned, use owner.symtab.
Otherwise symbol is arch-owned, use owner.arch. */
@@ -1575,13 +1575,13 @@ symbol::value_block () const
return m_value.block;
}
-extern int register_symbol_computed_impl (enum address_class,
+extern int register_symbol_computed_impl (location_class,
const struct symbol_computed_ops *);
-extern int register_symbol_block_impl (enum address_class aclass,
+extern int register_symbol_block_impl (location_class loc_class,
const struct symbol_block_ops *ops);
-extern int register_symbol_register_impl (enum address_class,
+extern int register_symbol_register_impl (location_class,
const struct symbol_register_ops *);
/* An instance of this type is used to represent a C++ template
@@ -2101,17 +2101,17 @@ struct field_of_this_result
symbol was not found in 'this'. If non-NULL, then one of the
other fields will be non-NULL as well. */
- struct type *type;
+ struct type *type = nullptr;
/* If the symbol was found as an ordinary field of 'this', then this
is non-NULL and points to the particular field. */
- struct field *field;
+ struct field *field = nullptr;
/* If the symbol was found as a function field of 'this', then this
is non-NULL and points to the particular field. */
- struct fn_fieldlist *fn_field;
+ struct fn_fieldlist *fn_field = nullptr;
};
/* Find the definition for a specified symbol name NAME
@@ -2482,8 +2482,7 @@ extern void collect_file_symbol_completion_matches
symbol_name_match_type name_match_type,
const char *, const char *, const char *);
-extern completion_list
- make_source_files_completion_list (const char *, const char *);
+extern completion_list make_source_files_completion_list (const char *);
/* Return whether SYM is a function/method, as opposed to a data symbol. */
diff --git a/gdb/syscalls/riscv-canonicalize-syscall-gen.py b/gdb/syscalls/riscv-canonicalize-syscall-gen.py
index c7dda93..40039bb 100755
--- a/gdb/syscalls/riscv-canonicalize-syscall-gen.py
+++ b/gdb/syscalls/riscv-canonicalize-syscall-gen.py
@@ -111,7 +111,7 @@ class Generator:
canon_syscalls[syscall_num] = value
# this is a place for corner cases
elif syscall_name == "mmap":
- gdb_old_syscall_name = "gdb_old_mmap"
+ gdb_old_syscall_name = "gdb_sys_old_mmap"
value = (
f" case {syscall_num}: return {gdb_old_syscall_name};\n"
)
diff --git a/gdb/target-connection.c b/gdb/target-connection.c
index 60d7732..02eea05 100644
--- a/gdb/target-connection.c
+++ b/gdb/target-connection.c
@@ -149,10 +149,7 @@ info_connections_command (const char *args, int from_tty)
print_connection (current_uiout, args);
}
-void _initialize_target_connection ();
-
-void
-_initialize_target_connection ()
+INIT_GDB_FILE (target_connection)
{
add_info ("connections", info_connections_command,
_("\
diff --git a/gdb/target-dcache.c b/gdb/target-dcache.c
index 9fcdd1e..6be1224 100644
--- a/gdb/target-dcache.c
+++ b/gdb/target-dcache.c
@@ -161,9 +161,7 @@ maint_flush_dcache_command (const char *command, int from_tty)
gdb_printf (_("The dcache was flushed.\n"));
}
-void _initialize_target_dcache ();
-void
-_initialize_target_dcache ()
+INIT_GDB_FILE (target_dcache)
{
add_setshow_boolean_cmd ("stack-cache", class_support,
&stack_cache_enabled_1, _("\
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index 8042d25..dc5fbac 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -1880,9 +1880,7 @@ maintenance_check_xml_descriptions (const char *dir, int from_tty)
(long) selftests::xml_tdesc.size (), failed);
}
-void _initialize_target_descriptions ();
-void
-_initialize_target_descriptions ()
+INIT_GDB_FILE (target_descriptions)
{
cmd_list_element *cmd;
diff --git a/gdb/target.c b/gdb/target.c
index 522bed8..f7c43f6 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -2464,6 +2464,7 @@ target_pre_inferior ()
if (!gdbarch_has_global_solist (current_inferior ()->arch ()))
{
no_shared_libraries (current_program_space);
+ current_program_space->unset_solib_ops ();
invalidate_target_mem_regions ();
@@ -3204,8 +3205,8 @@ target_ops::fileio_fstat (int fd, struct stat *sb, fileio_error *target_errno)
}
int
-target_ops::fileio_stat (struct inferior *inf, const char *filename,
- struct stat *sb, fileio_error *target_errno)
+target_ops::fileio_lstat (struct inferior *inf, const char *filename,
+ struct stat *sb, fileio_error *target_errno)
{
*target_errno = FILEIO_ENOSYS;
return -1;
@@ -3331,17 +3332,17 @@ target_fileio_fstat (int fd, struct stat *sb, fileio_error *target_errno)
/* See target.h. */
int
-target_fileio_stat (struct inferior *inf, const char *filename,
- struct stat *sb, fileio_error *target_errno)
+target_fileio_lstat (struct inferior *inf, const char *filename,
+ struct stat *sb, fileio_error *target_errno)
{
for (target_ops *t = default_fileio_target (); t != NULL; t = t->beneath ())
{
- int ret = t->fileio_stat (inf, filename, sb, target_errno);
+ int ret = t->fileio_lstat (inf, filename, sb, target_errno);
if (ret == -1 && *target_errno == FILEIO_ENOSYS)
continue;
- target_debug_printf_nofunc ("target_fileio_stat (%s) = %d (%d)",
+ target_debug_printf_nofunc ("target_fileio_lstat (%s) = %d (%d)",
filename, ret,
ret != -1 ? 0 : *target_errno);
return ret;
@@ -4502,10 +4503,7 @@ set_write_memory_registers_permission (const char *args, int from_tty,
update_observer_mode ();
}
-void _initialize_target ();
-
-void
-_initialize_target ()
+INIT_GDB_FILE (target)
{
the_debug_target = new debug_target ();
diff --git a/gdb/target.h b/gdb/target.h
index 2d3bac7..365e894 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1016,8 +1016,8 @@ struct target_ops
filesystem seen by the debugger (GDB or, for remote targets, the
remote stub). Return 0 on success, or -1 if an error occurs (and
set *TARGET_ERRNO). */
- virtual int fileio_stat (struct inferior *inf, const char *filename,
- struct stat *sb, fileio_error *target_errno);
+ virtual int fileio_lstat (struct inferior *inf, const char *filename,
+ struct stat *sb, fileio_error *target_errno);
/* Close FD on the target. Return 0, or -1 if an error occurs
(and set *TARGET_ERRNO). */
@@ -2256,8 +2256,8 @@ extern int target_fileio_fstat (int fd, struct stat *sb,
filesystem seen by the debugger (GDB or, for remote targets, the remote
stub). Return 0 on success, or -1 if an error occurs (and set
*TARGET_ERRNO). */
-extern int target_fileio_stat (struct inferior *inf, const char *filename,
- struct stat *sb, fileio_error *target_errno);
+extern int target_fileio_lstat (struct inferior *inf, const char *filename,
+ struct stat *sb, fileio_error *target_errno);
/* Close FD on the target. Return 0, or -1 if an error occurs
(and set *TARGET_ERRNO). */
diff --git a/gdb/terminal.h b/gdb/terminal.h
index 54e5e98..720fd4a 100644
--- a/gdb/terminal.h
+++ b/gdb/terminal.h
@@ -19,6 +19,8 @@
#ifndef GDB_TERMINAL_H
#define GDB_TERMINAL_H
+#include "serial.h"
+
struct inferior;
extern void new_tty_prefork (std::string ttyname);
@@ -43,4 +45,17 @@ extern void gdb_save_tty_state (void);
have had a chance to alter it. */
extern void set_initial_gdb_ttystate (void);
+/* Restore initial tty state. */
+extern void restore_initial_gdb_ttystate (void);
+
+/* An RAII-based object that saves the tty state, and then restores it again
+ when this object is destroyed. */
+class scoped_gdb_ttystate
+{
+public:
+ scoped_gdb_ttystate ();
+ ~scoped_gdb_ttystate ();
+private:
+ serial_ttystate m_ttystate;
+};
#endif /* GDB_TERMINAL_H */
diff --git a/gdb/testsuite/Makefile.in b/gdb/testsuite/Makefile.in
index 4a6665d..fa2d9eb 100644
--- a/gdb/testsuite/Makefile.in
+++ b/gdb/testsuite/Makefile.in
@@ -386,7 +386,17 @@ check-all-boards: all $(abs_builddir)/site.exp
${abs_srcdir}/make-check-all.sh --keep-results \
--host-user "$(GDB_HOST_USERNAME)" \
--target-user "$(GDB_TARGET_USERNAME)" \
- "$(TESTS)"
+ "$(TESTS)" \
+ result=$$?; \
+ if test -d check-all; then \
+ $(SHELL) $(srcdir)/../../contrib/dg-extract-results.sh \
+ `find check-all -name gdb.sum -print` > check-all/gdb.sum; \
+ $(SHELL) $(srcdir)/../../contrib/dg-extract-results.sh -L \
+ `find check-all -name gdb.log -print` > check-all/gdb.log; \
+ sed -n '/=== gdb Summary ===/,$$ p' check-all/gdb.sum; \
+ fi; \
+ exit $$result
+
force:;
diff --git a/gdb/testsuite/gdb.ada/array_long_idx.exp b/gdb/testsuite/gdb.ada/array_long_idx.exp
new file mode 100644
index 0000000..13a4d3d
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/array_long_idx.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 that long array index types work.
+
+load_lib "ada.exp"
+
+require allow_ada_tests
+
+standard_ada_testfile main
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} {
+ return
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number STOP ${testdir}/main.adb]
+if {![runto "main.adb:$bp_location"]} {
+ return
+}
+
+gdb_test "print some_regular_access.all" \
+ [string_to_regexp " = (-2147483648 => (-9223372036854775808 => 1, 2, 3), (-9223372036854775808 => 4, 5, 6))"]
diff --git a/gdb/testsuite/gdb.ada/array_long_idx/main.adb b/gdb/testsuite/gdb.ada/array_long_idx/main.adb
new file mode 100644
index 0000000..6c4971f
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/array_long_idx/main.adb
@@ -0,0 +1,31 @@
+-- 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/>.
+
+with Pck; use Pck;
+
+procedure Main is
+
+ type Shorter_Integer is range -2147483648 .. 2147483647;
+ type Longer_Integer is range -9223372036854775808 .. 9223372036854775807;
+ type My_Array is array (Shorter_Integer range <>,
+ Longer_Integer range <>) of Integer;
+
+ type My_Reg_Acc is access all My_Array;
+
+ Some_Regular_Access : My_Reg_Acc := new My_Array'((1, 2, 3), (4, 5, 6));
+
+begin
+ Do_Nothing (Some_Regular_Access'Address); -- STOP
+end Main;
diff --git a/gdb/testsuite/gdb.ada/array_long_idx/pck.adb b/gdb/testsuite/gdb.ada/array_long_idx/pck.adb
new file mode 100644
index 0000000..54ddf5c
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/array_long_idx/pck.adb
@@ -0,0 +1,21 @@
+-- Copyright 2012-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/array_long_idx/pck.ads b/gdb/testsuite/gdb.ada/array_long_idx/pck.ads
new file mode 100644
index 0000000..db7c0a8
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/array_long_idx/pck.ads
@@ -0,0 +1,19 @@
+-- Copyright 2012-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/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/exec_changed.exp b/gdb/testsuite/gdb.ada/exec_changed.exp
index c52757e..31add11 100644
--- a/gdb/testsuite/gdb.ada/exec_changed.exp
+++ b/gdb/testsuite/gdb.ada/exec_changed.exp
@@ -84,7 +84,7 @@ if { [gdb_start_cmd] < 0 } {
# Try again, this time with just changing the file time of first.
-clean_restart "${binfile}$EXEEXT"
+clean_restart "${::testfile}$EXEEXT"
# Ensure we don't accidentally use the main symbol cache.
gdb_test_no_output "mt set symbol-cache-size 0"
diff --git a/gdb/testsuite/gdb.ada/file-then-restart.exp b/gdb/testsuite/gdb.ada/file-then-restart.exp
index faa9962..6e8e058 100644
--- a/gdb/testsuite/gdb.ada/file-then-restart.exp
+++ b/gdb/testsuite/gdb.ada/file-then-restart.exp
@@ -36,7 +36,7 @@ if {[gdb_compile_ada "${srcfile2}" "${binfile2}" executable {debug}] != ""} {
}
foreach_with_prefix scenario {kill no-kill} {
- clean_restart $binfile
+ clean_restart $::testfile
# Start the program, we should land in the program main procedure
if {[gdb_start_cmd] < 0} {
diff --git a/gdb/testsuite/gdb.ada/finish-var-size.exp b/gdb/testsuite/gdb.ada/finish-var-size.exp
index e038ed4..6365c95 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 { [ada_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/import.exp b/gdb/testsuite/gdb.ada/import.exp
index ab3a1c9..51ce7fa 100644
--- a/gdb/testsuite/gdb.ada/import.exp
+++ b/gdb/testsuite/gdb.ada/import.exp
@@ -54,6 +54,9 @@ gdb_test "print pkg.imported_var_ada" " = 42"
gdb_test "print pkg.exported_var_ada" " = 99"
gdb_test "print exported_var_ada" " = 99"
+gdb_breakpoint "local_imported_func" message
+gdb_test "print copy" " = 42"
+
# This passes with gcc 10 but fails with gcc 9. With gcc 9, we have:
# <1><1659>: Abbrev Number: 4 (DW_TAG_subprogram)
# <165a> DW_AT_external : 1
@@ -76,19 +79,16 @@ gdb_test "print exported_var_ada" " = 99"
# The fact that things start to work when adding the DW_AT_declaration is
# consistent with what is described in commit ff9baa5f1c5, so xfail this
# (without pinpointing it to a specific gcc PR or commit).
-if { [gcc_major_version] < 10 } {
- setup_xfail *-*-*
-}
-gdb_breakpoint "pkg.imported_func_ada" message
-gdb_breakpoint "imported_func" message
-if { [gcc_major_version] < 10 } {
- setup_xfail *-*-*
+foreach func {"pkg.imported_func_ada" "imported_func"} {
+ clean_restart $testfile
+ if { [gcc_major_version] < 10 } {
+ setup_xfail *-*-*
+ }
+ gdb_breakpoint $func message
}
-gdb_breakpoint "imported_func_ada" message
-gdb_breakpoint "local_imported_func" message
-gdb_breakpoint "pkg.exported_func_ada" message
-gdb_breakpoint "exported_func_ada" message
-gdb_breakpoint "exported_func" message
-
-gdb_test "print copy" " = 42"
+foreach func {"imported_func_ada" "pkg.exported_func_ada" \
+ "exported_func_ada" "exported_func"} {
+ clean_restart $testfile
+ gdb_breakpoint $func message
+}
diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert.exp b/gdb/testsuite/gdb.ada/mi_catch_assert.exp
index 1b4609a..c3dbfca 100644
--- a/gdb/testsuite/gdb.ada/mi_catch_assert.exp
+++ b/gdb/testsuite/gdb.ada/mi_catch_assert.exp
@@ -26,7 +26,7 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
###################################################
# 2. Try catching conditionnal failed assertion. #
diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex.exp b/gdb/testsuite/gdb.ada/mi_catch_ex.exp
index da3d340..0837028 100644
--- a/gdb/testsuite/gdb.ada/mi_catch_ex.exp
+++ b/gdb/testsuite/gdb.ada/mi_catch_ex.exp
@@ -30,7 +30,7 @@ set any_nb "\[0-9\]+"
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
####################################
# 1. Try catching all exceptions. #
diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
index 00e8f6e..0c50f59 100644
--- a/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
+++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
@@ -26,7 +26,7 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
#############################################
# 1. Try catching all exceptions handlers. #
diff --git a/gdb/testsuite/gdb.ada/mi_dyn_arr.exp b/gdb/testsuite/gdb.ada/mi_dyn_arr.exp
index c0e9f7f..b01f3e9 100644
--- a/gdb/testsuite/gdb.ada/mi_dyn_arr.exp
+++ b/gdb/testsuite/gdb.ada/mi_dyn_arr.exp
@@ -26,7 +26,7 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug]] != "" }
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
if {[mi_runto_main] < 0} {
return 0
diff --git a/gdb/testsuite/gdb.ada/mi_ex_cond.exp b/gdb/testsuite/gdb.ada/mi_ex_cond.exp
index 53ace22..43caf76 100644
--- a/gdb/testsuite/gdb.ada/mi_ex_cond.exp
+++ b/gdb/testsuite/gdb.ada/mi_ex_cond.exp
@@ -30,7 +30,7 @@ set any_nb "\[0-9\]+"
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.ada/mi_exc_info.exp b/gdb/testsuite/gdb.ada/mi_exc_info.exp
index b9d0072..a95fb23 100644
--- a/gdb/testsuite/gdb.ada/mi_exc_info.exp
+++ b/gdb/testsuite/gdb.ada/mi_exc_info.exp
@@ -26,7 +26,7 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug]] != "" }
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
if {[mi_runto_main] < 0} {
return 0
diff --git a/gdb/testsuite/gdb.ada/mi_interface.exp b/gdb/testsuite/gdb.ada/mi_interface.exp
index 630353d..f25adf0 100644
--- a/gdb/testsuite/gdb.ada/mi_interface.exp
+++ b/gdb/testsuite/gdb.ada/mi_interface.exp
@@ -28,7 +28,7 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
if {[mi_runto_main] < 0} {
return 0
diff --git a/gdb/testsuite/gdb.ada/mi_prot.exp b/gdb/testsuite/gdb.ada/mi_prot.exp
index 7f68ca8..4edc93b 100644
--- a/gdb/testsuite/gdb.ada/mi_prot.exp
+++ b/gdb/testsuite/gdb.ada/mi_prot.exp
@@ -28,7 +28,7 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable \
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
if {[mi_runto_main] < 0} {
return 0
diff --git a/gdb/testsuite/gdb.ada/mi_ref_changeable.exp b/gdb/testsuite/gdb.ada/mi_ref_changeable.exp
index 315e2b3..c69f615 100644
--- a/gdb/testsuite/gdb.ada/mi_ref_changeable.exp
+++ b/gdb/testsuite/gdb.ada/mi_ref_changeable.exp
@@ -26,7 +26,7 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug]] != "" }
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
if {[mi_runto_main] < 0} {
return 0
diff --git a/gdb/testsuite/gdb.ada/mi_string_access.exp b/gdb/testsuite/gdb.ada/mi_string_access.exp
index 25c0490..e29e17d 100644
--- a/gdb/testsuite/gdb.ada/mi_string_access.exp
+++ b/gdb/testsuite/gdb.ada/mi_string_access.exp
@@ -29,7 +29,7 @@ foreach_gnat_encoding scenario flags {all minimal} {
return -1
}
- mi_clean_restart $binfile-$scenario
+ mi_clean_restart $::testfile-$scenario
if {[mi_runto_main] < 0} {
return 0
diff --git a/gdb/testsuite/gdb.ada/mi_task_arg.exp b/gdb/testsuite/gdb.ada/mi_task_arg.exp
index 018e3bc..6c222ff 100644
--- a/gdb/testsuite/gdb.ada/mi_task_arg.exp
+++ b/gdb/testsuite/gdb.ada/mi_task_arg.exp
@@ -26,7 +26,7 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.ada/mi_task_info.exp b/gdb/testsuite/gdb.ada/mi_task_info.exp
index aa05a02..9895cfe 100644
--- a/gdb/testsuite/gdb.ada/mi_task_info.exp
+++ b/gdb/testsuite/gdb.ada/mi_task_info.exp
@@ -26,7 +26,7 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.ada/mi_var_access.exp b/gdb/testsuite/gdb.ada/mi_var_access.exp
index 9bfaeff..b595780 100644
--- a/gdb/testsuite/gdb.ada/mi_var_access.exp
+++ b/gdb/testsuite/gdb.ada/mi_var_access.exp
@@ -26,7 +26,7 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable debug] != "" } {
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
if {[mi_runto_main] < 0} {
return 0
diff --git a/gdb/testsuite/gdb.ada/mi_var_array.exp b/gdb/testsuite/gdb.ada/mi_var_array.exp
index a04673c..0ba90e7 100644
--- a/gdb/testsuite/gdb.ada/mi_var_array.exp
+++ b/gdb/testsuite/gdb.ada/mi_var_array.exp
@@ -29,7 +29,7 @@ foreach_gnat_encoding scenario flags {none all minimal} {
return -1
}
- mi_clean_restart $binfile-$scenario
+ mi_clean_restart $::testfile-$scenario
if {[mi_runto_main] < 0} {
return 0
diff --git a/gdb/testsuite/gdb.ada/mi_var_union.exp b/gdb/testsuite/gdb.ada/mi_var_union.exp
index 99882cf..b198800 100644
--- a/gdb/testsuite/gdb.ada/mi_var_union.exp
+++ b/gdb/testsuite/gdb.ada/mi_var_union.exp
@@ -31,7 +31,7 @@ foreach_gnat_encoding scenario flags {none all minimal} {
return -1
}
- mi_clean_restart $binfile-$scenario
+ mi_clean_restart $::testfile-$scenario
if {[mi_runto_main] < 0} {
return 0
diff --git a/gdb/testsuite/gdb.ada/mi_variant.exp b/gdb/testsuite/gdb.ada/mi_variant.exp
index 4c71f16..18693ce 100644
--- a/gdb/testsuite/gdb.ada/mi_variant.exp
+++ b/gdb/testsuite/gdb.ada/mi_variant.exp
@@ -30,7 +30,7 @@ foreach_gnat_encoding scenario flags {none all minimal} {
return -1
}
- mi_clean_restart $binfile-$scenario
+ mi_clean_restart $::testfile-$scenario
if {[mi_runto_main] < 0} {
return 0
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/operator_call.exp b/gdb/testsuite/gdb.ada/operator_call.exp
index e96107b..dc7f679 100644
--- a/gdb/testsuite/gdb.ada/operator_call.exp
+++ b/gdb/testsuite/gdb.ada/operator_call.exp
@@ -71,6 +71,12 @@ proc test_with_menu {command result} {
fail $command
}
}
+ "Argument to arithmetic operation not a number or boolean." {
+ fail $command
+ }
+ -re "No definition of \".*\" in current context." {
+ fail $command
+ }
timeout {
fail "$command (timeout)"
}
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/return-small-char-array.exp b/gdb/testsuite/gdb.ada/return-small-char-array.exp
new file mode 100644
index 0000000..75c781e
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/return-small-char-array.exp
@@ -0,0 +1,40 @@
+# 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 proc
+
+if { [gdb_compile_ada $srcfile $binfile executable debug] != "" } {
+ return -1
+}
+
+clean_restart $testfile
+
+set bp_location [gdb_get_line_number "STOP" $testdir/proc.adb]
+runto "proc.adb:$bp_location"
+
+gdb_test "print Value.Name(My_Value)" \
+ { = "abcd"}
+
+# Step into the function.
+gdb_test "step 2" \
+ "return Of_Value;"
+
+# and finish.
+gdb_test "finish" \
+ { = "abcd"}
diff --git a/gdb/testsuite/gdb.ada/return-small-char-array/proc.adb b/gdb/testsuite/gdb.ada/return-small-char-array/proc.adb
new file mode 100644
index 0000000..b18d9fe
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/return-small-char-array/proc.adb
@@ -0,0 +1,22 @@
+-- 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/>.
+
+with Value;
+procedure Proc is
+ My_Value : Value.T := "abcd";
+begin
+ null; -- STOP
+ My_Value := Value.Name(My_Value);
+end;
diff --git a/gdb/testsuite/gdb.ada/return-small-char-array/value.adb b/gdb/testsuite/gdb.ada/return-small-char-array/value.adb
new file mode 100644
index 0000000..2dd9faa
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/return-small-char-array/value.adb
@@ -0,0 +1,21 @@
+-- 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/>.
+
+package body Value is
+ function Name (Of_Value : T) return T is
+ begin
+ return Of_Value;
+ end Name;
+end Value;
diff --git a/gdb/testsuite/gdb.ada/return-small-char-array/value.ads b/gdb/testsuite/gdb.ada/return-small-char-array/value.ads
new file mode 100644
index 0000000..16b171e
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/return-small-char-array/value.ads
@@ -0,0 +1,20 @@
+-- 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/>.
+
+package Value is
+ type T is new String (1 .. 4);
+
+ function Name (Of_Value : T) return T;
+end;
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.ada/var_arr_typedef/pack.adb b/gdb/testsuite/gdb.ada/var_arr_typedef/pack.adb
index 2f9114a..80cfac1 100644
--- a/gdb/testsuite/gdb.ada/var_arr_typedef/pack.adb
+++ b/gdb/testsuite/gdb.ada/var_arr_typedef/pack.adb
@@ -20,6 +20,6 @@ package body Pack is
return I;
end Identity;
- procedure Do_Nothing (A : Array_Type) is null;
+ procedure Do_Nothing (A : System.Address) is null;
end Pack;
diff --git a/gdb/testsuite/gdb.ada/var_arr_typedef/pack.ads b/gdb/testsuite/gdb.ada/var_arr_typedef/pack.ads
index 2ceb071..353ec48 100644
--- a/gdb/testsuite/gdb.ada/var_arr_typedef/pack.ads
+++ b/gdb/testsuite/gdb.ada/var_arr_typedef/pack.ads
@@ -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 System; use System;
+
package Pack is
type Rec_Type is record
I : Integer;
@@ -23,7 +25,7 @@ package Pack is
type Array_Type is array (Positive range <>) of Vec_Type;
- procedure Do_Nothing (A : Array_Type);
+ procedure Do_Nothing (A : System.Address);
function Identity (I : Integer) return Integer;
end Pack;
diff --git a/gdb/testsuite/gdb.ada/var_arr_typedef/var_arr_typedef.adb b/gdb/testsuite/gdb.ada/var_arr_typedef/var_arr_typedef.adb
index 4a7f4cb..86609a8 100644
--- a/gdb/testsuite/gdb.ada/var_arr_typedef/var_arr_typedef.adb
+++ b/gdb/testsuite/gdb.ada/var_arr_typedef/var_arr_typedef.adb
@@ -24,5 +24,5 @@ procedure Var_Arr_Typedef is
A : constant Array_Type (1 .. Identity (4)) := (VA, VA, VB, VB);
begin
- Do_Nothing (A); -- BREAK
+ Do_Nothing (A'Address); -- BREAK
end Var_Arr_Typedef;
diff --git a/gdb/testsuite/gdb.arch/aarch64-frameptr-vecreg-unwind.c b/gdb/testsuite/gdb.arch/aarch64-frameptr-vecreg-unwind.c
new file mode 100644
index 0000000..44ed3e8
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-frameptr-vecreg-unwind.c
@@ -0,0 +1,62 @@
+/* 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/>. */
+
+volatile void dummy () {}
+
+long test_function(void)
+{
+ __asm__ volatile (
+ /* Zero d0 (64-bit vector register part of v0). */
+ "movi d0, #0\n\t"
+
+ /* Move the frame pointer (x29) to d0 using fmov. */
+ "fmov d0, x29\n\t"
+
+ /* Describe CFI: Frame pointer is now in d0. */
+ ".cfi_register x29, d0\n\t"
+
+ /* Clobber list: Specify all modified registers. */
+ : /* No output operands. */
+ : /* No input operands. */
+ : "d0"
+ );
+
+ dummy (); /* break-here */
+
+ __asm__ volatile (
+ /* Restore the frame pointer (x29) from d0 using fmov. */
+ "fmov x29, d0\n\t"
+
+ /* Describe CFI: Frame pointer is restored. */
+ ".cfi_restore x29\n\t"
+
+ /* Clobber list: Specify all modified registers. */
+ : /* No output operands. */
+ : /* No input operands. */
+ : "x29", "d0"
+ );
+
+ return 0;
+}
+
+int
+main ()
+{
+ long result = test_function ();
+ dummy ();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-frameptr-vecreg-unwind.exp b/gdb/testsuite/gdb.arch/aarch64-frameptr-vecreg-unwind.exp
new file mode 100644
index 0000000..2d710bc
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-frameptr-vecreg-unwind.exp
@@ -0,0 +1,33 @@
+# 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/>.
+
+require is_aarch64_target
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+ "${srcfile}" {debug}] } {
+ return -1
+}
+
+if {![runto_main]} {
+ return
+}
+
+gdb_breakpoint [gdb_get_line_number "break-here"]
+gdb_continue_to_breakpoint "break-here"
+gdb_test "with confirm off --return -1" "result = test_function \\(\\);"
+gdb_test "step" "dummy \\(\\);"
+gdb_test "print result" "= -1"
diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-core.c b/gdb/testsuite/gdb.arch/aarch64-gcs-core.c
new file mode 100644
index 0000000..f3362cb
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-gcs-core.c
@@ -0,0 +1,123 @@
+/* This test program 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 <stdio.h>
+#include <stdlib.h>
+#include <sys/auxv.h>
+#include <linux/prctl.h>
+#include <sys/syscall.h>
+
+/* Feature check for Guarded Control Stack. */
+#ifndef HWCAP_GCS
+#define HWCAP_GCS (1ULL << 32)
+#endif
+
+#ifndef PR_GET_SHADOW_STACK_STATUS
+#define PR_GET_SHADOW_STACK_STATUS 74
+#define PR_SET_SHADOW_STACK_STATUS 75
+#define PR_SHADOW_STACK_ENABLE (1UL << 0)
+#endif
+
+/* We need to use a macro to call prctl because after GCS is enabled, it's not
+ possible to return from the function which enabled it. This is because the
+ return address of the calling function isn't on the GCS. */
+#define my_syscall2(num, arg1, arg2) \
+ ({ \
+ register long _num __asm__("x8") = (num); \
+ register long _arg1 __asm__("x0") = (long)(arg1); \
+ register long _arg2 __asm__("x1") = (long)(arg2); \
+ register long _arg3 __asm__("x2") = 0; \
+ register long _arg4 __asm__("x3") = 0; \
+ register long _arg5 __asm__("x4") = 0; \
+ \
+ __asm__ volatile ("svc #0\n" \
+ : "=r"(_arg1) \
+ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
+ "r"(_arg5), "r"(_num) \
+ : "memory", "cc"); \
+ _arg1; \
+ })
+
+#define get_gcspr(void) \
+ ({ \
+ unsigned long *gcspr; \
+ \
+ /* Get GCSPR_EL0. */ \
+ asm volatile ("mrs %0, S3_3_C2_C5_1" : "=r"(gcspr) : : "cc"); \
+ \
+ gcspr; \
+ })
+
+/* Corrupt the return address to see if GDB will report a SIGSEGV with the
+ expected $_siginfo.si_code. */
+static void __attribute__ ((noinline))
+function (unsigned long *gcspr)
+{
+ /* x30 holds the return address. */
+ register long x30 __asm__("x30") __attribute__ ((unused));
+
+ /* Print GCSPR to stdout so that the testcase can capture it. */
+ printf ("%p\n", get_gcspr ());
+ fflush (stdout);
+
+ /* Cause a GCS exception. */
+ x30 = 0xbadc0ffee;
+ __asm__ volatile ("ret\n");
+}
+
+int
+main (void)
+{
+ if (!(getauxval (AT_HWCAP) & HWCAP_GCS))
+ {
+ fprintf (stderr, "GCS support not found in AT_HWCAP\n");
+ return EXIT_FAILURE;
+ }
+
+ /* Force shadow stacks on, our tests *should* be fine with or
+ without libc support and with or without this having ended
+ up tagged for GCS and enabled by the dynamic linker. We
+ can't use the libc prctl() function since we can't return
+ from enabling the stack. Also lock GCS if not already
+ locked so we can test behaviour when it's locked. */
+ unsigned long gcs_mode;
+ int ret = my_syscall2 (__NR_prctl, PR_GET_SHADOW_STACK_STATUS, &gcs_mode);
+ if (ret)
+ {
+ fprintf (stderr, "Failed to read GCS state: %d\n", ret);
+ return EXIT_FAILURE;
+ }
+
+ if (!(gcs_mode & PR_SHADOW_STACK_ENABLE))
+ {
+ gcs_mode = PR_SHADOW_STACK_ENABLE;
+ ret = my_syscall2 (__NR_prctl, PR_SET_SHADOW_STACK_STATUS, gcs_mode);
+ if (ret)
+ {
+ fprintf (stderr, "Failed to configure GCS: %d\n", ret);
+ return EXIT_FAILURE;
+ }
+ }
+
+ unsigned long *gcspr = get_gcspr ();
+
+ /* Pass gscpr to function just so it's used for something. */
+ function (gcspr); /* Break here. */
+
+ /* Avoid returning, in case libc doesn't understand GCS. */
+ exit (EXIT_SUCCESS);
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-core.exp b/gdb/testsuite/gdb.arch/aarch64-gcs-core.exp
new file mode 100644
index 0000000..9c4b7d5
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-gcs-core.exp
@@ -0,0 +1,116 @@
+# 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 reading and writing the core dump of a binary that uses a Guarded
+# Control Stack.
+
+require allow_aarch64_gcs_tests
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+ return
+}
+
+set linespec ${srcfile}:[gdb_get_line_number "Break here"]
+
+if ![runto $linespec] {
+ return
+}
+
+# Obtain an OS-generated core file. Save test program output to
+# ${binfile}.out.
+set core_filename [core_find $binfile {} {} "${binfile}.out"]
+set core_generated [expr {$core_filename != ""}]
+
+# Make sure GDB can read the given core file correctly.
+proc check_core_file {core_filename saved_gcspr} {
+ global decimal hex
+
+ # Load the core file.
+ if [gdb_test "core $core_filename" \
+ [multi_line \
+ "Core was generated by .*\\." \
+ "Program terminated with signal SIGSEGV, Segmentation fault" \
+ "Guarded Control Stack error\\." \
+ "#0 function \\(gcspr=$hex\\) at .*aarch64-gcs-core.c:$decimal" \
+ "$decimal.*__asm__ volatile \\(\"ret\\\\n\"\\);"] \
+ "load core file"] {
+ return -1
+ }
+
+ # Check the value of GCSPR in the core file.
+ gdb_test "print/x \$gcspr" "\\$\[0-9\]+ = $saved_gcspr" \
+ "gcspr contents from core file"
+}
+
+if {!$core_generated} {
+ untested "unable to create or find corefile"
+}
+
+if {$core_generated} {
+ clean_restart
+ gdb_load $binfile
+
+ with_test_prefix "OS corefile" {
+ # Read GCSPR value from saved output of the test program.
+ set out_id [open ${binfile}.out "r"]
+ set gcspr_in_core [gets $out_id]
+ close $out_id
+
+ check_core_file $core_filename $gcspr_in_core
+ }
+}
+
+if ![gcore_cmd_available] {
+ unsupported "target does not support gcore command."
+ return
+}
+
+clean_restart
+gdb_load $binfile
+
+if ![runto $linespec] {
+ return
+}
+
+# Continue until a crash. The line with the hex number is optional because
+# it's printed by the test program, and doesn't appear in the Expect buffer
+# when testing a remote target.
+gdb_test "continue" \
+ [multi_line \
+ "Continuing\\." \
+ "($hex\r\n)?" \
+ "Program received signal SIGSEGV, Segmentation fault" \
+ "Guarded Control Stack error\\." \
+ "function \\(gcspr=$hex\\) at .*aarch64-gcs-core.c:$decimal" \
+ {.*__asm__ volatile \("ret\\n"\);}] \
+ "continue to SIGSEGV"
+
+set gcspr_in_gcore [get_valueof "/x" "\$gcspr" "*unknown*"]
+
+# Generate the gcore core file.
+set gcore_filename [standard_output_file "${testfile}.gcore"]
+set gcore_generated [gdb_gcore_cmd "$gcore_filename" "generate gcore file"]
+
+gdb_assert { $gcore_generated } "gcore corefile created"
+if {$gcore_generated} {
+ clean_restart
+ gdb_load $binfile
+
+ with_test_prefix "gcore corefile" {
+ check_core_file $gcore_filename $gcspr_in_gcore
+ }
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.c b/gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.c
new file mode 100644
index 0000000..754fda1
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.c
@@ -0,0 +1,140 @@
+/* This test program 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 <stdio.h>
+#include <stdlib.h>
+#include <sys/auxv.h>
+#include <sys/syscall.h>
+#include <linux/prctl.h>
+
+/* Feature check for Guarded Control Stack. */
+#ifndef HWCAP_GCS
+#define HWCAP_GCS (1ULL << 32)
+#endif
+
+#ifndef PR_GET_SHADOW_STACK_STATUS
+#define PR_GET_SHADOW_STACK_STATUS 74
+#define PR_SET_SHADOW_STACK_STATUS 75
+#define PR_SHADOW_STACK_ENABLE (1UL << 0)
+#endif
+
+/* We need to use a macro to call prctl because after GCS is enabled, it's not
+ possible to return from the function which enabled it. This is because the
+ return address of the calling function isn't on the GCS. */
+#define my_syscall2(num, arg1, arg2) \
+ ({ \
+ register long _num __asm__("x8") = (num); \
+ register long _arg1 __asm__("x0") = (long)(arg1); \
+ register long _arg2 __asm__("x1") = (long)(arg2); \
+ register long _arg3 __asm__("x2") = 0; \
+ register long _arg4 __asm__("x3") = 0; \
+ register long _arg5 __asm__("x4") = 0; \
+ \
+ __asm__ volatile("svc #0\n" \
+ : "=r"(_arg1) \
+ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
+ "r"(_arg5), "r"(_num) \
+ : "memory", "cc"); \
+ _arg1; \
+ })
+
+#define get_gcspr(void) \
+ ({ \
+ unsigned long *gcspr; \
+ \
+ /* Get GCSPR_EL0. */ \
+ asm volatile("mrs %0, S3_3_C2_C5_1" : "=r"(gcspr) : : "cc"); \
+ \
+ gcspr; \
+ })
+
+static int __attribute__ ((noinline))
+function2 (void)
+{
+ return EXIT_SUCCESS;
+}
+
+/* Put branch and link instructions being tested into their own functions so
+ that the program returns one level up in the stack after the displaced
+ stepped instruction. This tests that GDB doesn't leave the GCS out of sync
+ with the regular stack. */
+
+static int __attribute__ ((noinline))
+function_bl (void)
+{
+ register int x0 __asm__("x0");
+
+ __asm__ ("bl function2\n"
+ : "=r"(x0)
+ :
+ : "x30");
+
+ return x0;
+}
+
+static int __attribute__ ((noinline))
+function_blr (void)
+{
+ register int x0 __asm__("x0");
+
+ __asm__ ("blr %1\n"
+ : "=r"(x0)
+ : "r"(&function2)
+ : "x30");
+
+ return x0;
+}
+
+int
+main (void)
+{
+ if (!(getauxval (AT_HWCAP) & HWCAP_GCS))
+ {
+ fprintf (stderr, "GCS support not found in AT_HWCAP\n");
+ return EXIT_FAILURE;
+ }
+
+ /* Force shadow stacks on, our tests *should* be fine with or
+ without libc support and with or without this having ended
+ up tagged for GCS and enabled by the dynamic linker. We
+ can't use the libc prctl() function since we can't return
+ from enabling the stack. */
+ unsigned long gcs_mode;
+ int ret = my_syscall2 (__NR_prctl, PR_GET_SHADOW_STACK_STATUS, &gcs_mode);
+ if (ret)
+ {
+ fprintf (stderr, "Failed to read GCS state: %d\n", ret);
+ return EXIT_FAILURE;
+ }
+
+ if (!(gcs_mode & PR_SHADOW_STACK_ENABLE))
+ {
+ gcs_mode = PR_SHADOW_STACK_ENABLE;
+ ret = my_syscall2 (__NR_prctl, PR_SET_SHADOW_STACK_STATUS, gcs_mode);
+ if (ret)
+ {
+ fprintf (stderr, "Failed to configure GCS: %d\n", ret);
+ return EXIT_FAILURE;
+ }
+ }
+
+ int ret1 = function_bl ();
+ int ret2 = function_blr ();
+
+ /* Avoid returning, in case libc doesn't understand GCS. */
+ exit (ret1 + ret2);
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.exp b/gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.exp
new file mode 100644
index 0000000..2359d96
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.exp
@@ -0,0 +1,86 @@
+# 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 displaced stepping in a program that uses a Guarded Control Stack.
+
+require allow_aarch64_gcs_tests
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
+ return
+}
+
+if ![runto_main] {
+ return
+}
+
+gdb_test_no_output "set breakpoint auto-hw off"
+gdb_test_no_output "set displaced-stepping on"
+
+# Get address of the branch and link instructions of interest.
+set addr_bl 0
+set test "get address of bl instruction"
+gdb_test_multiple "disassemble function_bl" $test -lbl {
+ -re "\r\n\\s+($hex) <\\+${decimal}>:\\s+bl\\s+${hex} <function2>(?=\r\n)" {
+ set addr_bl $expect_out(1,string)
+ exp_continue
+ }
+ -re -wrap "" {
+ gdb_assert { $addr_bl != 0 } $test
+ }
+}
+
+set addr_blr 0
+set test "get address of blr instruction"
+gdb_test_multiple "disassemble function_blr" $test -lbl {
+ -re "\r\n\\s+($hex) <\\+${decimal}>:\\s+blr\\s+x${decimal}(?=\r\n)" {
+ set addr_blr $expect_out(1,string)
+ exp_continue
+ }
+ -re -wrap "" {
+ gdb_assert { $addr_blr != 0 } $test
+ }
+}
+
+if { $addr_bl == 0 || $addr_blr == 0 } {
+ return
+}
+
+gdb_test "break *$addr_bl" \
+ "Breakpoint $decimal at $hex: file .*aarch64-gcs-disp-step.c, line ${decimal}." \
+ "set breakpoint at bl instruction"
+
+gdb_test "break *$addr_blr" \
+ "Breakpoint $decimal at $hex: file .*aarch64-gcs-disp-step.c, line ${decimal}." \
+ "set breakpoint at blr instruction"
+
+gdb_test "continue" \
+ [multi_line \
+ {Continuing\.} \
+ "" \
+ "Breakpoint $decimal, function_bl \\(\\) at .*aarch64-gcs-disp-step.c:${decimal}(?: \\\[GCS error\\\])?" \
+ {[^\r\n]+"bl function2\\n"}] \
+ "continue to breakpoint at bl"
+
+gdb_test "continue" \
+ [multi_line \
+ {Continuing\.} \
+ "" \
+ "Breakpoint $decimal, $hex in function_blr \\(\\) at .*aarch64-gcs-disp-step.c:${decimal}(?: \\\[GCS error\\\])?" \
+ {[^\r\n]+"blr %1\\n"}] \
+ "continue to breakpoint at blr"
+
+gdb_continue_to_end
diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-return.c b/gdb/testsuite/gdb.arch/aarch64-gcs-return.c
new file mode 100644
index 0000000..c062fea
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-gcs-return.c
@@ -0,0 +1,105 @@
+/* This test program 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 <stdio.h>
+#include <stdlib.h>
+#include <sys/auxv.h>
+#include <sys/syscall.h>
+#include <linux/prctl.h>
+
+/* Feature check for Guarded Control Stack. */
+#ifndef HWCAP_GCS
+#define HWCAP_GCS (1ULL << 32)
+#endif
+
+#ifndef PR_GET_SHADOW_STACK_STATUS
+#define PR_GET_SHADOW_STACK_STATUS 74
+#define PR_SET_SHADOW_STACK_STATUS 75
+#define PR_SHADOW_STACK_ENABLE (1UL << 0)
+#endif
+
+/* We need to use a macro to call prctl because after GCS is enabled, it's not
+ possible to return from the function which enabled it. This is because the
+ return address of the calling function isn't on the GCS. */
+#define my_syscall2(num, arg1, arg2) \
+ ({ \
+ register long _num __asm__("x8") = (num); \
+ register long _arg1 __asm__("x0") = (long)(arg1); \
+ register long _arg2 __asm__("x1") = (long)(arg2); \
+ register long _arg3 __asm__("x2") = 0; \
+ register long _arg4 __asm__("x3") = 0; \
+ register long _arg5 __asm__("x4") = 0; \
+ \
+ __asm__ volatile("svc #0\n" \
+ : "=r"(_arg1) \
+ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
+ "r"(_arg5), "r"(_num) \
+ : "memory", "cc"); \
+ _arg1; \
+ })
+
+static int __attribute__ ((noinline))
+call2 ()
+{
+ return 42; /* Break call2. */
+}
+
+static int __attribute__ ((noinline))
+call1 ()
+{
+ return call2 (); /* Break call1. */
+}
+
+int
+main ()
+{
+ if (!(getauxval (AT_HWCAP) & HWCAP_GCS))
+ {
+ fprintf (stderr, "GCS support not found in AT_HWCAP\n");
+ return EXIT_FAILURE;
+ }
+
+ /* Force shadow stacks on, our tests *should* be fine with or
+ without libc support and with or without this having ended
+ up tagged for GCS and enabled by the dynamic linker. We
+ can't use the libc prctl() function since we can't return
+ from enabling the stack. Also lock GCS if not already
+ locked so we can test behaviour when it's locked. */
+ unsigned long gcs_mode;
+ int ret = my_syscall2 (__NR_prctl, PR_GET_SHADOW_STACK_STATUS, &gcs_mode);
+ if (ret)
+ {
+ fprintf (stderr, "Failed to read GCS state: %d\n", ret);
+ return EXIT_FAILURE;
+ }
+
+ if (!(gcs_mode & PR_SHADOW_STACK_ENABLE))
+ {
+ gcs_mode = PR_SHADOW_STACK_ENABLE;
+ ret = my_syscall2 (__NR_prctl, PR_SET_SHADOW_STACK_STATUS, gcs_mode);
+ if (ret)
+ {
+ fprintf (stderr, "Failed to configure GCS: %d\n", ret);
+ return EXIT_FAILURE;
+ }
+ }
+
+ call1 (); /* Break begin. */
+
+ /* Avoid returning, in case libc doesn't understand GCS. */
+ exit (EXIT_SUCCESS);
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-return.exp b/gdb/testsuite/gdb.arch/aarch64-gcs-return.exp
new file mode 100644
index 0000000..6f695da
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-gcs-return.exp
@@ -0,0 +1,132 @@
+# 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 the GDB return command in a program that uses a Guarded Control Stack.
+# Based on the return tests in gdb.arch/amd64-shadow-stack-cmds.exp.
+# Note that potential GCS violations often only occur after resuming normal
+# execution. Therefore, it is important to test normal program
+# completion after testing the return command.
+
+require allow_aarch64_gcs_tests
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
+ return
+}
+
+set begin_line [gdb_get_line_number "Break begin"]
+set call1_line [gdb_get_line_number "Break call1"]
+set call2_line [gdb_get_line_number "Break call2"]
+
+if ![runto ${begin_line}] {
+ return
+}
+
+proc restart_and_run_infcall_call2 {} {
+ global binfile call2_line
+ clean_restart
+ gdb_load $binfile
+ if ![runto_main] {
+ return
+ }
+ set inside_infcall_str "The program being debugged stopped while in a function called from GDB"
+ gdb_breakpoint ${call2_line}
+ gdb_continue_to_breakpoint "Break call2" ".*Break call2.*"
+ gdb_test "call (int) call2()" \
+ "Breakpoint \[0-9\]*, call2.*$inside_infcall_str.*"
+}
+
+with_test_prefix "test inferior call and continue" {
+ gdb_breakpoint ${call1_line}
+ gdb_continue_to_breakpoint "Break call1" ".*Break call1.*"
+
+ gdb_test "call (int) call2()" "= 42"
+
+ gdb_continue_to_end
+}
+
+with_test_prefix "test return inside an inferior call" {
+ restart_and_run_infcall_call2
+
+ gdb_test "return" "\#0.*call2.*" \
+ "Test GCS return inside an inferior call" \
+ "Make.*return now\\? \\(y or n\\) " "y"
+
+ gdb_continue_to_end
+}
+
+with_test_prefix "test return 'above' an inferior call" {
+ restart_and_run_infcall_call2
+
+ gdb_test "frame 2" "call2 ().*" "move to frame 'above' inferior call"
+
+ gdb_test "return" "\#0.*call1.*" \
+ "Test GCS return 'above' an inferior call" \
+ "Make.*return now\\? \\(y or n\\) " "y"
+
+ gdb_continue_to_end
+}
+
+clean_restart
+gdb_load $binfile
+if ![runto ${begin_line}] {
+ return
+}
+
+# Extract GCS pointer inside main, call1 and call2 function.
+gdb_breakpoint ${call1_line}
+gdb_breakpoint ${call2_line}
+set gcspr_main [get_valueof /x "\$gcspr" 0 "get value of gcspr in main"]
+gdb_continue_to_breakpoint "Break call1" ".*Break call1.*"
+set gcspr_call1 [get_valueof /x "\$gcspr" 0 "get value of gcspr in call1"]
+gdb_continue_to_breakpoint "Break call2" ".*Break call2.*"
+set gcspr_call2 [get_valueof /x "\$gcspr" 0 "get value of gcspr in call2"]
+
+with_test_prefix "test frame level update" {
+ gdb_test "up" "call1.*" "move to frame 1"
+ gdb_test "print /x \$gcspr" "= $gcspr_call1" "check gcspr of frame 1"
+ gdb_test "up" "main.*" "move to frame 2"
+ gdb_test "print /x \$gcspr" "= $gcspr_main" "check gcspr of frame 2"
+ gdb_test "frame 0" "call2.*" "move to frame 0"
+ gdb_test "print /x \$gcspr" "= $gcspr_call2" "check gcspr of frame 0"
+}
+
+with_test_prefix "test return from current frame" {
+ gdb_test "return (int) 1" "#0.*call1.*" \
+ "Test GCS return from current frame" \
+ "Make.*return now\\? \\(y or n\\) " "y"
+
+ gdb_continue_to_end
+}
+
+clean_restart
+gdb_load $binfile
+if ![runto_main] {
+ return
+}
+
+with_test_prefix "test return from past frame" {
+ gdb_breakpoint ${call2_line}
+ gdb_continue_to_breakpoint "Break call2" ".*Break call2.*"
+
+ gdb_test "frame 1" ".*in call1.*"
+
+ gdb_test "return (int) 1" "#0.*main.*" \
+ "Test GCS return from past frame" \
+ "Make.*return now\\? \\(y or n\\) " "y"
+
+ gdb_continue_to_end
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-tdesc-without-linux.xml b/gdb/testsuite/gdb.arch/aarch64-gcs-tdesc-without-linux.xml
new file mode 100644
index 0000000..056ab58
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-gcs-tdesc-without-linux.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0"?>
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>aarch64</architecture>
+ <feature name="org.gnu.gdb.aarch64.core">
+ <flags id="cpsr_flags" size="4">
+ <field name="SP" start="0" end="0" type="bool"/>
+ <field name="EL" start="2" end="3" type="uint32"/>
+ <field name="nRW" start="4" end="4" type="bool"/>
+ <field name="F" start="6" end="6" type="bool"/>
+ <field name="I" start="7" end="7" type="bool"/>
+ <field name="A" start="8" end="8" type="bool"/>
+ <field name="D" start="9" end="9" type="bool"/>
+ <field name="BTYPE" start="10" end="11" type="uint32"/>
+ <field name="SSBS" start="12" end="12" type="bool"/>
+ <field name="IL" start="20" end="20" type="bool"/>
+ <field name="SS" start="21" end="21" type="bool"/>
+ <field name="PAN" start="22" end="22" type="bool"/>
+ <field name="UAO" start="23" end="23" type="bool"/>
+ <field name="DIT" start="24" end="24" type="bool"/>
+ <field name="TCO" start="25" end="25" type="bool"/>
+ <field name="V" start="28" end="28" type="bool"/>
+ <field name="C" start="29" end="29" type="bool"/>
+ <field name="Z" start="30" end="30" type="bool"/>
+ <field name="N" start="31" end="31" type="bool"/>
+ </flags>
+ <reg name="x0" bitsize="64" type="int" regnum="0"/>
+ <reg name="x1" bitsize="64" type="int" regnum="1"/>
+ <reg name="x2" bitsize="64" type="int" regnum="2"/>
+ <reg name="x3" bitsize="64" type="int" regnum="3"/>
+ <reg name="x4" bitsize="64" type="int" regnum="4"/>
+ <reg name="x5" bitsize="64" type="int" regnum="5"/>
+ <reg name="x6" bitsize="64" type="int" regnum="6"/>
+ <reg name="x7" bitsize="64" type="int" regnum="7"/>
+ <reg name="x8" bitsize="64" type="int" regnum="8"/>
+ <reg name="x9" bitsize="64" type="int" regnum="9"/>
+ <reg name="x10" bitsize="64" type="int" regnum="10"/>
+ <reg name="x11" bitsize="64" type="int" regnum="11"/>
+ <reg name="x12" bitsize="64" type="int" regnum="12"/>
+ <reg name="x13" bitsize="64" type="int" regnum="13"/>
+ <reg name="x14" bitsize="64" type="int" regnum="14"/>
+ <reg name="x15" bitsize="64" type="int" regnum="15"/>
+ <reg name="x16" bitsize="64" type="int" regnum="16"/>
+ <reg name="x17" bitsize="64" type="int" regnum="17"/>
+ <reg name="x18" bitsize="64" type="int" regnum="18"/>
+ <reg name="x19" bitsize="64" type="int" regnum="19"/>
+ <reg name="x20" bitsize="64" type="int" regnum="20"/>
+ <reg name="x21" bitsize="64" type="int" regnum="21"/>
+ <reg name="x22" bitsize="64" type="int" regnum="22"/>
+ <reg name="x23" bitsize="64" type="int" regnum="23"/>
+ <reg name="x24" bitsize="64" type="int" regnum="24"/>
+ <reg name="x25" bitsize="64" type="int" regnum="25"/>
+ <reg name="x26" bitsize="64" type="int" regnum="26"/>
+ <reg name="x27" bitsize="64" type="int" regnum="27"/>
+ <reg name="x28" bitsize="64" type="int" regnum="28"/>
+ <reg name="x29" bitsize="64" type="int" regnum="29"/>
+ <reg name="x30" bitsize="64" type="int" regnum="30"/>
+ <reg name="sp" bitsize="64" type="data_ptr" regnum="31"/>
+ <reg name="pc" bitsize="64" type="code_ptr" regnum="32"/>
+ <reg name="cpsr" bitsize="32" type="cpsr_flags" regnum="33"/>
+ </feature>
+ <feature name="org.gnu.gdb.aarch64.gcs">
+ <reg name="gcspr" bitsize="64" type="data_ptr" regnum="90" group="system"/>
+ </feature>
+</target>
diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.c b/gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.c
new file mode 100644
index 0000000..10cf749
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.c
@@ -0,0 +1,26 @@
+/* This test program 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 <stdio.h>
+
+int
+main (void)
+{
+ printf ("Hello, world!\n");
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.exp b/gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.exp
new file mode 100644
index 0000000..f0508cd
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.exp
@@ -0,0 +1,48 @@
+# 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 that GDB complains when given a target description with the GCS feature
+# but not the GCS Linux feature.
+
+require allow_aarch64_gcs_tests
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
+ return
+}
+
+set xml_path "${srcdir}/${subdir}/aarch64-gcs-tdesc-without-linux.xml"
+
+gdb_test "set tdesc filename ${xml_path}" \
+ "warning: Incomplete GCS support in the target: missing Linux part. GCS feature disabled." \
+ "warn about incomplete GCS support"
+
+# We can't test a debugging session on a remote target because with the
+# wrong tdesc, GDB expects a g packet reply with the wrong size.
+if {[gdb_protocol_is_remote]} {
+ return
+}
+
+if ![runto_main] {
+ return
+}
+
+gdb_test "print \$gcspr" " = <unavailable>" "GCSPR is unavailable"
+
+# Now check that we can continue the debugging session normally.
+gdb_test "next"
+
+gdb_continue_to_end
diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs.c b/gdb/testsuite/gdb.arch/aarch64-gcs.c
new file mode 100644
index 0000000..9eb2e9e
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-gcs.c
@@ -0,0 +1,180 @@
+/* This test program 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 <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/auxv.h>
+#include <sys/syscall.h>
+#include <linux/prctl.h>
+
+/* Feature check for Guarded Control Stack. */
+#ifndef HWCAP_GCS
+#define HWCAP_GCS (1ULL << 32)
+#endif
+
+#ifndef PR_GET_SHADOW_STACK_STATUS
+#define PR_GET_SHADOW_STACK_STATUS 74
+#define PR_SET_SHADOW_STACK_STATUS 75
+#define PR_SHADOW_STACK_ENABLE (1UL << 0)
+#endif
+
+/* We need to use a macro to call prctl because after GCS is enabled, it's not
+ possible to return from the function which enabled it. This is because the
+ return address of the calling function isn't on the GCS. */
+#define my_syscall2(num, arg1, arg2) \
+ ({ \
+ register long _num __asm__("x8") = (num); \
+ register long _arg1 __asm__("x0") = (long)(arg1); \
+ register long _arg2 __asm__("x1") = (long)(arg2); \
+ register long _arg3 __asm__("x2") = 0; \
+ register long _arg4 __asm__("x3") = 0; \
+ register long _arg5 __asm__("x4") = 0; \
+ \
+ __asm__ volatile ("svc #0\n" \
+ : "=r"(_arg1) \
+ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
+ "r"(_arg5), "r"(_num) \
+ : "memory", "cc"); \
+ _arg1; \
+ })
+
+#define get_gcspr(void) \
+ ({ \
+ unsigned long *gcspr; \
+ \
+ /* Get GCSPR_EL0. */ \
+ asm volatile ("mrs %0, S3_3_C2_C5_1" : "=r"(gcspr) : : "cc"); \
+ \
+ gcspr; \
+ })
+
+static unsigned long *handler_gcspr = 0;
+
+static void
+handler (int sig)
+{
+ handler_gcspr = get_gcspr ();
+}
+
+static int __attribute__ ((unused))
+called_from_gdb (int val)
+{
+ return val + 1;
+}
+
+/* Corrupt the return address to see if GDB will report a SIGSEGV with the
+ expected $_siginfo.si_code. */
+static void __attribute__ ((noinline))
+normal_function2 (void)
+{
+ /* x30 holds the return address. */
+ register unsigned long x30 __asm__("x30") __attribute__ ((unused));
+
+ /* Cause a GCS exception. */
+ x30 = 0xbadc0ffee;
+ /* Use explicit ret so that we can verify that a SIGSEGV was generated
+ exactly on the return instruction. */
+ __asm__ volatile ("ret\n");
+}
+
+static inline void __attribute__ ((__always_inline__))
+inline_function2 (void)
+{
+ normal_function2 ();
+}
+
+static void __attribute__ ((noinline))
+normal_function1 (void)
+{
+ inline_function2 ();
+}
+
+/* First in a sequence of inline and normal functions, to test GDB
+ backtrace. */
+static inline void __attribute__ ((__always_inline__))
+inline_function1 (void)
+{
+ normal_function1 ();
+}
+
+/* Trivial function, just so that GDB can test return with wrong GCSPR. */
+static void __attribute__ ((noinline))
+normal_function0 (void)
+{
+ /* Use explicit ret so that we can verify that a SIGSEGV was generated
+ exactly on the return instruction. */
+ __asm__ volatile ("ret\n");
+}
+
+int
+main (void)
+{
+ if (!(getauxval (AT_HWCAP) & HWCAP_GCS))
+ {
+ fprintf (stderr, "GCS support not found in AT_HWCAP\n");
+ return EXIT_FAILURE;
+ }
+
+ /* Force shadow stacks on, our tests *should* be fine with or
+ without libc support and with or without this having ended
+ up tagged for GCS and enabled by the dynamic linker. We
+ can't use the libc prctl() function since we can't return
+ from enabling the stack. Also lock GCS if not already
+ locked so we can test behaviour when it's locked. */
+ unsigned long gcs_mode;
+ int ret = my_syscall2 (__NR_prctl, PR_GET_SHADOW_STACK_STATUS, &gcs_mode);
+ if (ret)
+ {
+ fprintf (stderr, "Failed to read GCS state: %d\n", ret);
+ return EXIT_FAILURE;
+ }
+
+ if (!(gcs_mode & PR_SHADOW_STACK_ENABLE))
+ {
+ gcs_mode = PR_SHADOW_STACK_ENABLE;
+ ret = my_syscall2 (__NR_prctl, PR_SET_SHADOW_STACK_STATUS, gcs_mode);
+ if (ret)
+ {
+ fprintf (stderr, "Failed to configure GCS: %d\n", ret);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Regular function call. */
+ normal_function0 ();
+
+ /* This is used by GDB. */
+ __attribute__((unused)) unsigned long *gcspr = get_gcspr ();
+
+ struct sigaction act = { 0 };
+
+ act.sa_handler = &handler; /* Break here. */
+ if (sigaction (SIGUSR1, &act, NULL) == -1)
+ {
+ perror ("sigaction");
+ exit (EXIT_FAILURE);
+ }
+
+ raise (SIGUSR1);
+
+/* Call sequence of inline and normal functions, to test GDB backtrace. */
+ inline_function1 ();
+
+ /* Avoid returning, in case libc doesn't understand GCS. */
+ exit (EXIT_SUCCESS);
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs.exp b/gdb/testsuite/gdb.arch/aarch64-gcs.exp
new file mode 100644
index 0000000..b09e010
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-gcs.exp
@@ -0,0 +1,99 @@
+# 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 a binary that uses a Guarded Control Stack.
+
+require allow_aarch64_gcs_tests
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
+ return
+}
+
+set linespec ${srcfile}:[gdb_get_line_number "Break here"]
+
+if ![runto ${linespec}] {
+ return
+}
+
+gdb_test "print \$gcs_features_enabled" \
+ [string_to_regexp { = [ PR_SHADOW_STACK_ENABLE ]}] \
+ "GCS is enabled"
+
+gdb_test "print \$gcspr" ". = \\(void \\*\\) $hex" "GDB knows about gcspr"
+gdb_test "print \$gcspr == gcspr" ". = 1" "GDB has the correct gcspr value"
+gdb_test_no_output "set \$gcspr_in_main = \$gcspr" \
+ "save gcspr value in main for later"
+
+# If the inferior function call fails, we don't want the tests following it
+# to be affected.
+gdb_test_no_output "set unwindonsignal on"
+gdb_test "print called_from_gdb (41)" ". = 42" "call inferior function"
+
+gdb_test "break handler" "Breakpoint \[0-9\]+ .*aarch64-gcs.c, line \[0-9\]+\\."
+gdb_test "handle SIGUSR1 nostop" \
+ ".*\r\nSIGUSR1\\s+No\\s+Yes\\s+Yes\\s+User defined signal 1" \
+ "let the inferior receive SIGUSR1 uninterrupted"
+gdb_test "continue" \
+ ".*\r\nBreakpoint \[0-9\]+, handler \\(sig=10\\) at .*aarch64-gcs.c.*handler_gcspr = get_gcspr \\(\\);" \
+ "continue to signal handler"
+
+gdb_test_no_output "set \$gcspr_in_handler = \$gcspr" \
+ "save gcspr value in handler for later"
+# Select the frame above the <signal handler called> frame, which makes GDB
+# unwind the gcspr from the signal frame GCS context.
+gdb_test "frame 2" "#2 ($hex in )?\\S+ \\(.*\\) (at|from) \\S+.*" \
+ "reached frame 2"
+gdb_test "print \$gcspr" ". = \\(void \\*\\) $hex" "gcspr in frame level 2"
+gdb_test "print \$gcspr == \$gcspr_in_handler + 8" ". = 1" \
+ "gcspr unwound from signal context is correct"
+
+gdb_test "continue" \
+ [multi_line \
+ "Continuing\\." \
+ "" \
+ "Program received signal SIGSEGV, Segmentation fault" \
+ "Guarded Control Stack error\\." \
+ "normal_function2 \\(\\) at .*aarch64-gcs.c:$decimal" \
+ "${decimal}\\s+__asm__ volatile \\(\"ret\\\\n\"\\);"] \
+ "continue to SIGSEGV"
+
+gdb_test "print \$_siginfo.si_code" ". = 10" \
+ "test value of si_code when GCS SIGSEGV happens"
+# The GCS grows down, and there are two real frames until main.
+gdb_test "print \$gcspr == \$gcspr_in_main - 16" ". = 1" \
+ "test value of gcspr when GCS SIGSEGV happens"
+
+# Test writing to GCSPR.
+clean_restart
+gdb_load $binfile
+if ![runto normal_function0] {
+ return
+}
+
+gdb_test_no_output "set \$gcspr = 0xbadc0ffee" "set bogus gcspr value"
+# Continue to make sure that the value was actually written to the register.
+# The SIGSEGV isn't a GCS error because the problem isn't that the GCS entry
+# doesn't match the return address, but rather that that GCSPR is pointing
+# to an invalid address.
+gdb_test "continue" \
+ [multi_line \
+ "Continuing\\." \
+ "" \
+ "Program received signal SIGSEGV, Segmentation fault\\." \
+ "normal_function0 \\(\\) at .*aarch64-gcs.c:$decimal" \
+ "${decimal}\\s+__asm__ volatile \\(\"ret\\\\n\"\\);"] \
+ "continue after bad gcspr"
diff --git a/gdb/testsuite/gdb.arch/aarch64-mte-core.exp b/gdb/testsuite/gdb.arch/aarch64-mte-core.exp
index fdaa061..7da836e 100644
--- a/gdb/testsuite/gdb.arch/aarch64-mte-core.exp
+++ b/gdb/testsuite/gdb.arch/aarch64-mte-core.exp
@@ -145,7 +145,8 @@ proc test_mode { mode } {
# both correctly.
if {$gcore_generated} {
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
with_test_prefix "gcore corefile" {
test_mte_core_file $gcore_filename $mode
}
@@ -154,7 +155,8 @@ proc test_mode { mode } {
}
if {$core_generated} {
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
with_test_prefix "native corefile" {
test_mte_core_file $core_filename $mode
}
diff --git a/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp
index 7ce1fdf..e835ddf 100644
--- a/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp
+++ b/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp
@@ -29,7 +29,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} \
return -1
}
-clean_restart ${binfile}
+clean_restart $testfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl b/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl
index 44d0808..64cfd54 100644
--- a/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl
@@ -91,7 +91,8 @@ proc generate_sme_core_files { executable binfile id state vl svl} {
# and the native one generated by the Linux Kernel. Make sure GDB can read
# both correctly.
if {$gcore_generated} {
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
gdb_test_no_output "set print repeats 1" \
"adjust repeat count post-crash gcore"
@@ -103,7 +104,8 @@ proc generate_sme_core_files { executable binfile id state vl svl} {
}
if {$core_generated} {
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
gdb_test_no_output "set print repeats 1" \
"adjust repeat count post-crash native core"
diff --git a/gdb/testsuite/gdb.arch/alpha-step.exp b/gdb/testsuite/gdb.arch/alpha-step.exp
index e41bd97..bdbfeec 100644
--- a/gdb/testsuite/gdb.arch/alpha-step.exp
+++ b/gdb/testsuite/gdb.arch/alpha-step.exp
@@ -25,7 +25,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {}] !
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
proc test_stepi {function } {
# Restart the program from scratch. If GDB got confused during one
diff --git a/gdb/testsuite/gdb.arch/altivec-abi.exp b/gdb/testsuite/gdb.arch/altivec-abi.exp
index 12f523b..fb5367d 100644
--- a/gdb/testsuite/gdb.arch/altivec-abi.exp
+++ b/gdb/testsuite/gdb.arch/altivec-abi.exp
@@ -47,7 +47,8 @@ proc altivec_abi_tests { extra_flags force_abi } {
}
}
- clean_restart $binfile
+ clean_restart
+ gdb_load $::binfile
# Run to `main' where we begin our tests.
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.arch/amd64-byte.exp b/gdb/testsuite/gdb.arch/amd64-byte.exp
index ac70672..d084303 100644
--- a/gdb/testsuite/gdb.arch/amd64-byte.exp
+++ b/gdb/testsuite/gdb.arch/amd64-byte.exp
@@ -27,7 +27,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list
return
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.arch/amd64-disp-step-avx.exp b/gdb/testsuite/gdb.arch/amd64-disp-step-avx.exp
index 08d73d8..b11efa7 100644
--- a/gdb/testsuite/gdb.arch/amd64-disp-step-avx.exp
+++ b/gdb/testsuite/gdb.arch/amd64-disp-step-avx.exp
@@ -19,6 +19,7 @@
# instructions.
require is_x86_64_m64_target have_avx
+require support_displaced_stepping
standard_testfile .S
diff --git a/gdb/testsuite/gdb.arch/amd64-disp-step-self-call-alarm.c b/gdb/testsuite/gdb.arch/amd64-disp-step-self-call-alarm.c
index 03b868c..0fb2904 100644
--- a/gdb/testsuite/gdb.arch/amd64-disp-step-self-call-alarm.c
+++ b/gdb/testsuite/gdb.arch/amd64-disp-step-self-call-alarm.c
@@ -16,9 +16,27 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <unistd.h>
+#include <stdlib.h>
+
+extern void test_call (void);
+
+void
+unreachable (void)
+{
+ abort ();
+}
void
setup_alarm (void)
{
alarm (300);
}
+
+int
+main ()
+{
+ setup_alarm ();
+ test_call ();
+ unreachable ();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-disp-step-self-call.S b/gdb/testsuite/gdb.arch/amd64-disp-step-self-call.S
index 78a6859..20a8eb7 100644
--- a/gdb/testsuite/gdb.arch/amd64-disp-step-self-call.S
+++ b/gdb/testsuite/gdb.arch/amd64-disp-step-self-call.S
@@ -18,33 +18,12 @@
handling. */
.text
-
- .global main
-main:
- nop
-
- callq setup_alarm
-
- nop
-
-/***********************************************/
-
-/* test call/ret */
-
.global test_call
test_call:
call test_call
- nop
+ call unreachable
.global test_ret_end
test_ret_end:
nop
-/***********************************************/
-
-/* all done */
-
-done:
- mov $0,%rdi
- call exit
- hlt
.section .note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.arch/amd64-dword.exp b/gdb/testsuite/gdb.arch/amd64-dword.exp
index e8a527d..cd3d76b 100644
--- a/gdb/testsuite/gdb.arch/amd64-dword.exp
+++ b/gdb/testsuite/gdb.arch/amd64-dword.exp
@@ -27,7 +27,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list
return
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis-no-cfi.S b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis-no-cfi.S
new file mode 100644
index 0000000..39cf3e6
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis-no-cfi.S
@@ -0,0 +1,117 @@
+/* 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 is compiled from gdb.arch/amd64-extended-prologue-analysis.c
+ using gcc 11.4.0 with flags: -g0 -O1 -S -fno-omit-frame-pointer
+ -fno-asynchronous-unwind-tables. */
+
+ .file "amd64-extended-prologue-analysis.c"
+ .text
+ .globl bar
+ .type bar, @function
+bar:
+ endbr64
+ leal (%rdi,%rdi), %eax
+ ret
+ .size bar, .-bar
+ .globl foo
+ .type foo, @function
+foo:
+ endbr64
+ pushq %rbp
+ movq %rsp, %rbp
+ pushq %r15
+ pushq %r14
+ pushq %r13
+ pushq %r12
+ pushq %rbx
+ subq $280, %rsp
+ movl %edi, %ebx
+ movl %esi, %r14d
+ movl %edx, %r13d
+ movl %ecx, %r12d
+ movq %fs:40, %rax
+ movq %rax, -56(%rbp)
+ xorl %eax, %eax
+.L3:
+ leal (%rbx,%rax), %ecx
+ movslq %eax, %rdx
+ movb %cl, -320(%rbp,%rdx)
+ addl $1, %eax
+ cmpl $256, %eax
+ jne .L3
+ movl %ebx, %edi
+ call bar
+ movl %eax, %r15d
+ movl %r14d, %edi
+ call bar
+ leal (%r15,%rax), %r14d
+ movl %r13d, %edi
+ call bar
+ addl %eax, %r14d
+ movl %r12d, %edi
+ call bar
+ addl %r14d, %eax
+ addl %ebx, %eax
+ movq -56(%rbp), %rdx
+ subq %fs:40, %rdx
+ jne .L7
+ addq $280, %rsp
+ popq %rbx
+ popq %r12
+ popq %r13
+ popq %r14
+ popq %r15
+ popq %rbp
+ ret
+.L7:
+ call __stack_chk_fail@PLT
+ .size foo, .-foo
+ .globl main
+ .type main, @function
+main:
+ endbr64
+ pushq %rbp
+ movq %rsp, %rbp
+ subq $16, %rsp
+ leal (%rdi,%rdi), %ecx
+ leal 2(%rdi), %edx
+ leal 1(%rdi), %esi
+ call foo
+ movl %eax, -4(%rbp)
+ movl -4(%rbp), %eax
+ leave
+ ret
+ .size main, .-main
+ .ident "GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0"
+ .section .note.GNU-stack,"",@progbits
+ .section .note.gnu.property,"a"
+ .align 8
+ .long 1f - 0f
+ .long 4f - 1f
+ .long 5
+0:
+ .string "GNU"
+1:
+ .align 8
+ .long 0xc0000002
+ .long 3f - 2f
+2:
+ .long 0x3
+3:
+ .align 8
+4:
diff --git a/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis-offset.S b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis-offset.S
new file mode 100644
index 0000000..ea001b3
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis-offset.S
@@ -0,0 +1,112 @@
+/* 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 is compiled from gdb.arch/amd64-extended-prologue-analysis.c
+ using gcc 11.4.0 with flags: -g0 -O1 -S -fomit-frame-pointer
+ -fno-asynchronous-unwind-tables. */
+
+ .file "amd64-extended-prologue-analysis.c"
+ .text
+ .globl bar
+ .type bar, @function
+bar:
+ endbr64
+ leal (%rdi,%rdi), %eax
+ ret
+ .size bar, .-bar
+ .globl foo
+ .type foo, @function
+foo:
+ endbr64
+ pushq %r14
+ pushq %r13
+ pushq %r12
+ pushq %rbp
+ pushq %rbx
+ subq $272, %rsp
+ movl %edi, %ebx
+ movl %esi, %r13d
+ movl %edx, %r12d
+ movl %ecx, %ebp
+ movq %fs:40, %rax
+ movq %rax, 264(%rsp)
+ xorl %eax, %eax
+.L3:
+ leal (%rbx,%rax), %ecx
+ movslq %eax, %rdx
+ movb %cl, (%rsp,%rdx)
+ addl $1, %eax
+ cmpl $256, %eax
+ jne .L3
+ movl %ebx, %edi
+ call bar
+ movl %eax, %r14d
+ movl %r13d, %edi
+ call bar
+ leal (%r14,%rax), %r13d
+ movl %r12d, %edi
+ call bar
+ addl %eax, %r13d
+ movl %ebp, %edi
+ call bar
+ addl %r13d, %eax
+ addl %ebx, %eax
+ movq 264(%rsp), %rdx
+ subq %fs:40, %rdx
+ jne .L7
+ addq $272, %rsp
+ popq %rbx
+ popq %rbp
+ popq %r12
+ popq %r13
+ popq %r14
+ ret
+.L7:
+ call __stack_chk_fail@PLT
+ .size foo, .-foo
+ .globl main
+ .type main, @function
+main:
+ endbr64
+ subq $24, %rsp
+ leal (%rdi,%rdi), %ecx
+ leal 2(%rdi), %edx
+ leal 1(%rdi), %esi
+ call foo
+ movl %eax, 12(%rsp)
+ movl 12(%rsp), %eax
+ addq $24, %rsp
+ ret
+ .size main, .-main
+ .ident "GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0"
+ .section .note.GNU-stack,"",@progbits
+ .section .note.gnu.property,"a"
+ .align 8
+ .long 1f - 0f
+ .long 4f - 1f
+ .long 5
+0:
+ .string "GNU"
+1:
+ .align 8
+ .long 0xc0000002
+ .long 3f - 2f
+2:
+ .long 0x3
+3:
+ .align 8
+4:
diff --git a/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.S b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.S
new file mode 100644
index 0000000..691eee0
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.S
@@ -0,0 +1,143 @@
+/* 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 is compiled from gdb.arch/amd64-extended-prologue-analysis.c
+ using gcc 11.4.0 with flags: -g0 -O1 -S -fno-omit-frame-pointer. */
+
+ .file "amd64-extended-prologue-analysis.c"
+ .text
+ .globl bar
+ .type bar, @function
+bar:
+.LFB0:
+ .cfi_startproc
+ endbr64
+ leal (%rdi,%rdi), %eax
+ ret
+ .cfi_endproc
+.LFE0:
+ .size bar, .-bar
+ .globl foo
+ .type foo, @function
+foo:
+.LFB1:
+ .cfi_startproc
+ endbr64
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ pushq %r15
+ pushq %r14
+ pushq %r13
+ pushq %r12
+ pushq %rbx
+ subq $280, %rsp
+ .cfi_offset 15, -24
+ .cfi_offset 14, -32
+ .cfi_offset 13, -40
+ .cfi_offset 12, -48
+ .cfi_offset 3, -56
+ movl %edi, %ebx
+ movl %esi, %r14d
+ movl %edx, %r13d
+ movl %ecx, %r12d
+ movq %fs:40, %rax
+ movq %rax, -56(%rbp)
+ xorl %eax, %eax
+.L3:
+ leal (%rbx,%rax), %ecx
+ movslq %eax, %rdx
+ movb %cl, -320(%rbp,%rdx)
+ addl $1, %eax
+ cmpl $256, %eax
+ jne .L3
+ movl %ebx, %edi
+ call bar
+ movl %eax, %r15d
+ movl %r14d, %edi
+ call bar
+ leal (%r15,%rax), %r14d
+ movl %r13d, %edi
+ call bar
+ addl %eax, %r14d
+ movl %r12d, %edi
+ call bar
+ addl %r14d, %eax
+ addl %ebx, %eax
+ movq -56(%rbp), %rdx
+ subq %fs:40, %rdx
+ jne .L7
+ addq $280, %rsp
+ popq %rbx
+ popq %r12
+ popq %r13
+ popq %r14
+ popq %r15
+ popq %rbp
+ .cfi_remember_state
+ .cfi_def_cfa 7, 8
+ ret
+.L7:
+ .cfi_restore_state
+ call __stack_chk_fail@PLT
+ .cfi_endproc
+.LFE1:
+ .size foo, .-foo
+ .globl main
+ .type main, @function
+main:
+.LFB2:
+ .cfi_startproc
+ endbr64
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ subq $16, %rsp
+ leal (%rdi,%rdi), %ecx
+ leal 2(%rdi), %edx
+ leal 1(%rdi), %esi
+ call foo
+ movl %eax, -4(%rbp)
+ movl -4(%rbp), %eax
+ leave
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE2:
+ .size main, .-main
+ .ident "GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0"
+ .section .note.GNU-stack,"",@progbits
+ .section .note.gnu.property,"a"
+ .align 8
+ .long 1f - 0f
+ .long 4f - 1f
+ .long 5
+0:
+ .string "GNU"
+1:
+ .align 8
+ .long 0xc0000002
+ .long 3f - 2f
+2:
+ .long 0x3
+3:
+ .align 8
+4:
diff --git a/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.c b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.c
new file mode 100644
index 0000000..707b4fb
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.c
@@ -0,0 +1,56 @@
+/* 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/>. */
+
+int __attribute__ ((noinline))
+bar (int x)
+{
+ return x + x;
+}
+
+/* This function should generate a prologue in shape of:
+ push %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ mov %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ push %reg1
+ push %reg2
+ sub $XXX, %rsp
+ .cfi_offset %reg2, 32
+ .cfi_offset %reg1, 24
+
+ So to be able to unwind a register, GDB needs to skip prologue past
+ register pushes and stack allocation (to access .cfi directives). */
+int __attribute__ ((noinline))
+foo (int a, int b, int c, int d)
+{
+ /* "volatile" alone isn't enough for clang to not optimize it out and
+ allocate space on the stack. */
+ volatile char s[256];
+ for (int i = 0; i < 256; i++)
+ s[i] = (char) (a + i);
+
+ a += bar (a) + bar (b) + bar (c) + bar (d);
+ return a;
+}
+
+int
+main (int argc, char **argv)
+{
+ volatile int a = foo (argc, argc + 1, argc + 2, argc * 2);
+ return a;
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.exp b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.exp
new file mode 100644
index 0000000..356afc7
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.exp
@@ -0,0 +1,208 @@
+# 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 verifies that when placing a breakpoint on a function with a frame
+# pointer, instructions that push callee-saved registers and stack allocation
+# in the prologue are skipped, without debug info. When stopped on such
+# breakpoint, the pushed registers should be able to be immediately unwound.
+# With debug info present, GDB would try to use prologue-end markers found in
+# the line table to determine where the prologue ends.
+#
+# It is also tested both with and without .eh_frame's .cfi directives - with
+# them, GDB can only unwind a register once stopped after .cfi directive for
+# that register's push.
+
+require is_x86_64_m64_target
+standard_testfile .c -no-cfi.S .S -offset.S
+
+proc test_run {} {
+ gdb_breakpoint "foo"
+ gdb_continue_to_breakpoint "Continue to foo"
+
+ gdb_test "backtrace" "#0\[^\r\n\]+in foo\[^s\]+#1\[^\r\n\]+in main\[^s\]+" \
+ "Verify backtrace output in foo"
+
+ set main_r12 [get_integer_valueof "\$r12" "null"]
+ gdb_assert { $main_r12 ne "null" }
+
+ set foo_r12 [expr "$main_r12 + 2"]
+ gdb_test "print \$r12=$foo_r12" "$foo_r12" "Set foo's %r12=$foo_r12"
+ gdb_test "up" ".*main.*" "Go up a frame from foo"
+ gdb_test "print \$r12" "$main_r12" "foo's %r12 unwound"
+ gdb_test "down" ".*foo.*" "Go back down a frame to foo"
+ gdb_test "print \$r12" "$foo_r12" "foo's %r12 unwound back"
+}
+
+proc offset_test_run {} {
+ gdb_breakpoint "*foo"
+ gdb_continue_to_breakpoint "Continue to entry of foo"
+
+ set old_reg_val [get_integer_valueof "\$r12" "null"]
+ gdb_assert { $old_reg_val ne "null" }
+
+ set new_reg_val [expr "$old_reg_val + 3"]
+ gdb_test "print \$r14=$new_reg_val" "$new_reg_val" "Set %r14=$new_reg_val"
+ gdb_test "print \$r13=$new_reg_val" "$new_reg_val" "Set %r13=$new_reg_val"
+ gdb_test "print \$r12=$new_reg_val" "$new_reg_val" "Set %r12=$new_reg_val"
+
+ set addr_past_prologue "null"
+ gdb_test_multiple "disassemble" "Disassemble foo" -lbl {
+ -re "\r\n\\s*($::hex) <\\+($::decimal)>:\\s*mov.*(?=\r\n)" {
+ set addr_past_prologue $expect_out(1,string)
+ exp_continue
+ }
+
+ -re -wrap "" {
+ gdb_assert { $addr_past_prologue ne "null" } $gdb_test_name
+ }
+ }
+
+ gdb_assert { $addr_past_prologue ne "null" }
+
+ gdb_breakpoint "*$addr_past_prologue"
+ gdb_continue_to_breakpoint "Continue past foo's prologue"
+
+ gdb_test "up" ".*main.*" "Go up a frame from foo"
+ gdb_test "print \$r14" "$new_reg_val" "Verify %r14 value"
+ gdb_test "print \$r13" "$new_reg_val" "Verify %r13 value"
+ gdb_test "print \$r12" "$new_reg_val" "Verify %r12 value"
+}
+
+# Tests are done for two versions (not counting with and w/o .cfi):
+# - binary compiled from C source, which verifies we actually test against
+# the code that compilers produce and we expect
+# - binary compiled from ASM source, which verifies that we properly analyze
+# prologue sequences even when compiler introduces a sudden change in how
+# it generates assembly
+#
+# With those 2 versions, we can easily distinguish GDB breaking analyzer and
+# compilers behaving differently, if there ever is an impactful change in how
+# they generate prologues.
+with_test_prefix "w/o .cfi directives" {
+ with_test_prefix "compiler gen" {
+ # -fno-asynchronous-unwind-tables is needed to get rid of .cfi
+ # directives in .eh_frame section.
+ if { [gdb_can_simple_compile fno-asynchronous-unwind-tables \
+ { void foo () { } } object -fno-asynchronous-unwind-tables] == 0 } {
+ unsupported \
+ "compiler doesn't support -fno-asynchronous-unwind-tables flag"
+ } else {
+ # For at least gcc 11.4/clang 14.0.0 and later, -O1 makes them more
+ # eager to use registers in the prologue.
+ #
+ # At least gcc 11.4 and later by default does not generate full
+ # debug info, "nodebug" is there for other compilers.
+ if { [prepare_for_testing "failed to prepare" "$testfile-no-cfi-C" \
+ $srcfile { optimize=-O1 nodebug
+ additional_flags=-fno-asynchronous-unwind-tables
+ additional_flags=-fno-omit-frame-pointer}] } {
+ return
+ }
+
+ if { ![runto_main] } {
+ untested "unable to run to main"
+ return
+ }
+
+ test_run
+ }
+ }
+
+ with_test_prefix "ASM source" {
+ if { [prepare_for_testing "failed to prepare" "$testfile-no-cfi-S" \
+ $srcfile2 nodebug ] } {
+ return
+ }
+
+ if { ![runto_main] } {
+ untested "unable to run to main"
+ return
+ }
+
+ test_run
+ }
+}
+
+with_test_prefix "with .cfi directives" {
+ with_test_prefix "compiler gen" {
+ if { [prepare_for_testing "failed to prepare" "$testfile-cfi-C" \
+ $srcfile { optimize=-O1
+ nodebug additional_flags=-fno-omit-frame-pointer}] } {
+ return
+ }
+
+ if { ![runto_main] } {
+ untested "unable to run to main"
+ return
+ }
+
+ test_run
+ }
+
+ with_test_prefix "ASM source" {
+ if { [prepare_for_testing "failed to prepare" "$testfile-cfi-S" \
+ $srcfile3 nodebug ] } {
+ return
+ }
+
+ if { ![runto_main] } {
+ untested "unable to run to main"
+ return
+ }
+
+ test_run
+ }
+}
+
+# This section exists to verify that we properly assign offsets for functions
+# w/o a frame pointer, for registers when they're pushed. If they were assigned
+# in a wrong way, we might end up unwinding improper register values.
+with_test_prefix "offset initialization" {
+ with_test_prefix "compiler gen" {
+ if { [gdb_can_simple_compile fno-asynchronous-unwind-tables \
+ { void foo () { } } object -fno-asynchronous-unwind-tables] == 0 } {
+ unsupported \
+ "compiler doesn't support -fno-asynchronous-unwind-tables flag"
+ } else {
+ if { [prepare_for_testing "failed to prepare" "$testfile-offset-C" \
+ $srcfile { optimize=-O1 nodebug
+ additional_flags=-fno-asynchronous-unwind-tables
+ additional_flags=-fomit-frame-pointer}] } {
+ return
+ }
+
+ if { ![runto_main] } {
+ untested "unable to run to main"
+ return
+ }
+
+ offset_test_run
+ }
+ }
+
+ with_test_prefix "ASM source" {
+ if { [prepare_for_testing "failed to prepare" "$testfile-offset-S" \
+ $srcfile4 nodebug ] } {
+ return
+ }
+
+ if { ![runto_main] } {
+ untested "unable to run to main"
+ return
+ }
+
+ offset_test_run
+ }
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-frameptr-vecreg-unwind.c b/gdb/testsuite/gdb.arch/amd64-frameptr-vecreg-unwind.c
new file mode 100644
index 0000000..1b79a65
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-frameptr-vecreg-unwind.c
@@ -0,0 +1,63 @@
+/* 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/>. */
+
+volatile void dummy () {}
+
+long test_function(void)
+{
+ __asm__ volatile (
+ /* Clear xmm0. */
+ "vxorps %%xmm0, %%xmm0, %%xmm0\n\t"
+
+ /* Move the frame pointer (rbp) to xmm0. */
+ "movq %%rbp, %%xmm0\n\t"
+
+ /* CFI: Frame pointer is in xmm0. */
+ ".cfi_register %%rbp, %%xmm0\n\t"
+
+ /* Clobber list: Specify all modified registers */
+ : // No output operands
+ : // No input operands
+ : "xmm0"
+ );
+
+ dummy (); /* break-here */
+
+ /* Pseudo-epilogue: Restore rbp from xmm0. */
+ __asm__ volatile (
+ /* Restore rbp. */
+ "movq %%xmm0, %%rbp\n\t"
+
+ /* Describe CFI: Frame pointer is restored. */
+ ".cfi_restore %%rbp\n\t"
+
+ /* Clobber list: Specify all modified registers */
+ : /* No output operands. */
+ : /* No input operands. */
+ : /* Despite clobbering rbp, gcc doesn't let us list it here. */
+ );
+
+ return 0;
+}
+
+int
+main ()
+{
+ long result = test_function ();
+ dummy ();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-frameptr-vecreg-unwind.exp b/gdb/testsuite/gdb.arch/amd64-frameptr-vecreg-unwind.exp
new file mode 100644
index 0000000..3c0b319
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-frameptr-vecreg-unwind.exp
@@ -0,0 +1,40 @@
+# 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 verifies that we can read and write the value of a pseudo register
+# in unwound frames. For the test, we choose one raw register, rbx, and one
+# pseudo register that is backed by rbx, ebx. We have two frames (the inner one,
+# #0 and the outer one, #1) that each set a value for rbx. We verify that we
+# can read both rbx and ebx correctly for each frame, and that when we write to
+# ebx, rbx for that frame is correctly updated.
+
+require is_x86_64_m64_target
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+ "${srcfile}" {debug}] } {
+ return -1
+}
+
+if {![runto_main]} {
+ return
+}
+
+gdb_breakpoint [gdb_get_line_number "break-here"]
+gdb_continue_to_breakpoint "break-here"
+gdb_test "with confirm off --return -1" "result = test_function \\(\\);"
+gdb_test "step" "dummy \\(\\);"
+gdb_test "print result" "= -1"
diff --git a/gdb/testsuite/gdb.arch/amd64-init-x87-values.exp b/gdb/testsuite/gdb.arch/amd64-init-x87-values.exp
index 11004fa..871972c 100644
--- a/gdb/testsuite/gdb.arch/amd64-init-x87-values.exp
+++ b/gdb/testsuite/gdb.arch/amd64-init-x87-values.exp
@@ -40,7 +40,7 @@ if { [build_executable "failed to prepare" ${testfile} ${srcfile} $options] } {
proc_with_prefix check_x87_regs_around_init {} {
global binfile
- clean_restart ${binfile}
+ clean_restart ${::testfile}
# Get things started.
if {![runto_main]} {
@@ -115,7 +115,7 @@ proc_with_prefix check_x87_regs_around_init {} {
proc_with_prefix check_setting_mxcsr_before_enable {} {
global binfile gdb_prompt
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if {![runto_main]} {
return 0
@@ -149,7 +149,7 @@ proc_with_prefix check_setting_mxcsr_before_enable {} {
proc_with_prefix check_setting_x87_regs_before_enable {} {
global binfile
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.arch/amd64-invalid-stack-middle.exp b/gdb/testsuite/gdb.arch/amd64-invalid-stack-middle.exp
index 03ecba6..451c84b 100644
--- a/gdb/testsuite/gdb.arch/amd64-invalid-stack-middle.exp
+++ b/gdb/testsuite/gdb.arch/amd64-invalid-stack-middle.exp
@@ -45,7 +45,7 @@ gdb_test "bt" "^#0 +breakpt *\\(\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in func5\[^\
gdb_test "bt" "^#0 +breakpt *\\(\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in func5\[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in func4\[^\r\n\]*\r\n#3 +0x\[0-9a-f\]+ in func3\[^\r\n\]*\r\nBacktrace stopped: Cannot access memory at address 0x\[0-9a-f\]+" \
"second backtrace, with error message"
-clean_restart ${binfile}
+clean_restart ${::testfile}
if ![runto breakpt] {
return -1
@@ -59,7 +59,7 @@ gdb_test "interpreter-exec mi \"-stack-info-depth\"" \
"\\^done,depth=\"4\"" \
"check mi -stack-info-depth command, second time"
-clean_restart ${binfile}
+clean_restart ${::testfile}
if ![runto breakpt] {
return -1
diff --git a/gdb/testsuite/gdb.arch/amd64-invalid-stack-top.exp b/gdb/testsuite/gdb.arch/amd64-invalid-stack-top.exp
index 134dfda..b715ecf 100644
--- a/gdb/testsuite/gdb.arch/amd64-invalid-stack-top.exp
+++ b/gdb/testsuite/gdb.arch/amd64-invalid-stack-top.exp
@@ -49,7 +49,7 @@ gdb_test "bt no-filters" "^#0 +$hex in func2 \\(\\)\r\nBacktrace stopped: Cannot
gdb_test "bt no-filters" "^#0 +$hex in func2 \\(\\)\r\nBacktrace stopped: Cannot access memory at address 0x\[0-9a-f\]+" \
"second backtrace, with error message"
-clean_restart ${binfile}
+clean_restart ${::testfile}
if ![runto breakpt] {
return -1
@@ -63,7 +63,7 @@ gdb_test "interpreter-exec mi \"-stack-info-depth\"" \
"\\^done,depth=\"1\"" \
"check mi -stack-info-depth command, second time"
-clean_restart ${binfile}
+clean_restart ${::testfile}
if ![runto breakpt] {
return -1
diff --git a/gdb/testsuite/gdb.arch/amd64-prologue-skip.exp b/gdb/testsuite/gdb.arch/amd64-prologue-skip.exp
index 04f3266..c96c0c7 100644
--- a/gdb/testsuite/gdb.arch/amd64-prologue-skip.exp
+++ b/gdb/testsuite/gdb.arch/amd64-prologue-skip.exp
@@ -14,7 +14,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
standard_testfile .S
-set binfile ${binfile}.o
+set testfile $testfile.o
+set binfile [standard_output_file $testfile]
require is_x86_64_m64_target
@@ -23,7 +24,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" object {debug}]
return
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test "break *pushrbp" " at 0x1: file .*"
gdb_test "break pushrbp" " at 0x1: file .*"
diff --git a/gdb/testsuite/gdb.arch/amd64-prologue-xmm.exp b/gdb/testsuite/gdb.arch/amd64-prologue-xmm.exp
index 7c16238..8447973 100644
--- a/gdb/testsuite/gdb.arch/amd64-prologue-xmm.exp
+++ b/gdb/testsuite/gdb.arch/amd64-prologue-xmm.exp
@@ -28,7 +28,7 @@ if [info exists COMPILE] {
require is_x86_64_m64_target
}
-if {[prepare_for_testing "failed to prepare" ${binfile} $srcfile $opts]} {
+if {[prepare_for_testing "failed to prepare" ${testfile} $srcfile $opts]} {
return -1
}
diff --git a/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp
index 6333311..49721dd 100644
--- a/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp
+++ b/gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp
@@ -32,7 +32,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} \
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.arch/amd64-shadow-stack-cmds.exp b/gdb/testsuite/gdb.arch/amd64-shadow-stack-cmds.exp
new file mode 100644
index 0000000..0ae172d
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-shadow-stack-cmds.exp
@@ -0,0 +1,143 @@
+# Copyright 2024-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 shadow stack enabling for frame level update, the return and the
+# call commands.
+# As potential CET violations often only occur after resuming normal
+# execution, test normal program continuation after each return or call
+# commands.
+
+require allow_ssp_tests
+
+standard_testfile amd64-shadow-stack.c
+
+# Restart GDB an run until breakpoint in call2.
+
+proc restart_and_run_infcall_call2 {} {
+ global binfile
+ clean_restart ${::testfile}
+ if { ![runto_main] } {
+ return -1
+ }
+ set inside_infcall_str "The program being debugged stopped while in a function called from GDB"
+ gdb_breakpoint [ gdb_get_line_number "break call2" ]
+ gdb_continue_to_breakpoint "break call2" ".*break call2.*"
+ gdb_test "call (int) call2()" \
+ "Breakpoint \[0-9\]*, call2.*$inside_infcall_str.*"
+}
+
+save_vars { ::env(GLIBC_TUNABLES) } {
+
+ append_environment GLIBC_TUNABLES "glibc.cpu.hwcaps" "SHSTK"
+
+ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
+ {debug additional_flags="-fcf-protection=return"}] } {
+ return -1
+ }
+
+ clean_restart ${::testfile}
+ if { ![runto_main] } {
+ return -1
+ }
+
+ with_test_prefix "test inferior call and continue" {
+ gdb_breakpoint [ gdb_get_line_number "break call1" ]
+ gdb_continue_to_breakpoint "break call1" ".*break call1.*"
+
+ gdb_test "call (int) call2()" "= 42"
+
+ gdb_continue_to_end
+ }
+
+ with_test_prefix "test return inside an inferior call" {
+ restart_and_run_infcall_call2
+
+ gdb_test "return" "\#0.*call2.*" \
+ "Test shadow stack return inside an inferior call" \
+ "Make.*return now\\? \\(y or n\\) " "y"
+
+ gdb_continue_to_end
+ }
+
+ with_test_prefix "test return 'above' an inferior call" {
+ restart_and_run_infcall_call2
+
+ gdb_test "frame 2" "call2 ().*" "move to frame 'above' inferior call"
+
+ gdb_test "return" "\#0.*call1.*" \
+ "Test shadow stack return 'above' an inferior call" \
+ "Make.*return now\\? \\(y or n\\) " "y"
+
+ gdb_continue_to_end
+ }
+
+ clean_restart ${::testfile}
+ if { ![runto_main] } {
+ return -1
+ }
+
+ set call1_line [ gdb_get_line_number "break call1" ]
+ set call2_line [ gdb_get_line_number "break call2" ]
+
+ # Extract shadow stack pointer inside main, call1 and call2 function.
+ gdb_breakpoint $call1_line
+ gdb_breakpoint $call2_line
+ set ssp_main [get_valueof /x "\$pl3_ssp" 0 "get value of ssp in main"]
+ gdb_continue_to_breakpoint "break call1" ".*break call1.*"
+ set ssp_call1 [get_valueof /x "\$pl3_ssp" 0 "get value of ssp in call1"]
+ gdb_continue_to_breakpoint "break call2" ".*break call2.*"
+ set ssp_call2 [get_valueof /x "\$pl3_ssp" 0 "get value of ssp in call2"]
+
+ with_test_prefix "test frame level update" {
+ gdb_test "up" "call1.*" "move to frame 1"
+ gdb_test "print /x \$pl3_ssp" "= $ssp_call1" "check pl3_ssp of frame 1"
+ gdb_test "up" "main.*" "move to frame 2"
+ gdb_test "print /x \$pl3_ssp" "= $ssp_main" "check pl3_ssp of frame 2"
+ gdb_test "frame 0" "call2.*" "move to frame 0"
+ gdb_test "print /x \$pl3_ssp" "= $ssp_call2" "check pl3_ssp of frame 0"
+ }
+
+ with_test_prefix "test return from current frame" {
+ gdb_test "return (int) 1" "#0.*call1.*" \
+ "Test shadow stack return from current frame" \
+ "Make.*return now\\? \\(y or n\\) " "y"
+
+ # Potential CET violations often only occur after resuming normal execution.
+ # Therefore, it is important to test normal program continuation after
+ # testing the return command.
+ gdb_continue_to_end
+ }
+
+ clean_restart ${::testfile}
+ if { ![runto_main] } {
+ return -1
+ }
+
+ with_test_prefix "test return from past frame" {
+ gdb_breakpoint $call2_line
+ gdb_continue_to_breakpoint "break call2" ".*break call2.*"
+
+ gdb_test "frame 1" ".*in call1.*"
+
+ gdb_test "return (int) 1" "#0.*main.*" \
+ "Test shadow stack return from past frame" \
+ "Make.*return now\\? \\(y or n\\) " "y"
+
+ # Potential CET violations often only occur after resuming normal execution.
+ # Therefore, it is important to test normal program continuation after
+ # testing the return command.
+ gdb_continue_to_end
+ }
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-shadow-stack-corefile.c b/gdb/testsuite/gdb.arch/amd64-shadow-stack-corefile.c
new file mode 100644
index 0000000..5e84793
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-shadow-stack-corefile.c
@@ -0,0 +1,46 @@
+/* This test program 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 <stdio.h>
+
+/* Call the return instruction before function epilogue to trigger a
+ control-flow exception. */
+void
+function ()
+{
+ unsigned long ssp;
+ #ifndef __ILP32__
+ asm volatile ("xor %0, %0; rdsspq %0" : "=r" (ssp));
+ #else
+ asm volatile ("xor %0, %0; rdsspd %0" : "=r" (ssp));
+ #endif
+
+ /* Print ssp to stdout so that the testcase can capture it. */
+ printf ("%p\n", (void *) ssp);
+ fflush (stdout);
+
+ /* Manually cause a control-flow exception by executing a return
+ instruction before function epilogue, so the address atop the stack
+ is not the return instruction. */
+ __asm__ volatile ("ret\n");
+}
+
+int
+main (void)
+{
+ function (); /* Break here. */
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-shadow-stack-corefile.exp b/gdb/testsuite/gdb.arch/amd64-shadow-stack-corefile.exp
new file mode 100644
index 0000000..039f528
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-shadow-stack-corefile.exp
@@ -0,0 +1,119 @@
+# Copyright 2024-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 shadow stack pointer note in core dumps.
+# Based on the corefile tests in gdb.arch/aarch64-gcs-core.exp.
+
+require allow_ssp_tests
+
+standard_testfile
+
+# Make sure GDB can read the given core file correctly.
+
+proc check_core_file {core_filename saved_pl3_ssp} {
+ global decimal
+
+ # Load the core file.
+ if [gdb_test "core $core_filename" \
+ [multi_line \
+ "Core was generated by .*\\." \
+ "Program terminated with signal SIGSEGV, Segmentation fault.*" \
+ "#0 function \\(\\) at .*amd64-shadow-stack-corefile.c:$decimal" \
+ "$decimal.*__asm__ volatile \\(\"ret\\\\n\"\\);"] \
+ "load core file"] {
+ return
+ }
+
+ # Check the value of ssp in the core file.
+ gdb_test "print/x \$pl3_ssp" "\\$\[0-9\]+ = $saved_pl3_ssp" \
+ "pl3_ssp contents from core file $saved_pl3_ssp"
+}
+
+save_vars { ::env(GLIBC_TUNABLES) } {
+
+ append_environment GLIBC_TUNABLES "glibc.cpu.hwcaps" "SHSTK"
+
+ if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
+ {debug additional_flags="-fcf-protection=return"}] } {
+ return
+ }
+
+ set linespec ${srcfile}:[gdb_get_line_number "Break here"]
+
+ if ![runto $linespec] {
+ return
+ }
+
+ # Obtain an OS-generated core file. Save test program output to
+ # ${binfile}.out.
+ set core_filename [core_find $binfile {} {} "${binfile}.out"]
+ set core_generated [expr {$core_filename != ""}]
+
+ if {!$core_generated} {
+ untested "unable to create or find corefile"
+ }
+
+ # Load the core file and check the value of the shadow stack pointer.
+ if {$core_generated} {
+ clean_restart $::testfile
+
+ with_test_prefix "OS corefile" {
+ # Read ssp value from saved output of the test program.
+ set out_id [open ${binfile}.out "r"]
+ set ssp_in_gcore [gets $out_id]
+ close $out_id
+ check_core_file $core_filename $ssp_in_gcore
+ }
+ }
+
+ if ![gcore_cmd_available] {
+ unsupported "target does not support gcore command."
+ return
+ }
+
+ clean_restart $::testfile
+
+ if ![runto $linespec] {
+ return
+ }
+
+ # Continue until a crash. The line with the hex number is optional because
+ # it's printed by the test program, and doesn't appear in the Expect buffer
+ # when testing a remote target.
+
+ gdb_test "continue" \
+ [multi_line \
+ "Continuing\\." \
+ "($hex\r\n)?" \
+ "Program received signal SIGSEGV, Segmentation fault.*" \
+ "function \\(\\) at .*amd64-shadow-stack-corefile.c:$decimal" \
+ {.*__asm__ volatile \("ret\\n"\);}] \
+ "continue to SIGSEGV"
+
+ set ssp_in_gcore [get_valueof "/x" "\$pl3_ssp" "*unknown*"]
+
+ # Generate the gcore core file.
+ set gcore_filename [standard_output_file "${testfile}.gcore"]
+ set gcore_generated [gdb_gcore_cmd "$gcore_filename" "generate gcore file"]
+
+ gdb_assert { $gcore_generated } "gcore corefile created"
+ if { $gcore_generated } {
+ clean_restart $::testfile
+
+ with_test_prefix "gcore corefile" {
+ check_core_file $gcore_filename $ssp_in_gcore
+ }
+ }
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-shadow-stack-disp-step.exp b/gdb/testsuite/gdb.arch/amd64-shadow-stack-disp-step.exp
new file mode 100644
index 0000000..e4efa00
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-shadow-stack-disp-step.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 continue from call instructions with shadow stack and displaced
+# stepping being enabled.
+
+require allow_ssp_tests support_displaced_stepping
+
+standard_testfile amd64-shadow-stack.c
+
+save_vars { ::env(GLIBC_TUNABLES) } {
+
+ append_environment GLIBC_TUNABLES "glibc.cpu.hwcaps" "SHSTK"
+
+ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
+ additional_flags="-fcf-protection=return"] } {
+ return
+ }
+
+ # Enable displaced stepping.
+ gdb_test_no_output "set displaced-stepping on"
+ gdb_test "show displaced-stepping" ".* displaced stepping .* is on.*"
+
+ if { ![runto_main] } {
+ return
+ }
+
+ # Get the address of the call to the call1 function.
+ set call1_addr -1
+ gdb_test_multiple "disassemble main" "" {
+ -re -wrap "($hex) <\\+($decimal)>:\\s*call\\s*0x.*<call1>.*" {
+ set call1_addr $expect_out(1,string)
+ pass $gdb_test_name
+ }
+ }
+
+ if { $call1_addr == -1 } {
+ return
+ }
+
+ # Get the address of the call to the call2 function.
+ set call2_addr -1
+ gdb_test_multiple "disassemble call1" "" {
+ -re -wrap "($hex) <\\+($decimal)>:\\s*call\\s*0x.*<call2>.*" {
+ set call2_addr $expect_out(1,string)
+ pass $gdb_test_name
+ }
+ }
+
+ if { $call2_addr == -1 } {
+ return
+ }
+
+ gdb_test "break *$call1_addr" \
+ "Breakpoint $decimal at $hex.*" \
+ "break at the address of the call1 instruction"
+
+ gdb_test "break *$call2_addr" \
+ "Breakpoint $decimal at $hex.*" \
+ "break at the address of the call2 instruction"
+
+ gdb_test "continue" \
+ "Breakpoint $decimal, $call1_addr in main ().*" \
+ "continue until call1 instruction"
+
+ # Test continue from breakpoint at call1 and call2 instructions.
+ gdb_test "continue" \
+ "Breakpoint $decimal, $call2_addr in call1 ().*" \
+ "continue from call1 instruction"
+
+ gdb_continue_to_end "continue from call2 instruction"
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-shadow-stack.c b/gdb/testsuite/gdb.arch/amd64-shadow-stack.c
new file mode 100644
index 0000000..4a1ca1e
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-shadow-stack.c
@@ -0,0 +1,40 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024-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/>. */
+
+static int
+call2 ()
+{
+ return 42; /* break call2. */
+}
+
+static int
+call1 ()
+{
+ return call2 (); /* break call1. */
+}
+
+int
+main ()
+{
+ /* Depending on instruction generation we might end up in the call
+ instruction of call1 function after "runto_main". Avoid this by
+ adding a nop instruction, to simplify the testing in
+ amd64-shadow-stack-disp-step.exp. */
+ asm ("nop");
+ call1 (); /* break main. */
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-shadow-stack.exp b/gdb/testsuite/gdb.arch/amd64-shadow-stack.exp
new file mode 100644
index 0000000..e9f6fa6
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-shadow-stack.exp
@@ -0,0 +1,71 @@
+# Copyright 2024-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 accessing the shadow stack pointer register.
+
+require allow_ssp_tests
+
+standard_testfile
+
+# Write PL3_SSP register with invalid shadow stack pointer value.
+proc write_invalid_ssp {} {
+ gdb_test "print /x \$pl3_ssp = 0x12345678" "= 0x12345678" "set pl3_ssp value"
+ gdb_test "print /x \$pl3_ssp" "= 0x12345678" "read pl3_ssp value after setting"
+}
+
+save_vars { ::env(GLIBC_TUNABLES) } {
+
+ append_environment GLIBC_TUNABLES "glibc.cpu.hwcaps" "SHSTK"
+
+ if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
+ additional_flags="-fcf-protection=return"] } {
+ return
+ }
+
+ if {![runto_main]} {
+ return
+ }
+
+ with_test_prefix "invalid ssp" {
+ write_invalid_ssp
+
+ # Continue until SIGSEV to test that the value is written back to HW.
+ gdb_test "continue" \
+ [multi_line \
+ "Continuing\\." \
+ "" \
+ "Program received signal SIGSEGV, Segmentation fault\\." \
+ "$hex in main \\(\\)"] \
+ "continue to SIGSEGV"
+ }
+
+ clean_restart ${::testfile}
+ if { ![runto_main] } {
+ return
+ }
+
+ with_test_prefix "restore original ssp" {
+ # Read PL3_SSP register.
+ set ssp_main [get_hexadecimal_valueof "\$pl3_ssp" "read pl3_ssp value"]
+
+ write_invalid_ssp
+
+ # Restore original value.
+ gdb_test "print /x \$pl3_ssp = $ssp_main" "= $ssp_main" "restore original value"
+
+ # Now we should not see a SIGSEV, since the original value is restored.
+ gdb_continue_to_end
+ }
+}
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/amd64-word.exp b/gdb/testsuite/gdb.arch/amd64-word.exp
index d5dfb02..8a6b28d 100644
--- a/gdb/testsuite/gdb.arch/amd64-word.exp
+++ b/gdb/testsuite/gdb.arch/amd64-word.exp
@@ -27,7 +27,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list
return
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp
index 892cfba..9cbf71d 100644
--- a/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp
+++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp
@@ -34,7 +34,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} \
return -1
}
-clean_restart ${binfile}
+clean_restart $testfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp b/gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp
index c474a99..4cbb12e 100644
--- a/gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp
+++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp
@@ -29,7 +29,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} \
return -1
}
-clean_restart ${binfile}
+clean_restart $testfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp b/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp
index 15c4050..32f085a 100644
--- a/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp
+++ b/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp
@@ -33,7 +33,7 @@ if { [build_executable "failed to prepare" ${testfile} ${srcfile} \
save_vars { GDBFLAGS } {
append GDBFLAGS " --readnever"
- if { [clean_restart ${binfile}] == -1 } {
+ if { [clean_restart $testfile] == -1 } {
return -1
}
}
diff --git a/gdb/testsuite/gdb.arch/e500-prologue.exp b/gdb/testsuite/gdb.arch/e500-prologue.exp
index e8f3ebd..b1eb865 100644
--- a/gdb/testsuite/gdb.arch/e500-prologue.exp
+++ b/gdb/testsuite/gdb.arch/e500-prologue.exp
@@ -27,7 +27,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {}] !
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Insert a breakpoint in FUNCTION and verifies that the breakpoint was
# inserted at the expected location. EXPECTED_LOCATION should be an
diff --git a/gdb/testsuite/gdb.arch/e500-regs.exp b/gdb/testsuite/gdb.arch/e500-regs.exp
index 543ce63..6d69ccc 100644
--- a/gdb/testsuite/gdb.arch/e500-regs.exp
+++ b/gdb/testsuite/gdb.arch/e500-regs.exp
@@ -136,7 +136,8 @@ gdb_expect_list "info vector" ".*$gdb_prompt $" {
# We must restart everything, because we have set important registers to
# some unusual values.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return 0
}
diff --git a/gdb/testsuite/gdb.arch/gdb1291.exp b/gdb/testsuite/gdb.arch/gdb1291.exp
index ad3b8f9..9f460c8 100644
--- a/gdb/testsuite/gdb.arch/gdb1291.exp
+++ b/gdb/testsuite/gdb.arch/gdb1291.exp
@@ -33,7 +33,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable ""] !
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
#
# Run to `main' where we begin our tests.
diff --git a/gdb/testsuite/gdb.arch/gdb1431.exp b/gdb/testsuite/gdb.arch/gdb1431.exp
index 34bc8d6..bc65d26 100644
--- a/gdb/testsuite/gdb.arch/gdb1431.exp
+++ b/gdb/testsuite/gdb.arch/gdb1431.exp
@@ -35,7 +35,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable ""] !
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
#
# Run to `main' where we begin our tests.
diff --git a/gdb/testsuite/gdb.arch/gdb1558.exp b/gdb/testsuite/gdb.arch/gdb1558.exp
index f690468..3de5723 100644
--- a/gdb/testsuite/gdb.arch/gdb1558.exp
+++ b/gdb/testsuite/gdb.arch/gdb1558.exp
@@ -32,7 +32,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {"add
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_test "b -q main" "Breakpoint 1.*" "set breakpoint at main"
gdb_test "b -q sub1" "Breakpoint 2.*" "set breakpoint at sub1"
diff --git a/gdb/testsuite/gdb.arch/i386-avx.exp b/gdb/testsuite/gdb.arch/i386-avx.exp
index 8f07a3d..ba41a8c 100644
--- a/gdb/testsuite/gdb.arch/i386-avx.exp
+++ b/gdb/testsuite/gdb.arch/i386-avx.exp
@@ -42,7 +42,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
return
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
@@ -93,7 +93,7 @@ with_test_prefix "force-disable xml descriptions" {
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set remote target-features-packet off\""
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.arch/i386-bp_permanent.exp b/gdb/testsuite/gdb.arch/i386-bp_permanent.exp
index 1d3713f..6eb9ee6 100644
--- a/gdb/testsuite/gdb.arch/i386-bp_permanent.exp
+++ b/gdb/testsuite/gdb.arch/i386-bp_permanent.exp
@@ -33,7 +33,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list
}
-clean_restart $binfile
+clean_restart $::testfile
#
# Run to `main' where we begin our tests.
diff --git a/gdb/testsuite/gdb.arch/i386-byte.exp b/gdb/testsuite/gdb.arch/i386-byte.exp
index dcbcb40..1eff977 100644
--- a/gdb/testsuite/gdb.arch/i386-byte.exp
+++ b/gdb/testsuite/gdb.arch/i386-byte.exp
@@ -28,7 +28,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list
return
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.arch/i386-disp-step-self-call-alarm.c b/gdb/testsuite/gdb.arch/i386-disp-step-self-call-alarm.c
index 03b868c..0fb2904 100644
--- a/gdb/testsuite/gdb.arch/i386-disp-step-self-call-alarm.c
+++ b/gdb/testsuite/gdb.arch/i386-disp-step-self-call-alarm.c
@@ -16,9 +16,27 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <unistd.h>
+#include <stdlib.h>
+
+extern void test_call (void);
+
+void
+unreachable (void)
+{
+ abort ();
+}
void
setup_alarm (void)
{
alarm (300);
}
+
+int
+main ()
+{
+ setup_alarm ();
+ test_call ();
+ unreachable ();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/i386-disp-step-self-call.S b/gdb/testsuite/gdb.arch/i386-disp-step-self-call.S
index 466e50c..20a8eb7 100644
--- a/gdb/testsuite/gdb.arch/i386-disp-step-self-call.S
+++ b/gdb/testsuite/gdb.arch/i386-disp-step-self-call.S
@@ -18,33 +18,12 @@
handling. */
.text
-
- .global main
-main:
- nop
-
- call setup_alarm
-
- nop
-
-/***********************************************/
-
-/* test call/ret */
-
.global test_call
test_call:
call test_call
- nop
+ call unreachable
.global test_ret_end
test_ret_end:
nop
-/***********************************************/
-
-/* all done */
-
-done:
- pushl $0
- call exit
- hlt
.section .note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.arch/i386-dr3-watch.exp b/gdb/testsuite/gdb.arch/i386-dr3-watch.exp
index 4fe2608..11b4773 100644
--- a/gdb/testsuite/gdb.arch/i386-dr3-watch.exp
+++ b/gdb/testsuite/gdb.arch/i386-dr3-watch.exp
@@ -23,7 +23,7 @@ require {is_any_target "i?86-*-*" "x86_64-*-*"}
standard_testfile
-if [prepare_for_testing "failed to prepare" ${binfile} ${srcfile} {debug $additional_flags}] {
+if [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} {debug $additional_flags}] {
return -1
}
diff --git a/gdb/testsuite/gdb.arch/i386-gnu-cfi.exp b/gdb/testsuite/gdb.arch/i386-gnu-cfi.exp
index b51f034..c446fae 100644
--- a/gdb/testsuite/gdb.arch/i386-gnu-cfi.exp
+++ b/gdb/testsuite/gdb.arch/i386-gnu-cfi.exp
@@ -40,7 +40,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfilec} ${srcdir}/${subdir}/${srcfile
# Get things started.
-clean_restart $binfile
+clean_restart $::testfile
# We should stop in abort(3).
diff --git a/gdb/testsuite/gdb.arch/i386-permbkpt.exp b/gdb/testsuite/gdb.arch/i386-permbkpt.exp
index b979d6e..1118cb4 100644
--- a/gdb/testsuite/gdb.arch/i386-permbkpt.exp
+++ b/gdb/testsuite/gdb.arch/i386-permbkpt.exp
@@ -30,7 +30,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test "break -q main" "" "first permanent break"
gdb_test "break -q main" "" "second permanent break"
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..b289b84 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 ${::testfile}
+
+ 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.arch/i386-prologue.exp b/gdb/testsuite/gdb.arch/i386-prologue.exp
index 72246f4..bfab6d1 100644
--- a/gdb/testsuite/gdb.arch/i386-prologue.exp
+++ b/gdb/testsuite/gdb.arch/i386-prologue.exp
@@ -53,7 +53,7 @@ proc skip_breakpoint { msg } {
}
-clean_restart $binfile
+clean_restart $::testfile
#
# Run to `main' where we begin our tests.
diff --git a/gdb/testsuite/gdb.arch/i386-signal.exp b/gdb/testsuite/gdb.arch/i386-signal.exp
index 30f212b..80d1827 100644
--- a/gdb/testsuite/gdb.arch/i386-signal.exp
+++ b/gdb/testsuite/gdb.arch/i386-signal.exp
@@ -30,7 +30,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
runto func
gdb_test "backtrace 10" \
diff --git a/gdb/testsuite/gdb.arch/i386-size-overlap.exp b/gdb/testsuite/gdb.arch/i386-size-overlap.exp
index ca8383d..db88673 100644
--- a/gdb/testsuite/gdb.arch/i386-size-overlap.exp
+++ b/gdb/testsuite/gdb.arch/i386-size-overlap.exp
@@ -30,7 +30,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
# We use gdb_run_cmd so this stands a chance to work for remote
# targets too.
diff --git a/gdb/testsuite/gdb.arch/i386-size.exp b/gdb/testsuite/gdb.arch/i386-size.exp
index b08182f..997e629 100644
--- a/gdb/testsuite/gdb.arch/i386-size.exp
+++ b/gdb/testsuite/gdb.arch/i386-size.exp
@@ -35,7 +35,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
# We use gdb_run_cmd so this stands a chance to work for remote
# targets too.
diff --git a/gdb/testsuite/gdb.arch/i386-sse.exp b/gdb/testsuite/gdb.arch/i386-sse.exp
index f0aa5ec..154f5ea 100644
--- a/gdb/testsuite/gdb.arch/i386-sse.exp
+++ b/gdb/testsuite/gdb.arch/i386-sse.exp
@@ -40,7 +40,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
return
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.arch/i386-unwind.exp b/gdb/testsuite/gdb.arch/i386-unwind.exp
index 99acfe9..76f0a78 100644
--- a/gdb/testsuite/gdb.arch/i386-unwind.exp
+++ b/gdb/testsuite/gdb.arch/i386-unwind.exp
@@ -33,7 +33,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
# Testcase for backtrace/1435.
diff --git a/gdb/testsuite/gdb.arch/i386-word.exp b/gdb/testsuite/gdb.arch/i386-word.exp
index 0da49c0..ed02d27 100644
--- a/gdb/testsuite/gdb.arch/i386-word.exp
+++ b/gdb/testsuite/gdb.arch/i386-word.exp
@@ -28,7 +28,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list
return
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.arch/ia64-breakpoint-shadow.exp b/gdb/testsuite/gdb.arch/ia64-breakpoint-shadow.exp
index 8e8ed9b..d6fd14c 100644
--- a/gdb/testsuite/gdb.arch/ia64-breakpoint-shadow.exp
+++ b/gdb/testsuite/gdb.arch/ia64-breakpoint-shadow.exp
@@ -23,7 +23,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# We need to start the inferior to place the breakpoints in the memory at all.
if ![runto_main] {
diff --git a/gdb/testsuite/gdb.arch/mips-fpregset-core.exp b/gdb/testsuite/gdb.arch/mips-fpregset-core.exp
index aa55ede..d67cef2 100644
--- a/gdb/testsuite/gdb.arch/mips-fpregset-core.exp
+++ b/gdb/testsuite/gdb.arch/mips-fpregset-core.exp
@@ -79,7 +79,8 @@ set core_supported [expr {$corefile != ""}]
# Generate a core file with "gcore".
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
runto break_here
@@ -116,7 +117,8 @@ proc mips_fpregset_core_test { supported corefile } {
upvar host_triplet host_triplet
upvar binfile binfile
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
set test "load core file"
if { $supported } {
diff --git a/gdb/testsuite/gdb.arch/mips-octeon-bbit.exp b/gdb/testsuite/gdb.arch/mips-octeon-bbit.exp
index 3fb6f9c..f43127d 100644
--- a/gdb/testsuite/gdb.arch/mips-octeon-bbit.exp
+++ b/gdb/testsuite/gdb.arch/mips-octeon-bbit.exp
@@ -86,7 +86,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
pass "compilation"
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Native needs run.
runto_main
diff --git a/gdb/testsuite/gdb.arch/pa-nullify.exp b/gdb/testsuite/gdb.arch/pa-nullify.exp
index 87afe7a..ad246ca 100644
--- a/gdb/testsuite/gdb.arch/pa-nullify.exp
+++ b/gdb/testsuite/gdb.arch/pa-nullify.exp
@@ -40,7 +40,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {}] !
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# In the first test, we do a "step" on a function whose last instruction
# contains a branch-with-nullify. The instruction in the delay slot belongs
diff --git a/gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp b/gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp
index 13e3fd3..f95bddf 100644
--- a/gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp
@@ -28,7 +28,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {}] !
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Insert a breakpoint in FUNCTION and verifies that the breakpoint was
# inserted at the expected location. EXPECTED_LOCATION should be an
diff --git a/gdb/testsuite/gdb.arch/powerpc-altivec.exp b/gdb/testsuite/gdb.arch/powerpc-altivec.exp
index 987da07..bc8ff7a 100644
--- a/gdb/testsuite/gdb.arch/powerpc-altivec.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-altivec.exp
@@ -27,7 +27,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}]
return -1
}
-clean_restart ${objfile}
+clean_restart
+gdb_load $objfile
# Disassemble the function.
set func ""
diff --git a/gdb/testsuite/gdb.arch/powerpc-altivec2.exp b/gdb/testsuite/gdb.arch/powerpc-altivec2.exp
index 3bf7c57..6fddd34 100644
--- a/gdb/testsuite/gdb.arch/powerpc-altivec2.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-altivec2.exp
@@ -27,7 +27,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}]
return -1
}
-clean_restart ${objfile}
+clean_restart
+gdb_load $objfile
# Disassemble the function.
set func ""
diff --git a/gdb/testsuite/gdb.arch/powerpc-altivec3.exp b/gdb/testsuite/gdb.arch/powerpc-altivec3.exp
index ff1d79a..7b1d0c3 100644
--- a/gdb/testsuite/gdb.arch/powerpc-altivec3.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-altivec3.exp
@@ -27,7 +27,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}]
return -1
}
-clean_restart ${objfile}
+clean_restart
+gdb_load $objfile
# Disassemble the function.
set func ""
diff --git a/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp b/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp
index 42fc51e..cb5a371 100644
--- a/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp
@@ -29,7 +29,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {qui
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp b/gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp
index a7614fa..13163d2 100644
--- a/gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp
@@ -34,7 +34,7 @@ if {[build_executable "compile" $binfile $gen_src] == -1} {
return -1
}
-clean_restart $binfile
+clean_restart $testfile
if {![runto_main]} {
return -1
diff --git a/gdb/testsuite/gdb.arch/powerpc-htm-regs.exp b/gdb/testsuite/gdb.arch/powerpc-htm-regs.exp
index 6fcb69f..5e2923f 100644
--- a/gdb/testsuite/gdb.arch/powerpc-htm-regs.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-htm-regs.exp
@@ -82,7 +82,8 @@ with_test_prefix "check htm support" {
return
}
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
# Displaced-stepping a tbegin. causes problems,
# so we make the breakpoint temporary.
@@ -131,7 +132,7 @@ if {[build_executable "compile" $binfile $srcfile {debug}] == -1} {
return
}
-clean_restart $binfile
+clean_restart $testfile
gdb_breakpoint [gdb_get_line_number "first marker"] temporary
diff --git a/gdb/testsuite/gdb.arch/powerpc-power10.exp b/gdb/testsuite/gdb.arch/powerpc-power10.exp
index 1bb7174..124baaf 100644
--- a/gdb/testsuite/gdb.arch/powerpc-power10.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-power10.exp
@@ -27,7 +27,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}]
return -1
}
-clean_restart ${objfile}
+clean_restart
+gdb_load $objfile
# Disassemble the function.
set func ""
diff --git a/gdb/testsuite/gdb.arch/powerpc-power7.exp b/gdb/testsuite/gdb.arch/powerpc-power7.exp
index f33405d..8885a91 100644
--- a/gdb/testsuite/gdb.arch/powerpc-power7.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-power7.exp
@@ -27,7 +27,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}]
return -1
}
-clean_restart ${objfile}
+clean_restart
+gdb_load $objfile
# Disassemble the function.
set func ""
diff --git a/gdb/testsuite/gdb.arch/powerpc-power8.exp b/gdb/testsuite/gdb.arch/powerpc-power8.exp
index ab69b0f..f740ae8 100644
--- a/gdb/testsuite/gdb.arch/powerpc-power8.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-power8.exp
@@ -27,7 +27,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}]
return -1
}
-clean_restart ${objfile}
+clean_restart
+gdb_load $objfile
# Disassemble the function.
set func ""
diff --git a/gdb/testsuite/gdb.arch/powerpc-power9.exp b/gdb/testsuite/gdb.arch/powerpc-power9.exp
index b1bfa9d..8dcf536 100644
--- a/gdb/testsuite/gdb.arch/powerpc-power9.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-power9.exp
@@ -27,7 +27,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}]
return -1
}
-clean_restart ${objfile}
+clean_restart
+gdb_load $objfile
# Disassemble the function.
set func ""
diff --git a/gdb/testsuite/gdb.arch/powerpc-ppr-dscr.exp b/gdb/testsuite/gdb.arch/powerpc-ppr-dscr.exp
index ef6bb9d..1b4c608 100644
--- a/gdb/testsuite/gdb.arch/powerpc-ppr-dscr.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-ppr-dscr.exp
@@ -66,7 +66,7 @@ proc ppr_dscr_available {} {
}
with_test_prefix "check PPR/DSCR access" {
- clean_restart $binfile
+ clean_restart $::testfile
if ![runto_main] {
return
@@ -86,7 +86,7 @@ with_test_prefix "check PPR/DSCR access" {
}
# Now do the actual test
-clean_restart $binfile
+clean_restart $::testfile
if ![runto_main] {
return
diff --git a/gdb/testsuite/gdb.arch/powerpc-prologue-frame.exp b/gdb/testsuite/gdb.arch/powerpc-prologue-frame.exp
index 3c79039..156a70e 100644
--- a/gdb/testsuite/gdb.arch/powerpc-prologue-frame.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-prologue-frame.exp
@@ -26,7 +26,7 @@ if {[gdb_compile \
}
-clean_restart ${binfile}
+clean_restart $testfile
if ![runto bar] {
untested "could not run to bar"
diff --git a/gdb/testsuite/gdb.arch/powerpc-prologue.exp b/gdb/testsuite/gdb.arch/powerpc-prologue.exp
index 4e697c1..44877a1 100644
--- a/gdb/testsuite/gdb.arch/powerpc-prologue.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-prologue.exp
@@ -31,7 +31,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {}] !
}
-clean_restart $binfile
+clean_restart $testfile
#
# Run to `main' where we begin our tests.
diff --git a/gdb/testsuite/gdb.arch/powerpc-tar.exp b/gdb/testsuite/gdb.arch/powerpc-tar.exp
index b44d554..a060ec8 100644
--- a/gdb/testsuite/gdb.arch/powerpc-tar.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-tar.exp
@@ -68,7 +68,7 @@ proc tar_available {} {
# Do one pass to check if TAR is usable, system
# software can prevent it from being used.
with_test_prefix "check TAR access" {
- clean_restart $binfile
+ clean_restart $::testfile
if ![runto_main] {
return
@@ -84,7 +84,7 @@ with_test_prefix "check TAR access" {
}
# Now do the actual test
-clean_restart $binfile
+clean_restart $::testfile
if ![runto_main] {
return
diff --git a/gdb/testsuite/gdb.arch/powerpc-vector-regs.exp b/gdb/testsuite/gdb.arch/powerpc-vector-regs.exp
index 9e9162e..4537646 100644
--- a/gdb/testsuite/gdb.arch/powerpc-vector-regs.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-vector-regs.exp
@@ -30,7 +30,7 @@ if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable {debug}]
}
# Check if our test binary can actually run on this processor.
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_run_cmd
@@ -44,7 +44,7 @@ gdb_test_multiple "" "wait for exit" {
}
# Run the actual test.
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_breakpoint [gdb_get_line_number "marker"]
diff --git a/gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp b/gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp
index be1f93a..db568c6 100644
--- a/gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp
@@ -34,7 +34,7 @@ if {[build_executable "compile" $binfile $gen_src] == -1} {
return -1
}
-clean_restart $binfile
+clean_restart $testfile
if {![runto_main]} {
return -1
diff --git a/gdb/testsuite/gdb.arch/powerpc-vsx.exp b/gdb/testsuite/gdb.arch/powerpc-vsx.exp
index a6832e6..73a0fdc 100644
--- a/gdb/testsuite/gdb.arch/powerpc-vsx.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-vsx.exp
@@ -27,7 +27,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}]
return -1
}
-clean_restart ${objfile}
+clean_restart
+gdb_load $objfile
# Disassemble the function.
set func ""
diff --git a/gdb/testsuite/gdb.arch/powerpc-vsx2.exp b/gdb/testsuite/gdb.arch/powerpc-vsx2.exp
index d5cb18e..dfee7a3 100644
--- a/gdb/testsuite/gdb.arch/powerpc-vsx2.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-vsx2.exp
@@ -27,7 +27,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}]
return -1
}
-clean_restart ${objfile}
+clean_restart
+gdb_load $objfile
# Disassemble the function.
set func ""
diff --git a/gdb/testsuite/gdb.arch/powerpc-vsx3.exp b/gdb/testsuite/gdb.arch/powerpc-vsx3.exp
index bd54eaf..fd725f9 100644
--- a/gdb/testsuite/gdb.arch/powerpc-vsx3.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-vsx3.exp
@@ -27,7 +27,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}]
return -1
}
-clean_restart ${objfile}
+clean_restart
+gdb_load $objfile
# Disassemble the function.
set func ""
diff --git a/gdb/testsuite/gdb.arch/ppc-dfp.exp b/gdb/testsuite/gdb.arch/ppc-dfp.exp
index d7a8312..20145ae 100644
--- a/gdb/testsuite/gdb.arch/ppc-dfp.exp
+++ b/gdb/testsuite/gdb.arch/ppc-dfp.exp
@@ -31,7 +31,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {quie
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
gdb_breakpoint [gdb_get_line_number "Set DFP rounding mode."]
diff --git a/gdb/testsuite/gdb.arch/ppc-fp.exp b/gdb/testsuite/gdb.arch/ppc-fp.exp
index 4733296..c8342bb 100644
--- a/gdb/testsuite/gdb.arch/ppc-fp.exp
+++ b/gdb/testsuite/gdb.arch/ppc-fp.exp
@@ -31,7 +31,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {quie
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
gdb_breakpoint [gdb_get_line_number "Invalid operation."]
gdb_breakpoint [gdb_get_line_number "Division by zero."]
diff --git a/gdb/testsuite/gdb.arch/ppc-longdouble.exp b/gdb/testsuite/gdb.arch/ppc-longdouble.exp
index f3603f1..739e36f 100644
--- a/gdb/testsuite/gdb.arch/ppc-longdouble.exp
+++ b/gdb/testsuite/gdb.arch/ppc-longdouble.exp
@@ -28,7 +28,7 @@ proc do_test { name {opts {}} } {
return
}
- clean_restart ${binfile}.${name}
+ clean_restart ${::testfile}.${name}
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.arch/pr25124.exp b/gdb/testsuite/gdb.arch/pr25124.exp
index 4c43716..4e7c114 100644
--- a/gdb/testsuite/gdb.arch/pr25124.exp
+++ b/gdb/testsuite/gdb.arch/pr25124.exp
@@ -25,7 +25,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable debug
return -1
}
-clean_restart $binfile
+clean_restart $testfile
# Check if the disassemble ouput is correct.
gdb_test "x /i main+8" \
diff --git a/gdb/testsuite/gdb.arch/sparc-sysstep.exp b/gdb/testsuite/gdb.arch/sparc-sysstep.exp
index 40de862..4dfc514 100644
--- a/gdb/testsuite/gdb.arch/sparc-sysstep.exp
+++ b/gdb/testsuite/gdb.arch/sparc-sysstep.exp
@@ -28,7 +28,7 @@ set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}
set opts {}
-if {[prepare_for_testing "failed to prepare" ${binfile} $srcfile {additional_flags=-g}]} {
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {additional_flags=-g}]} {
return -1
}
diff --git a/gdb/testsuite/gdb.arch/thumb-prologue.exp b/gdb/testsuite/gdb.arch/thumb-prologue.exp
index 112c111..2ee82fb 100644
--- a/gdb/testsuite/gdb.arch/thumb-prologue.exp
+++ b/gdb/testsuite/gdb.arch/thumb-prologue.exp
@@ -27,7 +27,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {"add
}
-clean_restart $binfile
+clean_restart $testfile
#
# Run to `main' where we begin our tests.
diff --git a/gdb/testsuite/gdb.arch/thumb2-it.exp b/gdb/testsuite/gdb.arch/thumb2-it.exp
index 49031e1..e6ef06d 100644
--- a/gdb/testsuite/gdb.arch/thumb2-it.exp
+++ b/gdb/testsuite/gdb.arch/thumb2-it.exp
@@ -24,7 +24,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable debug
return -1
}
-clean_restart $binfile
+clean_restart $testfile
if {![runto_main]} {
return -1
diff --git a/gdb/testsuite/gdb.arch/vsx-regs.exp b/gdb/testsuite/gdb.arch/vsx-regs.exp
index 645207f..df74ef3 100644
--- a/gdb/testsuite/gdb.arch/vsx-regs.exp
+++ b/gdb/testsuite/gdb.arch/vsx-regs.exp
@@ -184,7 +184,8 @@ if {!$core_supported} {
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
set core_loaded [gdb_core_cmd "$corefile" "re-load generated corefile"]
if { $core_loaded == -1 } {
diff --git a/gdb/testsuite/gdb.base/a2-run.exp b/gdb/testsuite/gdb.base/a2-run.exp
index 4e95e56..966e12a 100644
--- a/gdb/testsuite/gdb.base/a2-run.exp
+++ b/gdb/testsuite/gdb.base/a2-run.exp
@@ -18,6 +18,8 @@
# Can't do this test without stdio support.
require {!gdb_skip_stdio_test "a2run.exp"}
+set have_startup_shell [have_startup_shell]
+
#
# test running programs
#
@@ -166,9 +168,8 @@ gdb_run_cmd
setup_xfail "arm-*-coff"
gdb_test_stdio "" "720" "" "run \"$testfile\" again after setting args"
-# GOAL: Test that shell is being used with "run". For remote debugging
-# targets, there is no guarantee that a "shell" (whatever that is) is used.
-if {![is_remote target]} {
+# GOAL: Test that shell is being used with "run".
+if { $have_startup_shell == 1 } {
gdb_test_stdio "run `echo 8`" \
"40320" "" "run \"$testfile\" with shell"
}
diff --git a/gdb/testsuite/gdb.base/access-mem-running.exp b/gdb/testsuite/gdb.base/access-mem-running.exp
index ecff427..280e89b 100644
--- a/gdb/testsuite/gdb.base/access-mem-running.exp
+++ b/gdb/testsuite/gdb.base/access-mem-running.exp
@@ -32,7 +32,8 @@ proc test { non_stop } {
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop $non_stop\""
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
}
if ![runto_main] {
diff --git a/gdb/testsuite/gdb.base/annota1.exp b/gdb/testsuite/gdb.base/annota1.exp
index 06dbec2..744d825 100644
--- a/gdb/testsuite/gdb.base/annota1.exp
+++ b/gdb/testsuite/gdb.base/annota1.exp
@@ -533,7 +533,8 @@ proc thread_test {} {
if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug nowarnings}] == "" } {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if {![runto_main]} {
return
}
diff --git a/gdb/testsuite/gdb.base/annotate-symlink.exp b/gdb/testsuite/gdb.base/annotate-symlink.exp
index f7f6f18..a5d431e 100644
--- a/gdb/testsuite/gdb.base/annotate-symlink.exp
+++ b/gdb/testsuite/gdb.base/annotate-symlink.exp
@@ -20,7 +20,7 @@ standard_testfile realname-expand.c realname-expand-real.c
require {!is_remote host}
set srcdirabs [file join [pwd] $srcdir]
-set srcfilelink [standard_output_file realname-expand-link.c]
+set srcfilelink [build_standard_output_file realname-expand-link.c]
remote_exec build "ln -sf ${srcdirabs}/${subdir}/${srcfile2} $srcfilelink"
diff --git a/gdb/testsuite/gdb.base/args.exp b/gdb/testsuite/gdb.base/args.exp
index 33952e4..573543c 100644
--- a/gdb/testsuite/gdb.base/args.exp
+++ b/gdb/testsuite/gdb.base/args.exp
@@ -21,6 +21,7 @@ require {!target_info exists noargs}
# This test requires starting new inferior processes, skip it if the target
# board is a stub.
require !use_gdb_stub
+require {expr [have_startup_shell] != -1}
standard_testfile
@@ -29,74 +30,174 @@ if {[build_executable $testfile.exp $testfile $srcfile] == -1} {
return -1
}
-# NAME is the name to use for the tests and ARGLIST is the list of
-# arguments that are passed to GDB when it is started.
+# Assuming a running GDB. Check the status of the single inferior
+# argument feature. When this feature is on GDB passes inferior
+# arguments as a single combined string. When this feature is off GDB
+# will split the inferior arguments into multiple separate strings.
#
-# The optional RE_LIST is the list of patterns to check the arguments
-# against, these patterns should match ARGLIST. If the arguments are
-# expected to show up unmodified in the test output then RE_LIST can
-# be dropped, and this proc will reuse ARGLIST.
-
-proc args_test { name arglist {re_list {}} } {
-
- # If RE_LIST is not supplied then we can reuse ARGLIST, this
- # implies that the arguments will appear unmodified in the test
- # output.
- if {[llength $re_list] == 0} {
- set re_list $arglist
+# Return true when arguments are being split, or false when a single
+# combined string is being sent.
+
+proc is_argument_splitting_on {} {
+ set arg_splitting true
+
+ gdb_test_multiple "show remote single-inferior-argument-feature-packet" "" {
+ -re -wrap "Support for the 'single-inferior-argument-feature' packet on the current remote target is \"(on|off)\"\\.(.*)" {
+ set value $expect_out(1,string)
+ pass $gdb_test_name
+ if { $value eq "on" } {
+ set arg_splitting false
+ }
+ }
+ -re -wrap "Support for the 'single-inferior-argument-feature' packet on the current remote target is \"auto\", currently (enabled|disabled)\\.(.*)" {
+ set value $expect_out(1,string)
+ pass $gdb_test_name
+ if { $value eq "enabled" } {
+ set arg_splitting false
+ }
+ }
}
- foreach_with_prefix startup_with_shell { on off } {
- save_vars { ::GDBFLAGS } {
- set ::GDBFLAGS "$::GDBFLAGS --args $::binfile $arglist"
-
- clean_restart $::binfile
-
- gdb_test_no_output "set startup-with-shell ${startup_with_shell}" \
- "set startup-with-shell for $name"
+ return $arg_splitting
+}
- runto_main
- gdb_breakpoint [gdb_get_line_number "set breakpoint here"]
- gdb_continue_to_breakpoint "breakpoint for $name"
+# NAME is the name to use for the tests and ARGLIST is the list of
+# arguments that are passed to GDB when it is started.
+#
+# The optional RE_ESC_LIST is the list of patterns to check the
+# inferior arguments against when GDB is started using --args. If
+# RE_ESC_LIST is not given then ARGLIST is reused, this implies that
+# the inferior arguments appear unchanged in the test output.
+#
+# The optional RE_NO_ESC_LIST is the list of patterns to check the
+# inferior arguments against when GDB is started using
+# --no-escape-args. If RE_NO_ESC_LIST is not given then RE_ESC_LIST
+# is reused, this implies that there's no difference between the test
+# output when the arguments are escaped or not.
+
+proc args_test { name arglist {re_esc_list {}} {re_no_esc_list {}} } {
+
+ # If either of the two regexp lists are not specificed then we can
+ # use an earlier argument value instead.
+ #
+ # For the first regexp list, if this is missing then we use the
+ # argument list, this assumes that the arguments will appear
+ # unmodified in the output.
+ if {[llength $re_esc_list] == 0} {
+ set re_esc_list $arglist
+ }
- set expected_len [expr 1 + [llength $re_list]]
- gdb_test "print argc" "\\\$$::decimal = $expected_len" "argc for $name"
+ # If the second regexp list is missing then we reuse the first
+ # regexp list. This assumes there's no difference between escaped
+ # and unescaped arguments in the output.
+ if {[llength $re_no_esc_list] == 0} {
+ set re_no_esc_list $re_esc_list
+ }
- set i 1
- foreach arg $re_list {
- gdb_test "print argv\[$i\]" "\\\$$::decimal = $::hex \"$arg\"" \
- "argv\[$i\] for $name"
- set i [expr $i + 1]
+ foreach_with_prefix startup_with_shell { on off } {
+ foreach_with_prefix arg_flag { args no-escape-args } {
+ save_vars { ::GDBFLAGS } {
+ set ::GDBFLAGS "$::GDBFLAGS --${arg_flag} $::binfile $arglist"
+
+ clean_restart $::testfile
+
+ gdb_test_no_output \
+ "set startup-with-shell ${startup_with_shell}" \
+ "set startup-with-shell for $name"
+
+ runto_main
+ gdb_breakpoint [gdb_get_line_number "set breakpoint here"]
+ gdb_continue_to_breakpoint "breakpoint for $name"
+
+ if { $arg_flag eq "args" || $startup_with_shell eq "off" } {
+ set re_list $re_esc_list
+ } else {
+ set re_list $re_no_esc_list
+ }
+
+ set expected_len [expr 1 + [llength $re_list]]
+ gdb_test "print argc" \
+ "\\\$$::decimal = $expected_len" "argc for $name"
+
+ set i 1
+ foreach arg $re_list {
+ if { $arg eq "\n" } {
+ set arg {\\n}
+ } elseif { $arg eq "\"" } {
+ set arg {\\\"}
+ }
+
+ # If we are starting with a shell, we're not escaping
+ # special shell characters in arguments passed to GDB,
+ # we're using a remote target, and the arguments contain
+ # a shell variable (indicated with a '$'), then this
+ # test will currently fail if we are splitting the
+ # arguments.
+ if { $startup_with_shell eq "on"
+ && $arg_flag eq "no-escape-args"
+ && [gdb_protocol_is_remote]
+ && [string first "\$" $arglist] != -1
+ && [is_argument_splitting_on] } {
+ setup_xfail "*-*-*" gdb/28392
+ }
+
+ gdb_test "print argv\[$i\]" \
+ "\\\$$::decimal = $::hex \"$arg\"" \
+ "argv\[$i\] for $name"
+ set i [expr $i + 1]
+ }
}
}
}
}
-# Test that the --args are processed correctly.
+# Run all the tests.
+proc run_all_tests {} {
+ # Test that the --args are processed correctly.
+
+ args_test basic {{1} {3}}
+
+ # Test that the --args are processed correctly even if one of them is
+ # empty.
-args_test basic {{1} {3}}
+ args_test "one empty" {{1} {} {3}}
-# Test that the --args are processed correctly even if one of them is
-# empty.
+ # Try with 2 empty args.
-args_test "one empty" {{1} {} {3}}
+ args_test "two empty" {{1} {} {} 3}
-# Try with 2 empty args.
+ # Try with arguments containing literal single quotes.
-args_test "two empty" {{1} {} {} 3}
+ args_test "one empty with single quotes" {{1} {''} {3}}
-# Try with arguments containing literal single quotes.
+ args_test "two empty with single quotes" {{1} {''} {''} {3}}
-args_test "one empty with single quotes" {{1} {''} {3}}
+ # Try with arguments containing literal newlines.
-args_test "two empty with single quotes" {{1} {''} {''} {3}}
+ args_test "one newline" {{1} "\n" {3}} {1 \\\\n 3}
-# Try with arguments containing literal newlines.
+ args_test "two newlines" {{1} "\n" "\n" {3}} {1 \\\\n \\\\n 3}
-args_test "one newline" {{1} "\n" {3}} {1 \\\\n 3}
+ args_test "lone single quote" {{1} \' {3}}
-args_test "two newlines" {{1} "\n" "\n" {3}} {1 \\\\n \\\\n 3}
+ args_test "lone double quote" {{1} \" {3}} {1 \\\\\" 3}
-args_test "lone single quote" {{1} \' {3}}
+ save_vars { ::env(TEST) } {
+ set ::env(TEST) "ABCD"
+ args_test "shell variable" {{$TEST}} {\\$TEST} {{ABCD}}
+ }
+}
+
+run_all_tests
-args_test "lone double quote" {{1} \" {3}} {1 \\\\\" 3}
+# For extended-remote targets, disable the packet which passes
+# inferior arguments as a single string. This changes how the vRun
+# (extended-remote only) packet works.
+if {[target_info gdb_protocol] == "extended-remote"} {
+ with_test_prefix "single-inferior-arg disabled" {
+ save_vars { GDBFLAGS } {
+ append GDBFLAGS " -ex \"set remote single-inferior-argument-feature-packet off\""
+ run_all_tests
+ }
+ }
+}
diff --git a/gdb/testsuite/gdb.base/arrayidx.exp b/gdb/testsuite/gdb.base/arrayidx.exp
index 4fc221f..757ce92 100644
--- a/gdb/testsuite/gdb.base/arrayidx.exp
+++ b/gdb/testsuite/gdb.base/arrayidx.exp
@@ -24,7 +24,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debu
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/assign.exp b/gdb/testsuite/gdb.base/assign.exp
index a69655d..aaee796 100644
--- a/gdb/testsuite/gdb.base/assign.exp
+++ b/gdb/testsuite/gdb.base/assign.exp
@@ -33,7 +33,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
#
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/attach-fail-twice.exp b/gdb/testsuite/gdb.base/attach-fail-twice.exp
index 529002d..5e5d73f 100644
--- a/gdb/testsuite/gdb.base/attach-fail-twice.exp
+++ b/gdb/testsuite/gdb.base/attach-fail-twice.exp
@@ -77,7 +77,8 @@ proc test_good_attach {test} {
}
proc_with_prefix test {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
# GDB used to have a bug on Windows where failing to attach once
# made a subsequent "attach" or "run" hang. So it's important for
diff --git a/gdb/testsuite/gdb.base/attach-non-pgrp-leader.exp b/gdb/testsuite/gdb.base/attach-non-pgrp-leader.exp
index 2ce092d..c43a11c 100644
--- a/gdb/testsuite/gdb.base/attach-non-pgrp-leader.exp
+++ b/gdb/testsuite/gdb.base/attach-non-pgrp-leader.exp
@@ -36,7 +36,8 @@ proc do_test {} {
# Attach to the parent, run it to a known point, extract the
# child's PID, and detach.
with_test_prefix "parent" {
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
gdb_test "attach $parent_pid" \
"Attaching to program.*, process $parent_pid.*" \
@@ -56,7 +57,8 @@ proc do_test {} {
# Start over, and attach to the child this time.
with_test_prefix "child" {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_test "attach $child_pid" \
"Attaching to program.*, process $child_pid.*" \
diff --git a/gdb/testsuite/gdb.base/attach-wait-input.exp b/gdb/testsuite/gdb.base/attach-wait-input.exp
index 84c9bab..47e3d25 100644
--- a/gdb/testsuite/gdb.base/attach-wait-input.exp
+++ b/gdb/testsuite/gdb.base/attach-wait-input.exp
@@ -43,7 +43,8 @@ proc start_program {binfile} {
global gdb_prompt
global decimal
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if {![runto setup_done]} {
return 0
diff --git a/gdb/testsuite/gdb.base/attach.c b/gdb/testsuite/gdb.base/attach.c
index b3c5498..5133dd0 100644
--- a/gdb/testsuite/gdb.base/attach.c
+++ b/gdb/testsuite/gdb.base/attach.c
@@ -5,7 +5,7 @@
exit unless/until gdb sets the variable to non-zero.)
*/
#include <stdio.h>
-#include <unistd.h>
+#include "gdb_watchdog.h"
int bidule = 0;
volatile int should_exit = 0;
@@ -14,7 +14,7 @@ int main ()
{
int local_i = 0;
- alarm (60);
+ gdb_watchdog (60);
while (! should_exit)
{
diff --git a/gdb/testsuite/gdb.base/attach.exp b/gdb/testsuite/gdb.base/attach.exp
index 0d1550a..d0a29f2 100644
--- a/gdb/testsuite/gdb.base/attach.exp
+++ b/gdb/testsuite/gdb.base/attach.exp
@@ -56,7 +56,8 @@ proc_with_prefix do_attach_failure_tests {} {
global escapedbinfile
global srcfile
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
# Figure out a regular expression that will match the sysroot,
# noting that the default sysroot is "target:", and also noting
@@ -215,7 +216,8 @@ proc_with_prefix do_attach_tests {} {
global timeout
global decimal
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
# Figure out a regular expression that will match the sysroot,
# noting that the default sysroot is "target:", and also noting
@@ -519,7 +521,8 @@ proc_with_prefix do_attach_exec_mismatch_handling_tests {} {
global binfile2
global binfile3
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
# Start two programs that can be attached to.
# The first program contains a 'int bidule' variable, the second a 'float bidule'.
diff --git a/gdb/testsuite/gdb.base/auxv.exp b/gdb/testsuite/gdb.base/auxv.exp
index 090d9ba..38efa45 100644
--- a/gdb/testsuite/gdb.base/auxv.exp
+++ b/gdb/testsuite/gdb.base/auxv.exp
@@ -41,7 +41,8 @@ set core_works [expr [isnative] && ! [is_remote target]]
# Run GDB on the test program up to where it will dump core.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_test_no_output "set print sevenbit-strings"
gdb_test_no_output "set width 0"
diff --git a/gdb/testsuite/gdb.base/backtrace-through-cu-nodebug.exp b/gdb/testsuite/gdb.base/backtrace-through-cu-nodebug.exp
index 53bf642..652e8c1 100644
--- a/gdb/testsuite/gdb.base/backtrace-through-cu-nodebug.exp
+++ b/gdb/testsuite/gdb.base/backtrace-through-cu-nodebug.exp
@@ -31,7 +31,7 @@ proc prepare_test {has_cfi} {
"${objcallerfile}" \
object [list {additional_flags=-fomit-frame-pointer \
-funwind-tables -fasynchronous-unwind-tables}]] != "" } {
- untested "couldn't compile with cfi"
+ untested "couldn't compile"
return false
}
} else {
@@ -41,7 +41,7 @@ proc prepare_test {has_cfi} {
object [list {additional_flags=-fomit-frame-pointer \
-fno-unwind-tables \
-fno-asynchronous-unwind-tables}]] != "" } {
- untested "couldn't compile without cfi"
+ untested "couldn't compile"
return false
}
}
@@ -52,17 +52,15 @@ proc prepare_test {has_cfi} {
return false
}
- clean_restart "$binfile-${extension}"
+ clean_restart
+ gdb_load $binfile-$extension
- with_test_prefix "${extension}" {
-
- if ![runto callback] then {
- fail "has_cfi=$has_cfi: Can't run to callback"
- return false
- }
- gdb_test_no_output "maint frame-unwinder disable ARCH"
- return true
+ if { ![runto callback] } {
+ fail "has_cfi=$has_cfi: Can't run to callback"
+ return false
}
+ gdb_test_no_output "maint frame-unwinder disable ARCH"
+ return true
}
if {[gdb_compile "${srcdir}/${subdir}/${srcfile2}" \
@@ -72,15 +70,45 @@ if {[gdb_compile "${srcdir}/${subdir}/${srcfile2}" \
return
}
-if { [prepare_test false] } {
- gdb_test "bt" \
+proc_with_prefix no-cfi {} {
+ if { ![prepare_test false] } {
+ return
+ }
+
+ set re_msg \
+ [string_list_to_regexp \
+ "Required frame unwinder may have been disabled," \
+ " see 'maint info frame-unwinders'"]
+ set hs {[^\r\n]}
+ set re_bt_line "#0\\s+[string_to_regexp {callback ()}] $hs+"
+ set re_bt_no_filters \
[multi_line \
- "\[^\r\n\]+Required frame unwinder may have been disabled, \[^\r\n\]+" \
- "#0\\s+callback \\(\\) \[^\r\n\]+"] \
- "verify unwind fail without CFI"
+ $re_bt_line \
+ $re_msg]
+ gdb_test "bt -no-filters" \
+ $re_bt_no_filters \
+ "verify no-filters unwind fail"
+
+ # Flush frame cache to retrigger the message.
+ gdb_test "maint flush register-cache" \
+ [string_to_regexp "Register cache flushed."]
+
+ # This output may occur when we run into the message while applying the
+ # frame filters.
+ set re_bt \
+ [multi_line \
+ $hs+$re_msg \
+ $re_bt_line]
+ gdb_test "bt" \
+ "($re_bt|$re_bt_no_filters)" \
+ "verify unwind fail"
}
-if { [prepare_test true] } {
+proc_with_prefix cfi {} {
+ if { ![prepare_test true] } {
+ return
+ }
+
if { [istarget "arm*-*-*"] } {
setup_kfail backtrace/31950 *-*-*
}
@@ -89,6 +117,12 @@ if { [prepare_test true] } {
# #1 0x00000000004004e9 in caller ()
# #2 0x00000000004004cd in main () at ...
gdb_test "bt" \
- "#0 +callback $text\r\n#1 $text in caller $text\r\n#2 $text in main $text" \
- "Verify unwinding works based only on CFI information"
+ [multi_line \
+ "#0 +callback $text" \
+ "#1 $text in caller $text" \
+ "#2 $text in main $text"] \
+ "Verify unwinding works"
}
+
+no-cfi
+cfi
diff --git a/gdb/testsuite/gdb.base/backtrace.exp b/gdb/testsuite/gdb.base/backtrace.exp
index 35784b4..3020666 100644
--- a/gdb/testsuite/gdb.base/backtrace.exp
+++ b/gdb/testsuite/gdb.base/backtrace.exp
@@ -17,11 +17,7 @@
standard_testfile
-set flags {}
-lappend flags debug
-lappend_include_file flags $srcdir/lib/attributes.h
-
-if { [prepare_for_testing "failed to prepare" $testfile $srcfile $flags] } {
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
return -1
}
diff --git a/gdb/testsuite/gdb.base/basic-edit-cmd.exp b/gdb/testsuite/gdb.base/basic-edit-cmd.exp
index 8a23c9b..7ad8ab9 100644
--- a/gdb/testsuite/gdb.base/basic-edit-cmd.exp
+++ b/gdb/testsuite/gdb.base/basic-edit-cmd.exp
@@ -68,7 +68,8 @@ save_vars { env(EDITOR) } {
"try edit when no symbol file is loaded"
# Now start with a test binary.
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
with_test_prefix "before starting inferior" {
diff --git a/gdb/testsuite/gdb.base/bfp-test.exp b/gdb/testsuite/gdb.base/bfp-test.exp
index 7781fe1..53d274f 100644
--- a/gdb/testsuite/gdb.base/bfp-test.exp
+++ b/gdb/testsuite/gdb.base/bfp-test.exp
@@ -23,7 +23,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debu
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/bg-exec-sigint-bp-cond.exp b/gdb/testsuite/gdb.base/bg-exec-sigint-bp-cond.exp
index 18e20e0..2e2a8e6 100644
--- a/gdb/testsuite/gdb.base/bg-exec-sigint-bp-cond.exp
+++ b/gdb/testsuite/gdb.base/bg-exec-sigint-bp-cond.exp
@@ -34,7 +34,8 @@ if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
# AFTER_KILL_COND is appended to the breakpoint condition, after "kill
# -SIGINT $gdb_pid".
proc test { {after_kill_cond ""} } {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/bg-execution-repeat.exp b/gdb/testsuite/gdb.base/bg-execution-repeat.exp
index d5580fb..e7bdf49 100644
--- a/gdb/testsuite/gdb.base/bg-execution-repeat.exp
+++ b/gdb/testsuite/gdb.base/bg-execution-repeat.exp
@@ -33,7 +33,8 @@ proc test {continue_cmd} {
global binfile
global linenum
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if ![runto_main] {
return
diff --git a/gdb/testsuite/gdb.base/bigcore.exp b/gdb/testsuite/gdb.base/bigcore.exp
index 7727e48..f917eb8 100644
--- a/gdb/testsuite/gdb.base/bigcore.exp
+++ b/gdb/testsuite/gdb.base/bigcore.exp
@@ -117,7 +117,8 @@ proc test {dumper} {
# Run GDB on the bigcore program up-to where it will dump core.
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
gdb_test_no_output "set print sevenbit-strings"
gdb_test_no_output "set width 0"
diff --git a/gdb/testsuite/gdb.base/bitfields2.exp b/gdb/testsuite/gdb.base/bitfields2.exp
index a99660a..3e981dd 100644
--- a/gdb/testsuite/gdb.base/bitfields2.exp
+++ b/gdb/testsuite/gdb.base/bitfields2.exp
@@ -233,7 +233,8 @@ proc bitfield_set {} {
}
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_test_no_output "set print sevenbit-strings"
runto_main
diff --git a/gdb/testsuite/gdb.base/bp-cmds-continue-ctrl-c.exp b/gdb/testsuite/gdb.base/bp-cmds-continue-ctrl-c.exp
index 4fc8f06..648992c 100644
--- a/gdb/testsuite/gdb.base/bp-cmds-continue-ctrl-c.exp
+++ b/gdb/testsuite/gdb.base/bp-cmds-continue-ctrl-c.exp
@@ -118,7 +118,8 @@ proc do_test {} {
# "attach".
with_test_prefix "run" {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if {![runto_main]} {
return -1
@@ -129,7 +130,8 @@ with_test_prefix "run" {
with_test_prefix "attach" {
if {[can_spawn_for_attach]} {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
set test_spawn_id [spawn_wait_for_attach $binfile]
set testpid [spawn_id_get_pid $test_spawn_id]
diff --git a/gdb/testsuite/gdb.base/bp-cond-failure.exp b/gdb/testsuite/gdb.base/bp-cond-failure.exp
index d645454..f33092b 100644
--- a/gdb/testsuite/gdb.base/bp-cond-failure.exp
+++ b/gdb/testsuite/gdb.base/bp-cond-failure.exp
@@ -26,7 +26,7 @@
standard_testfile
-if { [prepare_for_testing "failed to prepare" ${binfile} "${srcfile}" \
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
{debug c++}] == -1 } {
return
}
@@ -45,7 +45,8 @@ if { [is_address_zero_readable] } {
}
proc run_test { cond_eval access_type bpexpr nloc } {
- clean_restart ${::binfile}
+ clean_restart
+ gdb_load $::binfile
if { ![runto_main] } {
return -1
@@ -75,7 +76,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 +85,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-disabled-by-cond.exp b/gdb/testsuite/gdb.base/bp-disabled-by-cond.exp
index f0bdd16..371b9e7 100644
--- a/gdb/testsuite/gdb.base/bp-disabled-by-cond.exp
+++ b/gdb/testsuite/gdb.base/bp-disabled-by-cond.exp
@@ -52,7 +52,8 @@ set exit_bp_line [gdb_get_line_number "BP before exit" $srcfile]
# Restart the inferior, which should unload the shared library, GDB
# should mark the b/p as disabled due to its condition again.
proc run_test { hit_cond } {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if {![runto_main]} {
return
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..3ae5efe 100644
--- a/gdb/testsuite/gdb.base/bp-permanent.exp
+++ b/gdb/testsuite/gdb.base/bp-permanent.exp
@@ -42,7 +42,8 @@ proc test {always_inserted sw_watchpoint} {
global gdb_prompt
global srcfile binfile
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if {![runto_main]} {
return -1
@@ -134,7 +135,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 +175,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..a7c7d92
--- /dev/null
+++ b/gdb/testsuite/gdb.base/break-dbg.exp
@@ -0,0 +1,80 @@
+# 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\\)"
+
+set re_warning_xml_disabled \
+ [string_to_regexp \
+ [join \
+ [list \
+ "warning: Can not parse XML syscalls information;" \
+ "XML support was disabled at compile time."]]]
+gdb_test "catch syscall" \
+ [multi_line \
+ "^($re_warning_xml_disabled" \
+ ")?Catchpoint $decimal [string_to_regexp {(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/break-fun-addr.exp b/gdb/testsuite/gdb.base/break-fun-addr.exp
index 9f5325a..ba6e32e 100644
--- a/gdb/testsuite/gdb.base/break-fun-addr.exp
+++ b/gdb/testsuite/gdb.base/break-fun-addr.exp
@@ -44,7 +44,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile1}" "${binfile1}" executable {d
# on the first instruction of function "main" ("*main"), then
# run to that breakpoint.
-clean_restart ${binfile1}
+clean_restart
+gdb_load $binfile1
with_test_prefix "${testfile1}" {
diff --git a/gdb/testsuite/gdb.base/break-idempotent.exp b/gdb/testsuite/gdb.base/break-idempotent.exp
index ed23b64..3b32c89 100644
--- a/gdb/testsuite/gdb.base/break-idempotent.exp
+++ b/gdb/testsuite/gdb.base/break-idempotent.exp
@@ -161,7 +161,7 @@ foreach_with_prefix pie { "nopie" "pie" } {
set binfile [standard_output_file $testfile-$pie]
- if {[prepare_for_testing "failed to prepare" $binfile $srcfile $opts]} {
+ if {[prepare_for_testing "failed to prepare" $testfile-$pie $srcfile $opts]} {
continue
}
diff --git a/gdb/testsuite/gdb.base/break-interp.exp b/gdb/testsuite/gdb.base/break-interp.exp
index 649cc86..038c3ea 100644
--- a/gdb/testsuite/gdb.base/break-interp.exp
+++ b/gdb/testsuite/gdb.base/break-interp.exp
@@ -78,7 +78,8 @@ gdb_test_multiple $test $test {
}
set interp_system [section_get [standard_output_file $binfile_test] .interp]
-clean_restart $interp_system
+clean_restart
+gdb_load $interp_system
set dl_main_found 0
gdb_test_multiple "info addr dl_main" "" {
-re -wrap "Symbol \"dl_main\" is a function at address $hex\\." {
@@ -218,6 +219,7 @@ proc test_core {file displacement} {
set corefile [core_find $file {} "segv"]
if {$corefile == ""} {
+ untested "unable to create or find corefile"
return
}
diff --git a/gdb/testsuite/gdb.base/bt-on-fatal-signal.exp b/gdb/testsuite/gdb.base/bt-on-fatal-signal.exp
index 06402dc..63428a1 100644
--- a/gdb/testsuite/gdb.base/bt-on-fatal-signal.exp
+++ b/gdb/testsuite/gdb.base/bt-on-fatal-signal.exp
@@ -61,7 +61,8 @@ foreach test_data {{SEGV "Segmentation fault"} \
# Restart GDB.
save_vars { GDB } {
set GDB [gdb_no_core]
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
}
# Capture the pid of GDB.
diff --git a/gdb/testsuite/gdb.base/bt-selected-frame.exp b/gdb/testsuite/gdb.base/bt-selected-frame.exp
index 68f5ed4..bbe2a5a 100644
--- a/gdb/testsuite/gdb.base/bt-selected-frame.exp
+++ b/gdb/testsuite/gdb.base/bt-selected-frame.exp
@@ -24,7 +24,8 @@ if { [build_executable "failed to prepare" $testfile $srcfile debug] } {
proc check_selected_frame_after_bt { bt_cmd stack_pattern } {
global binfile
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
with_test_prefix $bt_cmd {
diff --git a/gdb/testsuite/gdb.base/call-rt-st.exp b/gdb/testsuite/gdb.base/call-rt-st.exp
index 244eba8..511e209 100644
--- a/gdb/testsuite/gdb.base/call-rt-st.exp
+++ b/gdb/testsuite/gdb.base/call-rt-st.exp
@@ -39,7 +39,8 @@ set allow_float_test [allow_float_test]
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_test_no_output "set print sevenbit-strings"
gdb_test_no_output "set print address off"
gdb_test_no_output "set width 0"
diff --git a/gdb/testsuite/gdb.base/call-sc.exp b/gdb/testsuite/gdb.base/call-sc.exp
index 4d0fccc..f67670d 100644
--- a/gdb/testsuite/gdb.base/call-sc.exp
+++ b/gdb/testsuite/gdb.base/call-sc.exp
@@ -46,7 +46,7 @@ proc start_scalars_test { type } {
set testfile "call-sc-${type}"
set binfile [standard_output_file ${testfile}]
- if { [prepare_for_testing "failed to prepare" $binfile $srcfile $flags] } {
+ if { [prepare_for_testing "failed to prepare" $testfile $srcfile $flags] } {
return -1
}
diff --git a/gdb/testsuite/gdb.base/call-signal-resume.exp b/gdb/testsuite/gdb.base/call-signal-resume.exp
index 10a2928..a74b8af 100644
--- a/gdb/testsuite/gdb.base/call-signal-resume.exp
+++ b/gdb/testsuite/gdb.base/call-signal-resume.exp
@@ -47,7 +47,8 @@ proc get_dummy_frame_number { } {
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if { ![runto_main] } {
return 0
diff --git a/gdb/testsuite/gdb.base/callexit.exp b/gdb/testsuite/gdb.base/callexit.exp
index c250c67..e0ce899 100644
--- a/gdb/testsuite/gdb.base/callexit.exp
+++ b/gdb/testsuite/gdb.base/callexit.exp
@@ -27,7 +27,8 @@ require {!target_info exists gdb,cannot_call_functions}
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if { ![runto_main] } {
return 0
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/catch-syscall.exp b/gdb/testsuite/gdb.base/catch-syscall.exp
index f3ddef5..9c5839c 100644
--- a/gdb/testsuite/gdb.base/catch-syscall.exp
+++ b/gdb/testsuite/gdb.base/catch-syscall.exp
@@ -630,7 +630,8 @@ proc test_catch_syscall_multi_arch {} {
test_catch_syscall_multi_arch_1 $arch1 $arch2 $syscall1_name \
$syscall2_name $syscall_number
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
}
proc do_syscall_tests_without_xml {} {
@@ -801,18 +802,21 @@ fill_all_syscalls_numbers
# Execute the tests, using XML support
gdb_exit
if { [allow_xml_test] } {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
do_syscall_tests
# Now, we have to see if GDB displays a warning when we
# don't set the data-directory but try to use catch syscall
# anyway. For that, we must restart GDB first.
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
test_catch_syscall_fail_nodatadir
}
# Restart gdb
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Execute the tests, without XML support. In this case, GDB will
# only display syscall numbers, and not syscall names.
diff --git a/gdb/testsuite/gdb.base/checkpoint.exp b/gdb/testsuite/gdb.base/checkpoint.exp
index 89b36f5..55eba5d 100644
--- a/gdb/testsuite/gdb.base/checkpoint.exp
+++ b/gdb/testsuite/gdb.base/checkpoint.exp
@@ -290,7 +290,8 @@ gdb_test "restart 10" "has no checkpoints" "no more checkpoint 10"
# Now let's try setting a large number of checkpoints (>600)
#
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
runto_main
gdb_breakpoint $break1_loc
@@ -356,7 +357,8 @@ gdb_test "kill" "" "kill all one with many checkpoints" \
#
with_test_prefix "delete checkpoint 0" {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
runto_main
gdb_test "checkpoint" "Checkpoint 1: fork returned pid $decimal\\."
diff --git a/gdb/testsuite/gdb.base/chng-syms.exp b/gdb/testsuite/gdb.base/chng-syms.exp
index a561689..dbc523d 100644
--- a/gdb/testsuite/gdb.base/chng-syms.exp
+++ b/gdb/testsuite/gdb.base/chng-syms.exp
@@ -36,7 +36,8 @@ proc expect_to_stop_here { ident } {
gdb_test "" "Breakpoint \[0-9\]*, stop_here .*" "running to stop_here $ident"
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_test "break stop_here if (var1 == 42)" \
"Breakpoint.*at.* file .*$srcfile, line.*" \
diff --git a/gdb/testsuite/gdb.base/clear_non_user_bp.exp b/gdb/testsuite/gdb.base/clear_non_user_bp.exp
index f078b97..c016d07 100644
--- a/gdb/testsuite/gdb.base/clear_non_user_bp.exp
+++ b/gdb/testsuite/gdb.base/clear_non_user_bp.exp
@@ -47,7 +47,8 @@ if { [gdb_compile "${srcdir}/${subdir}/main.c" "${binfile}" executable {debug}]
}
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.base/cli-suppress-notification.exp b/gdb/testsuite/gdb.base/cli-suppress-notification.exp
index 19f9c55..6880d98 100644
--- a/gdb/testsuite/gdb.base/cli-suppress-notification.exp
+++ b/gdb/testsuite/gdb.base/cli-suppress-notification.exp
@@ -17,7 +17,7 @@
standard_testfile
-if {[prepare_for_testing "failed to prepare" ${binfile} ${srcfile}]} {
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
return
}
diff --git a/gdb/testsuite/gdb.base/code-expr.exp b/gdb/testsuite/gdb.base/code-expr.exp
index 4288617..8af2ee6 100644
--- a/gdb/testsuite/gdb.base/code-expr.exp
+++ b/gdb/testsuite/gdb.base/code-expr.exp
@@ -29,7 +29,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_test_no_output "set print sevenbit-strings"
gdb_test_no_output "set print address off"
diff --git a/gdb/testsuite/gdb.base/color-prompt.exp b/gdb/testsuite/gdb.base/color-prompt.exp
new file mode 100644
index 0000000..c037185
--- /dev/null
+++ b/gdb/testsuite/gdb.base/color-prompt.exp
@@ -0,0 +1,29 @@
+# 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 using a prompt with color in CLI.
+
+# Using tuiterm requires setting TERM on host.
+require {!is_remote host}
+
+# We use a tuiterm, which allows us to determine cursor position.
+tuiterm_env
+Term::clean_restart 8 80
+
+# We start with an empty screen, to generate a visible prompt.
+Term::gen_prompt
+
+set tui 0
+source $srcdir/$subdir/../gdb.tui/color-prompt.exp.tcl
diff --git a/gdb/testsuite/gdb.base/command-line-input.exp b/gdb/testsuite/gdb.base/command-line-input.exp
index af228dc..9760f1a 100644
--- a/gdb/testsuite/gdb.base/command-line-input.exp
+++ b/gdb/testsuite/gdb.base/command-line-input.exp
@@ -18,19 +18,59 @@
# Test issuing a command split in multiple lines with continuation
# characters.
-gdb_exit
-gdb_start
+clean_restart
-set test "print 1\\\\n + 2"
-gdb_test_multiple "print 1\\\n + 2" $test {
- -re "^print 1\\\\\r\n \\+ 2\r\n\\\$$decimal = 3\r\n$gdb_prompt $" {
- pass $test
+set bs "\\"
+set re_bs [string_to_regexp $bs]
+set re_dollar [string_to_regexp $]
+
+set re \
+ [multi_line \
+ ^[string_to_regexp "print 1$bs"] \
+ [string_to_regexp " + 2"] \
+ "$re_dollar$decimal = 3" \
+ "$gdb_prompt $"]
+gdb_test_multiple "print 1$bs\n + 2" "print 1$bs${bs}n + 2" {
+ -re $re {
+ pass $gdb_test_name
+ }
+}
+
+set re \
+ [multi_line \
+ ^[string_to_regexp "print 1$bs"] \
+ "2" \
+ "$re_dollar$decimal = 12" \
+ "$gdb_prompt $"]
+gdb_test_multiple "print 1$bs\n2" "print 1$bs${bs}n2" {
+ -re $re {
+ pass $gdb_test_name
}
}
-set test "print 1\\\\n2"
-gdb_test_multiple "print 1\\\n2" $test {
- -re "^print 1\\\\\r\n2\r\n\\\$$decimal = 12\r\n$gdb_prompt $" {
- pass $test
+with_test_prefix "cancel multiline" {
+ send_gdb "print$bs\n 1"
+ gdb_test_multiple "" "setup" {
+ -re "print$re_bs\r\n 1" {
+ pass $gdb_test_name
+ }
+ }
+
+ send_gdb "\003"
+ gdb_test_multiple "" "cancel" {
+ -re -wrap "" {
+ pass $gdb_test_name
+ }
+ }
+
+ # Regression test for PR cli/33063.
+ gdb_test_multiple "print 2" "command after cancel" {
+ -re -wrap " = 2" {
+ pass $gdb_test_name
+ }
+ -re -wrap "" {
+ # Avoid undefined command error.
+ fail $gdb_test_name
+ }
}
}
diff --git a/gdb/testsuite/gdb.base/cond-expr.exp b/gdb/testsuite/gdb.base/cond-expr.exp
index e60fd16..2080937 100644
--- a/gdb/testsuite/gdb.base/cond-expr.exp
+++ b/gdb/testsuite/gdb.base/cond-expr.exp
@@ -39,7 +39,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.base/condbreak-bad.exp b/gdb/testsuite/gdb.base/condbreak-bad.exp
index 7aff409..19c16dc 100644
--- a/gdb/testsuite/gdb.base/condbreak-bad.exp
+++ b/gdb/testsuite/gdb.base/condbreak-bad.exp
@@ -17,7 +17,7 @@
standard_testfile
-if {[prepare_for_testing "failed to prepare" ${binfile} ${srcfile}]} {
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
return
}
diff --git a/gdb/testsuite/gdb.base/condbreak-multi-context.exp b/gdb/testsuite/gdb.base/condbreak-multi-context.exp
index dce162b..b4ea0f1 100644
--- a/gdb/testsuite/gdb.base/condbreak-multi-context.exp
+++ b/gdb/testsuite/gdb.base/condbreak-multi-context.exp
@@ -53,7 +53,8 @@ proc find_location_contexts { } {
global loc_name loc_index fill
global decimal hex gdb_prompt binfile
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
if {![runto_main]} {
return
@@ -130,7 +131,8 @@ proc check_bp_locations {bpnum states cond {msg ""}} {
proc_with_prefix scenario_1 { start_before } {
global warning decimal fill bkptno_num_re binfile
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
if { $start_before } {
if {![runto_main temporary]} {
@@ -242,7 +244,8 @@ proc setup_bps { bpnum1_name bpnum2_name } {
proc_with_prefix scenario_2 { start_before } {
global binfile bkptno_num_re
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
if { $start_before } {
if {![runto_main temporary]} {
@@ -290,7 +293,8 @@ proc_with_prefix scenario_2 { start_before } {
proc_with_prefix scenario_3 { start_before } {
global binfile bkptno_num_re loc_index warning
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
if { $start_before } {
if {![runto_main temporary]} {
@@ -367,7 +371,8 @@ proc_with_prefix scenario_3 { start_before } {
proc_with_prefix scenario_4 { start_before } {
global binfile bkptno_num_re loc_index warning
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
if { $start_before } {
if {![runto_main temporary]} {
diff --git a/gdb/testsuite/gdb.base/constvars.exp b/gdb/testsuite/gdb.base/constvars.exp
index 8f55945..dcc8d1b 100644
--- a/gdb/testsuite/gdb.base/constvars.exp
+++ b/gdb/testsuite/gdb.base/constvars.exp
@@ -34,7 +34,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable debug
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
#
diff --git a/gdb/testsuite/gdb.base/continue-after-aborted-step-over.exp b/gdb/testsuite/gdb.base/continue-after-aborted-step-over.exp
index 4764d72..8ba1f61 100644
--- a/gdb/testsuite/gdb.base/continue-after-aborted-step-over.exp
+++ b/gdb/testsuite/gdb.base/continue-after-aborted-step-over.exp
@@ -45,7 +45,8 @@ proc do_test {displaced breakpoint_always_inserted} {
global gdb_prompt decimal
global srcfile binfile
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_test_no_output "set displaced-stepping $displaced"
gdb_test_no_output "set breakpoint always-inserted $breakpoint_always_inserted"
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-exec-context.exp b/gdb/testsuite/gdb.base/corefile-exec-context.exp
index 7c9647c..23fd964 100644
--- a/gdb/testsuite/gdb.base/corefile-exec-context.exp
+++ b/gdb/testsuite/gdb.base/corefile-exec-context.exp
@@ -51,7 +51,8 @@ remote_exec build "mv $corefile $corefile_1"
# Load the core file and confirm that the full executable name is
# seen.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
set saw_generated_line false
gdb_test_multiple "core-file $corefile_1" "load core file no args" {
-re "^Core was generated by `[string_to_regexp $binfile]'\\.\r\n" {
@@ -80,7 +81,8 @@ remote_exec build "mv $corefile $corefile_2"
# Load the core file and confirm that the full executable name and
# argument list are seen.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
set saw_generated_line false
gdb_test_multiple "core-file $corefile_2" "load core file with args" {
-re "^Core was generated by `[string_to_regexp $binfile] $args'\\.\r\n" {
@@ -155,7 +157,8 @@ remote_exec build "mv $corefile $corefile_3"
# Restart, load the core file, and check the environment variable
# shows up.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Check for environment variable VAR_NAME in the environment, its
# value should be VAR_VALUE.
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..94ab454
--- /dev/null
+++ b/gdb/testsuite/gdb.base/corefile-shmem-zero-id.exp
@@ -0,0 +1,230 @@
+# 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
+ gdb_load $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
+gdb_load $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/corefile.exp b/gdb/testsuite/gdb.base/corefile.exp
index da1fdf3..c34dfb5 100644
--- a/gdb/testsuite/gdb.base/corefile.exp
+++ b/gdb/testsuite/gdb.base/corefile.exp
@@ -31,6 +31,7 @@ if {[build_executable $testfile.exp $testfile $srcfile debug] == -1} {
# mmapped data in core file" test.
set corefile [core_find $binfile {}]
if {$corefile == ""} {
+ untested "unable to create or find corefile"
return 0
}
@@ -96,7 +97,8 @@ foreach_with_prefix coreopt {--core= -core= "-c "} {
# Now restart normally.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Test basic corefile recognition via core-file command.
@@ -200,7 +202,8 @@ set coremmap_data_backup_filename \
remote_exec host "mv ${coremmap_data_filename} \
${coremmap_data_backup_filename}"
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Load the core file and check we get a warning about the
# coremmap.data file being missing.
@@ -229,7 +232,8 @@ remote_exec host "mv ${coremmap_data_backup_filename} \
# Test that we can unload the core with the "detach" command.
proc_with_prefix corefile_detach {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
gdb_test "core-file $::corefile" "Core was generated by .*" "load core"
gdb_test "detach" "No core file now\\." "detach core"
@@ -251,7 +255,8 @@ proc corefile_test_run {} {
return
}
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
gdb_test "core-file $corefile" "Core was generated by .*" "run: load core again"
set re "Local core dump file:"
diff --git a/gdb/testsuite/gdb.base/corefile2.exp b/gdb/testsuite/gdb.base/corefile2.exp
index 392705b..3975460 100644
--- a/gdb/testsuite/gdb.base/corefile2.exp
+++ b/gdb/testsuite/gdb.base/corefile2.exp
@@ -40,6 +40,7 @@ if {[build_executable $testfile.exp $testfile $srcfile debug] == -1} {
set corefile [core_find $binfile {}]
if {$corefile == ""} {
+ untested "unable to create or find corefile"
return 0
}
@@ -170,7 +171,8 @@ with_test_prefix "renamed binfile" {
# Restart and run to the abort call.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return
@@ -194,7 +196,8 @@ if {!$core_supported} {
gdb_test_no_output "maint print core-file-backed-mappings" \
"maint print core-file-backed-mapping with no core file"
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
set core_loaded [gdb_core_cmd "$corefile" "re-load generated corefile"]
if { $core_loaded == -1 } {
diff --git a/gdb/testsuite/gdb.base/corefile3.exp b/gdb/testsuite/gdb.base/corefile3.exp
index 57b2300..4528509 100644
--- a/gdb/testsuite/gdb.base/corefile3.exp
+++ b/gdb/testsuite/gdb.base/corefile3.exp
@@ -34,6 +34,7 @@ if {[build_executable $testfile.exp $testfile $srcfile] == -1} {
set corefile [core_find $binfile {}]
if {$corefile == ""} {
+ untested "unable to create or find corefile"
return
}
@@ -46,7 +47,8 @@ set backup_filename \
[standard_output_file coredir.[getpid]/coremmap.data.backup]
remote_exec host "mv ${data_filename} ${backup_filename}"
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Load the core file. The 'coremap.data' file cannot be found by GDB,
# but all the mappings for that file are r/w and should be present in
diff --git a/gdb/testsuite/gdb.base/cvexpr.exp b/gdb/testsuite/gdb.base/cvexpr.exp
index 3e527db..e2f8c35 100644
--- a/gdb/testsuite/gdb.base/cvexpr.exp
+++ b/gdb/testsuite/gdb.base/cvexpr.exp
@@ -517,7 +517,7 @@ foreach testspec $specs {
# These tests don't rely on the debug format.
with_test_prefix nodebug {
- if { [prepare_for_testing "failed to prepare" $binfile $srcfile {nodebug}] } {
+ if { [prepare_for_testing "failed to prepare" $testfile $srcfile {nodebug}] } {
return 0
}
diff --git a/gdb/testsuite/gdb.base/default-args.exp b/gdb/testsuite/gdb.base/default-args.exp
index efc4205..ae417ed 100644
--- a/gdb/testsuite/gdb.base/default-args.exp
+++ b/gdb/testsuite/gdb.base/default-args.exp
@@ -25,7 +25,8 @@ if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Basic/core tests using user-visible commands.
with_test_prefix "basics" {
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index 3abd049..b5e64c2 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
@@ -687,7 +759,6 @@ set show_conv_list \
{$_probe_arg10 = <error: No frame selected>} \
{$_probe_arg11 = <error: No frame selected>} \
{$_cimag = <internal function _cimag>} \
- {$_colorsupport = "monochrome"} \
{$_creal = <internal function _creal>} \
{$_isvoid = <internal function _isvoid>} \
{$_shell = <internal function _shell>} \
@@ -695,12 +766,10 @@ set show_conv_list \
{$_gdb_maint_setting = <internal function _gdb_maint_setting>} \
{$_gdb_setting_str = <internal function _gdb_setting_str>} \
{$_gdb_setting = <internal function _gdb_setting>} \
- {$_gdb_major = 17} \
- {$_gdb_minor = 1} \
{$_shell_exitsignal = void} \
{$_shell_exitcode = 0} \
- {$_active_linker_namespaces = 1} \
- {$_current_linker_namespace = <error: No registers.>}\
+ {$_linker_namespace_count = 0} \
+ {$_linker_namespace = <error: No registers.>}\
}
if [allow_python_tests] {
append show_conv_list \
@@ -716,10 +785,52 @@ if [allow_python_tests] {
{$_any_caller_matches = <internal function _any_caller_matches>} \
}
}
-gdb_test_list_exact "show convenience" "show convenience" \
- "\[^\r\n\]+\[\r\n\]+" \
- "\[^\r\n\]+" \
- $show_conv_list
+
+set lines [gdb_get_lines_no_pass "show convenience"]
+set matches 0
+set all_found 1
+foreach s $show_conv_list {
+ if { ![regexp (^|\r\n)[string_to_regexp $s](\r\n|$) $lines] } {
+ verbose -log "didn't match: '$s'"
+ set all_found 0
+ break
+ }
+ incr matches
+}
+
+set re_var [string_to_regexp {$_colorsupport}]
+if { [is_remote host] } {
+ set re_val {[^\r\n]+}
+} else {
+ set re_val [string_to_regexp {"monochrome"}]
+}
+if { [regexp "$re_var = $re_val" $lines] } {
+ incr matches
+} else {
+ set all_found 0
+}
+
+set re_vars \
+ [list \
+ [string_to_regexp {$_gdb_major}] \
+ [string_to_regexp {$_gdb_minor}]]
+foreach re_var $re_vars {
+ if { [regexp "$re_var = $decimal" $lines] } {
+ incr matches
+ } else {
+ set all_found 0
+ }
+}
+
+if { [regexp [string_to_regexp {$_tlb = void}] $lines] } {
+ incr matches
+} else {
+ # Convenience variable _tlb is added only if support for windows targets
+ # is enabled. Don't complain if it's missing.
+}
+
+gdb_assert { $all_found && $matches == [count_newlines $lines] } \
+ "show convenience"
#test show directories
gdb_test "show directories" "Source directories searched: .cdir\[:;\].cwd"
@@ -741,12 +852,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
@@ -792,30 +938,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/detach-sysroot-target.exp b/gdb/testsuite/gdb.base/detach-sysroot-target.exp
index 4248c86..c7466c0 100644
--- a/gdb/testsuite/gdb.base/detach-sysroot-target.exp
+++ b/gdb/testsuite/gdb.base/detach-sysroot-target.exp
@@ -22,7 +22,7 @@
standard_testfile
-if {[prepare_for_testing "failed to prepare" ${binfile} ${srcfile}]} {
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
return
}
diff --git a/gdb/testsuite/gdb.base/detach-while-running.exp b/gdb/testsuite/gdb.base/detach-while-running.exp
index 60943f3..34c2adc 100644
--- a/gdb/testsuite/gdb.base/detach-while-running.exp
+++ b/gdb/testsuite/gdb.base/detach-while-running.exp
@@ -45,7 +45,8 @@ proc test {} {
if {$is_remote} {
append ::GDBFLAGS " -ex \"maint set target-non-stop on\""
}
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
}
set test_spawn_id [spawn_wait_for_attach $binfile]
diff --git a/gdb/testsuite/gdb.base/detach.exp b/gdb/testsuite/gdb.base/detach.exp
index f9f67a8..c8d4350 100644
--- a/gdb/testsuite/gdb.base/detach.exp
+++ b/gdb/testsuite/gdb.base/detach.exp
@@ -42,7 +42,8 @@ proc do_detach_tests {} {
gdb_test "detach" "Detaching from program: .*$escapedbinfile, .*" "detach, $pass"
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
global pass
set pass "one"
diff --git a/gdb/testsuite/gdb.base/dfp-test.exp b/gdb/testsuite/gdb.base/dfp-test.exp
index 2a6c377..11f75da 100644
--- a/gdb/testsuite/gdb.base/dfp-test.exp
+++ b/gdb/testsuite/gdb.base/dfp-test.exp
@@ -28,7 +28,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {quie
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/display.exp b/gdb/testsuite/gdb.base/display.exp
index 7aed6d5..2fb6e07 100644
--- a/gdb/testsuite/gdb.base/display.exp
+++ b/gdb/testsuite/gdb.base/display.exp
@@ -52,7 +52,8 @@ if !$use_gdb_stub {
gdb_test "kill" ".*" "kill again"
gdb_test "detach" ".*" "detach again"
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
}
# Ok, on to real life
diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
index 8f52199..f3bdfb0 100644
--- a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
+++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
@@ -38,16 +38,80 @@ if { [build_executable "failed to build" $testfile $srcfile \
return
}
+# Return a list of shared libraries extract from the "info sharedlibrary"
+# command. Each item in the list is itself a list with the following items:
+#
+# - "from" address
+# - "to" address
+# - namespace ID
+# - name (file path)
+
+proc get_info_shared {} {
+ set from_re "($::hex)\\s+"
+ set to_re "($::hex)\\s+"
+ set ns_re "(?:($::decimal)\\s+)?"
+ set syms_read_re "(Yes( \\(\\*\\))?|No)\\s+"
+ set name_re "(\[^\r\n\]+)"
+ set libs {}
+
+ gdb_test_multiple "info sharedlibrary" "" {
+ -re {From\s+To\s+(Linker NS\s+)?Syms Read\s+Shared Object Library\r\n} {
+ exp_continue
+ }
+
+ -re "^${from_re}${to_re}${ns_re}${syms_read_re}${name_re}\r\n" {
+ set from $expect_out(1,string)
+ set to $expect_out(2,string)
+ set ns $expect_out(3,string)
+ set name $expect_out(4,string)
+
+ lappend libs [list $from $to $ns $name]
+ exp_continue
+ }
+
+ -re {^\(\*\): Shared library is missing debugging information\.\r\n} {
+ exp_continue
+ }
+
+ -re "^$::gdb_prompt " {
+ pass $gdb_test_name
+ }
+ }
+
+ return $libs
+}
+
+# Verify that "info sharedlibrary" does not contain duplicate entries.
+
+proc check_no_duplicates {} {
+ with_test_prefix "check no duplicates" {
+ set libs [get_info_shared]
+ array set seen {}
+ set seen_duplicate 0
+
+ foreach lib $libs {
+ if {[info exists seen($lib)]} {
+ verbose -log "already seen: $lib"
+ set seen_duplicate 1
+ }
+
+ set seen($lib) 1
+ }
+
+ gdb_assert {!$seen_duplicate} "no duplicates"
+ }
+}
+
# Run the command "info sharedlibrary" and get the first namespace
# for the so
proc get_first_so_ns {} {
set ns -1
set lib_regexp [string_to_regexp ${::binfile_lib}]
gdb_test_multiple "info sharedlibrary $::so_name" "get SO namespace" -lbl {
- -re "\r\nFrom\\s+To\\s+\(NS\\s+\)?Syms\\s+Read\\s+Shared Object Library(?=\r\n)" {
+ -re "\r\nFrom\\s+To\\s+\(Linker NS\\s+\)?Syms\\s+Read\\s+Shared Object Library(?=\r\n)" {
exp_continue
}
- -re "\r\n$::hex\\s+$::hex\\s+\\\[\\\[($::decimal)\\\]\\\]\\s+\[^\r\n]+${lib_regexp}(?=\r\n)" {
+ -re "\r\n$::hex\\s+$::hex\\s+($::decimal)\\s+\[^\r\n]+${lib_regexp}(?=\r\n)" {
if {$ns == -1} {
set ns $expect_out(1,string)
}
@@ -62,7 +126,8 @@ proc get_first_so_ns {} {
# Run the tests relating to the command "info sharedlibrary", to
# verify that the namespace ID is consistent.
proc test_info_shared {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if { ![runto_main] } {
return
@@ -78,9 +143,11 @@ proc test_info_shared {} {
# Next, test that we *do* print a namespace column after loading SOs.
gdb_test "info sharedlibrary" \
- "From\\s+To\\s+NS\\s+Syms\\s+Read\\s+Shared Object Library.*" \
+ "From\\s+To\\s+Linker NS\\s+Syms\\s+Read\\s+Shared Object Library.*" \
"after loading everything"
+ check_no_duplicates
+
gdb_assert {[get_first_so_ns] == 1} "before closing any library"
gdb_test "next" ".*second dlclose.*" "close first library"
@@ -107,21 +174,24 @@ proc test_info_shared {} {
# Run all tests related to the linkage namespaces convenience
# variables, _active_namespaces and _current_namespaces.
+# Also tests that the namespace ID is only printed at the correct
+# times.
proc_with_prefix test_conv_vars {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
- gdb_test "print \$_active_linker_namespaces" "1" \
- "1 namespace before starting inferior"
- gdb_test "print \$_current_linker_namespace" "No registers." \
+ gdb_test "print \$_linker_namespace_count" "0" \
+ "0 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" \
+ gdb_test "print \$_linker_namespace_count" "1" \
"Before activating namespaces"
- gdb_test "print \$_current_linker_namespace" ".*\"\\\[\\\[0\\\]\\\]\"" \
+ gdb_test "print \$_linker_namespace" ".* = 0" \
"Still in the default namespace"
gdb_breakpoint "inc" allow-pending
@@ -130,22 +200,29 @@ proc_with_prefix test_conv_vars {} {
foreach_with_prefix dl {3 2 1} {
gdb_continue_to_breakpoint "inc"
- gdb_test "print \$_current_linker_namespace" ".*\"\\\[\\\[$dl\\\]\\\]\"" \
+ 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 "print \$_linker_namespace_count" "4" "all SOs loaded"
gdb_test "next" ".*second dlclose.*" "close one SO"
- gdb_test "print \$_active_linker_namespaces" "3" "one SOs unloaded"
+ gdb_test "print \$_linker_namespace_count" "3" "one SOs unloaded"
gdb_test "next" ".*third dlclose.*" "close another SO"
- gdb_test "print \$_active_linker_namespaces" "2" "two SOs unloaded"
+ gdb_test "print \$_linker_namespace_count" "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
+ clean_restart
+ gdb_load $::binfile
if {![runto_main]} {
return
}
@@ -154,14 +231,21 @@ proc_with_prefix test_conv_vars {} {
# breakpoints and pending breakpoints at the same time with
# gdb_breakpoint.
gdb_test "next" ".*assert.*" "load the first SO"
- gdb_breakpoint "inc if \$_streq(\$_current_linker_namespace, \"\[\[2\]\]\")"
+ 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
+ clean_restart
+ gdb_load $::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
@@ -174,50 +258,44 @@ proc test_info_linker_namespaces {} {
# 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
+ set n_libraries 999
+
+ gdb_test_multiple "info linker-namespaces \[\[0\]\]" "print namespace 0" {
+ -re -wrap "($::decimal) librar(?:y|ies) loaded in linker namespace 0:.*" {
+ set n_libraries $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, and up to 2 more libraries.
+ gdb_assert {$n_libraries <= 3} "the correct number of libraries was reported"
+
+ set binfile_lib_re [string_to_regexp $::binfile_lib]
+
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]
+ set n_libraries 999
+
+ gdb_test_multiple "info linker-namespaces $ns" "print namespace $ns" {
+ -re ".*($::decimal) librar(?:y|ies) loaded in linker namespace $ns:\r\n" {
+ set n_libraries $expect_out(1,string)
exp_continue
}
- -re "^\r\n\[^\r\n\]+${::binfile_lib}\[^\r\n\]*(?=\r\n)" {
+
+ -re -wrap "${binfile_lib_re}.*" {
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
}
}
+
+ # 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.
+ gdb_assert {$n_libraries <= 4} "the correct number of libraries was reported"
+ gdb_assert {$found_test_so} "this testfile's SO was reported"
}
# These patterns are simpler, and purposefully glob multiple lines.
@@ -225,14 +303,15 @@ proc test_info_linker_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.." \
+ [multi_line "There are 4 linker namespaces loaded\\." \
+ "" \
+ "$::decimal librar(y|ies) loaded in linker namespace 0:" \
".*" \
- "There are $::decimal libraries loaded in linker namespace ..1.." \
+ "$::decimal librar(y|ies) loaded in linker namespace 1:" \
".*" \
- "There are $::decimal libraries loaded in linker namespace ..2.." \
+ "$::decimal librar(y|ies) loaded in linker namespace 2:" \
".*" \
- "There are $::decimal libraries loaded in linker namespace ..3.." \
+ "$::decimal librar(y|ies) loaded in linker namespace 3:" \
".*" ] "print namespaces with no argument"
}
diff --git a/gdb/testsuite/gdb.base/dlmopen.exp b/gdb/testsuite/gdb.base/dlmopen.exp
index da17002..c4eb7cd 100644
--- a/gdb/testsuite/gdb.base/dlmopen.exp
+++ b/gdb/testsuite/gdb.base/dlmopen.exp
@@ -95,9 +95,19 @@ if { $dyln_name eq "" } {
return
}
+# If the dynamic linker path contains a symlink, some instances show the real
+# path instead of the original path. Accept both.
+lassign [remote_exec target realpath "$dyln_name"] realpath_ret dyln_realpath_name
+
+if { $realpath_ret == 0 } {
+ set dyln_realpath_name [string trim $dyln_realpath_name]
+} else {
+ set dyln_realpath_name "not-a-valid-path"
+}
+
# Return true if FILENAME is the dynamic linker. Otherwise return false.
proc is_dyln { filename } {
- return [expr {$filename eq $::dyln_name}]
+ return [expr {$filename eq $::dyln_name || $filename eq $::dyln_realpath_name}]
}
# Check that 'info shared' show NUM occurrences of DSO.
@@ -106,7 +116,7 @@ proc check_dso_count { dso num } {
set count 0
gdb_test_multiple "info shared" "info shared" {
- -re "$hex $hex \(\[\[$::decimal\]\]\\s+\)\?Yes \[^\r\n\]*$dso\r\n" {
+ -re "$hex $hex \($::decimal\\s+\)\?Yes \[^\r\n\]*$dso\r\n" {
# use longer form so debug remote does not interfere
set count [expr $count + 1]
exp_continue
@@ -173,7 +183,8 @@ proc test_dlmopen {} {
# Setup for calling 'test_dlmopen', this is the version of the test
# that doesn't use 'attach'.
proc test_dlmopen_no_attach {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if { ![runto_main] } {
return
@@ -198,7 +209,8 @@ proc test_dlmopen_with_attach {} {
return
}
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
# Start the test program.
set test_spawn_id [spawn_wait_for_attach $::binfile]
@@ -233,7 +245,7 @@ proc get_dyld_info {} {
set dyld_count 0
set dyld_start_addr ""
gdb_test_multiple "info sharedlibrary" "" {
- -re "From\\s+To\\s+\(NS\\s+\)?Syms\\s+Read\\s+Shared Object Library\r\n" {
+ -re "From\\s+To\\s+\(Linker NS\\s+\)?Syms\\s+Read\\s+Shared Object Library\r\n" {
exp_continue
}
-re "^($::hex)\\s+$::hex\\s+\(\#$::decimal\\s+\)?\[^/\]+(/\[^\r\n\]+)\r\n" {
@@ -288,7 +300,8 @@ proc_with_prefix test_solib_unmap_events { } {
return
}
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if { ![runto_main] } {
return
@@ -358,15 +371,19 @@ proc_with_prefix test_solib_unmap_events { } {
# dynamic linker as pending when some instances of the library were
# unloaded, despite there really only being one copy of the dynamic
# linker actually loaded into the inferior's address space.
- gdb_test_multiple "info breakpoints $bpnum" "check b/p status" {
- -re -wrap "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+\\*$::hex\\s*\r\n\\s+stop only if \\(0\\)" {
- fail $gdb_test_name
- }
-
- -re -wrap "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$::hex\\s*\[^\r\n\]+\r\n\\s+stop only if \\(0\\)" {
- pass $gdb_test_name
- }
- }
+ set hs {[^\r\n]}
+ set re_pass \
+ [multi_line \
+ "" \
+ [join \
+ [list \
+ "$bpnum" "breakpoint" "keep" "y" "$::hex$hs+"] \
+ {\s+}] \
+ [string cat \
+ {\s+} \
+ [string_to_regexp "stop only if (0)"] \
+ ([string_to_regexp " (target evals)"])?]]
+ gdb_test "info breakpoints $bpnum" $re_pass "check b/p status"
# With all the dlclose calls now complete, we should be back to a
# single copy of the dynamic linker.
@@ -379,7 +396,8 @@ proc_with_prefix test_solib_unmap_events { } {
# Check that we can 'next' over the dlclose calls without GDB giving any
# warnings or errors.
proc_with_prefix test_next_over_dlclose {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if { ![runto_main] } {
return
diff --git a/gdb/testsuite/gdb.base/dprintf-bp-same-addr.exp b/gdb/testsuite/gdb.base/dprintf-bp-same-addr.exp
index 649784b..11a8310 100644
--- a/gdb/testsuite/gdb.base/dprintf-bp-same-addr.exp
+++ b/gdb/testsuite/gdb.base/dprintf-bp-same-addr.exp
@@ -28,7 +28,8 @@ proc test { style } {
global gdb_prompt binfile dp_location
with_test_prefix "$style" {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if ![runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.base/dprintf-detach.exp b/gdb/testsuite/gdb.base/dprintf-detach.exp
index dc3384b..431037c 100644
--- a/gdb/testsuite/gdb.base/dprintf-detach.exp
+++ b/gdb/testsuite/gdb.base/dprintf-detach.exp
@@ -37,7 +37,8 @@ proc dprintf_detach_test { breakpoint_always_inserted dprintf_style disconnected
with_test_prefix "$test_prefix" {
# Start with a clean gdb
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
gdb_test_no_output "set breakpoint always-inserted ${breakpoint_always_inserted}"
gdb_test_no_output "set dprintf-style ${dprintf_style}"
@@ -68,7 +69,8 @@ proc dprintf_detach_test { breakpoint_always_inserted dprintf_style disconnected
gdb_exit
# Check that the process still exists by attaching a new gdb to it.
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
set test "re-attach to inferior"
set is_gdbserver [target_is_gdbserver]
diff --git a/gdb/testsuite/gdb.base/dprintf-execution-x-script.exp b/gdb/testsuite/gdb.base/dprintf-execution-x-script.exp
index 06be468..65de2d5 100644
--- a/gdb/testsuite/gdb.base/dprintf-execution-x-script.exp
+++ b/gdb/testsuite/gdb.base/dprintf-execution-x-script.exp
@@ -93,7 +93,8 @@ do_test "" $test
# Restart GDB and 'source' the script; this will (still) run the program
# due to the 'run' command in the script.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
do_test "source $x_file" "load and run script using source command"
# This should leave us at the gdb prompt; Run program again using
diff --git a/gdb/testsuite/gdb.base/dprintf-pending.exp b/gdb/testsuite/gdb.base/dprintf-pending.exp
index 9242a84..f28e969 100644
--- a/gdb/testsuite/gdb.base/dprintf-pending.exp
+++ b/gdb/testsuite/gdb.base/dprintf-pending.exp
@@ -60,7 +60,8 @@ with_test_prefix "without symbols" {
gdb_test "" ".*x=3.*x=4.*x=3.*" "run to resolved dprintf"
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_load_shlib $lib_sl
#
diff --git a/gdb/testsuite/gdb.base/dprintf.exp b/gdb/testsuite/gdb.base/dprintf.exp
index 0135b86..262ccc1 100644
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -74,7 +74,8 @@ proc restart {} {
global binfile
global bp_location1 dp_location1
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if ![runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.base/dso2dso.exp b/gdb/testsuite/gdb.base/dso2dso.exp
index 24d4203..3b00f6d 100644
--- a/gdb/testsuite/gdb.base/dso2dso.exp
+++ b/gdb/testsuite/gdb.base/dso2dso.exp
@@ -54,7 +54,8 @@ if { [gdb_compile $srcdir/$subdir/$srcfile $binfile executable \
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_load_shlib $binfile_libdso2
gdb_load_shlib $binfile_libdso1
diff --git a/gdb/testsuite/gdb.base/dtrace-probe.exp b/gdb/testsuite/gdb.base/dtrace-probe.exp
index 32a72cc..5d4b9df 100644
--- a/gdb/testsuite/gdb.base/dtrace-probe.exp
+++ b/gdb/testsuite/gdb.base/dtrace-probe.exp
@@ -27,7 +27,8 @@ proc dtrace_test {} {
return -1
}
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
if ![runto_main] {
return -1
@@ -63,8 +64,8 @@ proc dtrace_test {} {
# Since test:progress-counter is disabled we can run to the second
# instance of the test:two-locations probe.
- runto "-probe-dtrace test:two-locations"]
- runto "-probe-dtrace test:two-locations"]
+ runto "-probe-dtrace test:two-locations"
+ runto "-probe-dtrace test:two-locations"
# Go back to the breakpoint on main() and enable the
# test:progress-counter probe. Set a breakpoint on it and see
diff --git a/gdb/testsuite/gdb.base/dump.c b/gdb/testsuite/gdb.base/dump.c
index bdcafbf..14b66b1 100644
--- a/gdb/testsuite/gdb.base/dump.c
+++ b/gdb/testsuite/gdb.base/dump.c
@@ -35,7 +35,7 @@ main()
for (i = 0; i < ARRSIZE; i++)
intarray[i] = i+1;
- intstruct.a = 12 * 1;
+ intstruct.a = (12 * 1) << 16;
intstruct.b = 12 * 2;
intstruct.c = 12 * 3;
intstruct.d = 12 * 4;
diff --git a/gdb/testsuite/gdb.base/dump.exp b/gdb/testsuite/gdb.base/dump.exp
index a55e5b0..64d897b 100644
--- a/gdb/testsuite/gdb.base/dump.exp
+++ b/gdb/testsuite/gdb.base/dump.exp
@@ -46,7 +46,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable ${op
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_test "dump mem /dev/null 0x10 0x20" "Cannot access memory at address 0x10" \
"inaccessible memory is reported"
@@ -107,14 +108,7 @@ set endian [get_endianness]
# Now generate some dump files.
proc make_dump_file { command msg } {
- global gdb_prompt
-
- gdb_test_multiple "${command}" "$msg" {
- -re ".*\[Ee\]rror.*$gdb_prompt $" { fail $msg }
- -re ".*\[Ww\]arning.*$gdb_prompt $" { fail $msg }
- -re ".*\[Uu\]ndefined .*$gdb_prompt $" { fail $msg }
- -re ".*$gdb_prompt $" { pass $msg }
- }
+ gdb_test_no_output "${command}" "$msg"
}
make_dump_file "dump val [set intarr1.bin] intarray" \
diff --git a/gdb/testsuite/gdb.base/duplicate-bp.exp b/gdb/testsuite/gdb.base/duplicate-bp.exp
index b1003f2..da5834b 100644
--- a/gdb/testsuite/gdb.base/duplicate-bp.exp
+++ b/gdb/testsuite/gdb.base/duplicate-bp.exp
@@ -24,7 +24,8 @@ proc test_setup { count } {
global srcfile
global binfile
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.base/eh_return.exp b/gdb/testsuite/gdb.base/eh_return.exp
index 5a4f524..703f9e9 100644
--- a/gdb/testsuite/gdb.base/eh_return.exp
+++ b/gdb/testsuite/gdb.base/eh_return.exp
@@ -71,7 +71,8 @@ if { $address == -1 } {
return 0
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_assert [gdb_breakpoint "*$address" no-message] "set breakpoint on address"
diff --git a/gdb/testsuite/gdb.base/errno.exp b/gdb/testsuite/gdb.base/errno.exp
index ff18214..ea1ff70 100644
--- a/gdb/testsuite/gdb.base/errno.exp
+++ b/gdb/testsuite/gdb.base/errno.exp
@@ -45,7 +45,8 @@
standard_testfile
proc do_tests {{do_xfail_cast 0} {do_xfail 0} {do_xfail_core_test 0}} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if ![runto_main] {
return
}
@@ -176,7 +177,8 @@ proc do_tests {{do_xfail_cast 0} {do_xfail 0} {do_xfail_core_test 0}} {
return
}
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
set core_loaded [gdb_core_cmd $corefile "load corefile"]
if { $core_loaded == -1 } {
diff --git a/gdb/testsuite/gdb.base/eval-skip.exp b/gdb/testsuite/gdb.base/eval-skip.exp
index 82c5fe0..b4c856e 100644
--- a/gdb/testsuite/gdb.base/eval-skip.exp
+++ b/gdb/testsuite/gdb.base/eval-skip.exp
@@ -39,7 +39,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.base/exe-lock.exp b/gdb/testsuite/gdb.base/exe-lock.exp
index 40a470f..2e375b4 100644
--- a/gdb/testsuite/gdb.base/exe-lock.exp
+++ b/gdb/testsuite/gdb.base/exe-lock.exp
@@ -27,7 +27,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debu
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
# Sanity-check: Verify that the executable exists. This is just to
# make sure that, when we verify later that the file does not exist,
diff --git a/gdb/testsuite/gdb.base/exec-invalid-sysroot.exp b/gdb/testsuite/gdb.base/exec-invalid-sysroot.exp
index 7ab446e..99f5e7d 100644
--- a/gdb/testsuite/gdb.base/exec-invalid-sysroot.exp
+++ b/gdb/testsuite/gdb.base/exec-invalid-sysroot.exp
@@ -69,5 +69,6 @@ proc do_exec_sysroot_test {} {
}
# Start with a fresh gdb
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
do_exec_sysroot_test
diff --git a/gdb/testsuite/gdb.base/execl-update-breakpoints.exp b/gdb/testsuite/gdb.base/execl-update-breakpoints.exp
index 27bd042..cd49df1 100644
--- a/gdb/testsuite/gdb.base/execl-update-breakpoints.exp
+++ b/gdb/testsuite/gdb.base/execl-update-breakpoints.exp
@@ -41,7 +41,8 @@ if { [gdb_compile $objfile $exec1 executable {debug text_segment=0x1000000}] !=
# First check whether the address of "main" in exec1 is readable in
# exec2. If it is, then skip the test as unsupported.
-clean_restart ${exec1}
+clean_restart
+gdb_load $exec1
if {![runto_main]} {
return -1
}
@@ -55,7 +56,8 @@ gdb_test_multiple "p/x &main" $test {
}
}
-clean_restart ${exec2}
+clean_restart
+gdb_load $exec2
if {![runto_main]} {
return -1
}
@@ -84,7 +86,8 @@ proc test { always_inserted } {
global exec1
global gdb_prompt
- clean_restart ${exec1}
+ clean_restart
+ gdb_load $exec1
gdb_test_no_output "set breakpoint always-inserted $always_inserted"
diff --git a/gdb/testsuite/gdb.base/exprs.exp b/gdb/testsuite/gdb.base/exprs.exp
index f703c18..ee0c198 100644
--- a/gdb/testsuite/gdb.base/exprs.exp
+++ b/gdb/testsuite/gdb.base/exprs.exp
@@ -26,7 +26,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
#
# set it up at a breakpoint so we can play with the variable values
@@ -285,11 +286,14 @@ gdb_test "print v_short + " \
gdb_test "print v_short =}{= 3" \
"A syntax error in expression, near `\\}\\{= 3'\\."
+set hs {[^\r\n]}
+set re_debug [string cat $hs* {[Ss]hift} $hs*]
+
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)" {
+ -re "\r\n${re_debug}(?=\r\n)" {
set saw_start 1
exp_continue
}
diff --git a/gdb/testsuite/gdb.base/fileio.c b/gdb/testsuite/gdb.base/fileio.c
index 0f20151..4ba5ab0 100644
--- a/gdb/testsuite/gdb.base/fileio.c
+++ b/gdb/testsuite/gdb.base/fileio.c
@@ -73,6 +73,10 @@ static const char *strerrno (int err);
#define STRING "Hello World"
+#define STRINGIFY(s) STRINGIFY_(s)
+#define STRINGIFY_(s) #s
+#define OUTDIR STRINGIFY (OUTDIR_)
+
static void stop (void) {}
/* A NULL string. We pass this to stat below instead of a NULL
diff --git a/gdb/testsuite/gdb.base/fileio.exp b/gdb/testsuite/gdb.base/fileio.exp
index 6996d6d..a6b4c23 100644
--- a/gdb/testsuite/gdb.base/fileio.exp
+++ b/gdb/testsuite/gdb.base/fileio.exp
@@ -27,7 +27,7 @@ if {[is_remote host]} {
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
executable \
- [list debug "additional_flags=-DOUTDIR=\"$outdir/\""]] != "" } {
+ [list debug additional_flags=[quote_for_host -DOUTDIR_=$outdir/]]] != "" } {
untested "failed to compile"
return -1
}
@@ -41,7 +41,8 @@ system "rm -rf [standard_output_file *.fileio.test]"
set oldtimeout $timeout
set timeout [expr "$timeout + 60"]
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_test_no_output "set print sevenbit-strings"
gdb_test_no_output "set print address off"
gdb_test_no_output "set width 0"
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/find.exp b/gdb/testsuite/gdb.base/find.exp
index ae68686..3b2dfb0 100644
--- a/gdb/testsuite/gdb.base/find.exp
+++ b/gdb/testsuite/gdb.base/find.exp
@@ -22,7 +22,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_test "break $srcfile:stop_here" \
"Breakpoint.*at.* file .*$srcfile, line.*" \
diff --git a/gdb/testsuite/gdb.base/fixsection.exp b/gdb/testsuite/gdb.base/fixsection.exp
index 9a5c996..3056851 100644
--- a/gdb/testsuite/gdb.base/fixsection.exp
+++ b/gdb/testsuite/gdb.base/fixsection.exp
@@ -32,7 +32,8 @@ if { [gdb_compile_shlib $libsrc $lib_sl $lib_opts] != ""
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_load_shlib ${lib_sl}
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.base/float128.exp b/gdb/testsuite/gdb.base/float128.exp
index 95b83af..b8d3a6c 100644
--- a/gdb/testsuite/gdb.base/float128.exp
+++ b/gdb/testsuite/gdb.base/float128.exp
@@ -30,7 +30,8 @@ if { [do_compile] != "" && [do_compile {-mfloat128}] != "" } {
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/floatn.exp b/gdb/testsuite/gdb.base/floatn.exp
index 7138d04..1b39ed8 100644
--- a/gdb/testsuite/gdb.base/floatn.exp
+++ b/gdb/testsuite/gdb.base/floatn.exp
@@ -30,7 +30,8 @@ if { [do_compile] != "" && [do_compile {-mfloat128}] != "" } {
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return
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..64bcea8 100644
--- a/gdb/testsuite/gdb.base/foll-exec.exp
+++ b/gdb/testsuite/gdb.base/foll-exec.exp.tcl
@@ -22,33 +22,56 @@ 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
+ gdb_load $execer_binfile
# Start the program running, and stop at main.
- #
if {![runto_main]} {
return
}
@@ -71,7 +94,8 @@ proc do_exec_tests {} {
return
}
- clean_restart $binfile
+ clean_restart
+ gdb_load $execer_binfile
# Start the program running, and stop at main.
#
@@ -120,7 +144,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 +184,8 @@ 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
+ gdb_load $execer_binfile
# Start the program running, and stop at main.
#
@@ -193,7 +218,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 +235,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 +253,8 @@ 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
+ gdb_load $execer_binfile
# Start the program running, and stop at main.
#
@@ -269,7 +295,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 +321,8 @@ 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
+ gdb_load $execer_binfile
# Start the program running, and stop at main.
#
@@ -330,7 +357,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 +383,8 @@ 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
+ gdb_load $execer_binfile
# Start the program running, and stop at main.
#
@@ -370,13 +398,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..cb49ef6 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
@@ -40,7 +41,8 @@ if { [build_executable "failed to prepare" ${testfile} ${srcfile} $opts] } {
}
proc do_test {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
gdb_locate_shlib $::shlib_path
gdb_test_no_output "set follow-fork-mode child"
gdb_test_no_output "set detach-on-fork off"
diff --git a/gdb/testsuite/gdb.base/fork-print-inferior-events.exp b/gdb/testsuite/gdb.base/fork-print-inferior-events.exp
index 26ed2f9..c24a9bc 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
@@ -71,7 +73,8 @@ set i 0
foreach_with_prefix print_inferior_events { "on" "off" } {
foreach_with_prefix follow_fork_mode { "child" "parent" } {
foreach_with_prefix detach_on_fork { "on" "off" } {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_test_no_output "set print inferior-events $print_inferior_events"
gdb_test_no_output "set follow-fork-mode $follow_fork_mode"
gdb_test_no_output "set detach-on-fork $detach_on_fork"
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/frame-args.exp b/gdb/testsuite/gdb.base/frame-args.exp
index 31e4d15..0daa3aa 100644
--- a/gdb/testsuite/gdb.base/frame-args.exp
+++ b/gdb/testsuite/gdb.base/frame-args.exp
@@ -19,7 +19,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debu
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto break_me]} {
return
diff --git a/gdb/testsuite/gdb.base/frame-info-consistent.exp b/gdb/testsuite/gdb.base/frame-info-consistent.exp
index 67bcd18..b594047 100644
--- a/gdb/testsuite/gdb.base/frame-info-consistent.exp
+++ b/gdb/testsuite/gdb.base/frame-info-consistent.exp
@@ -97,7 +97,8 @@ proc compare_frames {frames} {
proc test {enable} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
gdb_test_no_output "maint frame-unwinder $enable DEBUGINFO"
diff --git a/gdb/testsuite/gdb.base/frame-view.exp b/gdb/testsuite/gdb.base/frame-view.exp
index fa00c35..34ac668 100644
--- a/gdb/testsuite/gdb.base/frame-view.exp
+++ b/gdb/testsuite/gdb.base/frame-view.exp
@@ -28,7 +28,8 @@ if { [build_executable "failed to prepare" \
# "select-frame view".
proc test_select_frame_view { with_pretty_printer } {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if { $with_pretty_printer } {
require allow_python_tests
diff --git a/gdb/testsuite/gdb.base/fullname.exp b/gdb/testsuite/gdb.base/fullname.exp
index 430d0c4..ec90179 100644
--- a/gdb/testsuite/gdb.base/fullname.exp
+++ b/gdb/testsuite/gdb.base/fullname.exp
@@ -45,7 +45,8 @@ set line [gdb_get_line_number "set breakpoint 1 here"]
# Initialize GDB after getting the line number, to make sure
# symbols aren't loaded.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
set msg "set breakpoint by full path before loading symbols - built absolute"
if { [gdb_breakpoint [standard_output_file tmp-${srcfile}]:${line} {no-message}] != 0 } {
@@ -65,12 +66,13 @@ if { [gdb_breakpoint [standard_output_file tmp-${srcfile}]:${line} {no-message}]
}
# Build the test executable using a relative path.
-if { [gdb_compile [relative_filename [pwd] [standard_output_file tmp-${srcfile}]] \
+if { [gdb_compile [relative_filename [pwd] [build_standard_output_file tmp-${srcfile}]] \
"${binfile}" executable {debug}] != "" } {
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
set msg "set breakpoint by full path before loading symbols - built relative"
if { [gdb_breakpoint [standard_output_file tmp-${srcfile}]:${line} {no-message}] != 0 } {
@@ -99,7 +101,8 @@ with_cwd [standard_output_file {}] {
}
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
set msg "set breakpoint by full path before loading symbols - built other"
if { [gdb_breakpoint [standard_output_file tmp-${srcfile}]:${line} {no-message}] != 0 } {
diff --git a/gdb/testsuite/gdb.base/gcore-buffer-overflow.exp b/gdb/testsuite/gdb.base/gcore-buffer-overflow.exp
index 0fb79c7..5a6bfe6 100644
--- a/gdb/testsuite/gdb.base/gcore-buffer-overflow.exp
+++ b/gdb/testsuite/gdb.base/gcore-buffer-overflow.exp
@@ -29,7 +29,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_test_no_output "set args ${pattern}" \
"set buffer exceeding arguments"
diff --git a/gdb/testsuite/gdb.base/gcore-memory-usage.exp b/gdb/testsuite/gdb.base/gcore-memory-usage.exp
index bd041f2..14b03a0 100644
--- a/gdb/testsuite/gdb.base/gcore-memory-usage.exp
+++ b/gdb/testsuite/gdb.base/gcore-memory-usage.exp
@@ -47,8 +47,10 @@ proc get_mem_usage {pid prefix} {
# This proc restarts GDB, runs the inferior with the desired
# amount of memory, then checks how much memory is necessary
# to run the gcore command. It will return -1 if the gcore
-# command fails, 0 otherwise.
-proc run_test {megs} {
+# command fails, otherwise the amount of memory used by GDB
+# to generate that gcore. MAX_MEM is the maximum amount of
+# memory GDB is allowed to use, in megabytes.
+proc run_test {megs max_mem} {
with_test_prefix "$megs Mb" {
clean_restart $::testfile
@@ -74,23 +76,24 @@ proc run_test {megs} {
set diff_k [expr $mem_after - $mem_before]
set diff [expr $diff_k/1024]
verbose -log "The gcore command used $diff Mb ($diff_k Kb)"
- # The original plan was to compare to a multiple of MEGS
- # but since the requirements don't seem to go up as the
- # inferior allocated more memory, we instead just hardcode
- # 2 megs, since sometimes 1 is used.
- gdb_assert {$diff < 2} "gdb did not use too much memory"
+ gdb_assert {$diff <= $max_mem} "gdb did not use too much memory"
gdb_test_no_output "set spin=0" "Allow program to exit"
}
- return 0
+ return $diff
}
# If we couldn't create the first corefile, there's no point
-# in running the second part of the test.
-if {[run_test 4] != 0} {
+# in running the second part of the test. The maximum amount
+# of memory allowed is the same as the memory used by the
+# inferior.
+set mem_limit [run_test 4 4]
+if {$mem_limit < 0} {
return
}
# Surprisingly enough, the larger inferior doesn't seem to use
# any extra memory, it usually uses less memory. Which is good,
# it means our memory requirements aren't growing with the inferior.
-run_test 64
+# This test ensures that it remains true that a larger inferior will
+# not grow the memory requirements.
+run_test 64 $mem_limit
diff --git a/gdb/testsuite/gdb.base/gcore-relro-pie.exp b/gdb/testsuite/gdb.base/gcore-relro-pie.exp
index 361fdb6..641caf1 100644
--- a/gdb/testsuite/gdb.base/gcore-relro-pie.exp
+++ b/gdb/testsuite/gdb.base/gcore-relro-pie.exp
@@ -38,7 +38,8 @@ if [run_on_host "strip" "$strip_program" "-g -o ${stripped_binfile} $binfile"] {
set perm [file attributes ${binfile} -permissions]
file attributes ${stripped_binfile} -permissions $perm
-clean_restart ${stripped_binfile}
+clean_restart
+gdb_load $stripped_binfile
# The binary is stripped of debug info, but not minsyms.
if ![runto break_here] {
@@ -51,7 +52,8 @@ if {![gdb_gcore_cmd $gcorefile "save a corefile"]} {
# Now restart gdb with the unstripped binary and load the corefile.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_test "core ${gcorefile}" \
"Core was generated by .*" "re-load generated corefile"
diff --git a/gdb/testsuite/gdb.base/gcore-relro.exp b/gdb/testsuite/gdb.base/gcore-relro.exp
index 0090c37..2bbd064 100644
--- a/gdb/testsuite/gdb.base/gcore-relro.exp
+++ b/gdb/testsuite/gdb.base/gcore-relro.exp
@@ -34,7 +34,8 @@ set objfile [standard_output_file ${testfile}.o]
}
with_test_prefix "first session" {
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
gdb_load_shlib ${binfile_lib}
if ![runto lib] {
@@ -49,7 +50,8 @@ with_test_prefix "first session" {
# Now restart gdb and load the corefile.
with_test_prefix "second session" {
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
gdb_load_shlib ${binfile_lib}
gdb_test "core ${gcorefile}" "Core was generated by .*" \
diff --git a/gdb/testsuite/gdb.base/gcore-tls-pie.exp b/gdb/testsuite/gdb.base/gcore-tls-pie.exp
index c508b78..a8f7366 100644
--- a/gdb/testsuite/gdb.base/gcore-tls-pie.exp
+++ b/gdb/testsuite/gdb.base/gcore-tls-pie.exp
@@ -42,7 +42,8 @@ if [run_on_host "strip" "$strip_program" "-g -o ${stripped_binfile} $binfile"] {
set perm [file attributes ${binfile} -permissions]
file attributes ${stripped_binfile} -permissions $perm
-clean_restart ${stripped_binfile}
+clean_restart
+gdb_load $stripped_binfile
# The binary is stripped of debug info, but not minsyms.
if ![runto break_here] {
@@ -55,7 +56,8 @@ if {![gdb_gcore_cmd $gcorefile "save a corefile"]} {
# Now restart gdb with the unstripped binary and load the corefile.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_test "core ${gcorefile}" \
"Core was generated by .*" "re-load generated corefile"
diff --git a/gdb/testsuite/gdb.base/gcore.exp b/gdb/testsuite/gdb.base/gcore.exp
index 5251e3f..c8a4c11 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
@@ -57,7 +58,8 @@ if {!$core_supported} {
}
# Now restart gdb and load the corefile.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
set core_loaded [gdb_core_cmd "$corefile" "re-load generated corefile"]
if { $core_loaded == -1 } {
diff --git a/gdb/testsuite/gdb.base/gdb-index-err.exp b/gdb/testsuite/gdb.base/gdb-index-err.exp
index 973248a..b353836 100644
--- a/gdb/testsuite/gdb.base/gdb-index-err.exp
+++ b/gdb/testsuite/gdb.base/gdb-index-err.exp
@@ -90,13 +90,15 @@ foreach_with_prefix flag { "" "-dwarf-5" } {
}
# Add the index section to the executable.
- clean_restart ${binfile}.${extension}
+ clean_restart
+ gdb_load $binfile.$extension
gdb_assert {[ensure_gdb_index ${binfile}.${extension} ${flag}] == 1} \
"add index to executable"
# Reload the executable (which now has an index), and try to
# generate and index from it. This will fail.
- clean_restart ${binfile}.${extension}
+ clean_restart
+ gdb_load $binfile.$extension
gdb_test "save gdb-index ${flag} $already_indexed_dir" \
"Error while writing index for `[string_to_regexp $binfile.$extension]': Cannot use an index to create the index" \
"try to generate an index from a binary with an index"
diff --git a/gdb/testsuite/gdb.base/gdb1250.exp b/gdb/testsuite/gdb.base/gdb1250.exp
index 4e83c8c..2cabbf0 100644
--- a/gdb/testsuite/gdb.base/gdb1250.exp
+++ b/gdb/testsuite/gdb.base/gdb1250.exp
@@ -29,7 +29,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto abort {allow-pending}]} {
return
diff --git a/gdb/testsuite/gdb.base/gdb1555.exp b/gdb/testsuite/gdb.base/gdb1555.exp
index 648abd7..ab12a28 100644
--- a/gdb/testsuite/gdb.base/gdb1555.exp
+++ b/gdb/testsuite/gdb.base/gdb1555.exp
@@ -34,7 +34,8 @@ if { [gdb_compile_shlib $libsrc $libobj {debug}] != ""
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_load_shlib $libobj
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.base/gdbindex-stabs.exp b/gdb/testsuite/gdb.base/gdbindex-stabs.exp
index 506ad11..9becaa1 100644
--- a/gdb/testsuite/gdb.base/gdbindex-stabs.exp
+++ b/gdb/testsuite/gdb.base/gdbindex-stabs.exp
@@ -28,7 +28,8 @@ if {[gdb_compile "${srcdir}/${subdir}/${srcfile_stabs}" ${objfile_stabs} object
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
# FAIL was: No line number known for stabs_function.
gdb_test "list stabs_function" " marker-here .*"
diff --git a/gdb/testsuite/gdb.base/global-var-nested-by-dso.exp b/gdb/testsuite/gdb.base/global-var-nested-by-dso.exp
index 92d6c62..480396a 100644
--- a/gdb/testsuite/gdb.base/global-var-nested-by-dso.exp
+++ b/gdb/testsuite/gdb.base/global-var-nested-by-dso.exp
@@ -42,7 +42,8 @@ if { [gdb_compile $srcdir/$subdir/$srcfile $binfile executable \
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_load_shlib $binfile_lib1
gdb_load_shlib $binfile_lib2
diff --git a/gdb/testsuite/gdb.base/gnu-ifunc.exp b/gdb/testsuite/gdb.base/gnu-ifunc.exp
index c7afbe5..f134a0f 100644
--- a/gdb/testsuite/gdb.base/gnu-ifunc.exp
+++ b/gdb/testsuite/gdb.base/gnu-ifunc.exp
@@ -96,7 +96,8 @@ proc_with_prefix set-break {resolver_attr resolver_debug final_debug} {
set suffix [make_binsuffix $resolver_attr $resolver_debug $final_debug]
set lib_so [standard_output_file ${libfile}-$suffix.so]
- clean_restart $binfile-$suffix
+ clean_restart
+ gdb_load $binfile-$suffix
gdb_load_shlib ${lib_so}
if {![runto_main]} {
@@ -185,6 +186,11 @@ proc_with_prefix set-break {resolver_attr resolver_debug final_debug} {
# other two locations.
gdb_test "info breakpoints" "$location\r\n.*$location\r\n$location"
}
+
+ # At one point a bug existed such that GDB would trigger an assert
+ # while restarting the inferior with ifunc breakpoints set.
+ gdb_run_cmd
+ gdb_test "" "Breakpoint $::decimal,.*final \\(\[^\r\n\]*\\).*" "restart, run until breakpoint"
}
# Misc GNU ifunc tests. For the description of RESOLVER_ATTR,
@@ -218,7 +224,8 @@ proc misc_tests {resolver_attr resolver_debug final_debug} {
# Start with a fresh gdb.
- clean_restart $binfile-$suffix
+ clean_restart
+ gdb_load $binfile-$suffix
gdb_load_shlib ${lib_so}
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.base/gnu_vector.exp b/gdb/testsuite/gdb.base/gnu_vector.exp
index ac0bff3..62c2003 100644
--- a/gdb/testsuite/gdb.base/gnu_vector.exp
+++ b/gdb/testsuite/gdb.base/gnu_vector.exp
@@ -40,7 +40,8 @@ if { [do_compile {-mcpu=native}] != ""
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if { ![runto_main] } {
return -1
diff --git a/gdb/testsuite/gdb.base/hashline1.exp b/gdb/testsuite/gdb.base/hashline1.exp
index 9af144b..8e815ae 100644
--- a/gdb/testsuite/gdb.base/hashline1.exp
+++ b/gdb/testsuite/gdb.base/hashline1.exp
@@ -37,7 +37,8 @@ if { [gdb_compile $compile_name "${binfile}" executable {debug}] != "" } {
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
set bp_location [gdb_get_line_number "set breakpoint here" $new_srcfile]
diff --git a/gdb/testsuite/gdb.base/hashline2.exp b/gdb/testsuite/gdb.base/hashline2.exp
index 740f511..f12b4d1 100644
--- a/gdb/testsuite/gdb.base/hashline2.exp
+++ b/gdb/testsuite/gdb.base/hashline2.exp
@@ -34,7 +34,8 @@ if { [gdb_compile $new_srcfile "${binfile}" executable {debug}] != "" } {
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
set bp_location [gdb_get_line_number "set breakpoint here" ${new_srcfile}]
diff --git a/gdb/testsuite/gdb.base/hashline3.exp b/gdb/testsuite/gdb.base/hashline3.exp
index 2575c28..508f7c9 100644
--- a/gdb/testsuite/gdb.base/hashline3.exp
+++ b/gdb/testsuite/gdb.base/hashline3.exp
@@ -35,7 +35,8 @@ if { [gdb_compile $new_srcfile "${binfile}" executable {debug}] != "" } {
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
set bp_location [gdb_get_line_number "set breakpoint here" $new_srcfile]
diff --git a/gdb/testsuite/gdb.base/hbreak-in-shr-unsupported.exp b/gdb/testsuite/gdb.base/hbreak-in-shr-unsupported.exp
index 8598345..9355ce0 100644
--- a/gdb/testsuite/gdb.base/hbreak-in-shr-unsupported.exp
+++ b/gdb/testsuite/gdb.base/hbreak-in-shr-unsupported.exp
@@ -34,7 +34,8 @@ if { [gdb_compile_shlib ${srcdir}/${subdir}/${lib_src} ${lib_so} $lib_opts] != "
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_load_shlib $lib_so
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.base/hook-stop.exp b/gdb/testsuite/gdb.base/hook-stop.exp
index a7b6ccd..1c774ce 100644
--- a/gdb/testsuite/gdb.base/hook-stop.exp
+++ b/gdb/testsuite/gdb.base/hook-stop.exp
@@ -37,7 +37,8 @@ proc define_hook_stop {commands} {
proc setup {commands} {
global srcfile binfile
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if {![runto_main]} {
return -code return
diff --git a/gdb/testsuite/gdb.base/huge.exp b/gdb/testsuite/gdb.base/huge.exp
index f75b620..cb12964 100644
--- a/gdb/testsuite/gdb.base/huge.exp
+++ b/gdb/testsuite/gdb.base/huge.exp
@@ -42,7 +42,8 @@ for { set size $max } { $size >= $min } { set size [expr $size / 2] } {
require {expr $compilation_succeeded}
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
save_vars { timeout } {
set timeout 30
diff --git a/gdb/testsuite/gdb.base/infcall-exec.exp b/gdb/testsuite/gdb.base/infcall-exec.exp
index 33cc5b6..b819284 100644
--- a/gdb/testsuite/gdb.base/infcall-exec.exp
+++ b/gdb/testsuite/gdb.base/infcall-exec.exp
@@ -36,7 +36,8 @@ if { [is_remote target] } {
set binfile2 [gdb_remote_download target $binfile2]
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return -1
diff --git a/gdb/testsuite/gdb.base/infcall-failure-2.exp b/gdb/testsuite/gdb.base/infcall-failure-2.exp
new file mode 100644
index 0000000..2a7d784
--- /dev/null
+++ b/gdb/testsuite/gdb.base/infcall-failure-2.exp
@@ -0,0 +1,37 @@
+# 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/>.
+
+standard_testfile infcall-failure.c
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] == -1 } {
+ return
+}
+
+if { ![runto_main] } {
+ return
+}
+
+if { ![gdb_breakpoint "*0x1" message] } {
+ return
+}
+
+gdb_test "p foo ()" \
+ [multi_line \
+ [string_to_regexp "Command aborted."] \
+ ".*" ]
+
+# Check that gdb is still responsive. Regression test for PR gdb/33068.
+gdb_test "p 1 + 1" \
+ " = 2"
diff --git a/gdb/testsuite/gdb.base/infcall-failure.exp b/gdb/testsuite/gdb.base/infcall-failure.exp
index 66bccd1..594cb2b 100644
--- a/gdb/testsuite/gdb.base/infcall-failure.exp
+++ b/gdb/testsuite/gdb.base/infcall-failure.exp
@@ -39,7 +39,8 @@ proc start_gdb_and_runto_main { target_async target_non_stop } {
append ::GDBFLAGS \
" -ex \"maintenance set target-async ${target_async}\""
- clean_restart ${::binfile}
+ clean_restart
+ gdb_load $::binfile
}
if { ![runto_main] } {
@@ -131,7 +132,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 +168,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/infcall-nested-structs.exp.tcl b/gdb/testsuite/gdb.base/infcall-nested-structs.exp.tcl
index 3a11d7f..6c95934 100644
--- a/gdb/testsuite/gdb.base/infcall-nested-structs.exp.tcl
+++ b/gdb/testsuite/gdb.base/infcall-nested-structs.exp.tcl
@@ -81,7 +81,8 @@ proc start_nested_structs_test { lang types } {
}
# Start with a fresh gdb.
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
# Make certain that the output is consistent
gdb_test_no_output "set print sevenbit-strings"
@@ -91,7 +92,7 @@ proc start_nested_structs_test { lang types } {
gdb_test_no_output "set print elements 300"
# Advance to main
- if { ![runto_main] } then {
+ if { ![runto_main] } {
return 0
}
diff --git a/gdb/testsuite/gdb.base/infcall-timeout.exp b/gdb/testsuite/gdb.base/infcall-timeout.exp
index aa7dbc3..621a7b9 100644
--- a/gdb/testsuite/gdb.base/infcall-timeout.exp
+++ b/gdb/testsuite/gdb.base/infcall-timeout.exp
@@ -41,7 +41,8 @@ proc run_test { target_async target_non_stop non_stop unwind } {
append ::GDBFLAGS \
" -ex \"maintenance set target-async ${target_async}\""
- clean_restart ${::binfile}
+ clean_restart
+ gdb_load $::binfile
}
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.base/inferior-args.exp b/gdb/testsuite/gdb.base/inferior-args.exp
index 9406c78..b2916701 100644
--- a/gdb/testsuite/gdb.base/inferior-args.exp
+++ b/gdb/testsuite/gdb.base/inferior-args.exp
@@ -17,6 +17,7 @@
# This does not work on boards that don't support inferior arguments.
require {!target_info exists noargs}
+require {expr [have_startup_shell] != -1}
standard_testfile .c
@@ -42,7 +43,8 @@ proc do_test { method startup_with_shell inferior_args expected_results \
stub_suitable } {
global binfile hex
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_test_no_output "set startup-with-shell $startup_with_shell"
@@ -211,14 +213,31 @@ lappend test_desc_list [list "test four" \
[list "$hex \"'\"" \
"$hex \"\\\\\"\""]]
-foreach desc $test_desc_list {
- lassign $desc name stub_suitable args re_list
- with_test_prefix $name {
- foreach_with_prefix set_method { "start" "starti" "run" "set args" } {
- foreach_with_prefix startup_with_shell { on off } {
- do_test $set_method $startup_with_shell $args $re_list \
- $stub_suitable
+# Run all tests in the global TEST_DESC_LIST.
+proc run_all_tests {} {
+ foreach desc $::test_desc_list {
+ lassign $desc name stub_suitable args re_list
+ with_test_prefix $name {
+ foreach_with_prefix set_method { "start" "starti" "run" "set args" } {
+ foreach_with_prefix startup_with_shell { on off } {
+ do_test $set_method $startup_with_shell $args $re_list \
+ $stub_suitable
+ }
}
}
}
}
+
+run_all_tests
+
+# For extended-remote targets, disable the packet which passes
+# inferior arguments as a single string. This changes how the vRun
+# (extended-remote only) packet works.
+if {[target_info gdb_protocol] == "extended-remote"} {
+ with_test_prefix "single-inferior-arg disabled" {
+ save_vars { GDBFLAGS } {
+ append GDBFLAGS " -ex \"set remote single-inferior-argument-feature-packet off\""
+ run_all_tests
+ }
+ }
+}
diff --git a/gdb/testsuite/gdb.base/inferior-died.exp b/gdb/testsuite/gdb.base/inferior-died.exp
index 3992561..9ba3a4c 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
@@ -28,7 +25,8 @@ if { [build_executable "failed to build" ${testfile} ${testfile}.c] } {
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop on\""
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
}
gdb_test_no_output "set detach-on-fork off"
diff --git a/gdb/testsuite/gdb.base/info-proc.exp b/gdb/testsuite/gdb.base/info-proc.exp
index 8dff6a5..adc8894 100644
--- a/gdb/testsuite/gdb.base/info-proc.exp
+++ b/gdb/testsuite/gdb.base/info-proc.exp
@@ -63,7 +63,8 @@ if {[istarget "*-*-linux*"]} {
}
set gcorefile [standard_output_file $testfile.gcore]
if {[gdb_gcore_cmd $gcorefile "save a core file"]} {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_test "core $gcorefile" "Core was generated by.*" \
"core [file tail $gcorefile]"
diff --git a/gdb/testsuite/gdb.base/info-program.exp b/gdb/testsuite/gdb.base/info-program.exp
index 5a47e1e..da24880 100644
--- a/gdb/testsuite/gdb.base/info-program.exp
+++ b/gdb/testsuite/gdb.base/info-program.exp
@@ -35,7 +35,8 @@ standard_testfile
proc do_test { threads non-stop } {
save_vars { ::GDBFLAGS } {
append ::GDBFLAGS " -ex \"set non-stop ${non-stop}\""
- clean_restart $::binfile-$threads
+ clean_restart
+ gdb_load $::binfile-$threads
}
gdb_test "info program" \
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/info-types.exp.tcl b/gdb/testsuite/gdb.base/info-types.exp.tcl
index f75bb36..c05837b 100644
--- a/gdb/testsuite/gdb.base/info-types.exp.tcl
+++ b/gdb/testsuite/gdb.base/info-types.exp.tcl
@@ -33,7 +33,7 @@ proc run_test { lang } {
return -1
}
- if ![runto_main] then {
+ if { ![runto_main] } {
return 0
}
diff --git a/gdb/testsuite/gdb.base/info_sources_2.exp b/gdb/testsuite/gdb.base/info_sources_2.exp
index c469049..09e9972 100644
--- a/gdb/testsuite/gdb.base/info_sources_2.exp
+++ b/gdb/testsuite/gdb.base/info_sources_2.exp
@@ -35,7 +35,8 @@ if {[gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable \
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
set solib_name [gdb_load_shlib $solib_name]
@@ -72,13 +73,18 @@ proc run_info_sources { extra_args args } {
set objfile_name ""
set source_files {}
set files {}
+ # Note below we sanitize paths so we can compare against the
+ # host_file_normalize'd paths later. Note we sanitize, but
+ # don't normalize here, as the latter would turn a relative
+ # path into an absolute path, and this testcase wants to make
+ # sure that GDB prints the absolute path.
gdb_test_multiple $cmd "" {
-re "${command_regex}\r\n" {
exp_continue
}
-re "^(\[^\r\n\]+):\r\n" {
- set objfile_name $expect_out(1,string)
+ set objfile_name [host_file_sanitize $expect_out(1,string)]
if { $is_remote_target } {
set objfile_name [file tail $objfile_name]
}
@@ -101,7 +107,7 @@ proc run_info_sources { extra_args args } {
}
-re "^(\[^,\r\n\]+), " {
- set f $expect_out(1,string)
+ set f [host_file_sanitize $expect_out(1,string)]
lappend files $f
exp_continue
}
@@ -111,7 +117,7 @@ proc run_info_sources { extra_args args } {
return
}
- set f $expect_out(1,string)
+ set f [host_file_sanitize $expect_out(1,string)]
lappend files $f
set info_sources($objfile_name) $files
set $objfile_name ""
@@ -133,7 +139,7 @@ proc run_info_sources { extra_args args } {
}
# Figure out the path for SOURCEFILE that we're looking for.
- set sourcepath [file normalize ${srcdir}/${subdir}/${sourcefile}]
+ set sourcepath [host_file_normalize ${srcdir}/${subdir}/${sourcefile}]
if { $is_remote_target } {
set objfile [file tail $objfile]
@@ -156,32 +162,34 @@ proc run_info_sources { extra_args args } {
# The actual tests.
+set host_binfile [host_file_normalize $binfile$EXEEXT]
+
run_info_sources "" \
- ${binfile} ${srcfile} \
- ${binfile} ${testfile}-header.h \
+ ${host_binfile} ${srcfile} \
+ ${host_binfile} ${testfile}-header.h \
${solib_name} ${srcfile2} \
${solib_name} ${testfile}-header.h
run_info_sources "-basename info_sources_2" \
- ${binfile} ${srcfile} \
- ${binfile} ${testfile}-header.h \
+ ${host_binfile} ${srcfile} \
+ ${host_binfile} ${testfile}-header.h \
${solib_name} ${srcfile2} \
${solib_name} ${testfile}-header.h
run_info_sources "-basename \\.c" \
- ${binfile} ${srcfile} \
- ${binfile} !${testfile}-header.h \
+ ${host_binfile} ${srcfile} \
+ ${host_binfile} !${testfile}-header.h \
${solib_name} ${srcfile2} \
${solib_name} !${testfile}-header.h
run_info_sources "-basename -- -test\\.c" \
- ${binfile} ${srcfile} \
- ${binfile} !${testfile}-header.h \
+ ${host_binfile} ${srcfile} \
+ ${host_binfile} !${testfile}-header.h \
${solib_name} !${srcfile2} \
${solib_name} !${testfile}-header.h
run_info_sources "-basename -- -lib\\.c" \
- ${binfile} !${srcfile} \
- ${binfile} !${testfile}-header.h \
+ ${host_binfile} !${srcfile} \
+ ${host_binfile} !${testfile}-header.h \
${solib_name} ${srcfile2} \
${solib_name} !${testfile}-header.h
diff --git a/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.py b/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.py
index bc4a673..4ab7257 100644
--- a/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.py
+++ b/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.py
@@ -65,6 +65,10 @@ class TestUnwinder(Unwinder):
for reg in pending_frame.architecture().registers("general"):
val = pending_frame.read_register(reg)
+ # Having unavailable registers leads to a fall back to the standard
+ # unwinders. Don't add unavailable registers to avoid this.
+ if str(val) == "<unavailable>":
+ continue
unwinder.add_saved_register(reg, val)
return unwinder
diff --git a/gdb/testsuite/gdb.base/internal-string-values.exp b/gdb/testsuite/gdb.base/internal-string-values.exp
index aa68bc9..c1afa18 100644
--- a/gdb/testsuite/gdb.base/internal-string-values.exp
+++ b/gdb/testsuite/gdb.base/internal-string-values.exp
@@ -250,7 +250,8 @@ proc_with_prefix test_internal_var { } {
return
}
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if {![runto_main]} {
fail "could not run to main"
diff --git a/gdb/testsuite/gdb.base/interrupt-daemon-attach.exp b/gdb/testsuite/gdb.base/interrupt-daemon-attach.exp
index 3c46f5d..a42fc12 100644
--- a/gdb/testsuite/gdb.base/interrupt-daemon-attach.exp
+++ b/gdb/testsuite/gdb.base/interrupt-daemon-attach.exp
@@ -36,7 +36,8 @@ proc do_test {} {
# Attach to the parent, run it to a known point, extract the
# child's PID, and detach.
with_test_prefix "parent" {
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
gdb_test "attach $parent_pid" \
"Attaching to program.*, process $parent_pid.*" \
@@ -60,7 +61,8 @@ proc do_test {} {
with_test_prefix "child" {
global gdb_prompt
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_test "attach $child_pid" \
"Attaching to program.*, process $child_pid.*" \
diff --git a/gdb/testsuite/gdb.base/interrupt-daemon.exp b/gdb/testsuite/gdb.base/interrupt-daemon.exp
index 161f854..b909437 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}]} {
@@ -28,7 +30,8 @@ proc do_test {} {
global binfile
global gdb_prompt
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_test "set follow-fork-mode child" ".*"
diff --git a/gdb/testsuite/gdb.base/jit-bfd-name.exp b/gdb/testsuite/gdb.base/jit-bfd-name.exp
index 219929b..756a38b 100644
--- a/gdb/testsuite/gdb.base/jit-bfd-name.exp
+++ b/gdb/testsuite/gdb.base/jit-bfd-name.exp
@@ -46,7 +46,8 @@ if { [compile_jit_main ${main_srcfile} ${main_binfile} {}] != 0 } {
return
}
-clean_restart $::main_binfile
+clean_restart
+gdb_load $::main_binfile
if { ![runto_main] } {
return
}
diff --git a/gdb/testsuite/gdb.base/jit-elf-fork.exp b/gdb/testsuite/gdb.base/jit-elf-fork.exp
index 81d3350..92e7dc6 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
@@ -53,7 +54,8 @@ if { [compile_jit_main ${main_srcfile} ${main_binfile} {}] != 0 } {
# that the callers can continue execution until there.
proc do_setup { detach-on-fork follow-fork-mode } {
- clean_restart ${::main_binfile}
+ clean_restart
+ gdb_load $::main_binfile
gdb_test_no_output "set detach-on-fork ${detach-on-fork}"
gdb_test_no_output "set follow-fork-mode ${follow-fork-mode}"
diff --git a/gdb/testsuite/gdb.base/jit-elf-so.exp b/gdb/testsuite/gdb.base/jit-elf-so.exp
index c227748..8f16bdb 100644
--- a/gdb/testsuite/gdb.base/jit-elf-so.exp
+++ b/gdb/testsuite/gdb.base/jit-elf-so.exp
@@ -73,7 +73,8 @@ proc one_jit_test {solib_binfiles_target match_str} {
global main_loader_binfile main_loader_srcfile
global main_solib_binfile main_solib_binfile_target main_solib_srcfile
- clean_restart $main_loader_binfile
+ clean_restart
+ gdb_load $main_loader_binfile
gdb_locate_shlib $main_solib_binfile
# This is just to help debugging when things fail
diff --git a/gdb/testsuite/gdb.base/jit-elf.exp b/gdb/testsuite/gdb.base/jit-elf.exp
index a519565..2dc67a5 100644
--- a/gdb/testsuite/gdb.base/jit-elf.exp
+++ b/gdb/testsuite/gdb.base/jit-elf.exp
@@ -48,7 +48,8 @@ proc clean_reattach {} {
gdb_test_no_output "set var wait_for_gdb = 1"
gdb_test "detach" "Detaching from .*"
- clean_restart ${main_binfile}
+ clean_restart
+ gdb_load $main_binfile
if { ![gdb_attach $testpid \
-pattern "main.*at .*$::main_basename.c:.*"] } {
@@ -84,7 +85,8 @@ proc one_jit_test {jit_solibs_target match_str reattach} {
global test_verbose
global main_binfile main_srcfile
- clean_restart ${main_binfile}
+ clean_restart
+ gdb_load $main_binfile
# This is just to help debugging when things fail
if {$test_verbose > 0} {
diff --git a/gdb/testsuite/gdb.base/jit-reader-exec.exp b/gdb/testsuite/gdb.base/jit-reader-exec.exp
index ef6148b..e70f104 100644
--- a/gdb/testsuite/gdb.base/jit-reader-exec.exp
+++ b/gdb/testsuite/gdb.base/jit-reader-exec.exp
@@ -43,7 +43,8 @@ if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/jit-reader-simple.exp b/gdb/testsuite/gdb.base/jit-reader-simple.exp
index 77705eb..f577dba 100644
--- a/gdb/testsuite/gdb.base/jit-reader-simple.exp
+++ b/gdb/testsuite/gdb.base/jit-reader-simple.exp
@@ -103,9 +103,11 @@ proc jit_test_reread {standalone change_addr} {
with_test_prefix "initial run" {
if {$standalone} {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
} else {
- clean_restart $binfile_dl
+ clean_restart
+ gdb_load $binfile_dl
}
runto_main
@@ -175,7 +177,8 @@ foreach standalone {1 0} {
# see JIT breakpoints defined for both.
with_test_prefix "two JITers" {
- clean_restart $binfile_dl2
+ clean_restart
+ gdb_load $binfile_dl2
if {![runto_main]} {
return -1
diff --git a/gdb/testsuite/gdb.base/jit-reader.exp b/gdb/testsuite/gdb.base/jit-reader.exp
index 4462ab4..cd844ca 100644
--- a/gdb/testsuite/gdb.base/jit-reader.exp
+++ b/gdb/testsuite/gdb.base/jit-reader.exp
@@ -102,7 +102,8 @@ proc jit_reader_test {} {
set any "\[^\r\n\]*"
- clean_restart $jit_host_bin
+ clean_restart
+ gdb_load $jit_host_bin
gdb_load_shlib $jit_reader_bin
if {$test_verbose > 0} {
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/kill-during-detach.exp b/gdb/testsuite/gdb.base/kill-during-detach.exp
index e164234..290606a 100644
--- a/gdb/testsuite/gdb.base/kill-during-detach.exp
+++ b/gdb/testsuite/gdb.base/kill-during-detach.exp
@@ -76,7 +76,8 @@ set checkpoint_line [gdb_get_line_number "Checkpoint here"]
proc run_test { exit_p checkpoint_p } {
save_vars { ::GDBFLAGS } {
append ::GDBFLAGS " -ex \"set non-stop on\""
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
}
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.base/killed-outside.exp b/gdb/testsuite/gdb.base/killed-outside.exp
index 919584d..2b367e4 100644
--- a/gdb/testsuite/gdb.base/killed-outside.exp
+++ b/gdb/testsuite/gdb.base/killed-outside.exp
@@ -46,7 +46,8 @@ proc test {cmds_after_kill} {
global gdb_prompt
global decimal
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
if ![runto done] {
return
diff --git a/gdb/testsuite/gdb.base/langs.exp b/gdb/testsuite/gdb.base/langs.exp
index b84b7d6..aa8d8e0 100644
--- a/gdb/testsuite/gdb.base/langs.exp
+++ b/gdb/testsuite/gdb.base/langs.exp
@@ -93,7 +93,8 @@ if {[runto csub]} {
gdb_continue_to_end "first session"
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Try exercising the "minimal" language a bit...
diff --git a/gdb/testsuite/gdb.base/large-frame.exp b/gdb/testsuite/gdb.base/large-frame.exp
index 0418b5b..f0d7af6 100644
--- a/gdb/testsuite/gdb.base/large-frame.exp
+++ b/gdb/testsuite/gdb.base/large-frame.exp
@@ -28,12 +28,12 @@ if { [is_remote host] } {
# the test.
proc run_test { opt_level } {
- global srcfile srcfile2 binfile hex
+ global srcfile srcfile2 hex
standard_testfile large-frame-1.c large-frame-2.c
if {[prepare_for_testing_full "failed to prepare" \
- [list ${binfile}-${opt_level} debug \
+ [list $::testfile-$opt_level debug \
$srcfile [list debug] \
$srcfile2 [list nodebug optimize=-$opt_level]]]} {
return
diff --git a/gdb/testsuite/gdb.base/lineinc.exp b/gdb/testsuite/gdb.base/lineinc.exp
index cfd2ba7..2382fa5 100644
--- a/gdb/testsuite/gdb.base/lineinc.exp
+++ b/gdb/testsuite/gdb.base/lineinc.exp
@@ -86,7 +86,8 @@ if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" ${binfile} executable \
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
# Any command that causes GDB to read the debugging info for the
# lineinc.c compilation unit will do here.
diff --git a/gdb/testsuite/gdb.base/list-missing-source.exp b/gdb/testsuite/gdb.base/list-missing-source.exp
index 7807206..196a1f2 100644
--- a/gdb/testsuite/gdb.base/list-missing-source.exp
+++ b/gdb/testsuite/gdb.base/list-missing-source.exp
@@ -43,7 +43,8 @@ if { [gdb_compile "${srcfile}" "${binfile}" \
remote_file host delete $srcfile
# Now start GDB, run to main and try to list the source.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.base/list.exp b/gdb/testsuite/gdb.base/list.exp
index d005ceb..bdbb52b 100644
--- a/gdb/testsuite/gdb.base/list.exp
+++ b/gdb/testsuite/gdb.base/list.exp
@@ -385,7 +385,8 @@ proc test_only_end {} {
proc test_list_invalid_args {} {
global binfile
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
gdb_test "list -INVALID" \
"invalid explicit location argument, \"-INVALID\"" \
"first use of \"list -INVALID\""
@@ -393,7 +394,8 @@ proc test_list_invalid_args {} {
"invalid explicit location argument, \"-INVALID\"" \
"second use of \"list -INVALID\""
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
gdb_test "list +INVALID" "Function \"\\+INVALID\" not defined." \
"first use of \"list +INVALID\""
gdb_test "list +INVALID" "Function \"\\+INVALID\" not defined." \
@@ -499,7 +501,8 @@ proc test_list {command listsize1 listsize2 linerange1 linerange2} {
with_test_prefix "$command after stop: $listsize1, $listsize2" {
global binfile
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if {![runto_main]} {
return
}
diff --git a/gdb/testsuite/gdb.base/logical.exp b/gdb/testsuite/gdb.base/logical.exp
index 31007e8..b00d6d5 100644
--- a/gdb/testsuite/gdb.base/logical.exp
+++ b/gdb/testsuite/gdb.base/logical.exp
@@ -32,7 +32,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
#
diff --git a/gdb/testsuite/gdb.base/long_long.exp b/gdb/testsuite/gdb.base/long_long.exp
index 38ba03e..4fbb757 100644
--- a/gdb/testsuite/gdb.base/long_long.exp
+++ b/gdb/testsuite/gdb.base/long_long.exp
@@ -30,7 +30,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [con
# use this to debug:
#log_user 1
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto known_types]} {
return
diff --git a/gdb/testsuite/gdb.base/longjmp.exp b/gdb/testsuite/gdb.base/longjmp.exp
index caf0d5c..99552e6 100644
--- a/gdb/testsuite/gdb.base/longjmp.exp
+++ b/gdb/testsuite/gdb.base/longjmp.exp
@@ -26,7 +26,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
}
proc do_test { with_probes } {
- clean_restart ${::binfile}
+ clean_restart
+ gdb_load $::binfile
if { !$with_probes } {
gdb_test "maint ignore-probes libc ^longjmp$"
diff --git a/gdb/testsuite/gdb.base/macro-source-path.exp b/gdb/testsuite/gdb.base/macro-source-path.exp
index 47ad789..9c84227 100644
--- a/gdb/testsuite/gdb.base/macro-source-path.exp
+++ b/gdb/testsuite/gdb.base/macro-source-path.exp
@@ -33,7 +33,7 @@ require {!is_remote host}
# Set the current working directory to $out/cwd, so that we can test compiling
# using relative paths.
-set out_dir [standard_output_file ""]
+set out_dir [build_standard_output_file ""]
file mkdir $out_dir/cwd
file mkdir $out_dir/other
file copy -force $srcdir/$subdir/$srcfile $out_dir/cwd
@@ -53,7 +53,8 @@ proc test { src name } {
return
}
- clean_restart $binfile
+ clean_restart
+ gdb_load [host_file_normalize $binfile]
if { ![runto_main] } {
return
diff --git a/gdb/testsuite/gdb.base/macscp.exp b/gdb/testsuite/gdb.base/macscp.exp
index 0b5f863..63f1356 100644
--- a/gdb/testsuite/gdb.base/macscp.exp
+++ b/gdb/testsuite/gdb.base/macscp.exp
@@ -29,7 +29,8 @@ if {[gdb_compile "${srcdir}/${subdir}/macscp1.c" "${objfile}" \
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
# Ask GDB to show the current definition of MACRO, and return a list
diff --git a/gdb/testsuite/gdb.base/maint-info-inline-frames-and-blocks.exp b/gdb/testsuite/gdb.base/maint-info-inline-frames-and-blocks.exp
index 80f2d01..91d0379 100644
--- a/gdb/testsuite/gdb.base/maint-info-inline-frames-and-blocks.exp
+++ b/gdb/testsuite/gdb.base/maint-info-inline-frames-and-blocks.exp
@@ -201,7 +201,8 @@ gdb_test "maint info blocks" [make_blocks_result normal_func \
inline_func_a inline_func_b] \
"maint info blocks using stored \$pc, inferior still running"
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Use the recorded $pc value to check inline frames when the inferior
# is not executing.
diff --git a/gdb/testsuite/gdb.base/maint.exp b/gdb/testsuite/gdb.base/maint.exp
index 52282bc..3d49b36 100644
--- a/gdb/testsuite/gdb.base/maint.exp
+++ b/gdb/testsuite/gdb.base/maint.exp
@@ -52,6 +52,41 @@ 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
+ gdb_load $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 +240,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" \
diff --git a/gdb/testsuite/gdb.base/many-headers.exp b/gdb/testsuite/gdb.base/many-headers.exp
index f46b980..5e022da 100644
--- a/gdb/testsuite/gdb.base/many-headers.exp
+++ b/gdb/testsuite/gdb.base/many-headers.exp
@@ -33,6 +33,7 @@ if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
# Generate core file.
set corefile [core_find $binfile]
if {$corefile == ""} {
+ untested "unable to create or find corefile"
return 0
}
diff --git a/gdb/testsuite/gdb.base/max-depth.exp.tcl b/gdb/testsuite/gdb.base/max-depth.exp.tcl
index fcec47b..22bf180 100644
--- a/gdb/testsuite/gdb.base/max-depth.exp.tcl
+++ b/gdb/testsuite/gdb.base/max-depth.exp.tcl
@@ -30,12 +30,12 @@ proc compile_and_run_tests { lang } {
lappend flags "additional_flags=-std=c++11"
}
- if { [prepare_for_testing "failed to prepare" "${binfile}" "${srcfile}" "${flags}"] } {
+ if { [prepare_for_testing "failed to prepare" $testfile $srcfile $flags] } {
return 0
}
# Advance to main.
- if { ![runto_main] } then {
+ if { ![runto_main] } {
return 0
}
diff --git a/gdb/testsuite/gdb.base/miscexprs.exp b/gdb/testsuite/gdb.base/miscexprs.exp
index 86196fa..f723d75 100644
--- a/gdb/testsuite/gdb.base/miscexprs.exp
+++ b/gdb/testsuite/gdb.base/miscexprs.exp
@@ -44,7 +44,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [lis
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
#
diff --git a/gdb/testsuite/gdb.base/msym-bp-shl.exp b/gdb/testsuite/gdb.base/msym-bp-shl.exp
index b154ce6..41dc818 100644
--- a/gdb/testsuite/gdb.base/msym-bp-shl.exp
+++ b/gdb/testsuite/gdb.base/msym-bp-shl.exp
@@ -55,7 +55,8 @@ proc test {debug} {
return
}
- clean_restart $bin
+ clean_restart
+ gdb_load $bin
gdb_load_shlib $lib
# Should find two locations: the static foo in the
diff --git a/gdb/testsuite/gdb.base/multi-forks.exp b/gdb/testsuite/gdb.base/multi-forks.exp
index 61a240f..5d2d220 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
@@ -32,7 +28,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable $fla
# Start with a fresh gdb
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
global gdb_prompt
@@ -107,7 +104,8 @@ proc continue_to_exit_bp_loc {} {
# parent's branch.
foreach mode { "child" "parent" } {
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
runto_main
gdb_test_no_output "set follow-fork $mode"
@@ -139,7 +137,8 @@ foreach mode { "child" "parent" } {
# Start with a fresh gdb
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
runto_main
gdb_breakpoint $exit_bp_loc
diff --git a/gdb/testsuite/gdb.base/nodebug.exp b/gdb/testsuite/gdb.base/nodebug.exp
index 2d0a5a9..b839317 100644
--- a/gdb/testsuite/gdb.base/nodebug.exp
+++ b/gdb/testsuite/gdb.base/nodebug.exp
@@ -33,7 +33,8 @@ if { [gdb_compile $srcdir/$subdir/$srcfile $binfile executable $exec_opts] != "
# Start with a fresh gdb.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Run to FUNC and unload symbols from system shared libraries, to
# avoid conflicts with the minsyms in the program. E.g.,
diff --git a/gdb/testsuite/gdb.base/nofield.exp b/gdb/testsuite/gdb.base/nofield.exp
index 2e88725..31d0234 100644
--- a/gdb/testsuite/gdb.base/nofield.exp
+++ b/gdb/testsuite/gdb.base/nofield.exp
@@ -23,7 +23,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debu
set eol "\r\n"
set sp "\[ \t\]*"
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_test "ptype struct not_empty" \
"type = struct not_empty {$eol${sp}void \\*e;$eol${sp}void \\*u;$eol}"
diff --git a/gdb/testsuite/gdb.base/nostdlib.exp b/gdb/testsuite/gdb.base/nostdlib.exp
index ecf09a8..8dcefcf 100644
--- a/gdb/testsuite/gdb.base/nostdlib.exp
+++ b/gdb/testsuite/gdb.base/nostdlib.exp
@@ -49,7 +49,8 @@ foreach_with_prefix pie { "nopie" "pie" } {
return -1
}
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_breakpoint "*marker"
diff --git a/gdb/testsuite/gdb.base/options.exp b/gdb/testsuite/gdb.base/options.exp
index 7822e4a..8ac9f4e 100644
--- a/gdb/testsuite/gdb.base/options.exp
+++ b/gdb/testsuite/gdb.base/options.exp
@@ -205,7 +205,8 @@ proc_with_prefix test-print {{prefix ""}} {
}
global binfile
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if ![runto_main] {
return
@@ -317,7 +318,8 @@ proc_with_prefix test-backtrace {} {
"backtrace no-filters"
global binfile
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if ![runto_main] {
return
@@ -508,12 +510,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/paginate-after-ctrl-c-running.exp b/gdb/testsuite/gdb.base/paginate-after-ctrl-c-running.exp
index a831050..d60a0ea 100644
--- a/gdb/testsuite/gdb.base/paginate-after-ctrl-c-running.exp
+++ b/gdb/testsuite/gdb.base/paginate-after-ctrl-c-running.exp
@@ -31,7 +31,8 @@ proc test_ctrlc_while_target_running_does_not_paginate {} {
set testline [gdb_get_line_number "after sleep"]
with_test_prefix "ctrlc target running" {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.base/paginate-bg-execution.exp b/gdb/testsuite/gdb.base/paginate-bg-execution.exp
index dfd7823..40f98fc 100644
--- a/gdb/testsuite/gdb.base/paginate-bg-execution.exp
+++ b/gdb/testsuite/gdb.base/paginate-bg-execution.exp
@@ -30,7 +30,8 @@ proc test_bg_execution_pagination_return {} {
global decimal
with_test_prefix "paginate" {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.base/paginate-inferior-exit.exp b/gdb/testsuite/gdb.base/paginate-inferior-exit.exp
index 76176e2..6cc992b 100644
--- a/gdb/testsuite/gdb.base/paginate-inferior-exit.exp
+++ b/gdb/testsuite/gdb.base/paginate-inferior-exit.exp
@@ -29,7 +29,8 @@ proc test_paginate_inferior_exited {} {
global inferior_exited_re
with_test_prefix "paginate" {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.base/patch.exp b/gdb/testsuite/gdb.base/patch.exp
index 69e5581..f6abc59 100644
--- a/gdb/testsuite/gdb.base/patch.exp
+++ b/gdb/testsuite/gdb.base/patch.exp
@@ -34,7 +34,8 @@ with_test_prefix "exec" {
gdb_test "p extern_global = 2" " = 2" "modify value"
gdb_test "p extern_global" " = 2" "value modified"
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_test "p extern_global" " = 2" "value modified persisted"
}
@@ -43,7 +44,8 @@ with_test_prefix "exec" {
# Generate a core file.
with_test_prefix "gcore" {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/pc-not-saved.exp b/gdb/testsuite/gdb.base/pc-not-saved.exp
index 16e11bc..e761e93 100644
--- a/gdb/testsuite/gdb.base/pc-not-saved.exp
+++ b/gdb/testsuite/gdb.base/pc-not-saved.exp
@@ -60,7 +60,8 @@ gdb_assert { ![string equal $pc unknown] } \
"check we read the frame's PC"
# Restart and load the Python unwinder script.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_test_no_output "source ${remote_python_file}" "load python file"
# Tell the Python unwinder to use the frame-id we cached above.
diff --git a/gdb/testsuite/gdb.base/pie-fork.exp b/gdb/testsuite/gdb.base/pie-fork.exp
index 48c01d9..9d232c8 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]
@@ -27,7 +29,8 @@ if [build_executable "failed to prepare" $testfile $srcfile $opts] {
proc setup_test {detach_on_fork {follow_fork_mode "parent"}} {
global binfile
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
if ![runto_main] {
return
diff --git a/gdb/testsuite/gdb.base/pointers.exp b/gdb/testsuite/gdb.base/pointers.exp
index ab02181..4d4d58e 100644
--- a/gdb/testsuite/gdb.base/pointers.exp
+++ b/gdb/testsuite/gdb.base/pointers.exp
@@ -32,7 +32,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
#
diff --git a/gdb/testsuite/gdb.base/pr11022.exp b/gdb/testsuite/gdb.base/pr11022.exp
index e7bfba0..70a7d8b 100644
--- a/gdb/testsuite/gdb.base/pr11022.exp
+++ b/gdb/testsuite/gdb.base/pr11022.exp
@@ -24,7 +24,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.base/print-symbol-loading.exp b/gdb/testsuite/gdb.base/print-symbol-loading.exp
index 15f2c19..91e818b 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
@@ -35,7 +35,8 @@ if { [gdb_compile ${objfile} ${binfile} executable $opts] != "" } {
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_load_shlib ${binfile_lib}
if ![runto lib] {
@@ -94,7 +95,8 @@ proc test_load_shlib { print_symbol_loading } {
global binfile
global gdb_prompt
with_test_prefix "shlib ${print_symbol_loading}" {
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
if ![runto_main] {
return -1
}
diff --git a/gdb/testsuite/gdb.base/prologue.exp b/gdb/testsuite/gdb.base/prologue.exp
index 0d3902d..736e779 100644
--- a/gdb/testsuite/gdb.base/prologue.exp
+++ b/gdb/testsuite/gdb.base/prologue.exp
@@ -23,7 +23,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/ptr-typedef.exp b/gdb/testsuite/gdb.base/ptr-typedef.exp
index 53d03cc..8bffb26 100644
--- a/gdb/testsuite/gdb.base/ptr-typedef.exp
+++ b/gdb/testsuite/gdb.base/ptr-typedef.exp
@@ -22,7 +22,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
# Get things started.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if ![runto marker1] {
untested "couldn't run to marker1"
diff --git a/gdb/testsuite/gdb.base/quit-live.exp b/gdb/testsuite/gdb.base/quit-live.exp
index a95c980..46579d4 100644
--- a/gdb/testsuite/gdb.base/quit-live.exp
+++ b/gdb/testsuite/gdb.base/quit-live.exp
@@ -95,7 +95,8 @@ proc quit_with_live_inferior {appear_how extra_inferior quit_how} {
set test_spawn_id ""
if {$appear_how != "attach-nofile"} {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
} else {
clean_restart
}
diff --git a/gdb/testsuite/gdb.base/random-signal.exp b/gdb/testsuite/gdb.base/random-signal.exp
index bb5b482..16f9467 100644
--- a/gdb/testsuite/gdb.base/random-signal.exp
+++ b/gdb/testsuite/gdb.base/random-signal.exp
@@ -49,7 +49,8 @@ proc do_test {} {
# while gdb is processing the internal software watchtpoint
# single-step. With remote debugging, the ctrl-c reaches GDB first.
with_test_prefix "run" {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if {![runto_main]} {
return -1
@@ -62,7 +63,8 @@ with_test_prefix "run" {
# reaches GDB first. Test that as well.
with_test_prefix "attach" {
if {[can_spawn_for_attach]} {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
set test_spawn_id [spawn_wait_for_attach $binfile]
set testpid [spawn_id_get_pid $test_spawn_id]
diff --git a/gdb/testsuite/gdb.base/readline-ask.exp b/gdb/testsuite/gdb.base/readline-ask.exp
index 3f98e13..0fdfc76 100644
--- a/gdb/testsuite/gdb.base/readline-ask.exp
+++ b/gdb/testsuite/gdb.base/readline-ask.exp
@@ -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/>.
+require {!is_remote host}
+
standard_testfile .c
set inputrc ${srcdir}/${subdir}/${testfile}.inputrc
@@ -25,7 +27,8 @@ setenv TERM dumb
# INPUTRC gets reset for the next testfile.
setenv INPUTRC $inputrc
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if { ![readline_is_used] } {
unsupported "completion doesn't work when readline isn't used."
diff --git a/gdb/testsuite/gdb.base/readline-commands-eof.exp b/gdb/testsuite/gdb.base/readline-commands-eof.exp
index 021e40f..d55dd1d 100644
--- a/gdb/testsuite/gdb.base/readline-commands-eof.exp
+++ b/gdb/testsuite/gdb.base/readline-commands-eof.exp
@@ -43,7 +43,8 @@ if { ![readline_supports_eof_flag] } {
# arrived. If it is then GDB will start displaying extra blank lines
# after each line of input.
proc run_test {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
gdb_breakpoint main
diff --git a/gdb/testsuite/gdb.base/readline.exp b/gdb/testsuite/gdb.base/readline.exp
index 198d686..9b87790 100644
--- a/gdb/testsuite/gdb.base/readline.exp
+++ b/gdb/testsuite/gdb.base/readline.exp
@@ -21,6 +21,8 @@
# Tests for readline operations.
#
+require {!is_remote host}
+
# This function is used to test operate-and-get-next.
# NAME is the name of the test.
# ARGS is a list of alternating commands and expected results.
diff --git a/gdb/testsuite/gdb.base/readnever.exp b/gdb/testsuite/gdb.base/readnever.exp
index 6dfd576..891adf5 100644
--- a/gdb/testsuite/gdb.base/readnever.exp
+++ b/gdb/testsuite/gdb.base/readnever.exp
@@ -26,7 +26,7 @@ if { [build_executable "failed to build" $testfile $srcfile { debug }] == -1 } {
save_vars { GDBFLAGS } {
append GDBFLAGS " --readnever"
- if { [clean_restart ${binfile}] == -1 } {
+ if { [clean_restart $testfile] == -1 } {
return -1
}
}
diff --git a/gdb/testsuite/gdb.base/relativedebug.exp b/gdb/testsuite/gdb.base/relativedebug.exp
index d713771..2465ffd 100644
--- a/gdb/testsuite/gdb.base/relativedebug.exp
+++ b/gdb/testsuite/gdb.base/relativedebug.exp
@@ -24,7 +24,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
# Get things started.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
runto_main
diff --git a/gdb/testsuite/gdb.base/remote.exp b/gdb/testsuite/gdb.base/remote.exp
index 9917faf..c1d6a99 100644
--- a/gdb/testsuite/gdb.base/remote.exp
+++ b/gdb/testsuite/gdb.base/remote.exp
@@ -164,7 +164,8 @@ gdb_load_timed $binfile "limit" 0
# Get the size of random_data table (defaults to 48K).
set sizeof_random_data [get_sizeof "random_data" 48*1024]
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
#
# Part THREE: Check the upload behavior.
diff --git a/gdb/testsuite/gdb.base/reread.exp b/gdb/testsuite/gdb.base/reread.exp
index 7e7d2c8..6c71f40 100644
--- a/gdb/testsuite/gdb.base/reread.exp
+++ b/gdb/testsuite/gdb.base/reread.exp
@@ -106,7 +106,8 @@ foreach_with_prefix opts { "" "pie" } {
gdb_rename_execfile ${binfile1} ${binfile}
# Restart GDB entirely.
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
# Set a breakpoint on foo and run to it.
gdb_test "break foo" \
diff --git a/gdb/testsuite/gdb.base/reset-catchpoint-cond.exp b/gdb/testsuite/gdb.base/reset-catchpoint-cond.exp
index 062dc63..852576a 100644
--- a/gdb/testsuite/gdb.base/reset-catchpoint-cond.exp
+++ b/gdb/testsuite/gdb.base/reset-catchpoint-cond.exp
@@ -75,7 +75,8 @@ proc run_test { mode } {
return
}
- clean_restart $exec_name
+ clean_restart
+ gdb_load $exec_name
gdb_load_shlib $::libfile
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.base/restore.exp b/gdb/testsuite/gdb.base/restore.exp
index 9724032..5448fb4 100644
--- a/gdb/testsuite/gdb.base/restore.exp
+++ b/gdb/testsuite/gdb.base/restore.exp
@@ -96,7 +96,8 @@ restore_tests
set timeout $prev_timeout
# Test PR cli/23785
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
if { ![runto_main] } {
return -1
}
diff --git a/gdb/testsuite/gdb.base/return2.exp b/gdb/testsuite/gdb.base/return2.exp
index b657c11..e90a60b 100644
--- a/gdb/testsuite/gdb.base/return2.exp
+++ b/gdb/testsuite/gdb.base/return2.exp
@@ -103,7 +103,8 @@ proc return2_tests { } {
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
set timeout 30
return2_tests
diff --git a/gdb/testsuite/gdb.base/rtld-step.exp b/gdb/testsuite/gdb.base/rtld-step.exp
index 242cd47..d1e240b 100644
--- a/gdb/testsuite/gdb.base/rtld-step.exp
+++ b/gdb/testsuite/gdb.base/rtld-step.exp
@@ -114,7 +114,8 @@ if { [gdb_compile ${srcfile_main} ${binfile_main} executable $main_flags] != ""
return -1
}
-clean_restart ${binfile_main}
+clean_restart
+gdb_load $binfile_main
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.base/run-attach-while-running.exp b/gdb/testsuite/gdb.base/run-attach-while-running.exp
index ae1388d..7b40a5f 100644
--- a/gdb/testsuite/gdb.base/run-attach-while-running.exp
+++ b/gdb/testsuite/gdb.base/run-attach-while-running.exp
@@ -60,7 +60,8 @@ proc_with_prefix test { non-stop threaded run-or-attach } {
set ::GDBFLAGS "$::GDBFLAGS -ex \"maint set target-non-stop on\""
}
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
}
if { ![runto_main] } {
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..2c75d06 100644
--- a/gdb/testsuite/gdb.base/run-control-while-bg-execution.exp
+++ b/gdb/testsuite/gdb.base/run-control-while-bg-execution.exp
@@ -49,9 +49,15 @@ 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
+ clean_restart
+ gdb_load $::binfile
}
# Ensure we are at least after the getpid call, should we need it.
diff --git a/gdb/testsuite/gdb.base/run-fail-twice.exp b/gdb/testsuite/gdb.base/run-fail-twice.exp
index af8c61b..07cbdda 100644
--- a/gdb/testsuite/gdb.base/run-fail-twice.exp
+++ b/gdb/testsuite/gdb.base/run-fail-twice.exp
@@ -43,7 +43,8 @@ proc test_run {testname} {
proc_with_prefix test {} {
global gdb_prompt binfile
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_test_no_output "set confirm off"
diff --git a/gdb/testsuite/gdb.base/savedregs.exp b/gdb/testsuite/gdb.base/savedregs.exp
index 2c44566..d71d872 100644
--- a/gdb/testsuite/gdb.base/savedregs.exp
+++ b/gdb/testsuite/gdb.base/savedregs.exp
@@ -35,7 +35,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
}
# get things started
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
# Advance to main
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.base/sep.exp b/gdb/testsuite/gdb.base/sep.exp
index 5a1e077..6abf356 100644
--- a/gdb/testsuite/gdb.base/sep.exp
+++ b/gdb/testsuite/gdb.base/sep.exp
@@ -26,7 +26,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
set location [gdb_get_line_number "say_hello" "sep-proc.c"]
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
# Try to display the source code inside a file which is included by
# another source file. The purpose of this test is to verify that
@@ -45,7 +46,8 @@ gdb_test "list sep-proc.c:$location" \
# Try the same, but this time with a breakpoint. We need to exit
# GDB to make sure that we havn't loaded the full symbols yet when
# we test the breakpoint insertion.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
set test "breakpoint inside included file"
gdb_test_multiple "break sep-proc.c:$location" "$test" {
diff --git a/gdb/testsuite/gdb.base/sepsymtab.exp b/gdb/testsuite/gdb.base/sepsymtab.exp
index f5e8705..ed7a7a2 100644
--- a/gdb/testsuite/gdb.base/sepsymtab.exp
+++ b/gdb/testsuite/gdb.base/sepsymtab.exp
@@ -31,7 +31,8 @@ if [gdb_gnu_strip_debug $binfile no-main] {
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
set command "info sym main"
set command_regex [string_to_regexp $command]
diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
index 72a2632..73a200f 100644
--- a/gdb/testsuite/gdb.base/set-cwd.exp
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -184,7 +184,9 @@ proc_with_prefix test_cwd_reset { } {
}
test_cd_into_dir
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
test_tilde_expansion
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
test_cwd_reset
diff --git a/gdb/testsuite/gdb.base/set-inferior-tty.exp b/gdb/testsuite/gdb.base/set-inferior-tty.exp
index 64ec57b..c9b0a96 100644
--- a/gdb/testsuite/gdb.base/set-inferior-tty.exp
+++ b/gdb/testsuite/gdb.base/set-inferior-tty.exp
@@ -24,7 +24,8 @@ if {[build_executable $testfile.exp $testfile ${srcfile} ${compile_options}] ==
proc test_set_inferior_tty { command } {
global binfile
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
gdb_test_no_output "$command hello" "set inferior-tty to hello"
gdb_test "show inferior-tty" \
diff --git a/gdb/testsuite/gdb.base/setshow.exp b/gdb/testsuite/gdb.base/setshow.exp
index 79ff913..0e38a9d 100644
--- a/gdb/testsuite/gdb.base/setshow.exp
+++ b/gdb/testsuite/gdb.base/setshow.exp
@@ -29,7 +29,8 @@ if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable {debug}]
proc_with_prefix test_setshow_annotate {} {
# Start with a fresh gdb
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if {![runto_main]} {
return
@@ -78,7 +79,8 @@ proc_with_prefix test_setshow_annotate {} {
}
proc_with_prefix test_setshow_args {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/settings.exp b/gdb/testsuite/gdb.base/settings.exp
index 5e7cc24..d83023b 100644
--- a/gdb/testsuite/gdb.base/settings.exp
+++ b/gdb/testsuite/gdb.base/settings.exp
@@ -531,7 +531,8 @@ proc test-string {variant} {
global srcfile binfile
# Load symbols for the completion test below.
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
# Use these variables to make sure we don't call the wrong command
# by mistake.
diff --git a/gdb/testsuite/gdb.base/share-env-with-gdbserver.exp b/gdb/testsuite/gdb.base/share-env-with-gdbserver.exp
index 920f435..aa4b300 100644
--- a/gdb/testsuite/gdb.base/share-env-with-gdbserver.exp
+++ b/gdb/testsuite/gdb.base/share-env-with-gdbserver.exp
@@ -91,7 +91,8 @@ proc do_prepare_inferior { } {
proc do_test { var_value { var_name "" } { var_name_match "" } { var_value_match "" } } {
global binfile test_var_name
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if { $var_name == "" } {
set var_name $test_var_name
@@ -146,7 +147,8 @@ with_test_prefix "strange named var" {
proc test_set_unset_vars { } {
global binfile
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
with_test_prefix "set 3 environment variables" {
# Set some environment variables
@@ -205,7 +207,8 @@ with_test_prefix "test set/unset of vars" {
proc test_unset { } {
global hex decimal binfile gdb_prompt
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
do_prepare_inferior
@@ -234,7 +237,8 @@ proc test_unset { } {
}
with_test_prefix "set-then-unset" {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
# Test if setting and then unsetting $HOME works.
gdb_test_no_output "set environment HOME = test" "set HOME as test"
diff --git a/gdb/testsuite/gdb.base/shlib-call.exp b/gdb/testsuite/gdb.base/shlib-call.exp
index 6a5f6d8..d3ff1c3 100644
--- a/gdb/testsuite/gdb.base/shlib-call.exp
+++ b/gdb/testsuite/gdb.base/shlib-call.exp
@@ -59,7 +59,8 @@ if { [gdb_compile_shlib ${lib1src} ${lib1} $lib_opts] != ""
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_load_shlib $lib1
gdb_load_shlib $lib2
@@ -161,7 +162,8 @@ gdb_test "step" "mainshr1 \\(g=4\\) at.*return 2.g;" \
# Start with a fresh gdb.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# PR's 16495, 18213
# test that we can re-set breakpoints in shared libraries
diff --git a/gdb/testsuite/gdb.base/shlib-unload.exp b/gdb/testsuite/gdb.base/shlib-unload.exp
index 9d47416..0e1369e 100644
--- a/gdb/testsuite/gdb.base/shlib-unload.exp
+++ b/gdb/testsuite/gdb.base/shlib-unload.exp
@@ -69,7 +69,8 @@ proc_with_prefix test_bp_modified_events {} {
return
}
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if {![runto_main]} {
return
@@ -114,7 +115,8 @@ proc_with_prefix test_bp_modified_events {} {
# Check that GDB disables dprintf breakpoints within a shared library
# when the shared library is unloaded.
proc_with_prefix test_dprintf_after_unload {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if {![runto_main]} {
return
@@ -143,7 +145,8 @@ proc_with_prefix test_dprintf_after_unload {} {
# inferior. We should not get an error about re-setting the dprintf
# breakpoint.
proc_with_prefix test_dprintf_with_rerun {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if {![runto_main]} {
return
@@ -238,7 +241,8 @@ proc_with_prefix test_silent_nosharedlib {} {
}
foreach_with_prefix type { breakpoint dprintf } {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/shreloc.exp b/gdb/testsuite/gdb.base/shreloc.exp
index 8ab64a8..2bd79af 100644
--- a/gdb/testsuite/gdb.base/shreloc.exp
+++ b/gdb/testsuite/gdb.base/shreloc.exp
@@ -65,7 +65,8 @@ if { [gdb_compile_shlib $lib1src $lib1_sl $lib_opts] != ""} {
# Start with a fresh gdb.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_load_shlib $lib1_sl
gdb_load_shlib $lib2_sl
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/sigaltstack.exp b/gdb/testsuite/gdb.base/sigaltstack.exp
index 978ddeb..47013a0 100644
--- a/gdb/testsuite/gdb.base/sigaltstack.exp
+++ b/gdb/testsuite/gdb.base/sigaltstack.exp
@@ -33,7 +33,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
}
# get things started
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
# Pass all the alarms straight through (but verbosely)
gdb_test "handle SIGALRM print pass nostop"
diff --git a/gdb/testsuite/gdb.base/sigchld.exp b/gdb/testsuite/gdb.base/sigchld.exp
index 51d41c3..4011241 100644
--- a/gdb/testsuite/gdb.base/sigchld.exp
+++ b/gdb/testsuite/gdb.base/sigchld.exp
@@ -24,7 +24,8 @@ if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
runto_main
diff --git a/gdb/testsuite/gdb.base/siginfo-obj.exp b/gdb/testsuite/gdb.base/siginfo-obj.exp
index d63febb..52f7140 100644
--- a/gdb/testsuite/gdb.base/siginfo-obj.exp
+++ b/gdb/testsuite/gdb.base/siginfo-obj.exp
@@ -118,7 +118,8 @@ with_test_prefix "validate modified siginfo fields" {
# Test siginfo preservation in core files.
if {$gcore_created} {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_test "core $gcorefile" "Core was generated by.*" \
"core [file tail $gcorefile]"
diff --git a/gdb/testsuite/gdb.base/siginfo-thread.exp b/gdb/testsuite/gdb.base/siginfo-thread.exp
index bf0d58c..270b4e1 100644
--- a/gdb/testsuite/gdb.base/siginfo-thread.exp
+++ b/gdb/testsuite/gdb.base/siginfo-thread.exp
@@ -27,7 +27,8 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" \
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Advance to main
if {![runto_main]} {
@@ -92,7 +93,8 @@ gdb_test "p \$_siginfo.si_signo == $ssi_signo" " = 0" \
# Test siginfo preservation in core files.
if {$gcore_created} {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_test "core $gcorefile" "Core was generated by.*" \
"core [file tail $gcorefile]"
diff --git a/gdb/testsuite/gdb.base/signals-state-child.exp b/gdb/testsuite/gdb.base/signals-state-child.exp
index 608951f..00ad7f5 100644
--- a/gdb/testsuite/gdb.base/signals-state-child.exp
+++ b/gdb/testsuite/gdb.base/signals-state-child.exp
@@ -97,7 +97,8 @@ remote_close target
# Now run the program through gdb, and dump its initial signal actions
# and mask in "gdb.txt".
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return -1
diff --git a/gdb/testsuite/gdb.base/signals.exp b/gdb/testsuite/gdb.base/signals.exp
index d311361..5ff1e38 100644
--- a/gdb/testsuite/gdb.base/signals.exp
+++ b/gdb/testsuite/gdb.base/signals.exp
@@ -58,7 +58,8 @@ proc test_handle_all_print {} {
}
test_handle_all_print
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
if {[runto_main]} {
diff --git a/gdb/testsuite/gdb.base/signull.exp b/gdb/testsuite/gdb.base/signull.exp
index 478e471..9ad772f 100644
--- a/gdb/testsuite/gdb.base/signull.exp
+++ b/gdb/testsuite/gdb.base/signull.exp
@@ -37,7 +37,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debu
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
#
# Run to `main' where we begin our tests.
diff --git a/gdb/testsuite/gdb.base/sigrepeat.exp b/gdb/testsuite/gdb.base/sigrepeat.exp
index 9afa346..8fa92af 100644
--- a/gdb/testsuite/gdb.base/sigrepeat.exp
+++ b/gdb/testsuite/gdb.base/sigrepeat.exp
@@ -30,7 +30,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
}
# get things started
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
# Advance to main
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.base/sigstep.exp b/gdb/testsuite/gdb.base/sigstep.exp
index b49105c..2df5dd0 100644
--- a/gdb/testsuite/gdb.base/sigstep.exp
+++ b/gdb/testsuite/gdb.base/sigstep.exp
@@ -40,7 +40,8 @@ set other_handler_location [gdb_get_line_number "other handler location"]
proc restart {} {
global binfile
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_test "display/i \$pc"
diff --git a/gdb/testsuite/gdb.base/skip.exp b/gdb/testsuite/gdb.base/skip.exp
index 016e5eb..0c84cf9 100644
--- a/gdb/testsuite/gdb.base/skip.exp
+++ b/gdb/testsuite/gdb.base/skip.exp
@@ -309,7 +309,8 @@ with_test_prefix "step using -fi + -fu" {
with_test_prefix "skip delete completion" {
global binfile
- clean_restart "${binfile}"
+ clean_restart
+ gdb_load $binfile
if ![runto_main] {
return
}
diff --git a/gdb/testsuite/gdb.base/so-impl-ld.exp b/gdb/testsuite/gdb.base/so-impl-ld.exp
index d5c4143..1e309e5 100644
--- a/gdb/testsuite/gdb.base/so-impl-ld.exp
+++ b/gdb/testsuite/gdb.base/so-impl-ld.exp
@@ -33,7 +33,8 @@ if { [gdb_compile_shlib $libsrc $lib_sl $lib_opts] != ""
# Start with a fresh gdb
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_load_shlib $lib_sl
# This program implicitly loads SOM shared libraries.
diff --git a/gdb/testsuite/gdb.base/solib-abort.exp b/gdb/testsuite/gdb.base/solib-abort.exp
index 2f6d636..ab162a9 100644
--- a/gdb/testsuite/gdb.base/solib-abort.exp
+++ b/gdb/testsuite/gdb.base/solib-abort.exp
@@ -38,7 +38,8 @@ if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} $lib_flags] != ""
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.base/solib-disc.exp b/gdb/testsuite/gdb.base/solib-disc.exp
index ba7dcce..880f632 100644
--- a/gdb/testsuite/gdb.base/solib-disc.exp
+++ b/gdb/testsuite/gdb.base/solib-disc.exp
@@ -44,7 +44,8 @@ if { [gdb_compile_shlib $libsrc $libobj {debug}] != ""
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_load_shlib $libobj
if {![runto_main]} {
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/solib-symbol.exp b/gdb/testsuite/gdb.base/solib-symbol.exp
index f3ca612..4d3494c 100644
--- a/gdb/testsuite/gdb.base/solib-symbol.exp
+++ b/gdb/testsuite/gdb.base/solib-symbol.exp
@@ -34,7 +34,8 @@ if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} $lib_flags] != ""
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_load_shlib $binfile_lib
# Set a breakpoint in the binary.
diff --git a/gdb/testsuite/gdb.base/solib-weak.exp b/gdb/testsuite/gdb.base/solib-weak.exp
index 2d75a91..511ef37 100644
--- a/gdb/testsuite/gdb.base/solib-weak.exp
+++ b/gdb/testsuite/gdb.base/solib-weak.exp
@@ -84,7 +84,8 @@ proc do_test { lib1opts lib2opts lib1first } {
}
with_test_prefix $testopts {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_load_shlib $lib1
gdb_load_shlib $lib2
diff --git a/gdb/testsuite/gdb.base/source-dir.exp b/gdb/testsuite/gdb.base/source-dir.exp
index b2bf78c..e07a117 100644
--- a/gdb/testsuite/gdb.base/source-dir.exp
+++ b/gdb/testsuite/gdb.base/source-dir.exp
@@ -62,7 +62,7 @@ proc test_truncated_comp_dir {} {
# /some/path/to/gdb/build/testsuite/
# We are going to copy the source file out of the source tree into
# a location like this:
- # /some/path/to/gdb/build/testsuite/output/gdb.base/soure-dir/
+ # /some/path/to/gdb/build/testsuite/output/gdb.base/source-dir/
#
# We will then switch to this directory and compile the source
# file, however, we will ask GCC to remove this prefix from the
@@ -87,11 +87,12 @@ proc test_truncated_comp_dir {} {
return
}
- set working_dir [standard_output_file ""]
+ set working_dir [build_standard_output_file ""]
with_cwd $working_dir {
- set strip_dir [file normalize "${working_dir}/../.."]
+ set strip_dir [build_file_normalize "${working_dir}/../.."]
+ set h_strip_dir [host_file_normalize $strip_dir]
- set new_srcfile [standard_output_file ${srcfile}]
+ set new_srcfile [build_standard_output_file ${srcfile}]
set fd [open "$new_srcfile" w]
puts $fd "int
main ()
@@ -100,8 +101,17 @@ proc test_truncated_comp_dir {} {
}"
close $fd
+ # We ask GCC to remove both the build and host views of the
+ # path, because we don't know which one GCC uses. E.g., we're
+ # testing on MSYS2 with an MSYS2 cross-compiler that targets
+ # MinGW, then the path GCC uses is a Unix path. If OTOH we're
+ # testing on MSYS2 with a native Windows compiler, then the
+ # path GCC uses is a Windows path.
set options \
- "debug additional_flags=-fdebug-prefix-map=${strip_dir}="
+ [list \
+ "debug" \
+ "additional_flags=-fdebug-prefix-map=${strip_dir}=" \
+ "additional_flags=-fdebug-prefix-map=${h_strip_dir}="]
if { [gdb_compile "${srcfile}" "${binfile}" \
executable ${options}] != "" } {
untested "failed to compile"
@@ -109,7 +119,8 @@ proc test_truncated_comp_dir {} {
}
}
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
if { [ishost *-*-mingw*] } {
gdb_test_no_output "set directories \$cdir;\$cwd"
@@ -133,9 +144,9 @@ proc test_truncated_comp_dir {} {
"Does not include preprocessor macro info." ] \
"info source before setting directory search list"
- gdb_test "dir $strip_dir" \
+ gdb_test "dir $h_strip_dir" \
[search_dir_list [list \
- "$strip_dir" \
+ "$h_strip_dir" \
"\\\$cdir" \
"\\\$cwd"]] \
"setup source path search directory"
@@ -146,17 +157,23 @@ proc test_truncated_comp_dir {} {
"4\[ \t\]+return 0;" \
"5\[ \t\]+\\}" ]
- gdb_test "info source" \
- [multi_line \
- "Current source file is ${srcfile}" \
- "Compilation directory is \[^\n\r\]+" \
- "Located in ${new_srcfile}" \
- "Contains 5 lines." \
- "Source language is c." \
- "Producer is \[^\n\r\]+" \
- "\[^\n\r\]+" \
- "\[^\n\r\]+" ] \
- "info source after setting directory search list"
+ set re [multi_line \
+ "Current source file is ${srcfile}" \
+ "Compilation directory is \[^\n\r\]+" \
+ "Located in (\[^\n\r\]+)" \
+ "Contains 5 lines." \
+ "Source language is c." \
+ "Producer is \[^\n\r\]+" \
+ "\[^\n\r\]+" \
+ "\[^\n\r\]+"]
+ set test "info source after setting directory search list"
+ gdb_test_multiple "info source" $test {
+ -re -wrap "$re" {
+ set host_new_srcfile [host_file_normalize $new_srcfile]
+ set host_location [host_file_sanitize $expect_out(1,string)]
+ gdb_assert {$host_new_srcfile eq $host_location} $gdb_test_name
+ }
+ }
}
proc test_change_search_directory_with_empty_dirname {} {
diff --git a/gdb/testsuite/gdb.base/source-search.c b/gdb/testsuite/gdb.base/source-search.c
new file mode 100644
index 0000000..2320c5c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/source-search.c
@@ -0,0 +1,127 @@
+/* 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/>. */
+
+int
+main (void)
+{
+ /* Line 21 */
+ /* Line 22 */
+ /* Line 23 */
+ /* Line 24 */
+ /* Line 25 */
+ /* Line 26 */
+ /* Line 27 */
+ /* Line 28 */
+ /* Line 29 */
+ /* Line 30 */
+ /* Line 31 */
+ /* Line 32 */
+ /* Line 33 */
+ /* Line 34 */
+ /* Line 35 */
+ /* Line 36 */
+ /* Line 37 */
+ /* Line 38 */
+ /* Line 39 */
+ /* Line 40 */
+ /* Line 41 */
+ /* Line 42 */
+ /* Line 43 */
+ /* Line 44 */
+ /* Line 45 */
+ /* Line 46 */
+ /* Line 47 */
+ /* Line 48 */
+ /* Line 49 */
+ /* Line 50 */
+ /* Line 51 */
+ /* Line 52 */
+ /* Line 53 */
+ /* Line 54 */
+ /* Line 55 */
+ /* Line 56 */
+ /* Line 57 */
+ /* Line 58 */
+ /* Line 59 */
+ /* Line 60 */
+ /* Line 61 */
+ /* Line 62 */
+ /* Line 63 */
+ /* Line 64 */
+ /* Line 65 */
+ /* Line 66 */
+ /* Line 67 */
+ /* Line 68 */
+ /* Line 69 */
+ /* Line 70 */
+ /* Line 71 */
+ /* Line 72 */
+ /* Line 73 */
+ /* Line 74 */
+ /* Line 75 */
+ /* Line 76 */
+ /* Line 77 */
+ /* Line 78 */
+ /* Line 79 */
+ /* Line 80 */
+ /* Line 81 */
+ /* Line 82 */
+ /* Line 83 */
+ /* Line 84 */
+ /* Line 85 */
+ /* Line 86 */
+ /* Line 87 */
+ /* Line 88 */
+ /* Line 89 */
+ /* Line 90 */
+ /* Line 91 */
+ /* Line 92 */
+ /* Line 93 */
+ /* Line 94 */
+ /* Line 95 */
+ /* Line 96 */
+ /* Line 97 */
+ /* Line 98 */
+ /* Line 99 */
+ /* Line 100 */
+ /* Line 101 */
+ /* Line 102 */
+ /* Line 103 */
+ /* Line 104 */
+ /* Line 105 */
+ /* Line 106 */
+ /* Line 107 */
+ /* Line 108 */
+ /* Line 109 */
+ /* Line 110 */
+ /* Line 111 */
+ /* Line 112 */
+ /* Line 113 */
+ /* Line 114 */
+ /* Line 115 */
+ /* Line 116 */
+ /* Line 117 */
+ /* Line 118 */
+ /* Line 119 */
+ /* Line 120 */
+ /* Line 121 */
+ /* Line 122 */
+ /* Line 123 */
+ /* Line 124 */
+ /* Line 125 */
+ return 0;
+} /* Last line. */
diff --git a/gdb/testsuite/gdb.base/source-search.exp b/gdb/testsuite/gdb.base/source-search.exp
new file mode 100644
index 0000000..559c500
--- /dev/null
+++ b/gdb/testsuite/gdb.base/source-search.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/>.
+
+# Test 'forward-search' and 'reverse-search' commands. This test
+# relies on some hard-coded line numbers relating to the source file.
+# We could switch to using gdb_get_line_number, but it doesn't feel
+# like that would add much value; just don't change the source file.
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+ return
+}
+
+gdb_test "forward-search This testcase is part" \
+ "1\\s+/\\* This testcase is part of GDB, the GNU debugger\\." \
+ "search for first line of the file"
+
+gdb_test "forward-search This testcase is part" \
+ "Expression not found" \
+ "repeated search doesn't find the same first line"
+
+# The 'reverse-search' command starts searching from the line before
+# the last line displayed. So in this case, the reverse search starts
+# from line 0, i.e. nothing is searched.
+gdb_test "reverse-search This testcase is part" \
+ "Expression not found" \
+ "reverse search doesn't find the first line either"
+
+# List some source lines, and then perform some forward-searches. The
+# searches start from the first line after the last line displayed.
+gdb_test "list 20" ".*" \
+ "list source code ahead of a forward-search"
+gdb_test "forward-search Line 2" \
+ "25\\s+/\\* Line 25 \\*/" \
+ "first forward-search after a list"
+gdb_test "forward-search Line 2" \
+ "26\\s+/\\* Line 26 \\*/" \
+ "second forward-search after a list"
+gdb_test "forward-search Line 2" \
+ "27\\s+/\\* Line 27 \\*/" \
+ "third forward-search after a list"
+
+# Now reverse-search from where we got too.
+gdb_test "reverse-search Line 2" \
+ "26\\s+/\\* Line 26 \\*/" \
+ "first reverse-search for 'Line 2'"
+gdb_test "reverse-search Line 2" \
+ "25\\s+/\\* Line 25 \\*/" \
+ "second reverse-search for 'Line 2'"
+gdb_test "reverse-search Line 2" \
+ "24\\s+/\\* Line 24 \\*/" \
+ "third reverse-search for 'Line 2'"
+
+# List some source lines, and then perform a reverse-search. The
+# search starts frm the first line before the last line displayed.
+gdb_test "list 20" ".*" \
+ "list source code ahead of a reverse-search"
+gdb_test "reverse-search Line 2" \
+ "23\\s+/\\* Line 23 \\*/" \
+ "reverse-search after a list"
+
+# List the last lines of the file, then reverse search for the last
+# line. As reverse-search starts on the line before the last line
+# displayed, this will fail to find the last line.
+gdb_test "list 127"
+gdb_test "reverse-search Last line" \
+ "Expression not found" \
+ "reverse search for the last line fails"
+
+# List some lines from the middle of the file. Then try an invalid
+# 'list' command. Finally, check searches pick up from the middle of
+# the file where the first 'list' successfully completed.
+foreach_with_prefix search_direction { forward reverse } {
+ foreach_with_prefix bad_list { out-of-range backwards } {
+ gdb_test "list 50"
+
+ if { $bad_list eq "out-of-range" } {
+ gdb_test "list 1000" \
+ "Line number 995 out of range; \[^\r\n\]+ has 127 lines\\."
+ } else {
+ gdb_test_no_output "list 60,50"
+ }
+
+ if { $search_direction eq "forward" } {
+ set line 55
+ } else {
+ set line 53
+ }
+
+ gdb_test "${search_direction}-search Line" \
+ "$line\\s+/\\* Line $line \\*/"
+ }
+}
diff --git a/gdb/testsuite/gdb.base/stack-checking.exp b/gdb/testsuite/gdb.base/stack-checking.exp
index 5e55b43..15fc677 100644
--- a/gdb/testsuite/gdb.base/stack-checking.exp
+++ b/gdb/testsuite/gdb.base/stack-checking.exp
@@ -21,7 +21,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [con
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.base/startup-with-shell.exp b/gdb/testsuite/gdb.base/startup-with-shell.exp
index 80dfdf3..a6ebb57 100644
--- a/gdb/testsuite/gdb.base/startup-with-shell.exp
+++ b/gdb/testsuite/gdb.base/startup-with-shell.exp
@@ -22,6 +22,8 @@ require !use_gdb_stub
# (via dejagnu) yet.
require {!is_remote target}
+require {expr [have_startup_shell] != -1}
+
standard_testfile
if { [build_executable "failed to prepare" $testfile $srcfile debug] } {
@@ -40,7 +42,8 @@ run_on_host \
proc initial_setup_simple { startup_with_shell run_args } {
global hex decimal binfile unique_file
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_test_no_output "set startup-with-shell $startup_with_shell"
gdb_test_no_output "set print characters unlimited"
@@ -91,73 +94,97 @@ proc run_test_same { args re testname } {
run_test $args $re $re $testname
}
-# The regexp to match a single '\' character.
-set bs "\\\\"
-
-# Are we using 'remote' or 'extended-remote' protocol?
-set is_remote_p [gdb_protocol_is_remote]
-
-## Run the actual tests
-
-run_test "$unique_file_dir/*.unique-extension" \
- "\"$unique_file\"" \
- "\"$unique_file_dir/\\\*\.unique-extension\"" \
- "arg is glob" \
- $is_remote_p
-
-run_test_same "$unique_file_dir/\\*.unique-extension" \
- "\"$unique_file_dir/\\\*\.unique-extension\"" \
- "arg is escaped glob"
-
-save_vars { env(TEST) } {
- set env(TEST) "1234"
- run_test "\$TEST" \
- "\"1234\"" \
- "\"\\\$TEST\"" \
- "arg is shell variable" \
- $is_remote_p
+# Run the actual tests
+proc run_all_tests { { is_remote_with_split_args false } } {
+ # The regexp to match a single '\' character.
+ set bs "\\\\"
+
+ run_test "$::unique_file_dir/*.unique-extension" \
+ "\"$::unique_file\"" \
+ "\"$::unique_file_dir/\\\*\.unique-extension\"" \
+ "arg is glob" \
+ $is_remote_with_split_args
+
+ run_test_same "$::unique_file_dir/\\*.unique-extension" \
+ "\"$::unique_file_dir/\\\*\.unique-extension\"" \
+ "arg is escaped glob"
+
+ save_vars { ::env(TEST) } {
+ set ::env(TEST) "1234"
+ run_test "\$TEST" \
+ "\"1234\"" \
+ "\"\\\$TEST\"" \
+ "arg is shell variable" \
+ $is_remote_with_split_args
+
+ run_test_same "\\\$TEST" \
+ "\"\\\$TEST\"" \
+ "arg is escaped shell variable"
+ }
- run_test_same "\\\$TEST" \
- "\"\\\$TEST\"" \
- "arg is escaped shell variable"
+ run_test "\$(echo foo)" \
+ "\"foo\"" \
+ "\"\\\$\\(echo\"" \
+ "arg is parameter expansion, command execution" \
+ $is_remote_with_split_args
+
+ run_test "\$((2 + 3))" \
+ "\"5\"" \
+ "\"\\\$\\(\\(2\"" \
+ "arg is parameter expansion, expression evaluation" \
+ $is_remote_with_split_args
+
+ run_test_same "\"\\a\"" \
+ "\"${bs}${bs}a\"" \
+ "retain backslash in double quote arg"
+
+ run_test_same "'\\a'" \
+ "\"${bs}${bs}a\"" \
+ "retain backslash in single quote arg"
+
+ run_test_same "\"\\\$\"" \
+ "\"\\\$\"" \
+ "'\$' can be escaped in double quote arg"
+
+ run_test_same "'\\\$'" \
+ "\"${bs}${bs}\\\$\"" \
+ "'\$' is not escaped in single quote arg"
+
+ run_test_same "\"\\`\"" \
+ "\"\\`\"" \
+ "'`' can be escaped in double quote arg"
+
+ run_test_same "'\\`'" \
+ "\"${bs}${bs}`\"" \
+ "'`' is not escaped in single quote arg"
+
+ run_test_same "\"\\\"\"" \
+ "\"${bs}\"\"" \
+ "'\"' can be escaped in double quote arg"
+
+ run_test_same "'\\\"'" \
+ "\"${bs}${bs}${bs}\"\"" \
+ "'\"' is not escaped in single quote arg"
+
+ run_test_same "\"\\\\\"" \
+ "\"${bs}${bs}\"" \
+ "'\\' can be escaped in double quote arg"
+
+ run_test_same "'\\\\'" \
+ "\"${bs}${bs}${bs}${bs}\"" \
+ "'\\' is not escaped in single quote arg"
}
-run_test_same "\"\\a\"" \
- "\"${bs}${bs}a\"" \
- "retain backslash in double quote arg"
-
-run_test_same "'\\a'" \
- "\"${bs}${bs}a\"" \
- "retain backslash in single quote arg"
-
-run_test_same "\"\\\$\"" \
- "\"\\\$\"" \
- "'\$' can be escaped in double quote arg"
+run_all_tests
-run_test_same "'\\\$'" \
- "\"${bs}${bs}\\\$\"" \
- "'\$' is not escaped in single quote arg"
-
-run_test_same "\"\\`\"" \
- "\"\\`\"" \
- "'`' can be escaped in double quote arg"
-
-run_test_same "'\\`'" \
- "\"${bs}${bs}`\"" \
- "'`' is not escaped in single quote arg"
-
-run_test_same "\"\\\"\"" \
- "\"${bs}\"\"" \
- "'\"' can be escaped in double quote arg"
-
-run_test_same "'\\\"'" \
- "\"${bs}${bs}${bs}\"\"" \
- "'\"' is not escaped in single quote arg"
-
-run_test_same "\"\\\\\"" \
- "\"${bs}${bs}\"" \
- "'\\' can be escaped in double quote arg"
-
-run_test_same "'\\\\'" \
- "\"${bs}${bs}${bs}${bs}\"" \
- "'\\' is not escaped in single quote arg"
+# For extended-remote targets, disable the packet which passes
+# inferior arguments as a single string. This changes how the vRun
+# (extended-remote only) packet works.
+if {[target_info gdb_protocol] == "extended-remote"} {
+ with_test_prefix "single-inferior-arg disabled" {
+ save_vars { GDBFLAGS } {
+ append GDBFLAGS " -ex \"set remote single-inferior-argument-feature-packet off\""
+ run_all_tests true
+ }
+ }
+}
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/step-over-no-symbols.exp b/gdb/testsuite/gdb.base/step-over-no-symbols.exp
index 2eb8efe..1a91986 100644
--- a/gdb/testsuite/gdb.base/step-over-no-symbols.exp
+++ b/gdb/testsuite/gdb.base/step-over-no-symbols.exp
@@ -47,7 +47,8 @@ proc test_step_over { displaced } {
global hex
global binfile
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if ![runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.base/step-sw-breakpoint-adjust-pc.exp b/gdb/testsuite/gdb.base/step-sw-breakpoint-adjust-pc.exp
index 2dc67ea..2dde3bb 100644
--- a/gdb/testsuite/gdb.base/step-sw-breakpoint-adjust-pc.exp
+++ b/gdb/testsuite/gdb.base/step-sw-breakpoint-adjust-pc.exp
@@ -36,7 +36,8 @@ proc test {non_stop displaced always_inserted} {
save_vars { GDBFLAGS } {
set GDBFLAGS "$GDBFLAGS -ex \"set non-stop $non_stop\""
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
}
gdb_test_no_output "set displaced-stepping $displaced"
diff --git a/gdb/testsuite/gdb.base/step-test.exp b/gdb/testsuite/gdb.base/step-test.exp
index 28eccf7..39833a3 100644
--- a/gdb/testsuite/gdb.base/step-test.exp
+++ b/gdb/testsuite/gdb.base/step-test.exp
@@ -24,7 +24,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debu
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.base/structs.exp b/gdb/testsuite/gdb.base/structs.exp
index 31a45b5..fa7f786 100644
--- a/gdb/testsuite/gdb.base/structs.exp
+++ b/gdb/testsuite/gdb.base/structs.exp
@@ -56,7 +56,7 @@ proc start_structs_test { types } {
}
set binfile [standard_output_file ${testfile}]
- if { [prepare_for_testing "failed to prepare" $binfile $srcfile $flags] } {
+ if { [prepare_for_testing "failed to prepare" $testfile $srcfile $flags] } {
return -1
}
diff --git a/gdb/testsuite/gdb.base/structs2.exp b/gdb/testsuite/gdb.base/structs2.exp
index 8ccd50d..f377022 100644
--- a/gdb/testsuite/gdb.base/structs2.exp
+++ b/gdb/testsuite/gdb.base/structs2.exp
@@ -15,7 +15,7 @@
standard_testfile .c
-if { [prepare_for_testing "failed to prepare" $binfile $srcfile {debug}] } {
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile {debug}] } {
return -1
}
diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
index 59c93ee..6ab16ca 100644
--- a/gdb/testsuite/gdb.base/style.exp
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -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/>.
+require {!is_remote host}
+
load_lib gdb-python.exp
# Test CLI output styling.
@@ -75,7 +77,7 @@ proc run_style_tests { } {
# Restart GDB with the correct TERM variable setting, this
# means that GDB will enable styling.
- clean_restart_and_disable "restart 1" ${binfile}
+ clean_restart_and_disable "restart 1" $::testfile
set readnow [readnow]
@@ -323,12 +325,24 @@ proc run_style_tests { } {
gdb_test_no_output "set style version background 255"
gdb_test_no_output "set style version foreground #FED210"
gdb_test "show style version background" \
- "The \033\\\[38;2;254;210;16;48;5;255;22;27m.*\".*version.*\".*style.*\033\\\[m background color is: 255" \
+ "The \033\\\[38;2;254;210;16;48;5;255;22;23;24;27m.*\".*version.*\".*style.*\033\\\[m background color is: 255" \
"Version's 256-color background style"
gdb_test "show style version foreground" \
- "The \033\\\[38;2;254;210;16;48;5;255;22;27m.*\".*version.*\".*style.*\033\\\[m foreground color is: #FED210" \
+ "The \033\\\[38;2;254;210;16;48;5;255;22;23;24;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"
}
}
@@ -344,7 +358,7 @@ proc test_disable_disassembler_styling { } {
# Restart GDB with the correct TERM variable setting, this
# means that GDB will enable styling.
- clean_restart_and_disable "restart 3" $::binfile
+ clean_restart_and_disable "restart 3" $::testfile
set styled_hex [limited_style $::hex address]
set main [limited_style main function]
@@ -459,7 +473,7 @@ proc test_disassembler_error_handling { } {
# Restart GDB with the correct TERM variable setting, this
# means that GDB will enable styling.
- clean_restart_and_disable "restart 4" $::binfile
+ clean_restart_and_disable "restart 4" $::testfile
# Disable use of libopcodes for styling. As this function is
# only called when Python Pygments module is available, we
@@ -739,10 +753,293 @@ 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;23;24;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;23;24;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 \033" $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
+ gdb_load $::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
+ }
+ }
+
+ if { $desired_width < [string length $::pagination_prompt_str] + 2 } {
+ # Avoid readline wrapping after printing the pagination prompt.
+ return
+ }
+
+ # Now setup the screen width.
+ gdb_test_no_output "set width $desired_width" \
+ "set width to 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
+ gdb_load $::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;23;24;27m(?:ax)+\033\\\[m" {
+ exp_continue
+ }
+
+ -re "^\r\n\033\\\[32;49;22;23;24;27m(?:ax)+\033\\\[m(?=--)" {
+ exp_continue
+ }
+
+ -re "^\r\n\033\\\[32;49;22;23;24;27m(?:ax)+(?=--)" {
+ set saw_bad_styling true
+ exp_continue
+ }
+
+ -re "^\r\n\033\\\[32;49;22;23;24;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.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {[allow_python_tests] && [gdb_py_module_available "pygments"]} {
set python_disassembly_styling true
} else {
@@ -781,3 +1078,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/sym-file.exp b/gdb/testsuite/gdb.base/sym-file.exp
index 8197c0e..13febda 100644
--- a/gdb/testsuite/gdb.base/sym-file.exp
+++ b/gdb/testsuite/gdb.base/sym-file.exp
@@ -61,7 +61,8 @@ if {[gdb_compile_shlib $libsrc $lib_so {debug}] != ""} {
return
}
-if {[prepare_for_testing "failed to prepare" $binfile "$srcfile $srcfile2" $exec_opts]} {
+if { [prepare_for_testing "failed to prepare" $testfile "$srcfile $srcfile2" \
+ $exec_opts] } {
return
}
@@ -70,7 +71,8 @@ gdb_load_shlib ${lib_so}
proc do_test { remove_expr } {
global lib_basename lib_syms srcfile srcfile3
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/symtab-search-order.exp b/gdb/testsuite/gdb.base/symtab-search-order.exp
index cf0d507..34b1db0 100644
--- a/gdb/testsuite/gdb.base/symtab-search-order.exp
+++ b/gdb/testsuite/gdb.base/symtab-search-order.exp
@@ -33,7 +33,8 @@ if { [gdb_compile_shlib $lib1src $lib1 $lib_opts] != ""
# Start with a fresh gdb.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_load_shlib $lib1
if ![runto_main] {
diff --git a/gdb/testsuite/gdb.base/testenv.exp b/gdb/testsuite/gdb.base/testenv.exp
index beb59d2..59cd33c 100644
--- a/gdb/testsuite/gdb.base/testenv.exp
+++ b/gdb/testsuite/gdb.base/testenv.exp
@@ -27,7 +27,7 @@ standard_testfile .c
# Compile binary
# and start with a fresh gdb
-if { [prepare_for_testing "failed to prepare" ${binfile} ${srcfile}] } {
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
return -1
}
@@ -90,7 +90,8 @@ proc find_env {varname} {
proc_with_prefix test_set_unset_env {} {
global binfile
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
# First test with no TEST_GDB_VAR.
with_test_prefix "test1" {
@@ -151,7 +152,8 @@ proc_with_prefix test_inherit_env_var {} {
save_vars {env(TEST_GDB_GLOBAL)} {
set env(TEST_GDB_GLOBAL) "Global environment value"
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
gdb_breakpoint $bp_line
diff --git a/gdb/testsuite/gdb.base/tls-common.exp.tcl b/gdb/testsuite/gdb.base/tls-common.exp.tcl
index 7aa7f46..fc212a9 100644
--- a/gdb/testsuite/gdb.base/tls-common.exp.tcl
+++ b/gdb/testsuite/gdb.base/tls-common.exp.tcl
@@ -1,4 +1,4 @@
-# Copyright 2024 Free Software Foundation, Inc.
+# Copyright 2024-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
diff --git a/gdb/testsuite/gdb.base/tls-dlobj-lib.c b/gdb/testsuite/gdb.base/tls-dlobj-lib.c
index c69bab7..e82a064 100644
--- a/gdb/testsuite/gdb.base/tls-dlobj-lib.c
+++ b/gdb/testsuite/gdb.base/tls-dlobj-lib.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-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
diff --git a/gdb/testsuite/gdb.base/tls-dlobj.c b/gdb/testsuite/gdb.base/tls-dlobj.c
index 322bdda..a93f4a7 100644
--- a/gdb/testsuite/gdb.base/tls-dlobj.c
+++ b/gdb/testsuite/gdb.base/tls-dlobj.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-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
diff --git a/gdb/testsuite/gdb.base/tls-dlobj.exp b/gdb/testsuite/gdb.base/tls-dlobj.exp
index 02f2ff8..1509ec8 100644
--- a/gdb/testsuite/gdb.base/tls-dlobj.exp
+++ b/gdb/testsuite/gdb.base/tls-dlobj.exp
@@ -1,4 +1,4 @@
-# Copyright 2024 Free Software Foundation, Inc.
+# Copyright 2024-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
@@ -56,7 +56,8 @@ proc gdb_test_with_xfail { cmd re cond} {
}
proc do_tests {force_internal_tls} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if ![runto_main] {
return
}
@@ -288,7 +289,8 @@ proc do_tests {force_internal_tls} {
return
}
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
set core_loaded [gdb_core_cmd $corefile "load corefile"]
if { $core_loaded == -1 } {
diff --git a/gdb/testsuite/gdb.base/tls-multiobj.c b/gdb/testsuite/gdb.base/tls-multiobj.c
index 10e67da..dd4aadb 100644
--- a/gdb/testsuite/gdb.base/tls-multiobj.c
+++ b/gdb/testsuite/gdb.base/tls-multiobj.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-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
diff --git a/gdb/testsuite/gdb.base/tls-multiobj.exp b/gdb/testsuite/gdb.base/tls-multiobj.exp
index 97acb33..eb3721e 100644
--- a/gdb/testsuite/gdb.base/tls-multiobj.exp
+++ b/gdb/testsuite/gdb.base/tls-multiobj.exp
@@ -1,4 +1,4 @@
-# Copyright 2024 Free Software Foundation, Inc.
+# Copyright 2024-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
@@ -26,7 +26,8 @@ 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
+ clean_restart
+ gdb_load $::binfile
if ![runto_main] {
return
}
@@ -128,7 +129,8 @@ proc do_tests {force_internal_tls {do_kfail_tls_access 0}} {
return
}
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
set core_loaded [gdb_core_cmd $corefile "load corefile"]
if { $core_loaded == -1 } {
diff --git a/gdb/testsuite/gdb.base/tls-multiobj1.c b/gdb/testsuite/gdb.base/tls-multiobj1.c
index 86e7222..6207173 100644
--- a/gdb/testsuite/gdb.base/tls-multiobj1.c
+++ b/gdb/testsuite/gdb.base/tls-multiobj1.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-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
diff --git a/gdb/testsuite/gdb.base/tls-multiobj2.c b/gdb/testsuite/gdb.base/tls-multiobj2.c
index cea0709..9ff8b67 100644
--- a/gdb/testsuite/gdb.base/tls-multiobj2.c
+++ b/gdb/testsuite/gdb.base/tls-multiobj2.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-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
diff --git a/gdb/testsuite/gdb.base/tls-multiobj3.c b/gdb/testsuite/gdb.base/tls-multiobj3.c
index bb0f239..3594eba0 100644
--- a/gdb/testsuite/gdb.base/tls-multiobj3.c
+++ b/gdb/testsuite/gdb.base/tls-multiobj3.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-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
diff --git a/gdb/testsuite/gdb.base/tls-nothreads.c b/gdb/testsuite/gdb.base/tls-nothreads.c
index b3aaa33..cac20f8 100644
--- a/gdb/testsuite/gdb.base/tls-nothreads.c
+++ b/gdb/testsuite/gdb.base/tls-nothreads.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-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
diff --git a/gdb/testsuite/gdb.base/tls-nothreads.exp b/gdb/testsuite/gdb.base/tls-nothreads.exp
index 92a5cd9..c7b1476 100644
--- a/gdb/testsuite/gdb.base/tls-nothreads.exp
+++ b/gdb/testsuite/gdb.base/tls-nothreads.exp
@@ -1,4 +1,4 @@
-# Copyright 2024 Free Software Foundation, Inc.
+# Copyright 2024-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
@@ -18,7 +18,8 @@ source $srcdir/$subdir/tls-common.exp.tcl
standard_testfile
proc do_tests {force_internal_tls {do_kfail_tls_access 0}} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
if ![runto_main] {
return
}
@@ -105,7 +106,8 @@ proc do_tests {force_internal_tls {do_kfail_tls_access 0}} {
set objcopy [gdb_find_objcopy]
set cmd "$objcopy --strip-debug ${::binfile} $binfile_stripped"
if ![catch "exec $cmd" cmd_output] {
- clean_restart $binfile_stripped
+ clean_restart
+ gdb_load $binfile_stripped
if ![runto_main] {
return
}
@@ -155,7 +157,8 @@ proc do_tests {force_internal_tls {do_kfail_tls_access 0}} {
return
}
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
set core_loaded [gdb_core_cmd $corefile "load corefile"]
if { $core_loaded == -1 } {
diff --git a/gdb/testsuite/gdb.base/twice.exp b/gdb/testsuite/gdb.base/twice.exp
index 6f49c46..995cd4d 100644
--- a/gdb/testsuite/gdb.base/twice.exp
+++ b/gdb/testsuite/gdb.base/twice.exp
@@ -32,7 +32,8 @@ if { [gdb_compile $local_srcfile "${binfile}" executable $options] != "" } {
# Start with a fresh gdb.
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
if {[runto_main]} {
# Test that GDB can still detect whether we have line numbers
diff --git a/gdb/testsuite/gdb.base/type-opaque.exp b/gdb/testsuite/gdb.base/type-opaque.exp
index da060b9..f5d8582 100644
--- a/gdb/testsuite/gdb.base/type-opaque.exp
+++ b/gdb/testsuite/gdb.base/type-opaque.exp
@@ -32,7 +32,8 @@ if { [gdb_compile_shlib $libsrc $libobj {debug}] != ""
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_load_shlib ${libobj}
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.base/unload.exp b/gdb/testsuite/gdb.base/unload.exp
index 0761f27..b2d848d 100644
--- a/gdb/testsuite/gdb.base/unload.exp
+++ b/gdb/testsuite/gdb.base/unload.exp
@@ -50,7 +50,8 @@ if { [gdb_compile_shlib $libsrc $lib_sl $lib_opts] != ""
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_load_shlib $lib_sl
gdb_load_shlib $lib_sl2
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/varargs.exp b/gdb/testsuite/gdb.base/varargs.exp
index a34a578..534971c 100644
--- a/gdb/testsuite/gdb.base/varargs.exp
+++ b/gdb/testsuite/gdb.base/varargs.exp
@@ -49,7 +49,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
gdb_test_no_output "set print sevenbit-strings"
gdb_test_no_output "set print address off"
gdb_test_no_output "set width 0"
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/watch_thread_num.exp b/gdb/testsuite/gdb.base/watch_thread_num.exp
index 4a5c1c2..e1b54c0 100644
--- a/gdb/testsuite/gdb.base/watch_thread_num.exp
+++ b/gdb/testsuite/gdb.base/watch_thread_num.exp
@@ -31,7 +31,8 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart
+gdb_load $binfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/watchpoint-hw-attach.exp b/gdb/testsuite/gdb.base/watchpoint-hw-attach.exp
index b3892f3..afdb82e 100644
--- a/gdb/testsuite/gdb.base/watchpoint-hw-attach.exp
+++ b/gdb/testsuite/gdb.base/watchpoint-hw-attach.exp
@@ -26,29 +26,19 @@ 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
+clean_restart
+gdb_load $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 +52,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.base/watchpoint-running.exp b/gdb/testsuite/gdb.base/watchpoint-running.exp
index 1a5f9c3..04c4c52 100644
--- a/gdb/testsuite/gdb.base/watchpoint-running.exp
+++ b/gdb/testsuite/gdb.base/watchpoint-running.exp
@@ -43,7 +43,8 @@ proc test {stop_mode hw} {
# default.
append ::GDBFLAGS " -ex \"maint set target-non-stop on\""
}
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
}
gdb_test_no_output "set can-use-hw-watchpoints $hw"
diff --git a/gdb/testsuite/gdb.base/watchpoint-solib.exp b/gdb/testsuite/gdb.base/watchpoint-solib.exp
index 28b8d08..7f58a83 100644
--- a/gdb/testsuite/gdb.base/watchpoint-solib.exp
+++ b/gdb/testsuite/gdb.base/watchpoint-solib.exp
@@ -49,7 +49,8 @@ if { [gdb_compile_shlib $libsrc $lib_sl $lib_opts] != ""
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_load_shlib $lib_sl
runto_main
diff --git a/gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.exp b/gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.exp
index 2bedcaa..163ec3b 100644
--- a/gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.exp
+++ b/gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.exp
@@ -129,7 +129,8 @@ proc test {always_inserted} {
with_test_prefix "always-inserted $always_inserted" {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/watchpoint-unaligned.c b/gdb/testsuite/gdb.base/watchpoint-unaligned.c
index d3c1349..ca2fa45 100644
--- a/gdb/testsuite/gdb.base/watchpoint-unaligned.c
+++ b/gdb/testsuite/gdb.base/watchpoint-unaligned.c
@@ -18,6 +18,8 @@
#include <stdint.h>
#include <assert.h>
+static volatile int volatile_dummy;
+
static int again;
static volatile struct
@@ -53,6 +55,40 @@ write_size8twice (void)
data.u.size8twice[offset] = first;
data.u.size8twice[offset + 1] = second;
#endif
+
+ /* Setting a breakpoint on an instruction after an instruction triggering a
+ watchpoint makes it ambiguous which one will be reported.
+ Insert a dummy instruction in between to make sure the watchpoint gets
+ reported. */
+ volatile_dummy = 1;
+
+ return; /* write_size8twice_return */
+}
+
+static void
+read_size8twice (void)
+{
+ static uint64_t volatile first;
+ static uint64_t volatile second;
+
+#ifdef __aarch64__
+ volatile void *p = &data.u.size8twice[offset];
+ asm volatile ("ldp %0, %1, [%2]"
+ : "=r" (first), "=r" (second) /* output */
+ : "r" (p) /* input */
+ : /* clobber */);
+#else
+ first = data.u.size8twice[offset];
+ second = data.u.size8twice[offset + 1];
+#endif
+
+ /* Setting a breakpoint on an instruction after an instruction triggering a
+ watchpoint makes it ambiguous which one will be reported.
+ Insert a dummy instruction inbetween to make sure the watchpoint gets
+ reported. */
+ volatile_dummy = 1;
+
+ return; /* read_size8twice_return */
}
int
@@ -63,6 +99,7 @@ main (void)
assert (sizeof (data) == 8 + 3 * 8);
write_size8twice ();
+ read_size8twice ();
while (size)
{
diff --git a/gdb/testsuite/gdb.base/watchpoint-unaligned.exp b/gdb/testsuite/gdb.base/watchpoint-unaligned.exp
index 9220402..85b1eb7 100644
--- a/gdb/testsuite/gdb.base/watchpoint-unaligned.exp
+++ b/gdb/testsuite/gdb.base/watchpoint-unaligned.exp
@@ -151,6 +151,63 @@ foreach_with_prefix wpcount {4 7} {
gdb_assert $got_hit $test
}
+proc size8twice { function cmd offset index } {
+ clean_restart $::testfile
+
+ if { ![runto $function] } {
+ return -1
+ }
+
+ # Set offset in the inferior.
+ gdb_test_no_output "set var offset = $offset"
+
+ # Set a breakpoint.
+ set bp_src_string "${function}_return"
+ set bp_loc [gdb_get_line_number $bp_src_string]
+ gdb_breakpoint $bp_loc \
+ "Breakpoint $::decimal at $::hex" "$bp_src_string"
+
+ # Set a hardware watchpoint.
+ set watch_index [expr $offset + $index]
+ set test "$cmd data.u.size8twice\[$watch_index\]"
+ set wpnum 0
+ gdb_test_multiple $test "" {
+ -re -wrap "Hardware (read )?watchpoint ($::decimal): .*" {
+ set wpnum $expect_out(2,string)
+ pass $gdb_test_name
+ }
+ -re -wrap "Watchpoint ($::decimal): .*" {
+ if {[istarget "arm*-*-*"]} {
+ untested $gdb_test_name
+ } else {
+ fail $gdb_test_name
+ }
+ }
+ }
+
+ if { ! $wpnum } {
+ # No hardware watchpoint, we're done.
+ return 0
+ }
+
+ # Try to trigger the hardware watchpoint.
+ set got_hit 0
+ gdb_test_multiple "continue" "" {
+ -re -wrap "\r\nCould not insert hardware watchpoint .*" {
+ }
+ -re -wrap "Hardware (read )?watchpoint $wpnum:.*(New value|Value) = .*" {
+ set got_hit 1
+ send_gdb "continue\n"
+ exp_continue
+ }
+ -re -wrap " $bp_src_string .*" {
+ }
+ }
+ gdb_assert { $got_hit }
+
+ return $got_hit
+}
+
# We've got an array with 3 8-byte elements. Do a store of 16 bytes,
# to:
# - elements 0 and 1 (offset == 0), and
@@ -158,49 +215,21 @@ foreach_with_prefix wpcount {4 7} {
# For each case, check setting a watchpoint at:
# - the first written element (index == 0), and
# - the second element (index == 1).
-foreach_with_prefix offset { 0 1 } {
- foreach_with_prefix index { 0 1 } {
-
- clean_restart $binfile
-
- if ![runto_main] {
- return -1
- }
-
- gdb_test_no_output "set var offset = $offset"
- gdb_breakpoint [gdb_get_line_number "final_return"] \
- "Breakpoint $decimal at $hex" "final_return"
- set watch_index [expr $offset + $index]
- set test "watch data.u.size8twice\[$watch_index\]"
- set wpnum 0
- gdb_test_multiple $test $test {
- -re "Hardware watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" {
- set wpnum $expect_out(1,string)
- pass $gdb_test_name
- }
- -re "Watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" {
- if {[istarget "arm*-*-*"]} {
- untested $gdb_test_name
- } else {
- fail $gdb_test_name
- }
+foreach_with_prefix fun { write_size8twice read_size8twice } {
+ if { $fun == "write_size8twice" } {
+ set cmd "watch"
+ } else {
+ set cmd "rwatch"
+ }
+ foreach_with_prefix offset { 0 1 } {
+ foreach_with_prefix index { 0 1 } {
+ set res [size8twice $fun $cmd $offset $index]
+ if { $res != 1 } {
+ break
}
}
- if {$wpnum} {
- set test "continue"
- set got_hit 0
- gdb_test_multiple $test $test {
- -re "\r\nCould not insert hardware watchpoint .*\r\n$gdb_prompt $" {
- }
- -re "Hardware watchpoint $wpnum:.*New value = .*\r\n$gdb_prompt $" {
- set got_hit 1
- send_gdb "continue\n"
- exp_continue
- }
- -re " final_return .*\r\n$gdb_prompt $" {
- }
- }
- gdb_assert $got_hit "size8twice write"
+ if { $res != 1 } {
+ break
}
}
}
diff --git a/gdb/testsuite/gdb.base/watchpoints.exp b/gdb/testsuite/gdb.base/watchpoints.exp
index 37baa5e..d8e4d63 100644
--- a/gdb/testsuite/gdb.base/watchpoints.exp
+++ b/gdb/testsuite/gdb.base/watchpoints.exp
@@ -53,7 +53,8 @@ with_test_prefix "before inferior start" {
# This will turn hardware watchpoints back on and delete the watchpoint
# we just created.
- clean_restart ${binfile}
+ clean_restart
+ gdb_load $binfile
# Disable hardware watchpoints if necessary.
if {!$allow_hw_watchpoint_tests_p} {
diff --git a/gdb/testsuite/gdb.base/wchar.exp b/gdb/testsuite/gdb.base/wchar.exp
index 70f738c..f0e4777 100644
--- a/gdb/testsuite/gdb.base/wchar.exp
+++ b/gdb/testsuite/gdb.base/wchar.exp
@@ -72,3 +72,7 @@ gdb_test "print repeat_p" "= $hex L\"A$cent$cent\"\.\.\." \
# From PR cli/14977, but here because it requires wchar_t.
gdb_test "printf \"%ls\\n\", 0" "\\(null\\)"
+
+# From PR exp/33124 - a bug when converting escapes.
+set wbs {L'\\'}
+gdb_test "print $wbs" " = $decimal [string_to_regexp $wbs]"
diff --git a/gdb/testsuite/gdb.base/with-mf.exp b/gdb/testsuite/gdb.base/with-mf.exp
index 564d5d7..3ac5e1d 100644
--- a/gdb/testsuite/gdb.base/with-mf.exp
+++ b/gdb/testsuite/gdb.base/with-mf.exp
@@ -29,7 +29,8 @@ if { [ensure_gdb_index $binfile] == -1 } {
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
gdb_test "with language ada -- print g_s" \
" = \\(a => 1, b => 2, c => 3\\)"
diff --git a/gdb/testsuite/gdb.base/with.exp b/gdb/testsuite/gdb.base/with.exp
index a9b4a6c..d766e5d 100644
--- a/gdb/testsuite/gdb.base/with.exp
+++ b/gdb/testsuite/gdb.base/with.exp
@@ -25,7 +25,8 @@ if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
return -1
}
-clean_restart $binfile
+clean_restart
+gdb_load $binfile
# Test "maint with". VALUES is a list of values. A nested "with" is
# performed with each combination of pair of values from this list.
@@ -178,7 +179,8 @@ with_test_prefix "user-defined" {
# Check repeating.
with_test_prefix "repeat" {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
# "with" with no command reinvokes the previous command.
gdb_test "with language ada" \
@@ -209,7 +211,8 @@ with_test_prefix "repeat" {
# Basic run control.
with_test_prefix "run control" {
- clean_restart $binfile
+ clean_restart
+ gdb_load $binfile
if ![runto_main] {
return
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.compile/compile-tls.exp b/gdb/testsuite/gdb.compile/compile-tls.exp
index aaa8e03..e7db1da 100644
--- a/gdb/testsuite/gdb.compile/compile-tls.exp
+++ b/gdb/testsuite/gdb.compile/compile-tls.exp
@@ -26,7 +26,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
}
diff --git a/gdb/testsuite/gdb.compile/compile.exp b/gdb/testsuite/gdb.compile/compile.exp
index ff20b2e..eb87141 100644
--- a/gdb/testsuite/gdb.compile/compile.exp
+++ b/gdb/testsuite/gdb.compile/compile.exp
@@ -378,8 +378,9 @@ if { $srcfile3 != "" } {
require allow_shlib_tests
-set libbin [standard_output_file ${testfile}-shlib.so]
-set binfile [standard_output_file ${testfile}-shlib]
+set testfile $testfile-shlib
+set libbin [standard_output_file $testfile.so]
+set binfile [standard_output_file $testfile]
if { [gdb_compile_shlib ${srcdir}/${subdir}/${srcfile2} $libbin {debug}] != ""
|| [gdb_compile ${srcdir}/${subdir}/${srcfile} $binfile executable \
@@ -387,7 +388,7 @@ if { [gdb_compile_shlib ${srcdir}/${subdir}/${srcfile2} $libbin {debug}] != ""
return -1
}
-clean_restart $binfile
+clean_restart $testfile
gdb_load_shlib $libbin
if ![runto_main] {
diff --git a/gdb/testsuite/gdb.cp/call-c.exp b/gdb/testsuite/gdb.cp/call-c.exp
index f99d171..6d240c8 100644
--- a/gdb/testsuite/gdb.cp/call-c.exp
+++ b/gdb/testsuite/gdb.cp/call-c.exp
@@ -27,7 +27,7 @@ if {[gdb_compile "$srcdir/$subdir/${srcfile2}" "${objfilec}" object {debug}] !=
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
runto_main
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/gdb2384.exp b/gdb/testsuite/gdb.cp/gdb2384.exp
index 204bdeb..a53ec3a 100644
--- a/gdb/testsuite/gdb.cp/gdb2384.exp
+++ b/gdb/testsuite/gdb.cp/gdb2384.exp
@@ -35,7 +35,7 @@ if { [gdb_compile_shlib $srcdir/$subdir/$srcfile2 $sofile {debug c++}] != ""
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_load_shlib ${sofile}
diff --git a/gdb/testsuite/gdb.cp/infcall-nodebug.exp.tcl b/gdb/testsuite/gdb.cp/infcall-nodebug.exp.tcl
index 0a7bc76..764d31d 100644
--- a/gdb/testsuite/gdb.cp/infcall-nodebug.exp.tcl
+++ b/gdb/testsuite/gdb.cp/infcall-nodebug.exp.tcl
@@ -71,9 +71,9 @@ proc build_and_run_test { lang symbols } {
# Startup and run to main.
- clean_restart $binfile
+ clean_restart $::testfile
- if ![runto_main] then {
+ if { ![runto_main] } {
return
}
diff --git a/gdb/testsuite/gdb.cp/method-ref-return.cc b/gdb/testsuite/gdb.cp/method-ref-return.cc
new file mode 100644
index 0000000..4169bfe
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/method-ref-return.cc
@@ -0,0 +1,42 @@
+/* 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/>. */
+
+/* Test that we can access class method/data member via reference. */
+
+struct foo
+{
+ foo () : m_a (42) {}
+ int get_a () const { return m_a; }
+ int m_a;
+};
+
+struct bar
+{
+ bar () : m_foo () {}
+ const foo &get_foo () const { return m_foo; }
+ foo m_foo;
+};
+
+int
+main (int argc, char *argv[])
+{
+ bar b;
+ const foo &ref = b.get_foo ();
+ int ret = ref.m_a; // breakpoint here
+ ret += ref.get_a ();
+ return ret;
+} \ No newline at end of file
diff --git a/gdb/testsuite/gdb.cp/method-ref-return.exp b/gdb/testsuite/gdb.cp/method-ref-return.exp
new file mode 100644
index 0000000..1ac5ac9
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/method-ref-return.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/>.
+
+# Test calling methods and accessing members via reference.
+
+require allow_cplus_tests
+
+standard_testfile .cc
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} {
+ return -1
+}
+
+if {![runto_main]} {
+ return -1
+}
+
+# Set a breakpoint after the bar object is created and the reference is obtained.
+gdb_breakpoint [gdb_get_line_number "breakpoint here"]
+gdb_continue_to_breakpoint "after reference assignment"
+
+# Test that we can call the method through reference and get the expected result.
+gdb_test_multiple "print b.get_foo()" "print method call returning reference" {
+ -re "\\$\[0-9\]+ = \\(const foo &\\) @$hex: \\{m_a = 42\\}\r\n$gdb_prompt $" {
+ pass $gdb_test_name
+ }
+ -re "Could not validate memory tag: Value can't be converted to integer\\." {
+ fail "$gdb_test_name"
+ }
+}
+
+# Test accessing the member through the reference.
+gdb_test "print b.get_foo ().m_a" \
+ "\\$\[0-9\]+ = 42" \
+ "print member access through reference"
+
+# Test calling method on the referenced object.
+gdb_test "print b.get_foo ().get_a()" \
+ "\\$\[0-9\]+ = 42" \
+ "print method call on referenced object"
+
+# Test that the stored reference works correctly.
+gdb_test_multiple "print ref" "print stored reference" {
+ -re "\\$\[0-9\]+ = \\(const foo &\\) @$hex: \\{m_a = 42\\}\r\n$gdb_prompt $" {
+ pass $gdb_test_name
+ }
+ -re "Could not validate memory tag: Value can't be converted to integer\\." {
+ fail "$gdb_test_name"
+ }
+}
+
+gdb_test "print ref.m_a" \
+ "\\$\[0-9\]+ = 42" \
+ "print member through stored reference"
+
+gdb_test "print ref.get_a()" \
+ "\\$\[0-9\]+ = 42" \
+ "print method call through stored reference" \ No newline at end of file
diff --git a/gdb/testsuite/gdb.cp/pr10728.exp b/gdb/testsuite/gdb.cp/pr10728.exp
index 0525ac1..8201e24 100644
--- a/gdb/testsuite/gdb.cp/pr10728.exp
+++ b/gdb/testsuite/gdb.cp/pr10728.exp
@@ -42,7 +42,7 @@ if { [gdb_compile "${tfx}.o ${tfy}.o" ${binfile} executable {debug c++}] != ""
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.cp/print-global-stub.exp b/gdb/testsuite/gdb.cp/print-global-stub.exp
index 139e8b1..d847c00 100644
--- a/gdb/testsuite/gdb.cp/print-global-stub.exp
+++ b/gdb/testsuite/gdb.cp/print-global-stub.exp
@@ -19,14 +19,15 @@
require allow_cplus_tests
standard_testfile .cc
-set objfile [standard_output_file ${testfile}.o]
+set testfile $testfile.o
+set binfile [standard_output_file $testfile]
-if { [gdb_compile $srcdir/$subdir/$srcfile $objfile object \
+if { [gdb_compile $srcdir/$subdir/$srcfile $binfile object \
{c++ debug}] != "" } {
untested "failed to compile"
return -1
}
-clean_restart $objfile
+clean_restart $testfile
gdb_test "print s" " = <incomplete type>"
diff --git a/gdb/testsuite/gdb.cp/psmang.exp b/gdb/testsuite/gdb.cp/psmang.exp
index acc7b3b..67bc9cd9 100644
--- a/gdb/testsuite/gdb.cp/psmang.exp
+++ b/gdb/testsuite/gdb.cp/psmang.exp
@@ -190,6 +190,6 @@ gdb_test "break s::method1" "Breakpoint .* at .*: file .*psmang1.cc.*"
# We have to exit and restart GDB here, to make sure that all the
# compilation units are psymtabs again.
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test "break s::method2" "Breakpoint .* at .*: file .*psmang2.cc.*"
diff --git a/gdb/testsuite/gdb.cp/ref-params.exp b/gdb/testsuite/gdb.cp/ref-params.exp
index 97a56ab..4f2cbb5 100644
--- a/gdb/testsuite/gdb.cp/ref-params.exp
+++ b/gdb/testsuite/gdb.cp/ref-params.exp
@@ -32,7 +32,7 @@ proc gdb_start_again { text } {
global binfile
global srcfile
- clean_restart $binfile
+ clean_restart $::testfile
runto ${srcfile}:[gdb_get_line_number $text]
}
diff --git a/gdb/testsuite/gdb.cp/rvalue-ref-params.exp b/gdb/testsuite/gdb.cp/rvalue-ref-params.exp
index 8a5e66f..267dbc7 100644
--- a/gdb/testsuite/gdb.cp/rvalue-ref-params.exp
+++ b/gdb/testsuite/gdb.cp/rvalue-ref-params.exp
@@ -30,7 +30,7 @@ proc gdb_start_again {text prefix} {
global srcfile
with_test_prefix $prefix {
- clean_restart $binfile
+ clean_restart $::testfile
runto ${srcfile}:[gdb_get_line_number $text]
}
diff --git a/gdb/testsuite/gdb.cp/static-print-quit.exp b/gdb/testsuite/gdb.cp/static-print-quit.exp
index 8e0b61d..e4bce7f 100644
--- a/gdb/testsuite/gdb.cp/static-print-quit.exp
+++ b/gdb/testsuite/gdb.cp/static-print-quit.exp
@@ -27,32 +27,17 @@ clean_restart $testfile.o
gdb_test_no_output "set width 80"
gdb_test_no_output "set height 2"
-set test "print c - <return>"
-gdb_test_multiple "print c" $test {
- -re "\\$\[0-9\]+ = \{loooooooooooooooooooooooooooooooooooooooooooooong = 0, static field = \{\r\n--Type <RET>" {
- pass $test
+gdb_test_multiple "print c" "" {
+ -re "\\$\[0-9\]+ = \{loooooooooooooooooooooooooooooooooooooooooooooong = 0, static field = \{\r\n$pagination_prompt$" {
+ pass $gdb_test_name
}
- -re "\r\n--Type <RET>" {
+ -re "\r\n$pagination_prompt$" {
# gdb-7.1 did not crash with this testcase but it had the same bug.
untested "bug does not reproduce"
return 0
}
}
-set test "print c - q <return>"
-gdb_test_multiple "" $test {
- -re " for more, q to quit, " {
- pass $test
- }
-}
-
-set test "print c - remainder"
-gdb_test_multiple "" $test {
- -re "c to continue without paging--$" {
- pass $test
- }
-}
-
gdb_test "q" ".*"
# Now the obstack is uninitialized. Exercise it.
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.ctf/cross-tu-cyclic.exp b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
index 922729f..2a0e999 100644
--- a/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
+++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
@@ -37,6 +37,6 @@ gdb_test_no_output "set always-read-ctf on"
gdb_load $binfile
# Same thing with struct and union.
-gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ \t\]+struct B \\*foo;\[\r\n\]+\}.*" "ptype structure A"
-gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ \t\]+struct B \\*next;\[\r\n\]+\}.*" "ptype structure B"
+gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ \t\]+long a;\[\r\n\]+\[ \t\]+struct B \\*foo;\[\r\n\]+\}.*" "ptype structure A"
+gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ \t\]+int foo;\[\r\n\]+\[ \t\]+struct A \\*bar;\[\r\n\]+\}.*" "ptype structure B"
gdb_test "ptype struct C" "type = struct C \{\[\r\n\]+\[ \t\]+struct B \\*foo;\[\r\n\]+\[ \t\]+int b;\[\r\n\]+\}.*" "ptype structure C"
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/scopes.c b/gdb/testsuite/gdb.dap/scopes.c
index d8929f1..2a1d76c 100644
--- a/gdb/testsuite/gdb.dap/scopes.c
+++ b/gdb/testsuite/gdb.dap/scopes.c
@@ -27,6 +27,8 @@ int main ()
static int scalar = 23;
+ void *ptr = (void *) &scalar;
+
{
const char *inner = "inner block";
diff --git a/gdb/testsuite/gdb.dap/scopes.exp b/gdb/testsuite/gdb.dap/scopes.exp
index 59d344b..52efa68 100644
--- a/gdb/testsuite/gdb.dap/scopes.exp
+++ b/gdb/testsuite/gdb.dap/scopes.exp
@@ -70,7 +70,8 @@ lassign $scopes scope reg_scope
gdb_assert {[dict get $scope name] == "Locals"} "scope is locals"
gdb_assert {[dict get $scope presentationHint] == "locals"} \
"locals presentation hint"
-gdb_assert {[dict get $scope namedVariables] == 3} "three vars in scope"
+set count [dict get $scope namedVariables]
+gdb_assert {$count == 4} "four vars in scope"
gdb_assert {[dict get $reg_scope name] == "Registers"} \
"second scope is registers"
@@ -89,8 +90,8 @@ set refs1 [lindex [dap_check_request_and_response "fetch variables 0,1" \
set refs2 [lindex [dap_check_request_and_response "fetch variables 2" \
"variables" \
[format {o variablesReference [i %d] \
- start [i 2] count [i 1]} \
- $num]] \
+ start [i 2] count [i %d]} \
+ $num [expr {$count - 2}]]] \
0]
set vars [concat [dict get $refs1 body variables] \
@@ -115,6 +116,10 @@ foreach var $vars {
"scalar" {
gdb_assert {[dict get $var value] == 23} "check value of scalar"
}
+ "ptr" {
+ gdb_assert {[dict get $var memoryReference] != ""} \
+ "check memoryReference of ptr"
+ }
default {
fail "unknown variable $name"
}
@@ -128,11 +133,38 @@ set refs [lindex [dap_check_request_and_response "fetch contents of dei" \
set deivals [dict get $refs body variables]
gdb_assert {[llength $deivals] == 2} "dei has two members"
+# Request more children than exist. See PR dap/33228.
+set seq [dap_send_request variables \
+ [format {o variablesReference [i %d] count [i 100]} $dei_ref]]
+lassign [dap_read_response variables $seq] response ignore
+gdb_assert {[dict get $response success] == "false"} \
+ "variables with invalid count"
+
set num [dict get $reg_scope variablesReference]
-# The request succeeding is sufficient.
-set val [dap_check_request_and_response "fetch first register" \
+lassign [dap_check_request_and_response "fetch all registers" \
"variables" \
- [format {o variablesReference [i %d] count [i 1]} $num]]
+ [format {o variablesReference [i %d] count [i %d]} $num\
+ [dict get $reg_scope namedVariables]]] \
+ val events
+
+# If any register has children, try to fetch those as well. This is a
+# regression test for part of PR dap/33228.
+foreach var [dict get $val body variables] {
+ set regvar [dict get $var variablesReference]
+ if {$regvar > 0} {
+ # If variablesReference is non-zero, then there must be either
+ # named or indexed children.
+ if {[dict exists $var namedVariables]} {
+ set n [dict get $var namedVariables]
+ } else {
+ set n [dict get $var indexedVariables]
+ }
+
+ dap_check_request_and_response "fetch register children for $regvar" \
+ "variables" \
+ [format {o variablesReference [i %d] count [i %d]} $regvar $n]
+ }
+}
set num [dict get $scope variablesReference]
set refs [lindex [dap_check_request_and_response "set variable scalar" \
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..204b924 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
@@ -69,14 +69,15 @@ standard_testfile -1.c -2.c -3.c
# shared library, then use GDB to figure out the offset of the
# variable 'library_ptr' within the library.
set library_filename [standard_output_file "libfoo.so"]
-set binfile2 [standard_output_file "library_loader"]
+set testfile2 "library_loader"
+set binfile2 [standard_output_file $testfile2]
if {[prepare_for_testing_full "build exec which loads the shared library" \
[list $library_filename \
{ debug shlib build-id \
additional_flags=-DPOINTER_VALUE=0x12345678 } \
$srcfile2 {}] \
- [list $binfile2 [list debug shlib=$library_filename ] \
+ [list $testfile2 [list debug shlib=$library_filename ] \
$srcfile { debug }]] != 0} {
return
}
@@ -160,7 +161,7 @@ if { $ptr_expected_value eq "" } {
# Load this executable within GDB and confirm that we can use the
# offset we calculated previously to view the value of 'library_ptr'.
set opts [list debug additional_flags=-DSHLIB_FILENAME=\"$library_filename\"]
-if {[prepare_for_testing "prepare second executable" $binfile \
+if {[prepare_for_testing "prepare second executable" $testfile \
$srcfile3 $opts] != 0} {
return
}
@@ -260,7 +261,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
}
}
@@ -268,7 +269,7 @@ proc load_core_file { testname { line_re "" } } {
# And now restart GDB, load the core-file and check that the library shows as
# being mapped in, and that we can still read the library_ptr value from
# memory.
-clean_restart $binfile
+clean_restart $::testfile
load_core_file "load core file"
@@ -287,7 +288,7 @@ gdb_assert { $ptr_value == $ptr_expected_value } \
set library_backup_filename [standard_output_file "libfoo.so.backup"]
remote_exec build "mv \"$library_filename\" \"$library_backup_filename\""
-clean_restart $binfile
+clean_restart $::testfile
load_core_file "load corefile with library file missing" \
"warning: Can't open file [string_to_regexp $library_filename] during file-backed mapping note processing"
@@ -309,7 +310,7 @@ set build_id_filename \
remote_exec build "mkdir -p [file dirname $build_id_filename]"
remote_exec build "ln -sf $library_backup_filename $build_id_filename"
-clean_restart $binfile
+clean_restart $::testfile
gdb_test_no_output "set debug-file-directory $debugdir" \
"set debug-file-directory"
@@ -331,7 +332,7 @@ if {[build_executable "build second version of shared library" \
return
}
-clean_restart $binfile
+clean_restart $::testfile
load_core_file "load corefile with wrong library in place" \
"warning: File [string_to_regexp $library_filename] doesn't match build-id from core-file during file-backed mapping processing"
diff --git a/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp b/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
index 4b3894e..569519b 100644
--- a/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
+++ b/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
@@ -107,7 +107,7 @@ proc_with_prefix no_url { } {
setenv DEBUGINFOD_URLS ""
# Test that GDB cannot find source without debuginfod.
- clean_restart $binfile
+ clean_restart $::testfile
gdb_test_no_output "set substitute-path $outputdir /dev/null" \
"set substitute-path"
gdb_test "list" ".*No such file or directory.*"
@@ -126,7 +126,7 @@ proc_with_prefix no_url { } {
file rename -force $debuginfo $debugdir
# Test that GDB cannot find symbols without debuginfod.
- clean_restart $binfile
+ clean_restart $::testfile
gdb_test "file" ".*No symbol file.*"
set buildid "01234567890abcdef0123456"
@@ -157,7 +157,7 @@ proc_with_prefix no_url { } {
# Generate a core file and test that GDB cannot find the
# executable.
- clean_restart ${binfile}2
+ clean_restart ${::testfile}2
if ![runto_main] {
return -1
}
diff --git a/gdb/testsuite/gdb.debuginfod/solib-with-soname.exp b/gdb/testsuite/gdb.debuginfod/solib-with-soname.exp
index 9f1842c..67d9237 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 } {
@@ -132,7 +132,7 @@ if {$corefile eq ""} {
proc load_exec_and_core_file { expect_warning expect_download testname \
{debugdir ""} } {
with_test_prefix $testname {
- clean_restart $::binfile
+ clean_restart $::testfile
if { $debugdir ne "" } {
gdb_test_no_output "set debug-file-directory $debugdir" \
diff --git a/gdb/testsuite/gdb.disasm/am33.exp b/gdb/testsuite/gdb.disasm/am33.exp
index b5ae981..7515da1 100644
--- a/gdb/testsuite/gdb.disasm/am33.exp
+++ b/gdb/testsuite/gdb.disasm/am33.exp
@@ -795,7 +795,7 @@ proc dsp_autoincrement_tests { } {
}
}
-clean_restart $binfile
+clean_restart $::testfile
call_tests
movm_tests
diff --git a/gdb/testsuite/gdb.disasm/hppa.exp b/gdb/testsuite/gdb.disasm/hppa.exp
index e330809..53027d7 100644
--- a/gdb/testsuite/gdb.disasm/hppa.exp
+++ b/gdb/testsuite/gdb.disasm/hppa.exp
@@ -1365,7 +1365,7 @@ proc fmemLRbug_tests { } {
}
}
-clean_restart $binfile
+clean_restart $::testfile
all_integer_memory_tests
all_immediate_tests
diff --git a/gdb/testsuite/gdb.disasm/mn10300.exp b/gdb/testsuite/gdb.disasm/mn10300.exp
index 55ce96c..74e7c7c 100644
--- a/gdb/testsuite/gdb.disasm/mn10300.exp
+++ b/gdb/testsuite/gdb.disasm/mn10300.exp
@@ -529,7 +529,7 @@ proc sub_tests { } {
}
}
-clean_restart $binfile
+clean_restart $::testfile
add_tests
bcc_tests
diff --git a/gdb/testsuite/gdb.disasm/sh3.exp b/gdb/testsuite/gdb.disasm/sh3.exp
index 09b27a0..fc591a7 100644
--- a/gdb/testsuite/gdb.disasm/sh3.exp
+++ b/gdb/testsuite/gdb.disasm/sh3.exp
@@ -100,7 +100,7 @@ proc all_fp_misc_tests { } {
}
}
-clean_restart $binfile
+clean_restart $::testfile
all_fp_move_and_load_tests
all_fp_arithmetic_tests
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/backward-spec-inter-cu.exp b/gdb/testsuite/gdb.dwarf2/backward-spec-inter-cu.exp
index b62f928..1876849 100644
--- a/gdb/testsuite/gdb.dwarf2/backward-spec-inter-cu.exp
+++ b/gdb/testsuite/gdb.dwarf2/backward-spec-inter-cu.exp
@@ -20,6 +20,7 @@ load_lib dwarf.exp
# This test can only be run on targets which support DWARF-2 and use gas.
require dwarf2_support
+require !readnow
standard_testfile main.c -debug.S
@@ -98,6 +99,11 @@ foreach_with_prefix worker_threads $worker_threads_list {
gdb_load $binfile
+ set index [have_index $binfile]
+ if { ![string eq $index ""] } {
+ return
+ }
+
gdb_test "pipe maint print objfiles | grep ns::v" \
"$ws+qualified:$ws+ns::v" \
"v has parent ns"
diff --git a/gdb/testsuite/gdb.dwarf2/debug-names-missing-cu.exp b/gdb/testsuite/gdb.dwarf2/debug-names-missing-cu.exp
index d7d4fb8..1ec4a18 100644
--- a/gdb/testsuite/gdb.dwarf2/debug-names-missing-cu.exp
+++ b/gdb/testsuite/gdb.dwarf2/debug-names-missing-cu.exp
@@ -18,6 +18,10 @@ load_lib dwarf.exp
# This test can only be run on targets which support DWARF-2 and use gas.
require dwarf2_support
+# This test checks that no CU is initially expanded, which is negated
+# by readnow.
+require !readnow
+
standard_testfile _start.c debug-names.S
set func_info_vars \
diff --git a/gdb/testsuite/gdb.dwarf2/debug-names-non-ascending-cu.exp b/gdb/testsuite/gdb.dwarf2/debug-names-non-ascending-cu.exp
deleted file mode 100644
index d86b5c4..0000000
--- a/gdb/testsuite/gdb.dwarf2/debug-names-non-ascending-cu.exp
+++ /dev/null
@@ -1,81 +0,0 @@
-# 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/>.
-
-load_lib dwarf.exp
-
-# This test can only be run on targets which support DWARF-2 and use gas.
-require dwarf2_support
-
-standard_testfile _start.c debug-names.S
-
-set func_info_vars \
- [get_func_info _start [list debug additional_flags=-nostartfiles]]
-
-# Create the DWARF.
-set asm_file [standard_output_file $srcfile2]
-Dwarf::assemble {
- filename $asm_file
- add_dummy_cus 0
-} {
- global func_info_vars
- foreach var $func_info_vars {
- global $var
- }
-
- cu { label cu_label } {
- compile_unit {{language @DW_LANG_C}} {
- subprogram {
- {DW_AT_name _start}
- {DW_AT_low_pc $_start_start DW_FORM_addr}
- {DW_AT_high_pc $_start_end DW_FORM_addr}
- }
- }
- }
-
- cu { label cu_label_2 } {
- compile_unit {{language @DW_LANG_C}} {
- base_type {
- {name int}
- {byte_size 4 sdata}
- {encoding @DW_ATE_signed}
- }
- }
- }
-
- debug_names {} {
- cu cu_label_2
- cu cu_label
- name _start subprogram cu_label 0xEDDB6232
- name int base_type cu_label 0xB888030
- }
-}
-
-if [prepare_for_testing "failed to prepare" $testfile "${asm_file} ${srcfile}" \
- [list additional_flags=-nostartfiles]] {
- return -1
-}
-
-# Check for warning.
-set re \
- [list \
- "warning:" \
- "Section .debug_names has incorrect entry in CU table," \
- "ignoring .debug_names."]
-set re [join $re]
-gdb_assert {[regexp $re $gdb_file_cmd_msg]} "warning"
-
-# Verify that .debug_names section is ignored.
-set index [have_index $binfile]
-gdb_assert { [string equal $index ""] } ".debug_names not used"
diff --git a/gdb/testsuite/gdb.dwarf2/debug-names-tu.exp.tcl b/gdb/testsuite/gdb.dwarf2/debug-names-tu.exp.tcl
index 60d1d0d..4950458 100644
--- a/gdb/testsuite/gdb.dwarf2/debug-names-tu.exp.tcl
+++ b/gdb/testsuite/gdb.dwarf2/debug-names-tu.exp.tcl
@@ -18,6 +18,10 @@ load_lib dwarf.exp
# This test can only be run on targets which support DWARF-2 and use gas.
require dwarf2_support
+# When using readnow, the index isn't used, which invalidates this
+# test.
+require !readnow
+
standard_testfile _start.c debug-names.S
set func_info_vars \
diff --git a/gdb/testsuite/gdb.dwarf2/dw-form-ref-addr-with-type-units.exp b/gdb/testsuite/gdb.dwarf2/dw-form-ref-addr-with-type-units.exp
new file mode 100644
index 0000000..6253629
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw-form-ref-addr-with-type-units.exp
@@ -0,0 +1,109 @@
+# 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 is a reproducer for PR 29518:
+#
+# https://sourceware.org/bugzilla/show_bug.cgi?id=29518
+#
+# The root cause for the problem was that function
+# dwarf2_find_containing_comp_unit was searching the whole "all_units" vector,
+# containing both compile units and type units, causing it to sometimes
+# erroneously return a type unit. It should have been restricted to searching
+# compile units.
+#
+# To get dwarf2_find_containing_comp_unit to be called and reproduce the
+# original bug, we need a value with form DW_FORM_ref_addr pointing to a
+# different compile unit. This is produced by `%$int_type` below.
+
+load_lib dwarf.exp
+require dwarf2_support
+standard_testfile main.c .S
+
+set asm_file [standard_output_file $srcfile2]
+
+Dwarf::assemble $asm_file {
+ global srcfile
+ declare_labels int_type
+
+ # The source CU.
+ cu {version 4} {
+ compile_unit {
+ } {
+ subprogram {
+ {MACRO_AT_func {main}}
+ {type %$int_type}
+ }
+ }
+ }
+
+ # Create a bunch of empty / dummy CUs, to make the offset of int_type a bit
+ # higher.
+ for {set i 1} {$i < 10} {incr i} {
+ cu {version 4} {
+ compile_unit {} {}
+ }
+ }
+
+ # The target CU.
+ cu {version 4} {
+ compile_unit {
+ } {
+ int_type: DW_TAG_base_type {
+ {DW_AT_byte_size 4 DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_signed}
+ {DW_AT_name int}
+ }
+ }
+ }
+
+ # Create many TUs.
+ #
+ # We need enough type units in the "all_units" vector in order to steer the
+ # binary search in dwarf2_find_containing_comp_unit towards the type units
+ # region of the array.
+ for {set i 1} {$i < 20} {incr i} {
+ tu {version 4} $i the_type_i {
+ type_unit {} {
+ declare_labels dummy_int_type
+
+ the_type_i: structure_type {
+ {name s}
+ {byte_size 4 sdata}
+ } {
+ member {
+ {name i}
+ {type :$dummy_int_type}
+ }
+ }
+
+ dummy_int_type: base_type {
+ {name int}
+ {encoding @DW_ATE_signed}
+ {byte_size 4 sdata}
+ }
+ }
+ }
+ }
+}
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+ [list $srcfile $asm_file] {nodebug}] } {
+ return -1
+}
+
+# Without the corresponding fix, we get an internal error:
+#
+# gdb/dwarf2/read.c:3940: internal-error: load_full_comp_unit: Assertion `! this_cu->is_debug_types' failed.
+gdb_test "p main" " = {int \\(void\\)} $hex <main>"
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-aranges.exp b/gdb/testsuite/gdb.dwarf2/dw2-aranges.exp
index 8d941ba..0dd59bb 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-aranges.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-aranges.exp
@@ -32,7 +32,8 @@ Dwarf::assemble $asm_file {
}
}
-if { [prepare_for_testing "failed to prepare" $binfile [list $asm_file $srcfile ]] } {
+if { [prepare_for_testing "failed to prepare" $testfile \
+ [list $asm_file $srcfile ]] } {
return -1
}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-bad-elf.exp b/gdb/testsuite/gdb.dwarf2/dw2-bad-elf.exp
index fa9d000..ed03c27 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-bad-elf.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-bad-elf.exp
@@ -170,7 +170,7 @@ if { [build_executable ${testfile}.exp ${testfile} \
proc run_test { goto_main } {
global binfile decimal hex
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if { $goto_main } {
if ![runto_main] {
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-entry-points.c b/gdb/testsuite/gdb.dwarf2/dw2-entry-points.c
index ccfb150..258ebfa 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-entry-points.c
+++ b/gdb/testsuite/gdb.dwarf2/dw2-entry-points.c
@@ -33,11 +33,28 @@ bar_helper (void)
asm ("foobar_entry_label: .globl foobar_entry_label");
}
+__attribute__ ((noinline))
+void
+barso_helper (void)
+{
+ asm ("barso_helper_label: .globl barso_helper_label");
+ I++;
+ J++;
+ asm ("fooso_entry_label: .globl fooso_entry_label");
+ J++;
+ K++;
+ asm ("foobarso_entry_label: .globl foobarso_entry_label");
+}
+
int
main (void)
{
asm ("main_label: .globl main_label");
bar_helper ();
+ I = 0;
+ J = 0;
+ K = 0;
+ barso_helper ();
return 0;
}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-entry-points.exp b/gdb/testsuite/gdb.dwarf2/dw2-entry-points.exp
index bd22560..bba4cfb 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-entry-points.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-entry-points.exp
@@ -36,6 +36,7 @@ Dwarf::assemble $asm_file {
get_func_info main
get_func_info bar_helper
+ get_func_info barso_helper
set int_size [get_sizeof "int" 4]
@@ -135,8 +136,8 @@ Dwarf::assemble $asm_file {
{decl_file 1 data1}
{decl_line $bar_line data1}
{external 1 flag}
- {low_pc $bar_helper_start addr}
- {high_pc "$bar_helper_start + $bar_helper_len" addr}
+ {low_pc $barso_helper_start addr}
+ {high_pc "$barso_helper_start + $barso_helper_len" addr}
} {
formal_parameter {
{name I}
@@ -152,7 +153,7 @@ Dwarf::assemble $asm_file {
{name fooso}
{decl_file 1 data1}
{decl_line $foo_line data1}
- {low_pc foo_entry_label addr}
+ {low_pc fooso_entry_label addr}
} {
formal_parameter {
{name J}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-is-stmt-2.exp b/gdb/testsuite/gdb.dwarf2/dw2-is-stmt-2.exp
index 49091f7..ff91d63 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-is-stmt-2.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-is-stmt-2.exp
@@ -179,7 +179,7 @@ foreach entry $locs {
# through. This is checking that the is-stmt marked lines are
# displayed differently (without addresses) to addresses that are
# mid-way through a line, or not marked as is-stmt.
-clean_restart $binfile
+clean_restart $::testfile
runto_main
foreach entry $locs {
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-is-stmt.exp b/gdb/testsuite/gdb.dwarf2/dw2-is-stmt.exp
index 65d9559..d304963 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-is-stmt.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-is-stmt.exp
@@ -116,7 +116,7 @@ gdb_test "step" "/\\* main end \\*/" \
# Restart the test. This time, stop at a location we know is marked
# as a statement.
-clean_restart ${binfile}
+clean_restart ${::testfile}
runto_main
gdb_breakpoint "*line_label_3"
@@ -129,7 +129,7 @@ gdb_test "step" "/\\* main end \\*/" \
# Restart the test, this time, step through line by line, ensure we
# only stop at the places where is-stmt is true.
-clean_restart ${binfile}
+clean_restart ${::testfile}
runto_main
# Get the values of the labels where we expect to stop.
@@ -161,7 +161,7 @@ with_test_prefix "step to line_label_5" {
# Now restart the test, and place a breakpoint by line number. GDB
# should select the location that is marked as is-stmt.
-clean_restart ${binfile}
+clean_restart ${::testfile}
runto_main
set linum [gdb_get_line_number "main, set var to 0"]
gdb_breakpoint "$srcfile:$linum"
@@ -171,7 +171,7 @@ gdb_assert { $ll3 == $pc } "check initial \$pc"
# Restart the test again, this time we will test stepping by
# instruction.
-clean_restart ${binfile}
+clean_restart ${::testfile}
runto_main
# We will be at line_label_1 at this point - we already tested this
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-linkage-name-trust.exp b/gdb/testsuite/gdb.dwarf2/dw2-linkage-name-trust.exp
index 01eab48..7627e8e 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-linkage-name-trust.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-linkage-name-trust.exp
@@ -27,7 +27,7 @@ standard_testfile .S
set executable ${testfile}
if {[prepare_for_testing_full "failed to prepare" \
- [list $testfile c++ $testfile-main.cc {c++ debug} \
+ [list $testfile c++ $testfile-main.cc {c++ nodebug} \
$srcfile {}]]} {
return -1
}
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-multiple-debug-info.exp b/gdb/testsuite/gdb.dwarf2/dw2-multiple-debug-info.exp
index a8fa524..0092969 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-multiple-debug-info.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-multiple-debug-info.exp
@@ -31,6 +31,6 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" "$binfile" object \
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
gdb_test "ptype a" "type = class sp1::A .*"
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-opt-structptr.exp b/gdb/testsuite/gdb.dwarf2/dw2-opt-structptr.exp
index 486a4e8..870c8c1 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-opt-structptr.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-opt-structptr.exp
@@ -134,7 +134,7 @@ set re_address_class "@\[^\r\n\]+"
proc do_console_test {} {
global binfile
- clean_restart $binfile
+ clean_restart $::testfile
with_test_prefix "console" {
gdb_test_no_output "set print object on"
@@ -173,7 +173,7 @@ proc do_mi_test {} {
global binfile
with_test_prefix "mi" {
- if {[mi_clean_restart $binfile]} {
+ if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-prologue-end.exp b/gdb/testsuite/gdb.dwarf2/dw2-prologue-end.exp
index 23d8c26..070865b 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-prologue-end.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-prologue-end.exp
@@ -91,7 +91,7 @@ set prologue_end_line [gdb_get_line_number "main assign o"]
gdb_test "frame" ".*main \\\(\\\) at \[^\r\n\]*:$prologue_end_line\r\n.*"
with_test_prefix "ignore-prologue-end" {
- clean_restart $binfile
+ clean_restart $::testfile
gdb_test_no_output "maintenance set ignore-prologue-end-flag on"
if ![runto_main] {
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/dw2-var-zero-addr.exp b/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp
index f021f42..c6234d5 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-var-zero-addr.exp
@@ -34,7 +34,7 @@ test
save_vars { GDBFLAGS } {
set GDBFLAGS "$GDBFLAGS --readnow"
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
with_test_prefix "readnow" {
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-zero-range.exp b/gdb/testsuite/gdb.dwarf2/dw2-zero-range.exp
index 221bf7b..1d20688 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-zero-range.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-zero-range.exp
@@ -26,7 +26,8 @@ standard_testfile .c -shlib.c -dw.S
# Test for presence of complaint, with the lib relocated.
proc_with_prefix test_relocated { exec_path lib_path complaint_re readnow_p } {
- clean_restart $exec_path
+ clean_restart
+ gdb_load $exec_path
gdb_load_shlib $lib_path
if { ![runto_main] } {
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/entry-value-typedef.exp b/gdb/testsuite/gdb.dwarf2/entry-value-typedef.exp
index 44d58a8..f84f0f3 100644
--- a/gdb/testsuite/gdb.dwarf2/entry-value-typedef.exp
+++ b/gdb/testsuite/gdb.dwarf2/entry-value-typedef.exp
@@ -31,7 +31,7 @@ if {[gdb_compile "$srcdir/$subdir/$srcfile" "$binfile" executable {c++}] != ""}
return
}
-clean_restart $binfile
+clean_restart $::testfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.dwarf2/fission-base.exp b/gdb/testsuite/gdb.dwarf2/fission-base.exp
index 4d18ea0..9f70f30 100644
--- a/gdb/testsuite/gdb.dwarf2/fission-base.exp
+++ b/gdb/testsuite/gdb.dwarf2/fission-base.exp
@@ -35,7 +35,7 @@ if [build_executable_and_dwo_files "$testfile.exp" "${binfile}" {nodebug} \
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
if ![runto_main] {
return -1
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..7072b7e
--- /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 $::testfile
+
+gdb_test "ptype global_var" "type = int"
diff --git a/gdb/testsuite/gdb.dwarf2/fission-loclists-pie.exp b/gdb/testsuite/gdb.dwarf2/fission-loclists-pie.exp
index 5be2e8e..aa54718 100644
--- a/gdb/testsuite/gdb.dwarf2/fission-loclists-pie.exp
+++ b/gdb/testsuite/gdb.dwarf2/fission-loclists-pie.exp
@@ -40,7 +40,7 @@ if [build_executable_and_dwo_files "$testfile.exp" "${binfile}" \
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
if ![runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.dwarf2/fission-loclists.exp b/gdb/testsuite/gdb.dwarf2/fission-loclists.exp
index 95c1fac..59cd10b 100644
--- a/gdb/testsuite/gdb.dwarf2/fission-loclists.exp
+++ b/gdb/testsuite/gdb.dwarf2/fission-loclists.exp
@@ -35,7 +35,7 @@ if [build_executable_and_dwo_files "$testfile.exp" "${binfile}" {nodebug} \
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
if ![runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.dwarf2/fission-mix.exp b/gdb/testsuite/gdb.dwarf2/fission-mix.exp
index e4741c3..e6a430c 100644
--- a/gdb/testsuite/gdb.dwarf2/fission-mix.exp
+++ b/gdb/testsuite/gdb.dwarf2/fission-mix.exp
@@ -35,7 +35,7 @@ if {[gdb_compile "$objfile $objfile2" $binfile executable {debug}] != "" } {
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
gdb_test "break -q main" "Breakpoint .*"
diff --git a/gdb/testsuite/gdb.dwarf2/fission-multi-cu.exp b/gdb/testsuite/gdb.dwarf2/fission-multi-cu.exp
index 44e72d6..78f2798 100644
--- a/gdb/testsuite/gdb.dwarf2/fission-multi-cu.exp
+++ b/gdb/testsuite/gdb.dwarf2/fission-multi-cu.exp
@@ -203,7 +203,7 @@ if [build_executable_and_dwo_files "$testfile.exp" "${binfile}" {nodebug} \
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
if ![runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.dwarf2/fission-reread.exp b/gdb/testsuite/gdb.dwarf2/fission-reread.exp
index 6821747..238afb1 100644
--- a/gdb/testsuite/gdb.dwarf2/fission-reread.exp
+++ b/gdb/testsuite/gdb.dwarf2/fission-reread.exp
@@ -62,7 +62,7 @@ pass "$testfile - unload"
remote_file target delete $dwo
save_vars { GDBFLAGS } {
append GDBFLAGS " -iex \"maint set dwarf synchronous on\""
- clean_restart $binfile
+ clean_restart $::testfile
}
set output_dir [standard_output_file ""]
set cmd "save gdb-index"
diff --git a/gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp b/gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp
index e92e582..26d0af6 100644
--- a/gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp
+++ b/gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp
@@ -20,6 +20,7 @@ load_lib dwarf.exp
# This test can only be run on targets which support DWARF-2 and use gas.
require dwarf2_support
+require !readnow
standard_testfile main.c -debug.S
@@ -98,6 +99,11 @@ foreach_with_prefix worker_threads $worker_threads_list {
gdb_load $binfile
+ set index [have_index $binfile]
+ if { ![string eq $index ""] } {
+ return
+ }
+
gdb_test "pipe maint print objfiles | grep ns::v" \
"$ws+qualified:$ws+ns::v" \
"v has parent ns"
diff --git a/gdb/testsuite/gdb.dwarf2/frame-inlined-in-outer-frame.exp b/gdb/testsuite/gdb.dwarf2/frame-inlined-in-outer-frame.exp
index ef7cf92..6857a08 100644
--- a/gdb/testsuite/gdb.dwarf2/frame-inlined-in-outer-frame.exp
+++ b/gdb/testsuite/gdb.dwarf2/frame-inlined-in-outer-frame.exp
@@ -106,7 +106,7 @@ if { [build_executable ${testfile}.exp ${testfile} "$srcfile $dwarf_asm" \
return
}
-clean_restart $binfile
+clean_restart $::testfile
if { [gdb_starti_cmd] != 0 } {
fail "failed to run to first instruction"
diff --git a/gdb/testsuite/gdb.dwarf2/gdb-add-index-symlink.exp b/gdb/testsuite/gdb.dwarf2/gdb-add-index-symlink.exp
index cd05925..9233637 100644
--- a/gdb/testsuite/gdb.dwarf2/gdb-add-index-symlink.exp
+++ b/gdb/testsuite/gdb.dwarf2/gdb-add-index-symlink.exp
@@ -56,7 +56,8 @@ if { [ensure_gdb_index $symlink] == -1 } {
# Ok, we have a copy of $binfile with an index.
# Restart gdb and verify the index was used.
-clean_restart $symlink
+clean_restart
+gdb_load $symlink
gdb_test "mt print objfiles ${testfile}" \
"(gdb_index|debug_names).*" \
"index used"
diff --git a/gdb/testsuite/gdb.dwarf2/gdb-add-index.exp b/gdb/testsuite/gdb.dwarf2/gdb-add-index.exp
index 3285d1c..0fbd3a2 100644
--- a/gdb/testsuite/gdb.dwarf2/gdb-add-index.exp
+++ b/gdb/testsuite/gdb.dwarf2/gdb-add-index.exp
@@ -33,7 +33,7 @@ if { [ensure_gdb_index $binfile] == -1 } {
# Ok, we have a copy of $binfile with an index.
# Restart gdb and verify the index was used.
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test "mt print objfiles ${testfile}" \
"(gdb_index|debug_names).*" \
"index used"
diff --git a/gdb/testsuite/gdb.dwarf2/gdb-index-tilde.exp b/gdb/testsuite/gdb.dwarf2/gdb-index-tilde.exp
index c0d5225..a8c5c39 100644
--- a/gdb/testsuite/gdb.dwarf2/gdb-index-tilde.exp
+++ b/gdb/testsuite/gdb.dwarf2/gdb-index-tilde.exp
@@ -47,7 +47,7 @@ if { [prepare_for_testing "failed to prepare" "${testfile}" ${srcfile}] } {
}
# Start GDB and load in the executable.
-clean_restart ${binfile}
+clean_restart ${::testfile}
# If the executable was built with an index, or lacks the debug
# information required to create an index, then we'll not be able to
diff --git a/gdb/testsuite/gdb.dwarf2/gdb-index-types-dwarf5.exp b/gdb/testsuite/gdb.dwarf2/gdb-index-types-dwarf5.exp
index d6f5e48..a47d73a 100644
--- a/gdb/testsuite/gdb.dwarf2/gdb-index-types-dwarf5.exp
+++ b/gdb/testsuite/gdb.dwarf2/gdb-index-types-dwarf5.exp
@@ -13,6 +13,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# This test checks that .gdb_index is in use, which isn't the case
+# with readnow.
+require !readnow
+
standard_testfile
set flags {}
@@ -29,7 +33,7 @@ if { [ensure_gdb_index $binfile] != 1 } {
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
# Verify that .gdb_index section is not ignored.
set index [have_index $binfile]
diff --git a/gdb/testsuite/gdb.dwarf2/gdb-index.exp b/gdb/testsuite/gdb.dwarf2/gdb-index.exp
index ebeb62b..f7c3337 100644
--- a/gdb/testsuite/gdb.dwarf2/gdb-index.exp
+++ b/gdb/testsuite/gdb.dwarf2/gdb-index.exp
@@ -98,20 +98,24 @@ set test "check if index present"
set filter "gdb_index|debug_names|Psymtabs|Cooked"
set cmd "pipe mt print objfiles ${testfile} | grep -E \"$filter\""
set cmd_re [string_to_regexp $cmd]
+set testfile_with_index bla
gdb_test_multiple $cmd $test {
-re ^$cmd_re {
exp_continue
}
-re "gdb_index.*${gdb_prompt} $" {
- set binfile_with_index $binfile
+ set testfile_with_index $testfile
+ set binfile_with_index [standard_output_file $testfile_with_index]
set host_binfile_with_index [gdb_remote_download host $binfile]
}
-re "debug_names.*${gdb_prompt} $" {
- set binfile_with_index $binfile
+ set testfile_with_index $testfile
+ set binfile_with_index [standard_output_file $testfile_with_index]
set host_binfile_with_index [gdb_remote_download host $binfile]
}
-re "(Psymtabs|Cooked).*${gdb_prompt} $" {
lassign [local_add_gdb_index $binfile] binfile_with_index host_binfile_with_index
+ set testfile_with_index [file tail $binfile_with_index]
if { ${binfile_with_index} == "" } {
return -1
}
@@ -124,7 +128,7 @@ gdb_test_multiple $cmd $test {
# Ok, we have a copy of $binfile with an index.
# Restart gdb and verify the index was used.
-clean_restart ${binfile_with_index}
+clean_restart $testfile_with_index
gdb_test "mt print objfiles ${testfile}" \
"(gdb_index|debug_names).*" \
"index used"
diff --git a/gdb/testsuite/gdb.dwarf2/imported-unit-runto-main.exp b/gdb/testsuite/gdb.dwarf2/imported-unit-runto-main.exp
index c4bacb1..cdcb810 100644
--- a/gdb/testsuite/gdb.dwarf2/imported-unit-runto-main.exp
+++ b/gdb/testsuite/gdb.dwarf2/imported-unit-runto-main.exp
@@ -77,6 +77,6 @@ if { [ensure_gdb_index $binfile] == -1 } {
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
runto main
diff --git a/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location.exp b/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location.exp
index ea871d6..7665680 100644
--- a/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location.exp
+++ b/gdb/testsuite/gdb.dwarf2/locexpr-data-member-location.exp
@@ -330,7 +330,7 @@ if {[gdb_compile_shlib [list $libsrc $asm_file] $lib_so \
### Second GDB session.
with_test_prefix "second session" {
- clean_restart $binfile
+ clean_restart $::testfile
# Again, do whatever is necessary to make sure that the shared library is
# loaded for remote targets.
diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw4.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw4.exp
index c0c2635..d4407d7 100644
--- a/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw4.exp
+++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw4.exp
@@ -18,6 +18,10 @@
# Generate binaries imitating different ways source file paths can be passed to
# compilers. Test printing macros from those binaries.
+load_lib dwarf.exp
+
+require dwarf2_support
+
# The do_test proc comes from macro-source-path.exp.tcl.
source $srcdir/$subdir/macro-source-path.exp.tcl
diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw5.exp b/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw5.exp
index 0b3239e..23a40ba 100644
--- a/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw5.exp
+++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-clang14-dw5.exp
@@ -18,6 +18,10 @@
# Generate binaries imitating different ways source file paths can be passed to
# compilers. Test printing macros from those binaries.
+load_lib dwarf.exp
+
+require dwarf2_support
+
# The do_test proc comes from macro-source-path.exp.tcl.
source $srcdir/$subdir/macro-source-path.exp.tcl
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
index 940f997..99f7857 100644
--- a/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld234-dw5.exp
+++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld234-dw5.exp
@@ -18,6 +18,10 @@
# Generate binaries imitating different ways source file paths can be passed to
# compilers. Test printing macros from those binaries.
+load_lib dwarf.exp
+
+require dwarf2_support
+
# The do_test proc comes from macro-source-path.exp.tcl.
source $srcdir/$subdir/macro-source-path.exp.tcl
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
index dea0308..569b409 100644
--- a/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw4.exp
+++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw4.exp
@@ -18,6 +18,10 @@
# Generate binaries imitating different ways source file paths can be passed to
# compilers. Test printing macros from those binaries.
+load_lib dwarf.exp
+
+require dwarf2_support
+
# The do_test proc comes from macro-source-path.exp.tcl.
source $srcdir/$subdir/macro-source-path.exp.tcl
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
index 98a278e..0517d29 100644
--- a/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw5.exp
+++ b/gdb/testsuite/gdb.dwarf2/macro-source-path-gcc11-ld238-dw5.exp
@@ -18,6 +18,10 @@
# Generate binaries imitating different ways source file paths can be passed to
# compilers. Test printing macros from those binaries.
+load_lib dwarf.exp
+
+require dwarf2_support
+
# The do_test proc comes from macro-source-path.exp.tcl.
source $srcdir/$subdir/macro-source-path.exp.tcl
diff --git a/gdb/testsuite/gdb.dwarf2/macro-source-path.exp.tcl b/gdb/testsuite/gdb.dwarf2/macro-source-path.exp.tcl
index ecaf685..6254286 100644
--- a/gdb/testsuite/gdb.dwarf2/macro-source-path.exp.tcl
+++ b/gdb/testsuite/gdb.dwarf2/macro-source-path.exp.tcl
@@ -21,10 +21,6 @@
# 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 macro-source-path.c
lassign [function_range main $srcdir/$subdir/$srcfile] \
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.dwarf2/varval.exp b/gdb/testsuite/gdb.dwarf2/varval.exp
index 0693f43..6846ecb 100644
--- a/gdb/testsuite/gdb.dwarf2/varval.exp
+++ b/gdb/testsuite/gdb.dwarf2/varval.exp
@@ -348,6 +348,6 @@ if ![runto_main] {
}
gdb_test "print badval" "value has been optimized out"
gdb_test "print bad_die_val1" \
- "invalid dwarf2 offset 0xabcdef11"
+ {DWARF Error: could not find unit containing offset 0xabcdef11 \[in module .*/varval\]}
gdb_test "print bad_die_val2" \
"Bad DW_OP_GNU_variable_value DIE\\."
diff --git a/gdb/testsuite/gdb.fortran/array-slices.exp b/gdb/testsuite/gdb.fortran/array-slices.exp
index b1e3dad..f0b649b 100644
--- a/gdb/testsuite/gdb.fortran/array-slices.exp
+++ b/gdb/testsuite/gdb.fortran/array-slices.exp
@@ -56,7 +56,7 @@ proc array_slice_to_var { slice_str } {
proc run_test { repack } {
global binfile gdb_prompt
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if ![fortran_runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.fortran/call-no-debug.exp b/gdb/testsuite/gdb.fortran/call-no-debug.exp
index 1b158c4..75298cc 100644
--- a/gdb/testsuite/gdb.fortran/call-no-debug.exp
+++ b/gdb/testsuite/gdb.fortran/call-no-debug.exp
@@ -22,7 +22,7 @@ standard_testfile call-no-debug-prog.f90 call-no-debug-func.f90
load_lib fortran.exp
if {[prepare_for_testing_full "failed to prepare" \
- [list ${binfile} [list debug f90] \
+ [list $testfile [list debug f90] \
$srcfile [list debug f90] \
$srcfile2 [list nodebug f90]]]} {
return -1
diff --git a/gdb/testsuite/gdb.fortran/huge.exp b/gdb/testsuite/gdb.fortran/huge.exp
index 35bc6c8..47bac78 100644
--- a/gdb/testsuite/gdb.fortran/huge.exp
+++ b/gdb/testsuite/gdb.fortran/huge.exp
@@ -49,7 +49,7 @@ for { set size [expr $max] } { $size >= $min } { set size [expr $size / 2] } {
require {expr $compilation_succeeded}
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart ${::testfile}
save_vars { timeout } {
set timeout 30
diff --git a/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp b/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp
index ac8f742..b59fb2c 100644
--- a/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp
+++ b/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp
@@ -28,7 +28,7 @@ require allow_fortran_tests
standard_testfile mixed-lang-stack.c mixed-lang-stack.cpp mixed-lang-stack.f90
if {[prepare_for_testing_full "failed to prepare" \
- [list ${binfile} {debug f90 additional_flags=-lstdc++} \
+ [list $testfile {debug f90 additional_flags=-lstdc++} \
$srcfile {debug} \
$srcfile2 {debug c++ additional_flags=-std=c++11} \
$srcfile3 {debug f90}]]} {
@@ -43,7 +43,7 @@ proc run_tests { lang } {
with_test_prefix "lang=${lang}" {
global binfile hex have_index
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if ![runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.gdb/index-file.exp b/gdb/testsuite/gdb.gdb/index-file.exp
index 2252b79..ee5b645 100644
--- a/gdb/testsuite/gdb.gdb/index-file.exp
+++ b/gdb/testsuite/gdb.gdb/index-file.exp
@@ -30,9 +30,17 @@ if { $filename eq "" } {
return -1
}
+# If FILENAME is a libtool wrapper, then we need to get the path of the real
+# executable.
+set filename [selftest_libtool_get_real_gdb_executable $filename]
+if { $filename eq "" } {
+ return -1
+}
+
with_timeout_factor $timeout_factor {
# Start GDB, load FILENAME.
- clean_restart $filename
+ clean_restart
+ gdb_load $filename
}
# Record how many worker threads GDB is using.
diff --git a/gdb/testsuite/gdb.gdb/python-helper.exp b/gdb/testsuite/gdb.gdb/python-helper.exp
index 4b9adb0..33243c9 100644
--- a/gdb/testsuite/gdb.gdb/python-helper.exp
+++ b/gdb/testsuite/gdb.gdb/python-helper.exp
@@ -264,13 +264,31 @@ proc test_python_helper {} {
gdb_test -prompt $outer_prompt_re "print varobj_table" \
"htab_t with ${::decimal} elements"
+ set inferior_list_supported 1
+ set inferior_list_unsupported_re "type = intrusive_list"
+ gdb_test_multiple "what inferior_list" "" -prompt $outer_prompt_re {
+ -re -wrap $inferior_list_unsupported_re {
+ set inferior_list_supported 0
+ pass $gdb_test_name
+ }
+ -re -wrap "" {
+ pass $gdb_test_name
+ }
+ }
+
# Test the intrusive_list pretty-printer. A bug occurred in the
# pretty-printer for lists with more than one element. Verify that
# we see both elements of the inferior_list list being printed.
- gdb_test -prompt $outer_prompt_re "print inferior_list" "intrusive list of inferior = {.*, num = 1,.*, num = 2,.*}"
+ set test "print inferior_list"
+ if { $inferior_list_supported } {
+ gdb_test -prompt $outer_prompt_re $test \
+ "intrusive list of inferior = {.*, num = 1,.*, num = 2,.*}"
+ } else {
+ unsupported $test
+ }
return 0
}
# Use the self-test framework to run the test.
-do_self_tests captured_main test_python_helper
+do_self_tests test_python_helper
diff --git a/gdb/testsuite/gdb.gdb/selftest.exp b/gdb/testsuite/gdb.gdb/selftest.exp
index 1cf9265..f5cea1d 100644
--- a/gdb/testsuite/gdb.gdb/selftest.exp
+++ b/gdb/testsuite/gdb.gdb/selftest.exp
@@ -167,5 +167,5 @@ proc test_with_self { } {
save_vars { INTERNAL_GDBFLAGS } {
set INTERNAL_GDBFLAGS [string map {"-q" ""} $INTERNAL_GDBFLAGS]
- do_self_tests captured_main test_with_self
+ do_self_tests test_with_self
}
diff --git a/gdb/testsuite/gdb.gdb/unittest.exp b/gdb/testsuite/gdb.gdb/unittest.exp
index 795a32b..38955ca 100644
--- a/gdb/testsuite/gdb.gdb/unittest.exp
+++ b/gdb/testsuite/gdb.gdb/unittest.exp
@@ -63,7 +63,7 @@ proc run_selftests { binfile } {
gdb_exit
gdb_start
} else {
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
if { [is_remote host] } {
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..4c6a9c2 100644
--- a/gdb/testsuite/gdb.guile/scm-color.exp
+++ b/gdb/testsuite/gdb.guile/scm-color.exp
@@ -19,8 +19,12 @@
load_lib gdb-guile.exp
require allow_guile_tests
+require {!is_remote host}
-clean_restart
+# Start GDB with styling support.
+with_ansi_styling_terminal {
+ clean_restart
+}
gdb_install_guile_utils
gdb_install_guile_module
@@ -108,3 +112,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..acd78b9 100644
--- a/gdb/testsuite/gdb.guile/scm-parameter.exp
+++ b/gdb/testsuite/gdb.guile/scm-parameter.exp
@@ -39,7 +39,8 @@ if { [is_remote host] } {
gdb_test "guile (print (parameter-value \"directories\"))" \
"\\\$cdir.\\\$cwd"
} else {
- set escaped_directory [string_to_regexp "$srcdir/$subdir"]
+ set directory [host_file_normalize "$::srcdir/$::subdir"]
+ set escaped_directory [string_to_regexp $directory]
gdb_test "guile (print (parameter-value \"directories\"))" \
"$escaped_directory.\\\$cdir.\\\$cwd"
}
@@ -67,9 +68,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 +325,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,60 +398,218 @@ 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"
}
-rename scm_param_test_maybe_no_output ""
-
-# Test a color parameter.
+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"
-with_ansi_styling_terminal {
- # This enables 256 colors support and disables colors approximation.
- setenv TERM xterm-256color
- setenv COLORTERM truecolor
+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"
- # Start with a fresh gdb.
- gdb_exit
- gdb_start
- gdb_reinitialize_dir $srcdir/$subdir
+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_install_guile_utils
- gdb_install_guile_module
+gdb_test "show foo1 bar" "^The state of 'foo bar' is on\\." "show parameter 'foo bar'"
- # We use "." here instead of ":" so that this works on win32 too.
- set escaped_directory [string_to_regexp "$srcdir/$subdir"]
+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."]
- gdb_test_multiline "color gdb parameter" \
+with_test_prefix "empty doc string" {
+ gdb_test_multiline "empty doc string parameter" \
"guile" "" \
- "(define test-color-param" "" \
- " (make-parameter \"print test-color-param\"" "" \
- " #:command-class COMMAND_DATA" "" \
- " #:parameter-type PARAM_COLOR" "" \
- " #:doc \"When set, test param does something useful. When disabled, does nothing.\"" "" \
- " #:show-doc \"Show the state of the test-color-param.\"" "" \
- " #:set-doc \"Set the state of the test-color-param.\"" "" \
- " #:show-func (lambda (self value)" "" \
- " (format #f \"The state of the test-color-param is ~a.\" value))" "" \
- " #:initial-value (make-color \"green\")))" "" \
- "(register-parameter! test-color-param)" "" \
+ "(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"
- with_test_prefix "test-color-param" {
- with_test_prefix "initial-value" {
- gdb_test "guile (print (parameter-value test-color-param))" "= #<gdb:color green COLORSPACE_ANSI_8COLOR>" "color parameter value (green)"
- gdb_test "show print test-color-param" "The state of the test-color-param is green." "show initial value"
- gdb_test_no_output "set print test-color-param 255"
- }
- with_test_prefix "new-value" {
- gdb_test "show print test-color-param" "The state of the test-color-param is 255." "show new value"
- gdb_test "guile (print (parameter-value test-color-param))" "= #<gdb:color 255 COLORSPACE_XTERM_256COLOR>" "color parameter value (255)"
- gdb_test "set print test-color-param 256" "integer 256 out of range.*" "set invalid color parameter"
+ 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 ""
+
+# Test a color parameter.
+
+if { ![is_remote host] } {
+ with_ansi_styling_terminal {
+
+ # This enables 256 colors support and disables colors approximation.
+ setenv TERM xterm-256color
+ setenv COLORTERM truecolor
+
+ # Start with a fresh gdb.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+
+ gdb_install_guile_utils
+ gdb_install_guile_module
+
+ # We use "." here instead of ":" so that this works on win32 too.
+ set escaped_directory [string_to_regexp "$srcdir/$subdir"]
+
+ gdb_test_multiline "color gdb parameter" \
+ "guile" "" \
+ "(define test-color-param" "" \
+ " (make-parameter \"print test-color-param\"" "" \
+ " #:command-class COMMAND_DATA" "" \
+ " #:parameter-type PARAM_COLOR" "" \
+ " #:doc \"When set, test param does something useful. When disabled, does nothing.\"" "" \
+ " #:show-doc \"Show the state of the test-color-param.\"" "" \
+ " #:set-doc \"Set the state of the test-color-param.\"" "" \
+ " #:show-func (lambda (self value)" "" \
+ " (format #f \"The state of the test-color-param is ~a.\" value))" "" \
+ " #:initial-value (make-color \"green\")))" "" \
+ "(register-parameter! test-color-param)" "" \
+ "end"
+
+ with_test_prefix "test-color-param" {
+ with_test_prefix "initial-value" {
+ gdb_test "guile (print (parameter-value test-color-param))" "= #<gdb:color green COLORSPACE_ANSI_8COLOR>" "color parameter value (green)"
+ gdb_test "show print test-color-param" "The state of the test-color-param is green." "show initial value"
+ gdb_test_no_output "set print test-color-param 255"
+ }
+ with_test_prefix "new-value" {
+ gdb_test "show print test-color-param" "The state of the test-color-param is 255." "show new value"
+ gdb_test "guile (print (parameter-value test-color-param))" "= #<gdb:color 255 COLORSPACE_XTERM_256COLOR>" "color parameter value (255)"
+ gdb_test "set print test-color-param 256" "integer 256 out of range.*" "set invalid color parameter"
+ }
}
}
}
diff --git a/gdb/testsuite/gdb.guile/scm-pretty-print.exp b/gdb/testsuite/gdb.guile/scm-pretty-print.exp
index 09717a9..b95c0cb 100644
--- a/gdb/testsuite/gdb.guile/scm-pretty-print.exp
+++ b/gdb/testsuite/gdb.guile/scm-pretty-print.exp
@@ -33,7 +33,8 @@ proc run_lang_tests {exefile lang} {
set nl "\[\r\n\]+"
# Start with a fresh gdb.
- clean_restart $exefile
+ clean_restart
+ gdb_load $exefile
if ![gdb_guile_runto_main] {
return
@@ -114,7 +115,7 @@ run_lang_tests "${binfile}-cxx" "c++"
# Run various other tests.
-clean_restart $binfile
+clean_restart $::testfile
if ![gdb_guile_runto_main] {
return
diff --git a/gdb/testsuite/gdb.guile/scm-symbol.exp b/gdb/testsuite/gdb.guile/scm-symbol.exp
index b6ebffd..96bd560 100644
--- a/gdb/testsuite/gdb.guile/scm-symbol.exp
+++ b/gdb/testsuite/gdb.guile/scm-symbol.exp
@@ -141,7 +141,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}-cxx" executable "
return -1
}
-clean_restart ${binfile}-cxx
+clean_restart ${::testfile}-cxx
if ![gdb_guile_runto_main] {
return
diff --git a/gdb/testsuite/gdb.guile/scm-type.exp b/gdb/testsuite/gdb.guile/scm-type.exp
index 1167dd1..640dd5b 100644
--- a/gdb/testsuite/gdb.guile/scm-type.exp
+++ b/gdb/testsuite/gdb.guile/scm-type.exp
@@ -38,7 +38,8 @@ proc build_inferior {exefile lang} {
proc restart_gdb {exefile} {
global srcdir subdir
- clean_restart $exefile
+ clean_restart
+ gdb_load $exefile
if { ![allow_guile_tests] } {
return 0
diff --git a/gdb/testsuite/gdb.guile/scm-value.exp b/gdb/testsuite/gdb.guile/scm-value.exp
index 1567b13..d723aeb 100644
--- a/gdb/testsuite/gdb.guile/scm-value.exp
+++ b/gdb/testsuite/gdb.guile/scm-value.exp
@@ -309,7 +309,8 @@ proc test_value_after_death {} {
proc test_subscript_regression {exefile lang} {
# Start with a fresh gdb.
- clean_restart ${exefile}
+ clean_restart
+ gdb_load ${exefile}
if ![gdb_guile_runto_main ] {
return
@@ -427,7 +428,7 @@ if { [build_inferior "${binfile}" "c"] < 0 } {
}
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_install_guile_utils
gdb_install_guile_module
diff --git a/gdb/testsuite/gdb.linespec/explicit.exp b/gdb/testsuite/gdb.linespec/explicit.exp
index 12eaa51..b859b44 100644
--- a/gdb/testsuite/gdb.linespec/explicit.exp
+++ b/gdb/testsuite/gdb.linespec/explicit.exp
@@ -608,7 +608,7 @@ namespace eval $testfile {
}
# Test interaction of condition command and explicit linespec conditons.
- clean_restart [standard_output_file $exefile]
+ clean_restart $exefile
set tst "condition_command overrides explicit linespec condition"
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.exp b/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.exp
index 012be6b..120ee6c 100644
--- a/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.exp
+++ b/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.exp
@@ -32,7 +32,7 @@ if {[build_executable "failed to prepare" ${testfile} ${srcfile} $opts]} {
}
proc do_test {} {
- clean_restart $::binfile
+ clean_restart $::testfile
# To make things easier, just so we don't have to deal with the question.
gdb_test_no_output "set breakpoint pending on"
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/dw2-ref-missing-frame.exp b/gdb/testsuite/gdb.mi/dw2-ref-missing-frame.exp
index 3fd9b81..0565681 100644
--- a/gdb/testsuite/gdb.mi/dw2-ref-missing-frame.exp
+++ b/gdb/testsuite/gdb.mi/dw2-ref-missing-frame.exp
@@ -42,7 +42,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" $objsfile object {}] != ""
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
@@ -54,7 +54,7 @@ if [mi_runto func_nofb_marker] {
}
# GDB could have crashed.
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/gdb2549.exp b/gdb/testsuite/gdb.mi/gdb2549.exp
index 796c1fa..5aabc3b 100644
--- a/gdb/testsuite/gdb.mi/gdb2549.exp
+++ b/gdb/testsuite/gdb.mi/gdb2549.exp
@@ -94,7 +94,7 @@ proc register_tests { } {
register_test 666 t $binary
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
register_tests_no_exec
diff --git a/gdb/testsuite/gdb.mi/gdb669.exp b/gdb/testsuite/gdb.mi/gdb669.exp
index 086d3c1..da1db64 100644
--- a/gdb/testsuite/gdb.mi/gdb669.exp
+++ b/gdb/testsuite/gdb.mi/gdb669.exp
@@ -30,7 +30,7 @@ if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $option
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
check_mi_and_console_threads "at main"
diff --git a/gdb/testsuite/gdb.mi/gdb701.exp b/gdb/testsuite/gdb.mi/gdb701.exp
index 587481c..9ef6fb7 100644
--- a/gdb/testsuite/gdb.mi/gdb701.exp
+++ b/gdb/testsuite/gdb.mi/gdb701.exp
@@ -35,7 +35,7 @@ if {[gdb_compile $srcdir/$subdir/$srcfile $binfile executable debug] != ""} {
# If it doesn't, Bad Things Happen(TM).
# Run to main
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
# Step over "foo = 0"
diff --git a/gdb/testsuite/gdb.mi/gdb792.exp b/gdb/testsuite/gdb.mi/gdb792.exp
index f894eea..64f218a 100644
--- a/gdb/testsuite/gdb.mi/gdb792.exp
+++ b/gdb/testsuite/gdb.mi/gdb792.exp
@@ -28,7 +28,7 @@ if {[gdb_compile $srcdir/$subdir/$srcfile $binfile executable {debug c++}] != ""
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
diff --git a/gdb/testsuite/gdb.mi/interrupt-thread-group.exp b/gdb/testsuite/gdb.mi/interrupt-thread-group.exp
index ff35109..5f9e49e 100644
--- a/gdb/testsuite/gdb.mi/interrupt-thread-group.exp
+++ b/gdb/testsuite/gdb.mi/interrupt-thread-group.exp
@@ -30,7 +30,7 @@ if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile \
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop on\" -ex \"set mi-async\""
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
}
mi_detect_async
@@ -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-add-inferior.exp b/gdb/testsuite/gdb.mi/mi-add-inferior.exp
index d110e68..8c4926f 100644
--- a/gdb/testsuite/gdb.mi/mi-add-inferior.exp
+++ b/gdb/testsuite/gdb.mi/mi-add-inferior.exp
@@ -26,7 +26,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
return -1
}
-mi_clean_restart ${binfile}
+mi_clean_restart ${::testfile}
# Start execution to establish a connection.
mi_runto_main
diff --git a/gdb/testsuite/gdb.mi/mi-async-run.exp b/gdb/testsuite/gdb.mi/mi-async-run.exp
index 8352803..3df8769 100644
--- a/gdb/testsuite/gdb.mi/mi-async-run.exp
+++ b/gdb/testsuite/gdb.mi/mi-async-run.exp
@@ -35,7 +35,7 @@ proc test_async_run {} {
set GDBFLAGS [concat $GDBFLAGS " -ex \"set mi-async on\""]
- if {[mi_clean_restart $binfile]} {
+ if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-async.exp b/gdb/testsuite/gdb.mi/mi-async.exp
index 09db7f9..1c4e06c 100644
--- a/gdb/testsuite/gdb.mi/mi-async.exp
+++ b/gdb/testsuite/gdb.mi/mi-async.exp
@@ -42,7 +42,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
save_vars { GDBFLAGS } {
set GDBFLAGS [concat $GDBFLAGS " -ex \"set mi-async on\""]
- if {[mi_clean_restart $binfile]} {
+ if {[mi_clean_restart $::testfile]} {
return
}
}
diff --git a/gdb/testsuite/gdb.mi/mi-break-qualified.exp b/gdb/testsuite/gdb.mi/mi-break-qualified.exp
index b5e5e78..9adc2d9 100644
--- a/gdb/testsuite/gdb.mi/mi-break-qualified.exp
+++ b/gdb/testsuite/gdb.mi/mi-break-qualified.exp
@@ -93,7 +93,7 @@ proc test_break_qualified {} {
"delete temp breakpoints"
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp
index bb982c3..2a212c3 100644
--- a/gdb/testsuite/gdb.mi/mi-break.exp
+++ b/gdb/testsuite/gdb.mi/mi-break.exp
@@ -398,7 +398,7 @@ proc test_break {mi_mode} {
} else {
set start_ops ""
}
- if [mi_clean_restart $binfile $start_ops ] {
+ if [mi_clean_restart $::testfile $start_ops ] {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
index 9cb91de..46561e4 100644
--- a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
+++ b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
@@ -48,7 +48,7 @@ proc test_insert_delete_modify { } {
global lib_sl1 lib_sl2
global binfile
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
mi_load_shlibs $lib_sl1 $lib_sl2
@@ -184,7 +184,7 @@ proc test_pending_resolved { } {
global lib_sl1 lib_sl2
global mi_gdb_prompt
- if {[mi_clean_restart $binfile]} {
+ if {[mi_clean_restart $::testfile]} {
return
}
mi_load_shlibs $lib_sl1 $lib_sl2
@@ -279,7 +279,7 @@ proc test_auto_disable { } {
global lib_sl1 lib_sl2
global binfile
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
mi_load_shlibs $lib_sl1 $lib_sl2
diff --git a/gdb/testsuite/gdb.mi/mi-breakpoint-multiple-locations.exp b/gdb/testsuite/gdb.mi/mi-breakpoint-multiple-locations.exp
index cbf9f57..7995846 100644
--- a/gdb/testsuite/gdb.mi/mi-breakpoint-multiple-locations.exp
+++ b/gdb/testsuite/gdb.mi/mi-breakpoint-multiple-locations.exp
@@ -56,7 +56,7 @@ proc do_test { mi_version use_fix_flag expect_fixed_output } {
global MIFLAGS decimal binfile
set MIFLAGS "-i=mi${mi_version}"
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
mi_runto_main
diff --git a/gdb/testsuite/gdb.mi/mi-breakpoint-script.exp b/gdb/testsuite/gdb.mi/mi-breakpoint-script.exp
index af514e8..ce30d44 100644
--- a/gdb/testsuite/gdb.mi/mi-breakpoint-script.exp
+++ b/gdb/testsuite/gdb.mi/mi-breakpoint-script.exp
@@ -51,7 +51,7 @@ proc do_test { mi_version use_fix_flag expect_fixed_output } {
save_vars { ::MIFLAGS } {
set ::MIFLAGS "-i=mi${mi_version}"
- mi_clean_restart $::binfile
+ mi_clean_restart $::testfile
}
if $use_fix_flag {
diff --git a/gdb/testsuite/gdb.mi/mi-catch-cpp-exceptions.exp b/gdb/testsuite/gdb.mi/mi-catch-cpp-exceptions.exp
index 9053b18..ec023e6 100644
--- a/gdb/testsuite/gdb.mi/mi-catch-cpp-exceptions.exp
+++ b/gdb/testsuite/gdb.mi/mi-catch-cpp-exceptions.exp
@@ -27,7 +27,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
if {[mi_runto_main] < 0} {
return -1
}
@@ -46,7 +46,7 @@ proc restart_for_test {} {
global srcdir subdir binfile srcfile
global main_lineno
- if {[mi_clean_restart $binfile]} {
+ if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-catch-load.exp b/gdb/testsuite/gdb.mi/mi-catch-load.exp
index a9a5fdc..3c36cc9 100644
--- a/gdb/testsuite/gdb.mi/mi-catch-load.exp
+++ b/gdb/testsuite/gdb.mi/mi-catch-load.exp
@@ -36,7 +36,7 @@ gdb_download_shlib $binfile2
# test -catch-load
with_test_prefix "catch-load" {
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
mi_locate_shlib $binfile2
mi_runto_main
@@ -63,7 +63,7 @@ with_test_prefix "catch-load" {
# test -catch-unload
with_test_prefix "catch-unload" {
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
mi_locate_shlib $binfile2
mi_runto_main
diff --git a/gdb/testsuite/gdb.mi/mi-cli.exp b/gdb/testsuite/gdb.mi/mi-cli.exp
index a3ff7eb..b59a5ed 100644
--- a/gdb/testsuite/gdb.mi/mi-cli.exp
+++ b/gdb/testsuite/gdb.mi/mi-cli.exp
@@ -29,7 +29,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_gdb_test "-interpreter-exec" \
{\^error,msg="-interpreter-exec: Usage: -interpreter-exec interp command"} \
diff --git a/gdb/testsuite/gdb.mi/mi-cmd-param-changed.exp b/gdb/testsuite/gdb.mi/mi-cmd-param-changed.exp
index 5587b76..24d12c1 100644
--- a/gdb/testsuite/gdb.mi/mi-cmd-param-changed.exp
+++ b/gdb/testsuite/gdb.mi/mi-cmd-param-changed.exp
@@ -31,7 +31,7 @@ proc test_command_param_changed { } {
global binfile
with_test_prefix "cmd param" {
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
mi_runto_main
if { $scheduler_locking_supported } {
diff --git a/gdb/testsuite/gdb.mi/mi-cmd-user-context.exp b/gdb/testsuite/gdb.mi/mi-cmd-user-context.exp
index 806ed4c..324de5a 100644
--- a/gdb/testsuite/gdb.mi/mi-cmd-user-context.exp
+++ b/gdb/testsuite/gdb.mi/mi-cmd-user-context.exp
@@ -29,7 +29,7 @@ set main_break_line [gdb_get_line_number "main break line"]
set any "\[^\r\n\]*"
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_create_breakpoint "$srcfile:$main_break_line" "set breakpoint in main"
mi_run_cmd
mi_expect_stop "breakpoint-hit" "main" "" $srcfile $main_break_line \
diff --git a/gdb/testsuite/gdb.mi/mi-complete.exp b/gdb/testsuite/gdb.mi/mi-complete.exp
index 22acda3..ad29b3f 100644
--- a/gdb/testsuite/gdb.mi/mi-complete.exp
+++ b/gdb/testsuite/gdb.mi/mi-complete.exp
@@ -26,7 +26,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debu
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
# Don't run to main to avoid increasing the search scope to include
# debug info of shared libraries like glibc, libgcc, etc.
diff --git a/gdb/testsuite/gdb.mi/mi-condbreak-call-thr-state.exp b/gdb/testsuite/gdb.mi/mi-condbreak-call-thr-state.exp
index 02d02b2..7708a6d 100644
--- a/gdb/testsuite/gdb.mi/mi-condbreak-call-thr-state.exp
+++ b/gdb/testsuite/gdb.mi/mi-condbreak-call-thr-state.exp
@@ -59,7 +59,7 @@ proc test { variant } {
return -1
}
- if {[mi_clean_restart $binfile]} {
+ if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-condbreak-fail.exp b/gdb/testsuite/gdb.mi/mi-condbreak-fail.exp
index 43b1e2f..5bd8993 100644
--- a/gdb/testsuite/gdb.mi/mi-condbreak-fail.exp
+++ b/gdb/testsuite/gdb.mi/mi-condbreak-fail.exp
@@ -35,7 +35,7 @@ if [build_executable ${testfile}.exp ${binfile} ${srcfile}] {
proc run_test { unwind_on_signal } {
- if {[mi_clean_restart $::binfile]} {
+ if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-condbreak-throw.exp b/gdb/testsuite/gdb.mi/mi-condbreak-throw.exp
index 9897b2b..b4960a8 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
@@ -38,7 +38,7 @@ if [build_executable ${testfile}.exp ${binfile} ${srcfile} {debug c++}] {
proc run_test { unwind_on_exception } {
- if {[mi_clean_restart $::binfile]} {
+ if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-console.exp b/gdb/testsuite/gdb.mi/mi-console.exp
index efb1ea9..861ef42 100644
--- a/gdb/testsuite/gdb.mi/mi-console.exp
+++ b/gdb/testsuite/gdb.mi/mi-console.exp
@@ -53,7 +53,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-corefile.exp b/gdb/testsuite/gdb.mi/mi-corefile.exp
index 3f0e720..b491486 100644
--- a/gdb/testsuite/gdb.mi/mi-corefile.exp
+++ b/gdb/testsuite/gdb.mi/mi-corefile.exp
@@ -29,6 +29,7 @@ if {[build_executable $testfile.exp $testfile $srcfile debug] == -1} {
set corefile [core_find $binfile {}]
if {$corefile == ""} {
+ untested "unable to create or find corefile"
return 0
}
diff --git a/gdb/testsuite/gdb.mi/mi-detach.exp b/gdb/testsuite/gdb.mi/mi-detach.exp
index ff983c1..b485a9b 100644
--- a/gdb/testsuite/gdb.mi/mi-detach.exp
+++ b/gdb/testsuite/gdb.mi/mi-detach.exp
@@ -25,7 +25,7 @@ if {[build_executable $testfile.exp $testfile $srcfile {debug}] == -1} {
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
mi_gdb_test "-target-detach" "=thread-exited,id=\"1\".*=thread-group-exited,id=\"i1\".*" "detach"
diff --git a/gdb/testsuite/gdb.mi/mi-disassemble.exp b/gdb/testsuite/gdb.mi/mi-disassemble.exp
index 15ead33..90f79e3 100644
--- a/gdb/testsuite/gdb.mi/mi-disassemble.exp
+++ b/gdb/testsuite/gdb.mi/mi-disassemble.exp
@@ -345,7 +345,7 @@ proc test_disassembly_opcode_format {} {
"data-disassemble checking the opcodes bytes format"
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
test_disassembly_only
test_disassembly_with_opcodes
diff --git a/gdb/testsuite/gdb.mi/mi-dlmopen.exp b/gdb/testsuite/gdb.mi/mi-dlmopen.exp
index c0208eb..0e1d0bc 100644
--- a/gdb/testsuite/gdb.mi/mi-dlmopen.exp
+++ b/gdb/testsuite/gdb.mi/mi-dlmopen.exp
@@ -65,9 +65,19 @@ if { $dyln_name eq "" } {
set bp_main [gdb_get_line_number "bp.main" $srcfile]
set bp_loaded [gdb_get_line_number "bp.loaded" $srcfile]
+# If the dynamic linker path contains a symlink, some instances show the real
+# path instead of the original path. Accept both.
+lassign [remote_exec target realpath "$dyln_name"] realpath_ret dyln_realpath_name
+
+if { $realpath_ret == 0 } {
+ set dyln_realpath_name [string trim $dyln_realpath_name]
+} else {
+ set dyln_realpath_name "not-a-valid-path"
+}
+
# Return true if FILENAME is the dynamic linker. Otherwise return false.
proc is_dyln { filename } {
- return [expr {$filename eq $::dyln_name}]
+ return [expr {$filename eq $::dyln_name || $filename eq $::dyln_realpath_name}]
}
# Run 'info sharedlibrary' and count the number of mappings that look
@@ -81,7 +91,7 @@ proc get_dyld_info {} {
set dyld_count 0
set dyld_start_addr ""
gdb_test_multiple "info sharedlibrary" "" {
- -re "~\"From\\s+To(\\s+NS)?\\s+Syms\\s+Read\\s+Shared Object Library\\\\n\"\r\n" {
+ -re "~\"From\\s+To(\\s+Linker NS)?\\s+Syms\\s+Read\\s+Shared Object Library\\\\n\"\r\n" {
exp_continue
}
-re "^~\"($::hex)\\s+${::hex}(\\s+$::decimal)?\\s+\[^/\]+(/\[^\r\n\]+)\\\\n\"\r\n" {
@@ -122,7 +132,7 @@ proc get_dyld_info {} {
# number of unload events for the libraries created for this test, and
# additionally, check for dynamic linker unload events.
proc check_solib_unload_events {} {
- mi_clean_restart $::binfile
+ mi_clean_restart $::testfile
if {[mi_runto_main] == -1} {
return
diff --git a/gdb/testsuite/gdb.mi/mi-dprintf-modified.exp b/gdb/testsuite/gdb.mi/mi-dprintf-modified.exp
index c3e1bdf..0584a86 100644
--- a/gdb/testsuite/gdb.mi/mi-dprintf-modified.exp
+++ b/gdb/testsuite/gdb.mi/mi-dprintf-modified.exp
@@ -52,7 +52,7 @@ if { [build_executable "build exec" $binfile $srcfile $opts] == -1} {
set bp_line [gdb_get_line_number "Break here" $srcfile]
# Start the inferior.
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
# Place a breakpoint at the dlopen() line.
diff --git a/gdb/testsuite/gdb.mi/mi-dprintf-pending.exp b/gdb/testsuite/gdb.mi/mi-dprintf-pending.exp
index 2df9ad4..3685e42 100644
--- a/gdb/testsuite/gdb.mi/mi-dprintf-pending.exp
+++ b/gdb/testsuite/gdb.mi/mi-dprintf-pending.exp
@@ -39,7 +39,7 @@ if {[gdb_compile $srcdir/$subdir/$srcfile $binfile executable $exec_opts] != ""}
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-dprintf.exp b/gdb/testsuite/gdb.mi/mi-dprintf.exp
index 5d448e4..9d0b95a 100644
--- a/gdb/testsuite/gdb.mi/mi-dprintf.exp
+++ b/gdb/testsuite/gdb.mi/mi-dprintf.exp
@@ -31,7 +31,7 @@ if {[build_executable $testfile.exp $testfile $srcfile $flags] == -1} {
set bp_location1 [gdb_get_line_number "set breakpoint 1 here"]
set dp_location1 [gdb_get_line_number "set dprintf 1 here"]
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
set i 0
diff --git a/gdb/testsuite/gdb.mi/mi-eval.exp b/gdb/testsuite/gdb.mi/mi-eval.exp
index 27c27f5..2b21895 100644
--- a/gdb/testsuite/gdb.mi/mi-eval.exp
+++ b/gdb/testsuite/gdb.mi/mi-eval.exp
@@ -32,7 +32,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-exec-run.exp b/gdb/testsuite/gdb.mi/mi-exec-run.exp
index a7a61b8..43406cf 100644
--- a/gdb/testsuite/gdb.mi/mi-exec-run.exp
+++ b/gdb/testsuite/gdb.mi/mi-exec-run.exp
@@ -30,6 +30,8 @@ set MIFLAGS "-i=mi"
# cannot use it, then there is no point in running this testcase.
require !use_gdb_stub
+set have_startup_shell [have_startup_shell]
+
standard_testfile mi-start.c
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
@@ -172,6 +174,9 @@ remote_exec target "chmod \"a-x\" $binfile.nox"
foreach_with_prefix inferior-tty {"main" "separate"} {
foreach_with_prefix mi {"main" "separate"} {
foreach_with_prefix force-fail {0 1} {
+ if { ${force-fail} && $have_startup_shell == -1 } {
+ continue
+ }
test ${inferior-tty} ${mi} ${force-fail}
}
}
diff --git a/gdb/testsuite/gdb.mi/mi-exit-code.exp b/gdb/testsuite/gdb.mi/mi-exit-code.exp
index 344d565..af2c6bd 100644
--- a/gdb/testsuite/gdb.mi/mi-exit-code.exp
+++ b/gdb/testsuite/gdb.mi/mi-exit-code.exp
@@ -36,7 +36,7 @@ proc test_list_thread_groups { } {
"122\\^done,groups=\\\[\{id=\"i1\",type=\"process\"\}\]" \
"-list-thread-groups before run shows no exit-code"
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
with_test_prefix "first run" {
mi_runto_main
diff --git a/gdb/testsuite/gdb.mi/mi-fill-memory.exp b/gdb/testsuite/gdb.mi/mi-fill-memory.exp
index 0afc258..ab7e03a 100644
--- a/gdb/testsuite/gdb.mi/mi-fill-memory.exp
+++ b/gdb/testsuite/gdb.mi/mi-fill-memory.exp
@@ -27,7 +27,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}.c" "${binfile}" executable {d
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
mi_next_to "main" "" "mi-read-memory.c" "20" "next at main"
diff --git a/gdb/testsuite/gdb.mi/mi-fortran-modules.exp b/gdb/testsuite/gdb.mi/mi-fortran-modules.exp
index 8886702..48391bc 100644
--- a/gdb/testsuite/gdb.mi/mi-fortran-modules.exp
+++ b/gdb/testsuite/gdb.mi/mi-fortran-modules.exp
@@ -28,7 +28,7 @@ if {[build_executable "failed to prepare" ${testfile} \
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
diff --git a/gdb/testsuite/gdb.mi/mi-frame-regs.exp b/gdb/testsuite/gdb.mi/mi-frame-regs.exp
index f31e4a1..990abd5 100644
--- a/gdb/testsuite/gdb.mi/mi-frame-regs.exp
+++ b/gdb/testsuite/gdb.mi/mi-frame-regs.exp
@@ -62,7 +62,7 @@ proc_with_prefix do_floating_varobj_test {} {
global hex
global expect_out
- if {[mi_clean_restart $binfile]} {
+ if {[mi_clean_restart $::testfile]} {
fail "couldn't start gdb"
return
}
@@ -113,7 +113,7 @@ proc_with_prefix do_fixed_varobj_test {} {
global srcfile binfile
global hex
- if {[mi_clean_restart $binfile] != 0} {
+ if {[mi_clean_restart $::testfile] != 0} {
fail "couldn't start gdb"
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-fullname-deleted.exp b/gdb/testsuite/gdb.mi/mi-fullname-deleted.exp
index 130b5bf..6c1dbec 100644
--- a/gdb/testsuite/gdb.mi/mi-fullname-deleted.exp
+++ b/gdb/testsuite/gdb.mi/mi-fullname-deleted.exp
@@ -58,7 +58,7 @@ if { [gdb_compile "$srcfileabs" "${binfile}" executable {debug}] != "" } {
file delete -- $srcfileabs
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-info-os.exp b/gdb/testsuite/gdb.mi/mi-info-os.exp
index 5d8d3ff..c70dac6 100644
--- a/gdb/testsuite/gdb.mi/mi-info-os.exp
+++ b/gdb/testsuite/gdb.mi/mi-info-os.exp
@@ -32,7 +32,7 @@ if [build_executable "Failed to build $testfile" $testfile $srcfile \
return -1;
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-info-sources.exp b/gdb/testsuite/gdb.mi/mi-info-sources.exp
index f44fc29..80ca596 100644
--- a/gdb/testsuite/gdb.mi/mi-info-sources.exp
+++ b/gdb/testsuite/gdb.mi/mi-info-sources.exp
@@ -26,7 +26,7 @@ if {[build_executable $testfile.exp $testfile \
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
set readnow_p [mi_readnow]
diff --git a/gdb/testsuite/gdb.mi/mi-inheritance-syntax-error.exp b/gdb/testsuite/gdb.mi/mi-inheritance-syntax-error.exp
index 0ab2de2..3092b692 100644
--- a/gdb/testsuite/gdb.mi/mi-inheritance-syntax-error.exp
+++ b/gdb/testsuite/gdb.mi/mi-inheritance-syntax-error.exp
@@ -25,7 +25,7 @@ if {[gdb_compile $srcdir/$subdir/$srcfile $binfile executable {debug c++}] != ""
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-linespec-err-cp.exp b/gdb/testsuite/gdb.mi/mi-linespec-err-cp.exp
index 3314d5f..7eeb259 100644
--- a/gdb/testsuite/gdb.mi/mi-linespec-err-cp.exp
+++ b/gdb/testsuite/gdb.mi/mi-linespec-err-cp.exp
@@ -29,7 +29,7 @@ if {[build_executable "failed to prepare" $exefile $srcfile {debug c++}]} {
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
# Turn off the pending breakpoint queries.
mi_gdb_test "-interpreter-exec console \"set breakpoint pending off\"" \
diff --git a/gdb/testsuite/gdb.mi/mi-logging.exp b/gdb/testsuite/gdb.mi/mi-logging.exp
index de76e02..8235591 100644
--- a/gdb/testsuite/gdb.mi/mi-logging.exp
+++ b/gdb/testsuite/gdb.mi/mi-logging.exp
@@ -24,7 +24,7 @@ if [build_executable $testfile.exp $testfile $srcfile $opts] {
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
if {[mi_runto_main] < 0} {
return -1
diff --git a/gdb/testsuite/gdb.mi/mi-memory-changed.exp b/gdb/testsuite/gdb.mi/mi-memory-changed.exp
index bc2b6c3..6d02c33 100644
--- a/gdb/testsuite/gdb.mi/mi-memory-changed.exp
+++ b/gdb/testsuite/gdb.mi/mi-memory-changed.exp
@@ -22,7 +22,7 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
load_lib mi-support.exp
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
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-nonstop-exit.exp b/gdb/testsuite/gdb.mi/mi-nonstop-exit.exp
index 599e460..4729033 100644
--- a/gdb/testsuite/gdb.mi/mi-nonstop-exit.exp
+++ b/gdb/testsuite/gdb.mi/mi-nonstop-exit.exp
@@ -30,7 +30,7 @@ if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $option
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop on\""
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
}
mi_gdb_test "-gdb-set mi-async 1" ".*"
diff --git a/gdb/testsuite/gdb.mi/mi-nonstop.exp b/gdb/testsuite/gdb.mi/mi-nonstop.exp
index b8efef7..1ba37a3 100644
--- a/gdb/testsuite/gdb.mi/mi-nonstop.exp
+++ b/gdb/testsuite/gdb.mi/mi-nonstop.exp
@@ -41,7 +41,7 @@ if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $option
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop on\""
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
}
mi_gdb_test "-gdb-set mi-async 1" ".*"
diff --git a/gdb/testsuite/gdb.mi/mi-ns-stale-regcache.exp b/gdb/testsuite/gdb.mi/mi-ns-stale-regcache.exp
index 20d9e45..20936f1 100644
--- a/gdb/testsuite/gdb.mi/mi-ns-stale-regcache.exp
+++ b/gdb/testsuite/gdb.mi/mi-ns-stale-regcache.exp
@@ -43,7 +43,7 @@ if {[gdb_compile "$srcdir/$subdir/$srcfile" \
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop on\""
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
}
mi_gdb_test "-gdb-set mi-async 1" ".*"
diff --git a/gdb/testsuite/gdb.mi/mi-nsintrall.exp b/gdb/testsuite/gdb.mi/mi-nsintrall.exp
index 983c0fe..8c8aef8 100644
--- a/gdb/testsuite/gdb.mi/mi-nsintrall.exp
+++ b/gdb/testsuite/gdb.mi/mi-nsintrall.exp
@@ -30,7 +30,7 @@ if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $option
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop on\""
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
}
mi_gdb_test "-gdb-set mi-async 1" ".*"
diff --git a/gdb/testsuite/gdb.mi/mi-nsmoribund.exp b/gdb/testsuite/gdb.mi/mi-nsmoribund.exp
index da43a93..2307c2e 100644
--- a/gdb/testsuite/gdb.mi/mi-nsmoribund.exp
+++ b/gdb/testsuite/gdb.mi/mi-nsmoribund.exp
@@ -30,7 +30,7 @@ if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $option
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop on\""
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
}
mi_gdb_test "-gdb-set mi-async 1" ".*"
diff --git a/gdb/testsuite/gdb.mi/mi-nsthrexec.exp b/gdb/testsuite/gdb.mi/mi-nsthrexec.exp
index fd8aa54..1f9d1ae 100644
--- a/gdb/testsuite/gdb.mi/mi-nsthrexec.exp
+++ b/gdb/testsuite/gdb.mi/mi-nsthrexec.exp
@@ -35,7 +35,7 @@ if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $option
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop on\""
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
}
mi_gdb_test "-gdb-set mi-async 1" ".*"
diff --git a/gdb/testsuite/gdb.mi/mi-pending.exp b/gdb/testsuite/gdb.mi/mi-pending.exp
index 49839cb..eb0719c 100644
--- a/gdb/testsuite/gdb.mi/mi-pending.exp
+++ b/gdb/testsuite/gdb.mi/mi-pending.exp
@@ -45,7 +45,7 @@ if { [gdb_compile_pthreads $srcdir/$subdir/$srcfile $binfile executable $exec_op
}
# Start with a fresh gdb.
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
mi_load_shlibs $lib_sl1
diff --git a/gdb/testsuite/gdb.mi/mi-pthreads.exp b/gdb/testsuite/gdb.mi/mi-pthreads.exp
index 93f0344..117b2de 100644
--- a/gdb/testsuite/gdb.mi/mi-pthreads.exp
+++ b/gdb/testsuite/gdb.mi/mi-pthreads.exp
@@ -63,7 +63,7 @@ if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $option
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-py-modify-bp.exp b/gdb/testsuite/gdb.mi/mi-py-modify-bp.exp
index 4193757..5175899 100644
--- a/gdb/testsuite/gdb.mi/mi-py-modify-bp.exp
+++ b/gdb/testsuite/gdb.mi/mi-py-modify-bp.exp
@@ -31,7 +31,7 @@ if {[build_executable $testfile.exp $testfile $srcfile] == -1} {
set remote_python_file [gdb_remote_download host \
${srcdir}/${subdir}/${testfile}.py]
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
# Delete all breakpoints, watchpoints, tracepoints, and catchpoints.
diff --git a/gdb/testsuite/gdb.mi/mi-read-memory.exp b/gdb/testsuite/gdb.mi/mi-read-memory.exp
index 8de8728..4469123 100644
--- a/gdb/testsuite/gdb.mi/mi-read-memory.exp
+++ b/gdb/testsuite/gdb.mi/mi-read-memory.exp
@@ -25,7 +25,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
mi_next_to "main" "" "mi-read-memory.c" "20" "next at main"
diff --git a/gdb/testsuite/gdb.mi/mi-record-changed.exp b/gdb/testsuite/gdb.mi/mi-record-changed.exp
index e37540b..986efd9 100644
--- a/gdb/testsuite/gdb.mi/mi-record-changed.exp
+++ b/gdb/testsuite/gdb.mi/mi-record-changed.exp
@@ -24,7 +24,7 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
load_lib mi-support.exp
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
diff --git a/gdb/testsuite/gdb.mi/mi-reg-undefined.exp b/gdb/testsuite/gdb.mi/mi-reg-undefined.exp
index c7e0564..ef102ce 100644
--- a/gdb/testsuite/gdb.mi/mi-reg-undefined.exp
+++ b/gdb/testsuite/gdb.mi/mi-reg-undefined.exp
@@ -29,7 +29,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-regs.exp b/gdb/testsuite/gdb.mi/mi-regs.exp
index 0bb305b..aae00a6 100644
--- a/gdb/testsuite/gdb.mi/mi-regs.exp
+++ b/gdb/testsuite/gdb.mi/mi-regs.exp
@@ -108,7 +108,7 @@ require {istarget "sparc-*-*"}
mi_clean_restart
sparc_register_tests_no_exec
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
sparc_register_tests
diff --git a/gdb/testsuite/gdb.mi/mi-return.exp b/gdb/testsuite/gdb.mi/mi-return.exp
index ba296d5..998a1ff 100644
--- a/gdb/testsuite/gdb.mi/mi-return.exp
+++ b/gdb/testsuite/gdb.mi/mi-return.exp
@@ -31,7 +31,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-reverse.exp b/gdb/testsuite/gdb.mi/mi-reverse.exp
index d039240..aa25255 100644
--- a/gdb/testsuite/gdb.mi/mi-reverse.exp
+++ b/gdb/testsuite/gdb.mi/mi-reverse.exp
@@ -39,7 +39,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
if [supports_process_record] {
diff --git a/gdb/testsuite/gdb.mi/mi-simplerun.exp b/gdb/testsuite/gdb.mi/mi-simplerun.exp
index e390f14..5ee7881 100644
--- a/gdb/testsuite/gdb.mi/mi-simplerun.exp
+++ b/gdb/testsuite/gdb.mi/mi-simplerun.exp
@@ -34,7 +34,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-solib.exp b/gdb/testsuite/gdb.mi/mi-solib.exp
index c66d4b0..8ddca8d 100644
--- a/gdb/testsuite/gdb.mi/mi-solib.exp
+++ b/gdb/testsuite/gdb.mi/mi-solib.exp
@@ -34,7 +34,7 @@ if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} $lib_flags] != ""
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-stack.exp b/gdb/testsuite/gdb.mi/mi-stack.exp
index a91b76e..89f58c8 100644
--- a/gdb/testsuite/gdb.mi/mi-stack.exp
+++ b/gdb/testsuite/gdb.mi/mi-stack.exp
@@ -32,7 +32,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-start.exp b/gdb/testsuite/gdb.mi/mi-start.exp
index 745e5c9..d384230 100644
--- a/gdb/testsuite/gdb.mi/mi-start.exp
+++ b/gdb/testsuite/gdb.mi/mi-start.exp
@@ -28,7 +28,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-stepi.exp b/gdb/testsuite/gdb.mi/mi-stepi.exp
index 8ba6399..7f53c8b 100644
--- a/gdb/testsuite/gdb.mi/mi-stepi.exp
+++ b/gdb/testsuite/gdb.mi/mi-stepi.exp
@@ -63,7 +63,7 @@ proc test_stepi_nexti {} {
}
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
test_stepi_nexti
diff --git a/gdb/testsuite/gdb.mi/mi-stepn.exp b/gdb/testsuite/gdb.mi/mi-stepn.exp
index 489564a..f11e9c0 100644
--- a/gdb/testsuite/gdb.mi/mi-stepn.exp
+++ b/gdb/testsuite/gdb.mi/mi-stepn.exp
@@ -26,7 +26,7 @@ if [build_executable ${testfile}.exp ${testfile} ${srcfile} $opts] {
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
if {[mi_runto_main] < 0} {
return -1
diff --git a/gdb/testsuite/gdb.mi/mi-sym-info.exp b/gdb/testsuite/gdb.mi/mi-sym-info.exp
index ef8dd86..6b0bf2d 100644
--- a/gdb/testsuite/gdb.mi/mi-sym-info.exp
+++ b/gdb/testsuite/gdb.mi/mi-sym-info.exp
@@ -33,7 +33,7 @@ if {[build_executable "failed to prepare" ${testfile} \
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
# Don't run to main to avoid increasing the search scope to include
# debug info of shared libraries like libc, libgcc, etc.
diff --git a/gdb/testsuite/gdb.mi/mi-syn-frame.exp b/gdb/testsuite/gdb.mi/mi-syn-frame.exp
index 633f317..b3ec377 100644
--- a/gdb/testsuite/gdb.mi/mi-syn-frame.exp
+++ b/gdb/testsuite/gdb.mi/mi-syn-frame.exp
@@ -29,7 +29,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
mi_runto_main
diff --git a/gdb/testsuite/gdb.mi/mi-thread-bp-deleted.exp b/gdb/testsuite/gdb.mi/mi-thread-bp-deleted.exp
index 2a734c8..976b68d 100644
--- a/gdb/testsuite/gdb.mi/mi-thread-bp-deleted.exp
+++ b/gdb/testsuite/gdb.mi/mi-thread-bp-deleted.exp
@@ -47,7 +47,7 @@ foreach_mi_ui_mode mode {
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"maint set target-non-stop on\""
append GDBFLAGS " -ex \"set mi-async on\""
- mi_clean_restart $binfile $start_ops
+ mi_clean_restart $::testfile $start_ops
}
mi_runto_main
diff --git a/gdb/testsuite/gdb.mi/mi-thread-specific-bp.exp b/gdb/testsuite/gdb.mi/mi-thread-specific-bp.exp
index 86d050a..81ff274 100644
--- a/gdb/testsuite/gdb.mi/mi-thread-specific-bp.exp
+++ b/gdb/testsuite/gdb.mi/mi-thread-specific-bp.exp
@@ -90,7 +90,7 @@ foreach_mi_ui_mode mode {
set start_ops ""
}
- if {[mi_clean_restart $binfile $start_ops]} {
+ if {[mi_clean_restart $::testfile $start_ops]} {
break
}
diff --git a/gdb/testsuite/gdb.mi/mi-threads-interrupt.exp b/gdb/testsuite/gdb.mi/mi-threads-interrupt.exp
index ff74e7b..8aab3b8 100644
--- a/gdb/testsuite/gdb.mi/mi-threads-interrupt.exp
+++ b/gdb/testsuite/gdb.mi/mi-threads-interrupt.exp
@@ -33,7 +33,7 @@ proc test_continue_interrupt { } {
global binfile
global async
- if {[mi_clean_restart $binfile]} {
+ if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-until.exp b/gdb/testsuite/gdb.mi/mi-until.exp
index ee50c4f..e8f24bc 100644
--- a/gdb/testsuite/gdb.mi/mi-until.exp
+++ b/gdb/testsuite/gdb.mi/mi-until.exp
@@ -31,7 +31,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-var-block.exp b/gdb/testsuite/gdb.mi/mi-var-block.exp
index bdba639..3914c3a 100644
--- a/gdb/testsuite/gdb.mi/mi-var-block.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-block.exp
@@ -29,7 +29,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-var-child-f.exp b/gdb/testsuite/gdb.mi/mi-var-child-f.exp
index c424490..4856e3d 100644
--- a/gdb/testsuite/gdb.mi/mi-var-child-f.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-child-f.exp
@@ -28,7 +28,7 @@ if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-var-child.exp b/gdb/testsuite/gdb.mi/mi-var-child.exp
index 89ce9dd..4a3ba07 100644
--- a/gdb/testsuite/gdb.mi/mi-var-child.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-child.exp
@@ -29,7 +29,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-var-cmd.exp b/gdb/testsuite/gdb.mi/mi-var-cmd.exp
index 8c8c306..9e7b14c 100644
--- a/gdb/testsuite/gdb.mi/mi-var-cmd.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-cmd.exp
@@ -29,7 +29,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-var-cp.exp b/gdb/testsuite/gdb.mi/mi-var-cp.exp
index c1d70f1..eee1007 100644
--- a/gdb/testsuite/gdb.mi/mi-var-cp.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-cp.exp
@@ -25,7 +25,7 @@ if {[gdb_compile $srcdir/$subdir/$srcfile $binfile executable {debug c++}] != ""
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-var-create-rtti.exp b/gdb/testsuite/gdb.mi/mi-var-create-rtti.exp
index ad6ce5c..517449c 100644
--- a/gdb/testsuite/gdb.mi/mi-var-create-rtti.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-create-rtti.exp
@@ -23,7 +23,7 @@ if [build_executable $testfile.exp $testfile $srcfile $opts] {
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
if {[mi_runto_main] < 0} {
return -1
diff --git a/gdb/testsuite/gdb.mi/mi-var-display.exp b/gdb/testsuite/gdb.mi/mi-var-display.exp
index 61b3894..3ae593b 100644
--- a/gdb/testsuite/gdb.mi/mi-var-display.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-display.exp
@@ -29,7 +29,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
@@ -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/mi-var-invalidate.exp b/gdb/testsuite/gdb.mi/mi-var-invalidate.exp
index c1c52f2..800c22f 100644
--- a/gdb/testsuite/gdb.mi/mi-var-invalidate.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-invalidate.exp
@@ -44,7 +44,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {d
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-var-list-children-invalid-grandchild.exp b/gdb/testsuite/gdb.mi/mi-var-list-children-invalid-grandchild.exp
index 0f20c50f..597e2e0 100644
--- a/gdb/testsuite/gdb.mi/mi-var-list-children-invalid-grandchild.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-list-children-invalid-grandchild.exp
@@ -26,7 +26,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-var-rtti.exp b/gdb/testsuite/gdb.mi/mi-var-rtti.exp
index fcf8404..c2768b6 100644
--- a/gdb/testsuite/gdb.mi/mi-var-rtti.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-rtti.exp
@@ -25,7 +25,7 @@ if [build_executable $testfile.exp $testfile $srcfile $opts] {
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-vla-c99.exp b/gdb/testsuite/gdb.mi/mi-vla-c99.exp
index ec12e6f..5f23d05 100644
--- a/gdb/testsuite/gdb.mi/mi-vla-c99.exp
+++ b/gdb/testsuite/gdb.mi/mi-vla-c99.exp
@@ -29,7 +29,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" \
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-vla-fortran.exp b/gdb/testsuite/gdb.mi/mi-vla-fortran.exp
index 5077089..81e2d89 100644
--- a/gdb/testsuite/gdb.mi/mi-vla-fortran.exp
+++ b/gdb/testsuite/gdb.mi/mi-vla-fortran.exp
@@ -34,7 +34,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
# the type names can be printed differently.
set real [fortran_real4]
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi-watch-nonstop.exp b/gdb/testsuite/gdb.mi/mi-watch-nonstop.exp
index f9237c0..36d7410 100644
--- a/gdb/testsuite/gdb.mi/mi-watch-nonstop.exp
+++ b/gdb/testsuite/gdb.mi/mi-watch-nonstop.exp
@@ -38,7 +38,7 @@ if {[gdb_compile "$srcdir/$subdir/$srcfile" $binfile executable {debug}] != "" }
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop on\""
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
}
mi_gdb_test "-gdb-set mi-async 1" ".*"
diff --git a/gdb/testsuite/gdb.mi/mi-watch.exp b/gdb/testsuite/gdb.mi/mi-watch.exp
index e318a2b..43f2378 100644
--- a/gdb/testsuite/gdb.mi/mi-watch.exp
+++ b/gdb/testsuite/gdb.mi/mi-watch.exp
@@ -155,7 +155,7 @@ proc test_watchpoint_all {mi_mode type} {
} else {
set start_ops ""
}
- if [mi_clean_restart ${binfile} $start_ops] {
+ if [mi_clean_restart ${::testfile} $start_ops] {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi2-amd64-entry-value.exp b/gdb/testsuite/gdb.mi/mi2-amd64-entry-value.exp
index c7e21e9..0d51dc5 100644
--- a/gdb/testsuite/gdb.mi/mi2-amd64-entry-value.exp
+++ b/gdb/testsuite/gdb.mi/mi2-amd64-entry-value.exp
@@ -31,7 +31,7 @@ if [build_executable ${testfile}.exp ${binfile} ${srcfile} $opts] {
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi2-cli-display.exp b/gdb/testsuite/gdb.mi/mi2-cli-display.exp
index 656c93e..993b87c 100644
--- a/gdb/testsuite/gdb.mi/mi2-cli-display.exp
+++ b/gdb/testsuite/gdb.mi/mi2-cli-display.exp
@@ -25,7 +25,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/mi2-var-child.exp b/gdb/testsuite/gdb.mi/mi2-var-child.exp
index 9bd9054..3618d5a 100644
--- a/gdb/testsuite/gdb.mi/mi2-var-child.exp
+++ b/gdb/testsuite/gdb.mi/mi2-var-child.exp
@@ -29,7 +29,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp b/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp
index cb83329..7112248 100644
--- a/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp
+++ b/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp
@@ -102,7 +102,7 @@ proc do_test {sync_command} {
}
foreach_with_prefix sync-command {"run" "continue"} {
- if {[mi_clean_restart $binfile "separate-mi-tty"] != 0} {
+ if {[mi_clean_restart $::testfile "separate-mi-tty"] != 0} {
fail "could not start gdb"
break
}
diff --git a/gdb/testsuite/gdb.mi/pr11022.exp b/gdb/testsuite/gdb.mi/pr11022.exp
index ad8e3b2..1e01bf6 100644
--- a/gdb/testsuite/gdb.mi/pr11022.exp
+++ b/gdb/testsuite/gdb.mi/pr11022.exp
@@ -29,7 +29,7 @@ proc test_memory_changed_observer { mi_command } {
with_test_prefix "${mi_command}" {
global srcfile binfile
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
mi_runto_main
set line_number [gdb_get_line_number "break here"]
diff --git a/gdb/testsuite/gdb.mi/print-simple-values.exp b/gdb/testsuite/gdb.mi/print-simple-values.exp
index 1c56d68..23488e3 100644
--- a/gdb/testsuite/gdb.mi/print-simple-values.exp
+++ b/gdb/testsuite/gdb.mi/print-simple-values.exp
@@ -34,7 +34,7 @@ if [build_executable "failed to prepare" $testfile $srcfile $opts] {
return -1
}
-if [mi_clean_restart $binfile] {
+if [mi_clean_restart $::testfile] {
return
}
diff --git a/gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp b/gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp
index df370c9..c9e352d 100644
--- a/gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp
+++ b/gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp
@@ -29,7 +29,7 @@ if {[build_executable $testfile.exp $testfile ${srcfile} "debug"] == -1} {
# UI_TO_RUN is the UI that should issue the run command.
proc do_test { ui_to_run } {
- if {[mi_clean_restart $::binfile "separate-mi-tty"] != 0} {
+ if {[mi_clean_restart $::testfile "separate-mi-tty"] != 0} {
fail "could not start gdb"
return
}
diff --git a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
index 9198cfb..a0bf11f 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]
@@ -1327,7 +1329,7 @@ foreach_with_prefix mode { "all-stop" "non-stop" } {
set GDBFLAGS [concat $GDBFLAGS " -ex \"set non-stop 1\""]
}
- if { [mi_clean_restart $binfile "separate-mi-tty"] != 0 } {
+ if { [mi_clean_restart $::testfile "separate-mi-tty"] != 0 } {
break
}
}
diff --git a/gdb/testsuite/gdb.multi/attach-no-multi-process.exp b/gdb/testsuite/gdb.multi/attach-no-multi-process.exp
index 28aabaf..2813fa9 100644
--- a/gdb/testsuite/gdb.multi/attach-no-multi-process.exp
+++ b/gdb/testsuite/gdb.multi/attach-no-multi-process.exp
@@ -44,7 +44,7 @@ proc test {target_non_stop} {
"${::GDBFLAGS} -ex \"set remote multiprocess-feature-packet off\""
set ::GDBFLAGS \
"${::GDBFLAGS} -ex \"maint set target-non-stop ${target_non_stop}\""
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
# Start the first inferior.
@@ -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..4eb500e 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
@@ -45,11 +46,11 @@ if { [build_executable "failed to prepare" ${testfile} ${srcfile}] } {
proc do_test {} {
save_vars { ::GDBFLAGS } {
append ::GDBFLAGS " -ex \"maint set target-non-stop on\""
- clean_restart $::binfile
+ clean_restart $::testfile
}
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/gdb-settings.exp b/gdb/testsuite/gdb.multi/gdb-settings.exp
index b1acca0..368edde 100644
--- a/gdb/testsuite/gdb.multi/gdb-settings.exp
+++ b/gdb/testsuite/gdb.multi/gdb-settings.exp
@@ -44,7 +44,7 @@ set run [expr {![use_gdb_stub]}]
set inferiors {1 2}
# Start all the inferiors.
-clean_restart $binfile
+clean_restart $::testfile
foreach_with_prefix inf $inferiors {
if { $inf > 1 } {
gdb_test "add-inferior -exec $binfile" "Added inferior 2.*" \
diff --git a/gdb/testsuite/gdb.multi/inferior-specific-bp.exp b/gdb/testsuite/gdb.multi/inferior-specific-bp.exp
index db09095..6d2fc9e 100644
--- a/gdb/testsuite/gdb.multi/inferior-specific-bp.exp
+++ b/gdb/testsuite/gdb.multi/inferior-specific-bp.exp
@@ -22,8 +22,10 @@ if {[use_gdb_stub]} {
}
set srcfile1 ${srcfile}
-set binfile1 ${binfile}-1
-set binfile2 ${binfile}-2
+set testfile1 $testfile-1
+set testfile2 $testfile-2
+set binfile1 [standard_output_file $testfile1]
+set binfile2 [standard_output_file $testfile2]
if {[build_executable ${testfile}.exp ${binfile1} "${srcfile1}"] != 0} {
return -1
@@ -34,7 +36,7 @@ if {[build_executable ${testfile}.exp ${binfile2} "${srcfile2}"] != 0} {
}
# Start the first inferior.
-clean_restart ${binfile1}
+clean_restart $testfile1
if {![runto_main]} {
return
}
diff --git a/gdb/testsuite/gdb.multi/interrupt-bg-exec.c b/gdb/testsuite/gdb.multi/interrupt-bg-exec.c
new file mode 100644
index 0000000..b5fa568
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/interrupt-bg-exec.c
@@ -0,0 +1,47 @@
+/* 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>
+
+volatile int wait_for_gdb = 1;
+
+void
+breakpt (void)
+{
+ /* Nothing. */
+}
+
+void
+all_started (void)
+{
+ /* Nothing. */
+}
+
+int
+main (void)
+{
+ alarm (360);
+
+ all_started ();
+
+ while (wait_for_gdb)
+ sleep (1);
+
+ breakpt ();
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.multi/interrupt-bg-exec.exp b/gdb/testsuite/gdb.multi/interrupt-bg-exec.exp
new file mode 100644
index 0000000..065a112
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/interrupt-bg-exec.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/>.
+
+# In all-stop mode, set one inferior running in the background, then
+# continue a second inferior. When the second inferior hits a breakpoint,
+# both inferiors should be stopped.
+
+# This tests the use of native and remote targets. If we try to run
+# it with a board that forces native targets to become remote, then
+# this doesn't really make sense (for this test).
+require {string equal [target_info gdb_protocol] ""}
+
+source $srcdir/$subdir/multi-target.exp.tcl
+
+load_lib gdbserver-support.exp
+
+require allow_gdbserver_tests
+
+# This overrides the call in multi-target.exp.tcl.
+standard_testfile
+
+if { [build_executable "failed to build" $testfile $srcfile] } {
+ return
+}
+
+# Start two inferiors, TARGET_TYPE_1 and TARGET_TYPE_2 are strings, either
+# 'extended-remote' or 'native', and control the connection type of each
+# inferior.
+#
+# Set the first inferior running in the background, then continue theA
+# second inferior allowing it to hit a breakpoint.
+#
+# Once the breakpoint is hit, both inferiors should be stopped.
+proc run_test { target_type_1 target_type_2 } {
+ cleanup_gdbservers
+
+ clean_restart
+
+ gdb_test "disconnect" ".*"
+
+ gdb_test_no_output "set sysroot"
+
+ # multi-target depends on target running in non-stop mode. Force it
+ # on for remote targets, until this is the default.
+ gdb_test_no_output "maint set target-non-stop on"
+
+ # Run in all-stop mode.
+ gdb_test_no_output "set non-stop off"
+
+ if {![add_inferior 2 $target_type_1 $::binfile]} {
+ return 0
+ }
+
+ if {![add_inferior 3 $target_type_2 $::binfile]} {
+ return 0
+ }
+
+ # Check we see all the expected threads.
+ gdb_test "info threads" \
+ [multi_line \
+ "\\s+Id\\s+Target Id\\s+Frame\\s*" \
+ "\\s+2\\.1\\s+\[^\r\n\]+" \
+ "\\*\\s+3\\.1\\s+\[^\r\n\]+"] \
+ "check expected threads exist"
+
+ # The breakpoint will be set in both inferiors, but only inferior 3
+ # will hit it as 'wait_for_gdb' is cleared only in that inferior.
+ gdb_breakpoint breakpt
+ gdb_test "thread apply 3.1 set wait_for_gdb = 0"
+
+ # Let inferior 2 run in the background.
+ gdb_test "thread 2.1"
+ gdb_test -no-prompt-anchor "continue&"
+
+ # Run inferior 3 until it hits a breakpoint.
+ gdb_test "thread 3.1"
+ gdb_test "continue" \
+ [multi_line \
+ "Thread 3\\.1 \[^\r\n\]+ hit Breakpoint \[^\r\n\]+, breakpt \\(\\) \[^\r\n\]+" \
+ "$::decimal\\s+\[^\r\n\]+"] \
+ "continue to breakpt function"
+
+ # Check the state of all threads. None should be running.
+ set saw_inferior_2 false
+ set saw_inferior_3 false
+ gdb_test_multiple "info threads" "check threads after stop" {
+ -re "^info threads\r\n" {
+ exp_continue
+ }
+
+ -re "^\\s+Id\\s+Target Id\\s+Frame\\s*\r\n" {
+ exp_continue
+ }
+
+ -re "^\\s+2\\.1\\s+\[^\r\n\]+\\s+\\(running\\)\\s*\r\n" {
+ # Don't count this as seeing inferior 2 as the thread is
+ # incorrectly still marked as running. By not setting the
+ # SAW_INFERIOR_2 flag this test will now fail.
+ exp_continue
+ }
+
+ -re "^\\s+2\\.1\\s+\[^\r\n\]+\r\n" {
+ set saw_inferior_2 true
+ exp_continue
+ }
+
+ -re "^\\*\\s+3\\.1\\s+\[^\r\n\]+\r\n" {
+ set saw_inferior_3 true
+ exp_continue
+ }
+
+ -re "^$::gdb_prompt $" {
+ gdb_assert { $saw_inferior_2 && $saw_inferior_3 } \
+ $gdb_test_name
+ }
+
+ -re "^\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+ }
+}
+
+set all_target_types { extended-remote native }
+
+foreach_with_prefix target_type_1 $all_target_types {
+ foreach_with_prefix target_type_2 $all_target_types {
+ run_test $target_type_1 $target_type_2
+ }
+}
+
+multi_target_cleanup
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..fcd7cd2 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]} {
@@ -34,7 +36,7 @@ if {[build_executable "failed to prepare" $testfile $srcfile]} {
# Hence, go with the all-stop-on-top-of-non-stop mode.
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"maint set target-non-stop on\""
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
# Start inferior NUM.
diff --git a/gdb/testsuite/gdb.multi/multi-kill.exp b/gdb/testsuite/gdb.multi/multi-kill.exp
index 48a2534..1473372 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}]} {
@@ -34,7 +36,7 @@ if {[build_executable "failed to prepare" $testfile $srcfile {debug}]} {
# Hence, go with the all-stop-on-top-of-non-stop mode.
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"maint set target-non-stop on\""
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
# Wrap the entire test in a namespace to avoid contaminating other tests.
diff --git a/gdb/testsuite/gdb.multi/multi-re-run.exp b/gdb/testsuite/gdb.multi/multi-re-run.exp
index 002de57..89d43a4 100644
--- a/gdb/testsuite/gdb.multi/multi-re-run.exp
+++ b/gdb/testsuite/gdb.multi/multi-re-run.exp
@@ -20,25 +20,27 @@
# 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"
+set testfile1 "multi-re-run-1"
set srcfile1 multi-re-run-1.c
-set binfile1 [standard_output_file ${exec1}]
+set binfile1 [standard_output_file $testfile1]
-set exec2 "multi-re-run-2"
+set testfile2 "multi-re-run-2"
set srcfile2 multi-re-run-2.c
-set binfile2 [standard_output_file ${exec2}]
+set binfile2 [standard_output_file $testfile2]
with_test_prefix "exec1" {
- if { [build_executable "failed to prepare" ${exec1} "${srcfile1}" \
+ if { [build_executable "failed to prepare" $testfile1 $srcfile1 \
[list pthreads debug]] } {
return -1
}
}
with_test_prefix "exec2" {
- if { [build_executable "failed to prepare" ${exec2} "${srcfile2}" \
+ if { [build_executable "failed to prepare" $testfile2 $srcfile2 \
[list pthreads debug]] } {
return -1
}
@@ -53,7 +55,7 @@ proc test_re_run {re_run_inf} {
global gdb_prompt
global last_loaded_file
- clean_restart ${binfile1}
+ clean_restart $::testfile1
delete_breakpoints
diff --git a/gdb/testsuite/gdb.multi/multi-target.exp.tcl b/gdb/testsuite/gdb.multi/multi-target.exp.tcl
index 8c24602..1963db5 100644
--- a/gdb/testsuite/gdb.multi/multi-target.exp.tcl
+++ b/gdb/testsuite/gdb.multi/multi-target.exp.tcl
@@ -53,7 +53,7 @@ proc add_inferior {num target binfile {gcorefile ""}} {
return 0
}
}
- if ![runto "all_started"] then {
+ if { ![runto "all_started"] } {
return 0
}
delete_breakpoints
@@ -65,9 +65,9 @@ proc prepare_core {} {
global gcorefile gcore_created
global binfile
- clean_restart ${binfile}
+ clean_restart ${::testfile}
- if ![runto all_started] then {
+ if { ![runto all_started] } {
return -1
}
@@ -114,7 +114,7 @@ proc setup {non-stop {multi_process ""}} {
# Make GDB read files from the local file system, not through the
# remote targets, to speed things up.
set ::GDBFLAGS "${::GDBFLAGS} -ex \"set sysroot\""
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
# multi-target depends on target running in non-stop mode. Force
@@ -123,13 +123,13 @@ proc setup {non-stop {multi_process ""}} {
gdb_test_no_output "set non-stop ${non-stop}"
- if {${multi_process} ne ""} then {
+ if {${multi_process} ne ""} {
gdb_test \
"set remote multiprocess-feature-packet $multi_process" \
"Support for the 'multiprocess-feature' packet on future remote targets is set to \"${multi_process}\"."
}
- if ![runto all_started] then {
+ if { ![runto all_started] } {
return 0
}
@@ -175,12 +175,16 @@ 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
}
- if { [prepare_for_testing "failed to prepare" ${binfile} "${srcfile}" \
+ if { [prepare_for_testing "failed to prepare" $::testfile $srcfile \
{debug pthreads}] } {
return 0
}
diff --git a/gdb/testsuite/gdb.multi/multi-term-settings.exp b/gdb/testsuite/gdb.multi/multi-term-settings.exp
index 2f8b3b8..8618f1a 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}] {
@@ -136,7 +138,7 @@ proc coretest {inf1_how inf2_how} {
global gdb_spawn_id
global decimal
- clean_restart $binfile
+ clean_restart $::testfile
with_test_prefix "inf1" {
set inf1_spawn_id [create_inferior 1 $inf1_how]
diff --git a/gdb/testsuite/gdb.multi/pending-bp-del-inferior.exp b/gdb/testsuite/gdb.multi/pending-bp-del-inferior.exp
index a7055d7..781937d 100644
--- a/gdb/testsuite/gdb.multi/pending-bp-del-inferior.exp
+++ b/gdb/testsuite/gdb.multi/pending-bp-del-inferior.exp
@@ -37,7 +37,7 @@ if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} {
#
# Return true after a successful setup, otherwise, return false.
proc test_setup {} {
- clean_restart $::binfile
+ clean_restart $::testfile
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.multi/pending-bp.exp b/gdb/testsuite/gdb.multi/pending-bp.exp
index 1cd1cfb..30a75b9 100644
--- a/gdb/testsuite/gdb.multi/pending-bp.exp
+++ b/gdb/testsuite/gdb.multi/pending-bp.exp
@@ -45,7 +45,7 @@ if { [build_executable "failed to prepare" $testfile $srcfile \
# 'breakpoint pending' flag is enabled, so pending breakpoints can be created
# without GDB prompting the user.
proc do_test_setup { inf_1_stop inf_2_stop } {
- clean_restart ${::binfile}
+ clean_restart ${::testfile}
gdb_locate_shlib $::binfile_lib
@@ -328,5 +328,7 @@ proc_with_prefix py_test_clear_thread {} {
# Run all the tests.
test_no_inf_display
test_pending_toggle
-py_test_toggle_thread
-py_test_clear_thread
+if { [allow_python_tests] } {
+ py_test_toggle_thread
+ py_test_clear_thread
+}
diff --git a/gdb/testsuite/gdb.multi/remote-with-running-inferior.c b/gdb/testsuite/gdb.multi/remote-with-running-inferior.c
new file mode 100644
index 0000000..a610eda
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/remote-with-running-inferior.c
@@ -0,0 +1,38 @@
+/* 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>
+
+int global_var = 123;
+
+void
+breakpt (void)
+{
+ /* Nothing. */
+}
+
+int
+main (void)
+{
+ for (int i = 0; i < 30; ++i)
+ {
+ sleep (1);
+ breakpt ();
+ }
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.multi/remote-with-running-inferior.exp b/gdb/testsuite/gdb.multi/remote-with-running-inferior.exp
new file mode 100644
index 0000000..43842ba
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/remote-with-running-inferior.exp
@@ -0,0 +1,171 @@
+# 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/>.
+
+# Set an inferior running in the background (using "run&"), then
+# connect to gdbserver in a second inferior. When this test was added
+# there were two bugs in GDB. First, just connecting to gdbserver
+# while an inferior was running on a different connection type
+# (e.g. inferior 1 was native, and inferior 2 was gdbserver) would
+# trigger an assertion.
+#
+# Then, once the assertion was fixed, GDB would stop the thread from
+# the first inferior, but would fail to update it's state in GDB core,
+# this would leave the thread stopped, but GDB core thinking the
+# thread was running. Check this is fixed by looking at the 'info
+# threads' output after connecting to the remote target.
+
+# This tests the use of native and remote targets, and also depends on use
+# of the 'run' command. If we try to run it with a board that forces native
+# targets to become remote, then this test isn't going to work, especially
+# for 'remote' targets where 'run' is not supported.
+require {string equal [target_info gdb_protocol] ""}
+
+load_lib gdbserver-support.exp
+
+require allow_gdbserver_tests
+
+standard_testfile
+
+if { [build_executable "failed to build" $testfile $srcfile] } {
+ return
+}
+
+# Set non-stop mode based on NON_STOP. Start a native inferior running in
+# the background, then start a second, remote inferior. Based on the value
+# of NON_STOP we might expect the inferior thread to have been stopped.
+# Confirm inferior one is in the correct state, and that it can be
+# interrupted and/or resumed.
+proc run_test { target_non_stop non_stop } {
+ clean_restart $::testfile
+
+ # Setup non-stop settings.
+ gdb_test_no_output "maint set target-non-stop $target_non_stop"
+ gdb_test_no_output "set non-stop $non_stop"
+
+ # Start the first inferior running in the background.
+ gdb_test -no-prompt-anchor "run&" "Starting program: .*" "start background inferior"
+
+ # Add a second inferior.
+ gdb_test "add-inferior" "Added inferior 2.*"
+ gdb_test "inferior 2" "Switching to inferior 2.*"
+
+ # Setup the sysroot if possible. This will make connecting to
+ # gdbserver quicker.
+ if { ![is_remote host] && ![is_remote target] } {
+ gdb_test "set sysroot"
+ }
+
+ # Setup, and connect to, a remote target.
+ set target_exec [gdbserver_download_current_prog]
+ set res [gdbserver_start "" $target_exec]
+ set gdbserver_protocol [lindex $res 0]
+ set gdbserver_gdbport [lindex $res 1]
+ set res [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
+ gdb_assert {$res == 0} "connect to remote target"
+
+ # Check the info threads output. We're checking that we see the two
+ # threads we expect, that the correct thread (inferior two's thread)
+ # is current, and that none of the threads are running.
+ set state_inferior_1 ""
+ set state_inferior_2 ""
+ gdb_test_multiple "info threads" "" {
+ -re "^info threads\r\n" {
+ exp_continue
+ }
+
+ -re "^\\s+Id\\s+Target Id\\s+Frame\\s*\r\n" {
+ exp_continue
+ }
+
+ -re "^\\s+1\\.1\\s+\[^\r\n\]+\\(running\\)\r\n" {
+ set state_inferior_1 "running"
+ exp_continue
+ }
+
+ -re "^\\*\\s+2\\.1\\s+\[^\r\n\]+\\(running\\)\r\n" {
+ set state_inferior_2 "running"
+ exp_continue
+ }
+
+ -re "^\\s+1\\.1\\s+\[^\r\n\]+\r\n" {
+ set state_inferior_1 "stopped"
+ exp_continue
+ }
+
+ -re "^\\*\\s+2\\.1\\s+\[^\r\n\]+\r\n" {
+ set state_inferior_2 "stopped"
+ exp_continue
+ }
+
+ -re "^$::gdb_prompt $" {
+ if { $non_stop } {
+ gdb_assert { $state_inferior_1 == "running" \
+ && $state_inferior_2 == "stopped" } \
+ $gdb_test_name
+ } else {
+ gdb_assert { $state_inferior_1 == "stopped" \
+ && $state_inferior_2 == "stopped" } \
+ $gdb_test_name
+ }
+ }
+ }
+
+ # Allow inferior 2 to reach main. The confirms that inferior 2 can be
+ # set running again.
+ gdb_breakpoint main
+ gdb_continue_to_breakpoint "breakpoint in main"
+ gdb_test "bt 1" \
+ "#0\\s+main \\(\\) at\[^\r\n\]+" \
+ "check inferior 2 is in main"
+
+ # Switch to inferior 1 and allow it to continue. This is a
+ # critical part of the test. When the test was added a bug (in
+ # all-stop mode) would leave inferior 1 stopped, but GDB code
+ # would think the thread was running. As such. the thread
+ # couldn't be resumed again.
+ gdb_test "inferior 1" "Switching to inferior 1.*"
+
+ # In non-stop mode, thread 1.1 is correctly left running, so we
+ # need to stop it now.
+ if { $non_stop } {
+ gdb_test -no-prompt-anchor "interrupt"
+ gdb_test "p 1 + 1" " = 2" \
+ "simple print to resync output"
+ }
+
+ gdb_breakpoint breakpt
+ gdb_continue_to_breakpoint "continue to breakpoint in breakpt"
+ gdb_test "bt 1" \
+ [multi_line \
+ "#0\\s+breakpt \\(\\) at\[^\r\n\]+" \
+ "\\(More stack frames follow\\.\\.\\.\\)"] \
+ "check inferior 1 is in breakpt"
+
+ # Switch back to inferior 2. The testing infrastructure will try to
+ # use 'monitor exit' to close gdbserver. It helps if we are in the
+ # gdbserver inferior when the script finishes.
+ gdb_test "inferior 2" "Switching to inferior 2.*" \
+ "switch back to inferior 2"
+}
+
+# Multi-inferior support requires non-stop targets.
+foreach_with_prefix target_non_stop { auto on } {
+ # But it's OK if we're emulating all-stop mode on top of non-stop.
+ foreach_with_prefix non_stop { on off } {
+ run_test $target_non_stop $non_stop
+ }
+}
diff --git a/gdb/testsuite/gdb.multi/remove-inferiors.exp b/gdb/testsuite/gdb.multi/remove-inferiors.exp
index 586d958..52e6cb0 100644
--- a/gdb/testsuite/gdb.multi/remove-inferiors.exp
+++ b/gdb/testsuite/gdb.multi/remove-inferiors.exp
@@ -32,7 +32,7 @@ proc add_inferior { expected_num message } {
proc test_remove_inferiors { } {
global binfile
- clean_restart ${binfile}
+ clean_restart ${::testfile}
# Add another inferior and switch to it.
add_inferior 2 "add second inferior"
diff --git a/gdb/testsuite/gdb.multi/run-only-second-inf.exp b/gdb/testsuite/gdb.multi/run-only-second-inf.exp
index 7b6532c..3645962 100644
--- a/gdb/testsuite/gdb.multi/run-only-second-inf.exp
+++ b/gdb/testsuite/gdb.multi/run-only-second-inf.exp
@@ -31,7 +31,7 @@ if {[build_executable "failed to prepare" $testfile $srcfile {debug}]} {
# So, start GDB with this setting.
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"maint set target-non-stop on\""
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
# Add and start the second inferior.
diff --git a/gdb/testsuite/gdb.multi/sched-multi-add-inferior.exp b/gdb/testsuite/gdb.multi/sched-multi-add-inferior.exp
new file mode 100644
index 0000000..9344c80
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/sched-multi-add-inferior.exp
@@ -0,0 +1,109 @@
+# 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/>.
+
+# Start multiple inferiors while schedule-multiple is on. Make use of
+# the multi-target.exp.tcl support library for the helper procs, but
+# don't use its 'setup' proc as that only turns on schedule-multiple
+# after starting all the inferiors, and that is too late for this test.
+#
+# The specific bug that this test guards against was that, when a
+# native target starts and runs upto a breakpoint, the thread would
+# have its last signal recorded as SIGTRAP.
+#
+# When starting a gdbserver inferior (with schedule-multiple on) the
+# native target would also be resumed.
+#
+# However, GDBs 'run' command was failing to clear out the old signal
+# state from the native inferior, and so GDB would deliver a SIGTRAP
+# to that inferior, killing it.
+
+source $srcdir/$subdir/multi-target.exp.tcl
+
+if {![multi_target_prepare]} {
+ return
+}
+
+# Some breakpoint locations.
+set line1 [gdb_get_line_number "set break 1 here"]
+set line2 [gdb_get_line_number "set break 2 here"]
+
+# Start two inferiors using TARGET_TYPE_1 and TARGET_TYPE_2 (either
+# 'extended-remote' or 'native'). Due to the way that inferior 1 is
+# special (existing once GDB starts up), we just use the existing
+# helper functions to create inferiors 2 and 3 using these types, and
+# we leave inferior 1 unused.
+proc run_test { target_type_1 target_type_2 } {
+ cleanup_gdbservers
+
+ clean_restart
+
+ gdb_test_no_output "set sysroot"
+
+ # The schedule-multiple setting relies on all targets running in
+ # non-stop mode. Force it on for remote targets, until this is
+ # the default.
+ gdb_test_no_output "maint set target-non-stop on"
+
+ # Run in all-stop mode.
+ gdb_test_no_output "set non-stop off"
+
+ # Turn on schedule-multiple before starting any inferiors.
+ gdb_test_no_output "set schedule-multiple on"
+
+ if {![add_inferior 2 $target_type_1 $::binfile]} {
+ return 0
+ }
+
+ if {![add_inferior 3 $target_type_2 $::binfile]} {
+ return 0
+ }
+
+ # Check we see all the expected threads.
+ gdb_test "info threads" \
+ [multi_line \
+ "\\s+Id\\s+Target Id\\s+Frame\\s*" \
+ "\\s+2\\.1\\s+\[^\r\n\]+" \
+ "\\s+2\\.2\\s+\[^\r\n\]+" \
+ "\\*\\s+3\\.1\\s+\[^\r\n\]+" \
+ "\\s+3\\.2\\s+\[^\r\n\]+"]
+
+ # Ensure that all inferiors can be set running again.
+ gdb_test "break ${::srcfile}:${::line1} thread 3.1"
+ gdb_test "break ${::srcfile}:${::line2} thread 2.1"
+ gdb_test "continue" \
+ [multi_line \
+ "Thread 3\\.1 \[^\r\n\]+, main \\(\[^\r\n\]+\\) at \[^\r\n\]+" \
+ "$::decimal\\s+function1 \\(\\); /\\* set break 1 here \\*/"] \
+ "continue to function1"
+
+ # Unblock thread 2.1 and continue again. This time, thread 2.1
+ # will hit a breakpoint.
+ gdb_test "thread apply 2.1 set wait_for_gdb = 0" ".*"
+ gdb_test "continue" \
+ [multi_line \
+ "Thread 2\\.1 \[^\r\n\]+, main \\(\[^\r\n\]+\\) at \[^\r\n\]+" \
+ "$::decimal\\s+function2 \\(\\); /\\* set break 2 here \\*/"] \
+ "continue to function2"
+}
+
+set all_target_types { extended-remote native }
+
+foreach_with_prefix target_type_1 $all_target_types {
+ foreach_with_prefix target_type_2 $all_target_types {
+ run_test $target_type_1 $target_type_2
+ }
+}
+
+multi_target_cleanup
diff --git a/gdb/testsuite/gdb.multi/start-inferior-specific.exp b/gdb/testsuite/gdb.multi/start-inferior-specific.exp
index 819c1c3..39621f0 100644
--- a/gdb/testsuite/gdb.multi/start-inferior-specific.exp
+++ b/gdb/testsuite/gdb.multi/start-inferior-specific.exp
@@ -25,10 +25,13 @@
standard_testfile .c -other.c
+require allow_multi_inferior_tests
+
require !use_gdb_stub
set srcfile_other ${srcfile2}
-set binfile_other ${binfile}-other
+set testfile_other $testfile-other
+set binfile_other [standard_output_file $testfile_other]
if { [build_executable ${testfile}.exp ${binfile} "${srcfile}" {debug}] != 0 } {
return -1
@@ -46,7 +49,7 @@ proc do_test {} {
append ::GDBFLAGS " -ex \"maintenance set target-non-stop on\""
}
- clean_restart ${::binfile_other}
+ clean_restart $::testfile_other
}
gdb_test -no-prompt-anchor "run&" "Starting program: .*" "start background inferior"
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..431132e 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}]} {
@@ -29,7 +31,7 @@ if {[build_executable "failed to build" $testfile $srcfile {debug}]} {
proc do_test {dispose} {
global binfile bkptno_numopt_re
- clean_restart $binfile
+ clean_restart $::testfile
gdb_test_no_output "set follow-fork child"
gdb_test_no_output "set detach-on-fork off"
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.objc/basicclass.exp b/gdb/testsuite/gdb.objc/basicclass.exp
index 7f29aff..9e40c71 100644
--- a/gdb/testsuite/gdb.objc/basicclass.exp
+++ b/gdb/testsuite/gdb.objc/basicclass.exp
@@ -72,7 +72,7 @@ proc deduce_language_of_main {} {
proc do_objc_tests {} {
global binfile
- clean_restart $binfile
+ clean_restart $::testfile
deduce_language_of_main
}
diff --git a/gdb/testsuite/gdb.objc/nondebug.exp b/gdb/testsuite/gdb.objc/nondebug.exp
index dfdd9bc..9ca86ff 100644
--- a/gdb/testsuite/gdb.objc/nondebug.exp
+++ b/gdb/testsuite/gdb.objc/nondebug.exp
@@ -29,7 +29,7 @@ if {[gdb_compile_objc "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [
proc do_objc_tests {} {
global binfile
- clean_restart $binfile
+ clean_restart $::testfile
}
do_objc_tests
diff --git a/gdb/testsuite/gdb.objc/objcdecode.exp b/gdb/testsuite/gdb.objc/objcdecode.exp
index b7c38db..5414f0f 100644
--- a/gdb/testsuite/gdb.objc/objcdecode.exp
+++ b/gdb/testsuite/gdb.objc/objcdecode.exp
@@ -29,7 +29,7 @@ if {[gdb_compile_objc "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [
proc do_objc_tests {} {
global binfile
- clean_restart $binfile
+ clean_restart $::testfile
}
do_objc_tests
diff --git a/gdb/testsuite/gdb.objc/print.exp b/gdb/testsuite/gdb.objc/print.exp
index c18bf29..e3f4177 100644
--- a/gdb/testsuite/gdb.objc/print.exp
+++ b/gdb/testsuite/gdb.objc/print.exp
@@ -59,7 +59,7 @@ proc test_float_rejected {} {
clean_restart
-if [set_lang_objc] {
+if { [set_lang_objc] } {
test_float_accepted
test_float_rejected
} else {
diff --git a/gdb/testsuite/gdb.opencl/callfuncs.exp b/gdb/testsuite/gdb.opencl/callfuncs.exp
index 8ab8db7..6982461 100644
--- a/gdb/testsuite/gdb.opencl/callfuncs.exp
+++ b/gdb/testsuite/gdb.opencl/callfuncs.exp
@@ -21,8 +21,9 @@ load_lib opencl.exp
require allow_opencl_tests
-set testfile "callfuncs"
-set clprogram [remote_download target ${srcdir}/${subdir}/${testfile}.cl]
+standard_testfile .cl
+
+set clprogram [remote_download target $srcdir/$subdir/$srcfile]
# Compile the generic OpenCL host app
if { [gdb_compile_opencl_hostapp "${clprogram}" "${testfile}" "" ] != "" } {
@@ -30,7 +31,7 @@ if { [gdb_compile_opencl_hostapp "${clprogram}" "${testfile}" "" ] != "" } {
return -1
}
-clean_restart [standard_testfile $testfile]
+clean_restart $testfile
# Set breakpoint at the OpenCL kernel
gdb_test "tbreak testkernel" \
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.opt/inline-break.exp b/gdb/testsuite/gdb.opt/inline-break.exp
index d83ff75..7ecb3fa 100644
--- a/gdb/testsuite/gdb.opt/inline-break.exp
+++ b/gdb/testsuite/gdb.opt/inline-break.exp
@@ -247,7 +247,7 @@ foreach_with_prefix func {
"func_inline_caller"
"func_inline_callee"
} {
- clean_restart $binfile
+ clean_restart $::testfile
if {![runto_main]} {
continue
@@ -264,7 +264,7 @@ foreach_with_prefix func {
set line [gdb_get_line_number "break here"]
with_test_prefix "line number" {
- clean_restart $binfile
+ clean_restart $::testfile
if {![runto_main]} {
continue
@@ -288,7 +288,7 @@ with_test_prefix "line number" {
with_test_prefix "address" {
- clean_restart $binfile
+ clean_restart $::testfile
if {![runto_main]} {
continue
@@ -308,7 +308,7 @@ with_test_prefix "address" {
with_test_prefix "check alignment" {
- clean_restart $binfile
+ clean_restart $::testfile
if {![runto_main]} {
continue
diff --git a/gdb/testsuite/gdb.opt/inline-cmds.exp b/gdb/testsuite/gdb.opt/inline-cmds.exp
index eca897c..e80d6f7 100644
--- a/gdb/testsuite/gdb.opt/inline-cmds.exp
+++ b/gdb/testsuite/gdb.opt/inline-cmds.exp
@@ -241,7 +241,7 @@ gdb_test "step" ".*set breakpoint 2 here.*" "step into finish marker"
# Some architectures will have one or more instructions after
# the call instruction which still are part of the call sequence,
-# so it should be expected to return to the caller line after issue
+# so it should be expected to return to the caller line after issue
# a 'finish' command.
gdb_test_multiple "finish" "finish from marker to func1" {
-re -wrap "func1 \\(\\);" {
diff --git a/gdb/testsuite/gdb.opt/inline-entry.exp b/gdb/testsuite/gdb.opt/inline-entry.exp
index f185f10..0c6b0fb 100644
--- a/gdb/testsuite/gdb.opt/inline-entry.exp
+++ b/gdb/testsuite/gdb.opt/inline-entry.exp
@@ -43,11 +43,11 @@ if { [supports_statement_frontiers] } {
lappend options additional_flags=-gstatement-frontiers
}
-if { [prepare_for_testing "failed to prepare" $binfile $srcfile $options] } {
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile $options] } {
return
}
-if ![runto_main] {
+if { ![runto_main] } {
return
}
diff --git a/gdb/testsuite/gdb.opt/inline-small-func.exp b/gdb/testsuite/gdb.opt/inline-small-func.exp
index d77a10e..b04f957 100644
--- a/gdb/testsuite/gdb.opt/inline-small-func.exp
+++ b/gdb/testsuite/gdb.opt/inline-small-func.exp
@@ -41,7 +41,7 @@ if { [prepare_for_testing "failed to prepare" ${testfile} \
return -1
}
-if ![runto_main] {
+if { ![runto_main] } {
return -1
}
diff --git a/gdb/testsuite/gdb.opt/solib-intra-step.exp b/gdb/testsuite/gdb.opt/solib-intra-step.exp
index 4b7ab3a..9c6d6c5 100644
--- a/gdb/testsuite/gdb.opt/solib-intra-step.exp
+++ b/gdb/testsuite/gdb.opt/solib-intra-step.exp
@@ -34,7 +34,7 @@ if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} $lib_flags] != ""
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_load_shlib $binfile_lib
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.pascal/floats.exp b/gdb/testsuite/gdb.pascal/floats.exp
index a0c37ad..926c0c3 100644
--- a/gdb/testsuite/gdb.pascal/floats.exp
+++ b/gdb/testsuite/gdb.pascal/floats.exp
@@ -48,9 +48,9 @@ gdb_test "next" "u := 78\\.3;" "next to 'u := 78.3' line"
gdb_test "next" "l := 1;" "next to 'l := 1' line"
gdb_test "next" "i := 1;" "next to 'i := 1' line"
-# At that point,
+# At that point,
# r should be equal to 1.25
-gdb_test "print r" " = 1\\.25"
+gdb_test "print r" " = 1\\.25"
# s should be equal to 2.2
gdb_test "print s" " = 2\\.(199.*|2|200.*)"
# t should be equal to -3.2
@@ -120,7 +120,7 @@ gdb_test "next" "s := sin\\(u\\);" "advance to 's := sin(u)' line"
gdb_test "print r" " = -1" "test cos(pi) is equal to -1"
gdb_test "next" "" "go past 's := sin(u)' line"
-set msg "Test sin(pi) is equal to 0"
+set msg "Test sin(pi) is equal to 0"
gdb_test_multiple "print s" $msg {
-re ".* = (0|-?\[0-9\]\\.\[0-9\]*\[eE\](-?\[0-9\]*))\[\r\n\]+$gdb_prompt $" {
diff --git a/gdb/testsuite/gdb.pascal/gdb11492.exp b/gdb/testsuite/gdb.pascal/gdb11492.exp
index e39f522..67764c5 100644
--- a/gdb/testsuite/gdb.pascal/gdb11492.exp
+++ b/gdb/testsuite/gdb.pascal/gdb11492.exp
@@ -37,9 +37,9 @@ if { [gdb_breakpoint ${srcfile}:${bp_location1}] } {
gdb_test "continue" ""
gdb_test "print integer_array" { = \{50, 51, 52, 53, 54, 55, 56, 57\}}
-gdb_test "print /s integer_array" " = '23456789'"
+gdb_test "print /s integer_array" " = '23456789'"
-gdb_test "print char_array" " = '23456789'"
+gdb_test "print char_array" " = '23456789'"
gdb_test "print /d char_array" { = \{50, 51, 52, 53, 54, 55, 56, 57\}}
gdb_test "print /x char_array" { = \{0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39\}}
# Use next two times to avoid GPC line numbering problem
diff --git a/gdb/testsuite/gdb.pascal/hello.exp b/gdb/testsuite/gdb.pascal/hello.exp
index 904f2a9..ac10280 100644
--- a/gdb/testsuite/gdb.pascal/hello.exp
+++ b/gdb/testsuite/gdb.pascal/hello.exp
@@ -46,7 +46,7 @@ gdb_test "print st" \
# This test also fails for gpc because the program
# stops after the string has been written
-# while it should stop before writing it
+# while it should stop before writing it
if { $pascal_compiler_is_gpc } {
setup_xfail *-*-*
}
diff --git a/gdb/testsuite/gdb.pascal/integers.exp b/gdb/testsuite/gdb.pascal/integers.exp
index 5c878c5..12d15c8 100644
--- a/gdb/testsuite/gdb.pascal/integers.exp
+++ b/gdb/testsuite/gdb.pascal/integers.exp
@@ -43,9 +43,9 @@ gdb_test "print i" ".* = 0" "print i before assigned to 1"
gdb_test "next" "i := 1;" "next to 'i := 1' line"
gdb_test "next" "j := 2;" "next to 'j := 2' line"
-# At that point,
+# At that point,
# i should be equal to 1
-gdb_test "print i" " = 1"
+gdb_test "print i" " = 1"
# but j should still be equal to zero
if { $pascal_compiler_is_gpc } {
setup_xfail *-*-*
@@ -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.pascal/print.exp b/gdb/testsuite/gdb.pascal/print.exp
index 98b0879..18dff4b 100644
--- a/gdb/testsuite/gdb.pascal/print.exp
+++ b/gdb/testsuite/gdb.pascal/print.exp
@@ -59,7 +59,7 @@ proc test_float_rejected {} {
clean_restart
-if [set_lang_pascal] {
+if { [set_lang_pascal] } {
test_float_accepted
test_float_rejected
} else {
diff --git a/gdb/testsuite/gdb.pascal/types.exp b/gdb/testsuite/gdb.pascal/types.exp
index c234c28..b4949f5 100644
--- a/gdb/testsuite/gdb.pascal/types.exp
+++ b/gdb/testsuite/gdb.pascal/types.exp
@@ -25,7 +25,7 @@ proc test_integer_literal_types_accepted {} {
# Test various decimal values.
# Should be integer*4 probably.
- gdb_test "pt 123" "type = int"
+ gdb_test "pt 123" "type = int"
}
proc test_character_literal_types_accepted {} {
global gdb_prompt
diff --git a/gdb/testsuite/gdb.perf/backtrace.exp b/gdb/testsuite/gdb.perf/backtrace.exp
index 9ec099f..212298e 100644
--- a/gdb/testsuite/gdb.perf/backtrace.exp
+++ b/gdb/testsuite/gdb.perf/backtrace.exp
@@ -47,7 +47,7 @@ PerfTest::assemble {
} {
global binfile
- clean_restart $binfile
+ clean_restart $::testfile
if ![runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.perf/single-step.exp b/gdb/testsuite/gdb.perf/single-step.exp
index 920cf9d..354203e 100644
--- a/gdb/testsuite/gdb.perf/single-step.exp
+++ b/gdb/testsuite/gdb.perf/single-step.exp
@@ -39,7 +39,7 @@ PerfTest::assemble {
return 0
} {
global binfile
- clean_restart $binfile
+ clean_restart $::testfile
if ![runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.perf/skip-command.exp b/gdb/testsuite/gdb.perf/skip-command.exp
index b82d318..99ecad8 100644
--- a/gdb/testsuite/gdb.perf/skip-command.exp
+++ b/gdb/testsuite/gdb.perf/skip-command.exp
@@ -120,7 +120,7 @@ PerfTest::assemble {
return 0
} {
global binfile
- clean_restart $binfile
+ clean_restart $::testfile
return 0
} {
global SKIP_STEP_COUNT SKIP_DIRECTIVE_COUNT
diff --git a/gdb/testsuite/gdb.perf/skip-prologue.exp b/gdb/testsuite/gdb.perf/skip-prologue.exp
index 50df93a..dbeb9f8 100644
--- a/gdb/testsuite/gdb.perf/skip-prologue.exp
+++ b/gdb/testsuite/gdb.perf/skip-prologue.exp
@@ -51,7 +51,7 @@ PerfTest::assemble {
global binfile
global gdb_prompt
- clean_restart $binfile
+ clean_restart $::testfile
if ![runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.perf/solib.exp b/gdb/testsuite/gdb.perf/solib.exp
index 45f9330..1775bf6 100644
--- a/gdb/testsuite/gdb.perf/solib.exp
+++ b/gdb/testsuite/gdb.perf/solib.exp
@@ -72,7 +72,7 @@ PerfTest::assemble {
} {
global binfile
- clean_restart $binfile
+ clean_restart $::testfile
if ![runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.perf/template-breakpoints.exp b/gdb/testsuite/gdb.perf/template-breakpoints.exp
index 7d66e0f..db57731 100644
--- a/gdb/testsuite/gdb.perf/template-breakpoints.exp
+++ b/gdb/testsuite/gdb.perf/template-breakpoints.exp
@@ -47,7 +47,7 @@ PerfTest::assemble {
} {
global binfile
- clean_restart $binfile
+ clean_restart $::testfile
if ![runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp b/gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp
index dd6cb59..17b8afe 100644
--- a/gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp
+++ b/gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp
@@ -39,7 +39,7 @@ proc start_test { breakpoint_comment } {
# Start with a fresh gdb.
# This is important because the test can crash GDB.
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if {![runto_main]} {
untested "couldn't run to breakpoint"
diff --git a/gdb/testsuite/gdb.python/py-cmd.exp b/gdb/testsuite/gdb.python/py-cmd.exp
index f76c176..1fa3c73 100644
--- a/gdb/testsuite/gdb.python/py-cmd.exp
+++ b/gdb/testsuite/gdb.python/py-cmd.exp
@@ -278,13 +278,7 @@ gdb_test_multiline "input multi-line-output command" \
set test "verify pagination from test_multiline"
gdb_test_multiple "test_multiline" $test {
- -re "--Type <RET>" {
- exp_continue
- }
- -re " for more, q to quit" {
- exp_continue
- }
- -re ", c to continue without paging--$" {
+ -re "$pagination_prompt$" {
pass $test
}
}
@@ -328,4 +322,89 @@ proc_with_prefix test_command_redefining_itself {} {
"call command redefining itself 2"
}
+# Try to create commands using unknown prefixes and check GDB gives an
+# error. There's also a test in here for an ambiguous prefix, which
+# gives the same error.
+proc_with_prefix test_unknown_prefix {} {
+ clean_restart
+
+ gdb_test_no_output "python gdb.Command('foo1', gdb.COMMAND_NONE, prefix=True)"
+ gdb_test_no_output "python gdb.Command('foo cmd', gdb.COMMAND_NONE)"
+
+ foreach prefix { "xxx" "foo xxx" "foo1 xxx" } {
+ gdb_test "python gdb.Command('$prefix cmd', gdb.COMMAND_NONE)" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: Could not find command prefix $prefix\\." \
+ "Error occurred in Python: Could not find command prefix $prefix\\."]
+ }
+
+ gdb_test_no_output "python gdb.Command('foo2', gdb.COMMAND_NONE, prefix=True)"
+
+ foreach prefix { "foo" "foo xxx" "foo1 xxx" "foo2 xxx" } {
+ gdb_test "python gdb.Command('$prefix cmd2', gdb.COMMAND_NONE)" \
+ [multi_line \
+ "Python Exception <class 'RuntimeError'>: Could not find command prefix $prefix\\." \
+ "Error occurred in Python: Could not find command prefix $prefix\\."]
+ }
+}
+
+# Check what happens if a command object is called without an 'invoke'
+# method.
+proc_with_prefix test_deleting_invoke_methods {} {
+ clean_restart
+
+ gdb_test_multiline "create 'foo' prefix command" \
+ "python" "" \
+ "class test_prefix(gdb.Command):" "" \
+ " def __init__ (self):" "" \
+ " super().__init__ (\"foo\", gdb.COMMAND_USER, prefix=True)" "" \
+ " def invoke (self, arg, from_tty):" "" \
+ " print(\"In 'foo' invoke: %s\" % arg)" "" \
+ "foo = test_prefix()" "" \
+ "end" ""
+
+ gdb_test_multiline "create 'foo bar' command" \
+ "python" "" \
+ "class test_cmd(gdb.Command):" "" \
+ " def __init__ (self):" "" \
+ " super().__init__ (\"foo bar\", gdb.COMMAND_USER)" "" \
+ " def invoke (self, arg, from_tty):" "" \
+ " print(\"In 'foo bar' invoke: %s\" % arg)" "" \
+ "foo_bar = test_cmd()" "" \
+ "end" ""
+
+ gdb_test "foo def" "In 'foo' invoke: def" \
+ "call 'foo' with an unknown sub-command"
+
+ gdb_test "foo bar def" "In 'foo bar' invoke: def" \
+ "call 'foo bar' with arguments"
+
+ gdb_test_no_output "python del(foo_bar.__class__.invoke)" \
+ "delete invoke from test_cmd class"
+
+ with_test_prefix "after deleting test_cmd.invoke" {
+ gdb_test "foo def" "In 'foo' invoke: def" \
+ "call 'foo' with an unknown sub-command"
+
+ gdb_test "foo bar def" \
+ "^Python command object missing 'invoke' method\\." \
+ "call 'foo bar' with arguments"
+ }
+
+ gdb_test_no_output "python del(foo.__class__.invoke)" \
+ "delete invoke from test_prefix class"
+
+ with_test_prefix "after deleting test_prefix.invoke" {
+ gdb_test "foo def" \
+ "^Python command object missing 'invoke' method\\." \
+ "call 'foo' with an unknown sub-command"
+
+ gdb_test "foo bar def" \
+ "^Python command object missing 'invoke' method\\." \
+ "call 'foo bar' with arguments"
+ }
+}
+
test_command_redefining_itself
+test_unknown_prefix
+test_deleting_invoke_methods
diff --git a/gdb/testsuite/gdb.python/py-color-pagination.exp b/gdb/testsuite/gdb.python/py-color-pagination.exp
new file mode 100644
index 0000000..e7a9e4f
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-color-pagination.exp
@@ -0,0 +1,137 @@
+# Copyright (C) 2025 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite. It tests gdb.Color and how this
+# interacts with GDB's pagination system.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+require {!is_remote host}
+
+standard_testfile
+
+set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
+
+set str "<[string repeat - 78]>"
+
+# These define all the default attributes for a style: background
+# color, intensity, italics, and underlined.
+set other_attr ";49;22;23;24;27"
+
+# These colors set the foreground color only. Everything else is the
+# default.
+set black "(?:\033\\\[30${other_attr}m)"
+set red "(?:\033\\\[31${other_attr}m)"
+set green "(?:\033\\\[32${other_attr}m)"
+set yellow "(?:\033\\\[33${other_attr}m)"
+set blue "(?:\033\\\[34${other_attr}m)"
+set magenta "(?:\033\\\[35${other_attr}m)"
+set cyan "(?:\033\\\[36${other_attr}m)"
+set white "(?:\033\\\[37${other_attr}m)"
+
+set any_color "(?:${black}|${red}|${green}|${yellow}|${blue}|${magenta}|${cyan}|${white})"
+
+# Run the command 'TYPE-fill MODE' which fills the screen with output and
+# triggers the pagination prompt. Check that styling is applied correctly
+# to the output.
+proc test_pagination { type mode } {
+
+ # Start with a fresh GDB, but enable color support.
+ with_ansi_styling_terminal {
+ clean_restart
+ }
+
+ gdb_test_no_output "source $::pyfile" "source the script"
+
+ gdb_test_no_output "set width 80"
+ gdb_test_no_output "set height 15"
+
+ set saw_bad_color_handling false
+ set expected_restore_color ""
+ set last_color ""
+ gdb_test_multiple "$type-fill $mode" "" {
+ -re "^$type-fill $mode\r\n" {
+ exp_continue
+ }
+
+ -re "^(${::any_color})(${::any_color})$::str" {
+ # After a continuation prompt GDB will restore the previous
+ # color, and then we immediately switch to a new color.
+ set restored_color $expect_out(1,string)
+ if { $restored_color ne $expected_restore_color } {
+ set saw_bad_color_handling true
+ }
+ set last_color $expect_out(2,string)
+ exp_continue
+ }
+
+ -re "^(${::any_color})$::str" {
+ # This pattern matches printing STR in all cases that are not
+ # immediately after a pagination prompt. In this case there is
+ # a single escape sequence to set the color.
+ set last_color $expect_out(1,string)
+ exp_continue
+ }
+
+ -re "^\033\\\[${::decimal}m$::str" {
+ # This catches the case where the color's escape sequence has
+ # not been converted back into a full style. This indicates
+ # something went wrong in the pager_file::puts function.
+ set saw_bad_color_handling true
+ exp_continue
+ }
+
+ -re "^\033\\\[m$::pagination_prompt$" {
+ # After a pagination prompt we expect GDB to restore the last
+ # color.
+ set expected_restore_color $last_color
+
+ # Send '\n' to view more output.
+ send_gdb "\n"
+ exp_continue
+ }
+
+ -re "^$::pagination_prompt$" {
+ # After a pagination prompt we expect GDB to restore the last
+ # color.
+ set expected_restore_color $last_color
+
+ # If we didn't see a color reset sequence before the pagination
+ # prompt, then the prompt will have been printed in the wrong
+ # color, this is a GDB bug.
+ set saw_bad_color_handling true
+
+ # Send '\n' to view more output.
+ send_gdb "\n"
+ exp_continue
+ }
+
+ -re "^\r\n" {
+ # The matches the newline sent to the continuation prompt.
+ exp_continue
+ }
+
+ -re "^\033\\\[m\r\n$::gdb_prompt $" {
+ gdb_assert { !$saw_bad_color_handling } $gdb_test_name
+ }
+ }
+}
+
+foreach_with_prefix type { color } {
+ foreach_with_prefix mode { write print } {
+ test_pagination $type $mode
+ }
+}
diff --git a/gdb/testsuite/gdb.python/py-color-pagination.py b/gdb/testsuite/gdb.python/py-color-pagination.py
new file mode 100644
index 0000000..efd501e
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-color-pagination.py
@@ -0,0 +1,46 @@
+# Copyright (C) 2025 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import gdb
+
+basic_colors = ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"]
+
+
+def write(mode, text):
+ if mode == "write":
+ gdb.write(text)
+ else:
+ print(text, end="")
+
+
+class ColorTester(gdb.Command):
+ def __init__(self):
+ super().__init__("color-fill", gdb.COMMAND_USER)
+
+ def invoke(self, args, from_tty):
+ mode = args
+ str = "<" + "-" * 78 + ">"
+ for i in range(0, 20):
+ for color_name in basic_colors:
+ c = gdb.Color(color_name)
+ write(mode, c.escape_sequence(True))
+ write(mode, str)
+
+ default = gdb.Color("none")
+ write(mode, default.escape_sequence(True))
+ write(mode, "\n")
+
+
+ColorTester()
diff --git a/gdb/testsuite/gdb.python/py-color.exp b/gdb/testsuite/gdb.python/py-color.exp
index 3563d22..08089e5 100644
--- a/gdb/testsuite/gdb.python/py-color.exp
+++ b/gdb/testsuite/gdb.python/py-color.exp
@@ -18,9 +18,12 @@
load_lib gdb-python.exp
require allow_python_tests
+require {!is_remote host}
-# Start with a fresh gdb.
-clean_restart
+# Start with a fresh GDB, but enable color support.
+with_ansi_styling_terminal {
+ clean_restart
+}
gdb_test_no_output "python 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"
@@ -115,6 +118,12 @@ gdb_test [concat "python print (c_red.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):" "" \
diff --git a/gdb/testsuite/gdb.python/py-disasm.exp.tcl b/gdb/testsuite/gdb.python/py-disasm.exp.tcl
index c5099ba..5f45747 100644
--- a/gdb/testsuite/gdb.python/py-disasm.exp.tcl
+++ b/gdb/testsuite/gdb.python/py-disasm.exp.tcl
@@ -24,14 +24,16 @@ standard_testfile py-disasm.c
if { $kind == "obj" } {
- set obj [standard_output_file ${gdb_test_file_name}.o]
+ set testfile $testfile.o
+ set binfile [standard_output_file $testfile]
- if { [gdb_compile "$srcdir/$subdir/$srcfile" $obj object "debug"] != "" } {
- untested "failed to compile object file [file tail $obj]"
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile object \
+ "debug"] != "" } {
+ untested "failed to compile object file $testfile"
return -1
}
- clean_restart $obj
+ clean_restart $testfile
} else {
diff --git a/gdb/testsuite/gdb.python/py-exec-file.exp b/gdb/testsuite/gdb.python/py-exec-file.exp
index b3418a5..139ce83 100644
--- a/gdb/testsuite/gdb.python/py-exec-file.exp
+++ b/gdb/testsuite/gdb.python/py-exec-file.exp
@@ -19,8 +19,10 @@ load_lib gdb-python.exp
standard_testfile
-set binfile1 ${binfile}-a
-set binfile2 ${binfile}-b
+set testfile1 $testfile-a
+set binfile1 [standard_output_file $testfile1]
+set testfile2 $testfile-b
+set binfile2 [standard_output_file $testfile2]
if {[build_executable "failed to prepare first executable" \
$binfile1 $srcfile]} {
@@ -176,7 +178,7 @@ with_test_prefix "using 'symbol-file' command" {
# Check the executable_changed event when the executable changes on disk.
with_test_prefix "exec changes on disk" {
- clean_restart $binfile1
+ clean_restart $::testfile1
setup_exec_change_handler
diff --git a/gdb/testsuite/gdb.python/py-format-address.exp b/gdb/testsuite/gdb.python/py-format-address.exp
index 173297c..dd35627 100644
--- a/gdb/testsuite/gdb.python/py-format-address.exp
+++ b/gdb/testsuite/gdb.python/py-format-address.exp
@@ -27,10 +27,12 @@ foreach func_name { foo bar } {
}
}
-set binary_foo [standard_output_file "${testfile}-foo"]
-set binary_bar [standard_output_file "${testfile}-bar"]
+set testfile_foo $testfile-foo
+set testfile_bar $testfile-bar
+set binary_foo [standard_output_file $testfile_foo]
+set binary_bar [standard_output_file $testfile_bar]
-clean_restart $binary_foo
+clean_restart $testfile_foo
if ![runto_main] {
return -1
diff --git a/gdb/testsuite/gdb.python/py-format-string.exp b/gdb/testsuite/gdb.python/py-format-string.exp
index 114a606..8f38c18 100644
--- a/gdb/testsuite/gdb.python/py-format-string.exp
+++ b/gdb/testsuite/gdb.python/py-format-string.exp
@@ -47,7 +47,8 @@ proc build_inferior {exefile lang} {
proc prepare_gdb {exefile} {
global srcdir subdir srcfile testfile hex
- clean_restart $exefile
+ clean_restart
+ gdb_load $exefile
if {![runto_main]} {
return
@@ -1202,7 +1203,9 @@ with_test_prefix "format_string" {
set current_lang "c"
prepare_gdb "${binfile}"
test_all_common
- test_styling
+ if { ![is_remote host] } {
+ test_styling
+ }
}
}
}
diff --git a/gdb/testsuite/gdb.python/py-framefilter-mi.exp b/gdb/testsuite/gdb.python/py-framefilter-mi.exp
index de04236..03e5f90 100644
--- a/gdb/testsuite/gdb.python/py-framefilter-mi.exp
+++ b/gdb/testsuite/gdb.python/py-framefilter-mi.exp
@@ -28,7 +28,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.python/py-mi-objfile.exp b/gdb/testsuite/gdb.python/py-mi-objfile.exp
index 58ecbc5..39bac2b 100644
--- a/gdb/testsuite/gdb.python/py-mi-objfile.exp
+++ b/gdb/testsuite/gdb.python/py-mi-objfile.exp
@@ -33,7 +33,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
# gdb will find it.
set remote_python_file [gdb_remote_download host ${srcdir}/${subdir}/${pyfile}]
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp b/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp
index 07cd40f..7a9124b 100644
--- a/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp
+++ b/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp
@@ -29,7 +29,7 @@ if {[gdb_compile "$srcdir/$subdir/$srcfile" $binfile executable {debug}] != "" }
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
mi_gdb_test "source ${pyfile}" \
diff --git a/gdb/testsuite/gdb.python/py-mi.exp b/gdb/testsuite/gdb.python/py-mi.exp
index 7f1dffc..28d63c1 100644
--- a/gdb/testsuite/gdb.python/py-mi.exp
+++ b/gdb/testsuite/gdb.python/py-mi.exp
@@ -26,7 +26,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
return -1
}
-if {[mi_clean_restart $binfile]} {
+if {[mi_clean_restart $::testfile]} {
return
}
@@ -345,7 +345,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}-cxx" \
return -1
}
-if {[mi_clean_restart ${binfile}-cxx]} {
+if {[mi_clean_restart ${::testfile}-cxx]} {
return
}
diff --git a/gdb/testsuite/gdb.python/py-missing-objfile.exp b/gdb/testsuite/gdb.python/py-missing-objfile.exp
index 29bc555..ce4dc76 100644
--- a/gdb/testsuite/gdb.python/py-missing-objfile.exp
+++ b/gdb/testsuite/gdb.python/py-missing-objfile.exp
@@ -134,7 +134,7 @@ proc clean_restart_load_python {} {
# For sanity, lets check that we can load the specify the executable
# and then load the core-file the easy way.
with_test_prefix "initial sanity check" {
- clean_restart $binfile
+ clean_restart $::testfile
load_core_file
check_loaded_debug true true
}
diff --git a/gdb/testsuite/gdb.python/py-objfile.exp b/gdb/testsuite/gdb.python/py-objfile.exp
index 8d11028..befdb91 100644
--- a/gdb/testsuite/gdb.python/py-objfile.exp
+++ b/gdb/testsuite/gdb.python/py-objfile.exp
@@ -163,7 +163,8 @@ if ![ishost *-*-mingw*] {
remote_exec host "rm -f ${symlink_binary}"
remote_exec host "ln -sf ${testfile} ${symlink_binary}"
if [remote_file host exists "${symlink_binary}"] {
- clean_restart "${symlink_binary}"
+ clean_restart
+ gdb_load "${symlink_binary}"
gdb_test "python print (gdb.lookup_objfile (\"${symlink_binary}\").filename)" \
"${testfile}" "gdb.lookup_objfile of symlinked binary"
}
diff --git a/gdb/testsuite/gdb.python/py-parameter-prefix.exp b/gdb/testsuite/gdb.python/py-parameter-prefix.exp
new file mode 100644
index 0000000..eb09fe7
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-parameter-prefix.exp
@@ -0,0 +1,382 @@
+# Copyright (C) 2025 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite. It tests
+# gdb.ParameterPrefix. See each of the test procs for a full
+# description of what is being tested.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+
+clean_restart
+
+# Helper proc to generate the output of 'show PREFIX' commands for the
+# case where the prefix command doesn't handle unknown sub-commands.
+# In this case GDB will list the value of every sub-command under
+# PREFIX.
+proc make_show_prefix_re { prefix } {
+ return "$prefix param-1:\\s+The current value of '$prefix param-1' is \"off\"\\."
+}
+
+# Helper proc to generate the help text that describes all of the sub
+# commands under PREFIX. The MODE is either 'set' or 'show'. This
+# output will appear for 'help MODE PREFIX' and also for 'set PREFIX'.
+proc make_sub_cmd_help_re { mode prefix } {
+ if { $mode == "set" } {
+ set word "Set"
+ } else {
+ set word "Show"
+ }
+
+ return \
+ [multi_line \
+ "List of \"$mode $prefix\" subcommands:" \
+ "" \
+ "$mode $prefix param-1 -- $word the current value of '$prefix param-1'\\." \
+ "" \
+ "Type \"help $mode $prefix\" followed by subcommand name for full documentation\\." \
+ "Type \"apropos word\" to search for commands related to \"word\"\\." \
+ "Type \"apropos -v word\" for full documentation of commands related to \"word\"\\." \
+ "Command name abbreviations are allowed if unambiguous\\."]
+}
+
+# Helper proc to generate the output of 'help MODE PREFIX', where MODE
+# will be either 'set' or 'show'. The HELP_TEXT is the expected help
+# text for this prefix command, this should not be a regexp, as this
+# proc converts the text to a regexp.
+#
+# Return a single regexp which should match the output.
+proc make_help_re { mode prefix help_text } {
+ set help_re [string_to_regexp $help_text]
+
+ return \
+ [multi_line \
+ "$help_re" \
+ "" \
+ [make_sub_cmd_help_re $mode $prefix]]
+}
+
+# Create gdb.ParameterPrefix without using a sub-class, both with, and
+# without a doc string. For the doc string case, test single line,
+# and multi-line doc strings.
+proc_with_prefix test_basic_usage {} {
+ gdb_test_multiline "some basic ParameterPrefix usage" \
+ "python" "" \
+ "gdb.ParameterPrefix('prefix-1', gdb.COMMAND_NONE)" "" \
+ "gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.ParameterPrefix('prefix-2', gdb.COMMAND_NONE," "" \
+ " \"\"\"This is prefix-2 help string.\"\"\")" "" \
+ "gdb.Parameter('prefix-2 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.ParameterPrefix('prefix-3', gdb.COMMAND_NONE," "" \
+ " \"\"\"This is prefix-3 help string." "" \
+ " " "" \
+ " This help text spans multiple lines.\"\"\")" "" \
+ "gdb.Parameter('prefix-3 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end"
+
+ foreach mode { "set" "show" } {
+ gdb_test "help $mode prefix-1" \
+ [make_help_re $mode "prefix-1" \
+ "This command is not documented."]
+
+ gdb_test "help $mode prefix-2" \
+ [make_help_re $mode "prefix-2" \
+ "This is prefix-2 help string."]
+
+ gdb_test "help $mode prefix-3" \
+ [make_help_re $mode "prefix-3" \
+ [multi_line \
+ "This is prefix-3 help string." \
+ "" \
+ "This help text spans multiple lines."]]
+
+ foreach prefix { prefix-1 prefix-2 prefix-3 } {
+ gdb_test "$mode $prefix xxx" \
+ "^Undefined $mode $prefix command: \"xxx\"\\. Try \"help $mode $prefix\"\\."
+ }
+ }
+
+ foreach prefix { prefix-1 prefix-2 prefix-3 } {
+ gdb_test "set $prefix" \
+ [make_sub_cmd_help_re "set" $prefix]
+
+ gdb_test "show $prefix" \
+ [make_show_prefix_re $prefix]
+ }
+}
+
+# Create a sub-class of gdb.ParameterPrefix, but don't do anything
+# particularly interesting. Again test the with and without
+# documentation string cases.
+proc_with_prefix test_simple_sub_class {} {
+ gdb_test_multiline "some basic ParameterPrefix usage" \
+ "python" "" \
+ "class BasicParamPrefix(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ "BasicParamPrefix('prefix-4')" "" \
+ "gdb.Parameter('prefix-4 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class BasicParamPrefixWithSingleLineDoc(gdb.ParameterPrefix):" "" \
+ " \"\"\"This is a single line doc string.\"\"\"" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ "BasicParamPrefixWithSingleLineDoc('prefix-5')" "" \
+ "gdb.Parameter('prefix-5 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class BasicParamPrefixWithMultiLineDoc(gdb.ParameterPrefix):" "" \
+ " \"\"\"This is a multi line doc string." "" \
+ " " "" \
+ " The rest of the doc string is here.\"\"\"" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ "BasicParamPrefixWithMultiLineDoc('prefix-6')" "" \
+ "gdb.Parameter('prefix-6 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class BasicParamPrefixWithDocParameter(gdb.ParameterPrefix):" "" \
+ " \"\"\"This is an unsused doc string.\"\"\"" "" \
+ " def __init__(self, name, doc):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE, doc)" "" \
+ "BasicParamPrefixWithDocParameter('prefix-7'," "" \
+ " \"\"\"The doc string text is here.\"\"\")" "" \
+ "gdb.Parameter('prefix-7 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end"
+
+ foreach mode { "set" "show" } {
+ gdb_test "help $mode prefix-4" \
+ [make_help_re $mode "prefix-4" \
+ "This command is not documented."]
+
+ gdb_test "help $mode prefix-5" \
+ [make_help_re $mode "prefix-5" \
+ "This is a single line doc string."]
+
+ gdb_test "help $mode prefix-6" \
+ [make_help_re $mode "prefix-6" \
+ [multi_line \
+ "This is a multi line doc string." \
+ "" \
+ "The rest of the doc string is here."]]
+
+ gdb_test "help $mode prefix-7" \
+ [make_help_re $mode "prefix-7" \
+ "The doc string text is here."]
+
+ foreach prefix { prefix-4 prefix-5 prefix-6 prefix-7 } {
+ gdb_test "$mode $prefix xxx" \
+ "^Undefined $mode $prefix command: \"xxx\"\\. Try \"help $mode $prefix\"\\."
+ }
+ }
+
+ foreach prefix { prefix-4 prefix-5 prefix-6 prefix-7 } {
+ gdb_test "set $prefix" \
+ [make_sub_cmd_help_re "set" $prefix]
+
+ gdb_test "show $prefix" \
+ [make_show_prefix_re $prefix]
+ }
+}
+
+# Create a sub-class of gdb.ParameterPrefix, and make use of
+# 'invoke_set' and 'invoke_show'. Test that the invoke method is
+# executed when expected, and that, by default, these invoke methods
+# repeat when the user issues an empty command.
+proc_with_prefix test_prefix_with_invoke {} {
+ gdb_test_multiline "ParameterPrefix with invoke_set" \
+ "python" "" \
+ "class PrefixWithInvokeSet(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_set(self, args, from_tty):" "" \
+ " print(f\"invoke_set (a): \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithInvokeSet('prefix-8')" "" \
+ "gdb.Parameter('prefix-8 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class PrefixWithInvokeShow(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_show(self, args, from_tty):" "" \
+ " print(f\"invoke_show (b): \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithInvokeShow('prefix-9')" "" \
+ "gdb.Parameter('prefix-9 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class PrefixWithBothInvoke(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_set(self, args, from_tty):" "" \
+ " print(f\"invoke_set (c): \\\"{args}\\\" {from_tty}\")" "" \
+ " def invoke_show(self, args, from_tty):" "" \
+ " print(f\"invoke_show (d): \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithBothInvoke('prefix-10')" "" \
+ "gdb.Parameter('prefix-10 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end"
+
+ gdb_test "set prefix-8 xxx yyy" \
+ "^invoke_set \\(a\\): \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_set \\(a\\): \"xxx yyy\" True" \
+ "repeat set prefix-8 xxx yyy"
+
+ gdb_test "show prefix-8 xxx yyy" \
+ "^Undefined show prefix-8 command: \"xxx yyy\"\\. Try \"help show prefix-8\"\\."
+
+ gdb_test "set prefix-9 xxx yyy" \
+ "^Undefined set prefix-9 command: \"xxx yyy\"\\. Try \"help set prefix-9\"\\."
+
+ gdb_test "show prefix-9 xxx yyy" \
+ "^invoke_show \\(b\\): \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_show \\(b\\): \"xxx yyy\" True" \
+ "repeat show prefix-9 xxx yyy"
+
+ gdb_test "set prefix-10 xxx yyy" \
+ "^invoke_set \\(c\\): \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_set \\(c\\): \"xxx yyy\" True" \
+ "repeat set prefix-10 xxx yyy"
+
+ gdb_test "show prefix-10 xxx yyy" \
+ "^invoke_show \\(d\\): \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_show \\(d\\): \"xxx yyy\" True" \
+ "repeat show prefix-10 xxx yyy"
+
+ gdb_test "set prefix-8" \
+ "^invoke_set \\(a\\): \"\" True"
+
+ gdb_test "show prefix-8" \
+ [make_show_prefix_re "prefix-8"]
+
+ gdb_test "set prefix-9" \
+ [make_sub_cmd_help_re "set" "prefix-9"]
+
+ gdb_test "show prefix-9" \
+ "^invoke_show \\(b\\): \"\" True"
+
+ gdb_test "set prefix-10" \
+ "^invoke_set \\(c\\): \"\" True"
+
+ gdb_test "show prefix-10" \
+ "^invoke_show \\(d\\): \"\" True"
+}
+
+# Create ParameterPrefix sub-classes that make use of the
+# dont_repeat() method. Check that the relevant set/show invoke
+# callback doesn't repeat when an empty command is used.
+proc_with_prefix test_dont_repeat {} {
+ gdb_test_multiline "ParameterPrefix with invoke_set and dont_repeat" \
+ "python" "" \
+ "class PrefixWithInvokeAndDoNotRepeatSet(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_set(self, args, from_tty):" "" \
+ " self.dont_repeat()" "" \
+ " print(f\"invoke_set: \\\"{args}\\\" {from_tty}\")" "" \
+ " def invoke_show(self, args, from_tty):" "" \
+ " print(f\"invoke_show: \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithInvokeAndDoNotRepeatSet('prefix-11')" "" \
+ "gdb.Parameter('prefix-11 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "class PrefixWithInvokeAndDoNotRepeatShow(gdb.ParameterPrefix):" "" \
+ " def __init__(self, name):" "" \
+ " super().__init__(name, gdb.COMMAND_NONE)" "" \
+ " def invoke_set(self, args, from_tty):" "" \
+ " print(f\"invoke_set: \\\"{args}\\\" {from_tty}\")" "" \
+ " def invoke_show(self, args, from_tty):" "" \
+ " self.dont_repeat()" "" \
+ " print(f\"invoke_show: \\\"{args}\\\" {from_tty}\")" "" \
+ "PrefixWithInvokeAndDoNotRepeatShow('prefix-12')" "" \
+ "gdb.Parameter('prefix-12 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end"
+
+ gdb_test "set prefix-11 xxx yyy" \
+ "^invoke_set: \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^" \
+ "repeat set prefix-11 xxx yyy"
+
+ gdb_test "show prefix-11 xxx yyy" \
+ "^invoke_show: \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "invoke_show: \"xxx yyy\" True" \
+ "repeat show prefix-11 xxx yyy"
+
+ gdb_test "set prefix-12 xxx yyy" \
+ "^invoke_set: \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^\r\ninvoke_set: \"xxx yyy\" True" \
+ "repeat set prefix-12 xxx yyy"
+
+ gdb_test "show prefix-12 xxx yyy" \
+ "^invoke_show: \"xxx yyy\" True"
+
+ send_gdb "\n"
+ gdb_test "" "^" \
+ "repeat show prefix-12 xxx yyy"
+}
+
+# Create a parameter prefixm, and immediately add another prefix under
+# the first. The important thing here is that the second prefix is
+# created into an otherwise empty prefix as this triggered a bug at
+# one point.
+proc_with_prefix test_nested {} {
+ gdb_test_multiline "Create nested parameter prefixes" \
+ "python" "" \
+ "gdb.ParameterPrefix('prefix-13', gdb.COMMAND_NONE)" "" \
+ "gdb.ParameterPrefix('prefix-13 prefix-14', gdb.COMMAND_NONE)" "" \
+ "gdb.Parameter('prefix-13 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('prefix-13 param-2', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('prefix-13 prefix-14 param-3', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "gdb.Parameter('prefix-13 prefix-14 param-4', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ "end" ""
+
+ gdb_test "show prefix-13 prefix-14" \
+ [multi_line \
+ "^prefix-13 prefix-14 param-3: The current value of 'prefix-13 prefix-14 param-3' is \"off\"\\." \
+ "prefix-13 prefix-14 param-4: The current value of 'prefix-13 prefix-14 param-4' is \"off\"\\."]
+
+ gdb_test "show prefix-13" \
+ [multi_line \
+ "^prefix-13 param-1: The current value of 'prefix-13 param-1' is \"off\"\\." \
+ "prefix-13 param-2: The current value of 'prefix-13 param-2' is \"off\"\\." \
+ "prefix-13 prefix-14 param-3: The current value of 'prefix-13 prefix-14 param-3' is \"off\"\\." \
+ "prefix-13 prefix-14 param-4: The current value of 'prefix-13 prefix-14 param-4' is \"off\"\\."]
+
+ gdb_test "set prefix-13 prefix-14" \
+ [multi_line \
+ "" \
+ "set prefix-13 prefix-14 param-3 -- Set the current value of 'prefix-13 prefix-14 param-3'\\." \
+ "set prefix-13 prefix-14 param-4 -- Set the current value of 'prefix-13 prefix-14 param-4'\\." \
+ "" \
+ ".*"]
+
+ gdb_test "set prefix-13" \
+ [multi_line \
+ "" \
+ "set prefix-13 param-1 -- Set the current value of 'prefix-13 param-1'\\." \
+ "set prefix-13 param-2 -- Set the current value of 'prefix-13 param-2'\\." \
+ "set prefix-13 prefix-14 -- This command is not documented\\." \
+ "" \
+ ".*"]
+}
+
+test_basic_usage
+test_simple_sub_class
+test_prefix_with_invoke
+test_dont_repeat
+test_nested
diff --git a/gdb/testsuite/gdb.python/py-parameter.exp b/gdb/testsuite/gdb.python/py-parameter.exp
index c15bef1..30a477b 100644
--- a/gdb/testsuite/gdb.python/py-parameter.exp
+++ b/gdb/testsuite/gdb.python/py-parameter.exp
@@ -38,13 +38,17 @@ proc_with_prefix test_directories { } {
# doesn't set search directories on remote host.
set directories ".*\\\$cdir.\\\$cwd"
} else {
- set escaped_directory [string_to_regexp "$::srcdir/$::subdir"]
+ set directory [host_file_normalize "$::srcdir/$::subdir"]
+ set escaped_directory [string_to_regexp $directory]
set directories "$escaped_directory.\\\$cdir.\\\$cwd"
}
gdb_test "python print (gdb.parameter ('directories'))" $directories
}
proc_with_prefix test_data_directory { } {
+ # Proc assumes local host.
+ require {!is_remote host}
+
clean_restart
# Check we can correctly read the data-directory parameter. First,
@@ -187,6 +191,8 @@ proc_with_prefix test_enum_parameter { } {
# Test an color parameter.
proc_with_prefix test_color_parameter { } {
+ require {!is_remote host}
+
global env
with_ansi_styling_terminal {
# This enables 256 colors support and disables colors approximation.
@@ -346,6 +352,91 @@ proc_with_prefix test_really_undocumented_parameter { } {
"test general help"
}
+# Test a parameter in which the __doc__ string is empty or None.
+proc_with_prefix test_empty_doc_parameter {} {
+ gdb_test_multiline "empty __doc__ parameter" \
+ "python" "" \
+ "class EmptyDocParam(gdb.Parameter):" "" \
+ " __doc__ = \"\"" "" \
+ " def __init__(self, name):" "" \
+ " super ().__init__(name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "test_empty_doc_param = EmptyDocParam('print test-empty-doc-param')" ""\
+ "end"
+
+ # Setting the __doc__ string to empty means GDB will completely
+ # elide it from the output.
+ gdb_test "help set print test-empty-doc-param" \
+ "^Set the current value of 'print test-empty-doc-param'\\."
+
+ gdb_test_multiline "None __doc__ parameter" \
+ "python" "" \
+ "class NoneDocParam(gdb.Parameter):" "" \
+ " __doc__ = None" "" \
+ " def __init__(self, name):" "" \
+ " super ().__init__(name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "test_none_doc_param = NoneDocParam('print test-none-doc-param')" ""\
+ "end"
+
+ # Setting the __doc__ string to None, or anything else that isn't
+ # a string, causes GDB to use a default string instead.
+ gdb_test "help set print test-none-doc-param" \
+ [multi_line \
+ "^Set the current value of 'print test-none-doc-param'\\." \
+ "This command is not documented\\."]
+}
+
+# Test a parameter in which the set_doc/show_doc strings are either
+# empty, or None.
+proc_with_prefix test_empty_set_show_doc_parameter {} {
+ gdb_test_multiline "empty set/show doc parameter" \
+ "python" "" \
+ "class EmptySetShowParam(gdb.Parameter):" "" \
+ " set_doc = \"\"" "" \
+ " show_doc = \"\"" "" \
+ " def __init__(self, name):" "" \
+ " super ().__init__(name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "test_empty_set_show_param = EmptySetShowParam('print test-empty-set-show-param')" ""\
+ "end"
+
+ # Setting the set_doc/show_doc string to empty means GDB will use
+ # a suitable default string.
+ gdb_test "help set print test-empty-set-show-param" \
+ [multi_line \
+ "^Set the current value of 'print test-empty-set-show-param'\\." \
+ "This command is not documented\\."]
+
+ gdb_test "help show print test-empty-set-show-param" \
+ [multi_line \
+ "^Show the current value of 'print test-empty-set-show-param'\\." \
+ "This command is not documented\\."]
+
+ gdb_test_multiline "None set/show doc parameter" \
+ "python" "" \
+ "class NoneSetShowParam(gdb.Parameter):" "" \
+ " set_doc = None" "" \
+ " show_doc = None" "" \
+ " def __init__(self, name):" "" \
+ " super ().__init__(name, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)" "" \
+ " self.value = True" "" \
+ "test_none_set_show_param = NoneSetShowParam('print test-none-set-show-param')" ""\
+ "end"
+
+ # Setting the set_doc/show_doc string to None (or any non-string
+ # value) means GDB will use a suitable default string.
+ gdb_test "help set print test-none-set-show-param" \
+ [multi_line \
+ "^Set the current value of 'print test-none-set-show-param'\\." \
+ "This command is not documented\\."]
+
+ gdb_test "help show print test-none-set-show-param" \
+ [multi_line \
+ "^Show the current value of 'print test-none-set-show-param'\\." \
+ "This command is not documented\\."]
+}
+
# Test deprecated API. Do not use in your own implementations.
proc_with_prefix test_deprecated_api_parameter { } {
clean_restart
@@ -669,6 +760,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 +868,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-prettyprint.exp b/gdb/testsuite/gdb.python/py-prettyprint.exp
index 0b5ca9a..c342d45 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.exp
+++ b/gdb/testsuite/gdb.python/py-prettyprint.exp
@@ -36,7 +36,8 @@ proc run_lang_tests {exefile lang} {
set nl "\[\r\n\]+"
# Start with a fresh gdb.
- clean_restart $exefile
+ clean_restart
+ gdb_load $exefile
if {![runto_main]} {
return
@@ -192,7 +193,7 @@ with_test_prefix c++ {
# Run various other tests.
-clean_restart $binfile
+clean_restart $::testfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.python/py-source-styling-2.exp b/gdb/testsuite/gdb.python/py-source-styling-2.exp
index b13ee1f..ebf7f32 100644
--- a/gdb/testsuite/gdb.python/py-source-styling-2.exp
+++ b/gdb/testsuite/gdb.python/py-source-styling-2.exp
@@ -32,7 +32,9 @@ if { [build_executable "failed to build" $testfile $srcfile $opts] == -1 } {
return
}
-clean_restart
+with_ansi_styling_terminal {
+ clean_restart
+}
gdb_test_no_output "maint set gnu-source-highlight enabled off"
@@ -40,16 +42,14 @@ gdb_load $binfile
require {gdb_py_module_available pygments}
-with_ansi_styling_terminal {
- gdb_test_no_output "set style enabled on"
-
- gdb_test_multiple "list $line_number" "Styling of c++ keyword try" {
- -re -wrap " try\r\n.*" {
- # Unstyled.
- fail $gdb_test_name
- }
- -re -wrap "" {
- pass $gdb_test_name
- }
+gdb_test_no_output "set style enabled on"
+
+gdb_test_multiple "list $line_number" "Styling of c++ keyword try" {
+ -re -wrap " try\r\n.*" {
+ # Unstyled.
+ fail $gdb_test_name
+ }
+ -re -wrap "" {
+ pass $gdb_test_name
}
}
diff --git a/gdb/testsuite/gdb.python/py-source-styling.exp b/gdb/testsuite/gdb.python/py-source-styling.exp
index 308053c..5d79356 100644
--- a/gdb/testsuite/gdb.python/py-source-styling.exp
+++ b/gdb/testsuite/gdb.python/py-source-styling.exp
@@ -62,7 +62,7 @@ proc check_source_listing_styling { cmd expect_styled { testname "" } } {
# highlighting when GNU source highlight is not available (or is
# disabled, as is done in this test).
proc test_pygments_styling {} {
- clean_restart $::binfile
+ clean_restart $::testfile
# Remote host boards disable styling via GDB's command line. Turn
# it back on now.
@@ -91,7 +91,7 @@ proc test_pygments_styling {} {
# string, then set the correct host encoding, and try again. This
# time the conversion should succeed.
proc test_gdb_execute_non_utf8_source {} {
- clean_restart $::binfile
+ clean_restart $::testfile
# The default host charset is utf-8, the source code contains a
# non-utf-8 character, so this will fail.
@@ -117,7 +117,7 @@ proc test_gdb_execute_non_utf8_source {} {
# output to be returned via a string, and in other cases we ask for
# the output to be sent straight to stdout.
proc_with_prefix test_source_cache_style_tracking {} {
- clean_restart $::binfile
+ clean_restart $::testfile
# Remote host boards disable styling via GDB's command line. Turn
# it back on now.
diff --git a/gdb/testsuite/gdb.python/py-startup-opt.exp b/gdb/testsuite/gdb.python/py-startup-opt.exp
index 7410706..929c64d 100644
--- a/gdb/testsuite/gdb.python/py-startup-opt.exp
+++ b/gdb/testsuite/gdb.python/py-startup-opt.exp
@@ -17,6 +17,7 @@
# initialized.
require allow_python_tests
+require {!is_remote host}
# Return a list containing two directory paths for newly created home
# directories.
diff --git a/gdb/testsuite/gdb.python/py-styled-execute.exp b/gdb/testsuite/gdb.python/py-styled-execute.exp
index 0b27c63..198dab5 100644
--- a/gdb/testsuite/gdb.python/py-styled-execute.exp
+++ b/gdb/testsuite/gdb.python/py-styled-execute.exp
@@ -17,6 +17,7 @@
# on the value of the third argument passed to gdb.execute.
require allow_python_tests
+require {!is_remote host}
load_lib gdb-python.exp
diff --git a/gdb/testsuite/gdb.python/py-symbol.exp b/gdb/testsuite/gdb.python/py-symbol.exp
index 55cdebe..2029c28 100644
--- a/gdb/testsuite/gdb.python/py-symbol.exp
+++ b/gdb/testsuite/gdb.python/py-symbol.exp
@@ -44,7 +44,7 @@ if {!$readnow_p} {
}
# Restart so we don't have expanded symtabs after the previous test.
-clean_restart ${binfile}
+clean_restart ${::testfile}
# Test looking up a global symbol before we runto_main as this is the
# point where we don't have a current frame, and we don't want to
@@ -100,7 +100,6 @@ gdb_test_multiple $cmd "print value of rr" {
fail $gdb_test_name
}
}
-
gdb_test "python print (gdb.lookup_static_symbol ('rr').needs_frame)" \
"False" \
@@ -215,8 +214,10 @@ gdb_test "python print (t\[0\].symtab)" "${py_symbol_c}" "get symtab"
# C++ tests
# Recompile binary.
lappend opts c++
-if {[prepare_for_testing "failed to prepare" "${binfile}-cxx" \
- [list $srcfile $srcfile2] $opts]} {
+set testfile $testfile-cxx
+set binfile [standard_output_file $testfile]
+if { [prepare_for_testing "failed to prepare" $testfile \
+ [list $srcfile $srcfile2] $opts] } {
return -1
}
@@ -252,7 +253,7 @@ gdb_test "python print (cplusfunc.addr_class == gdb.SYMBOL_LOC_BLOCK)" "True" "t
# Test is_valid when the objfile is unloaded. This must be the last
# test as it unloads the object file in GDB.
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
}
diff --git a/gdb/testsuite/gdb.python/py-thrhandle.exp b/gdb/testsuite/gdb.python/py-thrhandle.exp
index 343bf4b..a959044 100644
--- a/gdb/testsuite/gdb.python/py-thrhandle.exp
+++ b/gdb/testsuite/gdb.python/py-thrhandle.exp
@@ -29,7 +29,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
runto_main
diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp
index 0bc4556..5472482 100644
--- a/gdb/testsuite/gdb.python/py-type.exp
+++ b/gdb/testsuite/gdb.python/py-type.exp
@@ -34,7 +34,8 @@ proc build_inferior {exefile lang} {
# Restart GDB.
proc restart_gdb {exefile} {
- clean_restart $exefile
+ clean_restart
+ gdb_load $exefile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.python/py-value.c b/gdb/testsuite/gdb.python/py-value.c
index a822346..f6dbf55 100644
--- a/gdb/testsuite/gdb.python/py-value.c
+++ b/gdb/testsuite/gdb.python/py-value.c
@@ -19,6 +19,14 @@
#include <stdlib.h>
#include <string.h>
+int long_array[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49
+};
+
struct s
{
int a;
@@ -60,6 +68,7 @@ struct Derived : public Base {
Base *base = new Derived ();
Derived derived;
Base &base_ref = derived;
+struct str pod;
void ptr_ref(int*& rptr_int)
{
diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp
index 93985a9..b4e80a2 100644
--- a/gdb/testsuite/gdb.python/py-value.exp
+++ b/gdb/testsuite/gdb.python/py-value.exp
@@ -431,7 +431,8 @@ proc test_value_after_death {} {
proc test_subscript_regression {exefile lang} {
# Start with a fresh gdb.
- clean_restart ${exefile}
+ clean_restart
+ gdb_load $exefile
if {![runto_main]} {
return
@@ -457,6 +458,8 @@ proc test_subscript_regression {exefile lang} {
"Derived \[*\]"
gdb_test "python print (gdb.parse_and_eval('base_ref').dynamic_type)" \
"Derived \[&\]"
+ gdb_test "python print (gdb.parse_and_eval('pod').dynamic_type)" \
+ "str"
# A static type case.
gdb_test "python print (gdb.parse_and_eval('5').dynamic_type)" \
"int"
@@ -680,6 +683,7 @@ proc_with_prefix test_value_bytes { } {
"python" "" \
"def check_value_bytes(var_name):" "" \
" val = gdb.parse_and_eval(var_name)" "" \
+ " assert not val.is_unavailable" "" \
" addr = val.address" "" \
" len = val.type.sizeof" "" \
" mem = gdb.selected_inferior().read_memory(addr, len)" "" \
@@ -762,13 +766,45 @@ proc test_assign {} {
"cannot assign to integer"
}
+# Test Value.is_unavailable
+proc test_unavailable {} {
+ set elem_size [get_valueof "/d" "sizeof(long_array\[0\])" "UNKNOWN" \
+ "get size of long_array element"]
+ set max [expr $elem_size * 10]
+
+ with_set "print elements" 5 {
+ with_max_value_size $max {
+ gdb_test "p long_array"
+
+ gdb_test_no_output "set print elements 15"
+
+ gdb_test_no_output "python v = gdb.history(0)"
+
+ gdb_test "python print(v.is_unavailable)" "^True" \
+ "overall object shows as unavailable"
+ for { set i 0 } { $i < 10 } { incr i } {
+ gdb_test "python print(v\[$i\].is_unavailable)" "^False" \
+ "array element $i is available"
+ gdb_test "python print(v\[$i\])" "^$i" \
+ "array element $i has correct value"
+ }
+ for { set i 10 } { $i < 15 } { incr i } {
+ gdb_test "python print(v\[$i\].is_unavailable)" "^True" \
+ "array element $i is unavailable"
+ gdb_test "python print(v\[$i\])" "^<unavailable>" \
+ "array element $i shows as unavailable"
+ }
+ }
+ }
+}
+
# Build C version of executable. C++ is built later.
if { [build_inferior "${binfile}" "c"] < 0 } {
return -1
}
# Start with a fresh gdb.
-clean_restart ${binfile}
+clean_restart ${::testfile}
test_history_count
test_value_creation
@@ -788,6 +824,7 @@ if {![runto_main]} {
return 0
}
+test_unavailable
test_value_in_inferior
test_value_from_buffer
test_value_sub_classes
@@ -809,3 +846,15 @@ if {[allow_cplus_tests]} {
test_subscript_regression "${binfile}-cxx" "c++"
}
}
+
+if {[allow_rust_tests]} {
+ gdb_test "set lang rust"
+
+ set cst 0x80000000000000000000000000000000
+ gdb_test "python print(int(gdb.parse_and_eval('${cst}u128')))" \
+ "170141183460469231731687303715884105728" \
+ "convert 128 bit unsigned constant to python int"
+ gdb_test "python print(int(gdb.parse_and_eval('${cst}i128')))" \
+ "-170141183460469231731687303715884105728" \
+ "convert 128 bit signed constant to python int"
+}
diff --git a/gdb/testsuite/gdb.python/py-varobj.exp b/gdb/testsuite/gdb.python/py-varobj.exp
index 7fb45f9..cf6a662 100644
--- a/gdb/testsuite/gdb.python/py-varobj.exp
+++ b/gdb/testsuite/gdb.python/py-varobj.exp
@@ -25,7 +25,7 @@ if {[gdb_compile "$srcdir/$subdir/$srcfile" $binfile executable {debug}] != ""}
return -1
}
-mi_clean_restart $binfile
+mi_clean_restart $::testfile
set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
mi_gdb_test "source ${pyfile}" \
diff --git a/gdb/testsuite/gdb.python/py-warning.exp b/gdb/testsuite/gdb.python/py-warning.exp
new file mode 100644
index 0000000..6b26a4e
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-warning.exp
@@ -0,0 +1,63 @@
+# Copyright (C) 2025 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test the gdb.warning() function.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+
+clean_restart
+
+# Basic usage.
+gdb_test "python gdb.warning(\"some text\")" \
+ "warning: some text"
+
+# Basic usage with named argument.
+gdb_test "python gdb.warning(text=\"a warning message\")" \
+ "warning: a warning message"
+
+# Make sure GDB prints format specifiers correctly.
+gdb_test "python gdb.warning(\"%s %d %p\")" \
+ "warning: %s %d %p"
+
+# Empty string gives an error.
+gdb_test "python gdb.warning(\"\")" \
+ [multi_line \
+ "Python Exception <class 'ValueError'>: Empty text string passed to gdb\\.warning" \
+ "Error occurred in Python: Empty text string passed to gdb\\.warning"]
+
+# Missing argument gives an error.
+set re1 \
+ [multi_line \
+ [string_to_regexp \
+ [concat \
+ "Python Exception <class 'TypeError'>:" \
+ "function missing required argument 'text' (pos 1)"]] \
+ [string_to_regexp \
+ [concat \
+ "Error occurred in Python:" \
+ "function missing required argument 'text' (pos 1)"]]]
+set re2 \
+ [multi_line \
+ [string_to_regexp \
+ [concat \
+ "Python Exception <class 'TypeError'>:" \
+ "Required argument 'text' (pos 1) not found"]] \
+ [string_to_regexp \
+ [concat \
+ "Error occurred in Python:" \
+ "Required argument 'text' (pos 1) not found"]]]
+gdb_test "python gdb.warning()" $re1|$re2
diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp
index 6b2f671..96977df 100644
--- a/gdb/testsuite/gdb.python/python.exp
+++ b/gdb/testsuite/gdb.python/python.exp
@@ -152,13 +152,7 @@ gdb_test_no_output "set height $lines"
set test "verify pagination beforehand"
gdb_test_multiple "python print (\"\\n\" * $lines)" $test {
- -re "--Type <RET>" {
- exp_continue
- }
- -re " for more, q to quit" {
- exp_continue
- }
- -re ", c to continue without paging--$" {
+ -re "$pagination_prompt$" {
pass $test
}
}
@@ -168,13 +162,7 @@ gdb_test "python if gdb.execute('python print (\"\\\\n\" * $lines)', to_string=T
set test "verify pagination afterwards"
gdb_test_multiple "python print (\"\\n\" * $lines)" $test {
- -re "--Type <RET>" {
- exp_continue
- }
- -re " for more, q to quit" {
- exp_continue
- }
- -re ", c to continue without paging--$" {
+ -re "$pagination_prompt$" {
pass $test
}
}
diff --git a/gdb/testsuite/gdb.replay/connect.exp b/gdb/testsuite/gdb.replay/connect.exp
index 5790d38..b25c372 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
@@ -70,9 +70,8 @@ proc_with_prefix record_initial_logfile {} {
# Connect to gdbreply using the global REMOTELOG. Runs to a breakpoint
# in main.
proc_with_prefix replay_without_error {} {
- global binfile
global remotelog
- clean_restart $binfile
+ clean_restart $::testfile
# Make sure we're disconnected, in case we're testing with an
# extended-remote board, therefore already connected.
gdb_test "disconnect" ".*"
@@ -97,7 +96,6 @@ proc_with_prefix replay_without_error {} {
# copy of REMOTELOG. Attempt to connect to the remote and expect to see
# the error reported by GDB.
proc_with_prefix replay_with_mustreplyempty_error {} {
- global binfile
global remotelog
global testfile
set newline E.errtext
@@ -107,7 +105,7 @@ proc_with_prefix replay_with_mustreplyempty_error {} {
# the vMustReplayEmty packet to an error.
update_log $remotelog $output_file "vMustReplyEmpty" $newline
- clean_restart $binfile
+ clean_restart $::testfile
# Make sure we're disconnected, in case we're testing with an
# extended-remote board, therefore already connected.
gdb_test "disconnect" ".*"
diff --git a/gdb/testsuite/gdb.reverse/i386-avx-reverse.c b/gdb/testsuite/gdb.reverse/i386-avx-reverse.c
index a37b65a..bf6cb77 100644
--- a/gdb/testsuite/gdb.reverse/i386-avx-reverse.c
+++ b/gdb/testsuite/gdb.reverse/i386-avx-reverse.c
@@ -30,6 +30,18 @@ char global_buf1[] = {0, 0, 0, 0, 0, 0, 0, 0,
char *dyn_buf0;
char *dyn_buf1;
+ /* Zero memory regions again, so that future tests can update them
+ without worry. */
+void
+reset_buffers ()
+{
+ for (int i = 0; i < 32; i++)
+ {
+ global_buf1[i] = 0;
+ dyn_buf1[i] = 0;
+ }
+}
+
int
vmov_test ()
{
@@ -168,6 +180,22 @@ vmov_test ()
asm volatile ("vmovapd %%xmm0, %0" : : "m"(*dyn_buf1));
asm volatile ("vmovaps %%ymm15, %0" : : "m"(*dyn_buf1));
+ /* Testing vmov[hl|lh]ps and vmov[h|l]pd. */
+ asm volatile ("vmovhlps %xmm1, %xmm8, %xmm0");
+ asm volatile ("vmovhlps %xmm1, %xmm2, %xmm15");
+ asm volatile ("vmovlhps %xmm1, %xmm8, %xmm0");
+ asm volatile ("vmovlhps %xmm1, %xmm2, %xmm15");
+
+ asm volatile ("vmovhps %0, %%xmm1, %%xmm0" : : "m"(buf0));
+ asm volatile ("vmovhps %%xmm0, %0" : "=m" (buf1));
+ asm volatile ("vmovhpd %0, %%xmm1, %%xmm15" : : "m"(global_buf0));
+ asm volatile ("vmovhpd %%xmm15, %0" : "=m" (global_buf1));
+ asm volatile ("vmovlpd %0, %%xmm1, %%xmm15" : : "m"(*dyn_buf0));
+ asm volatile ("vmovlpd %%xmm15, %0" : "=m" (*dyn_buf1));
+
+ asm volatile ("vmovddup %xmm1, %xmm15");
+ asm volatile ("vmovddup %ymm2, %ymm0");
+
/* We have a return statement to deal with
epilogue in different compilers. */
return 0; /* end vmov_test */
@@ -245,7 +273,7 @@ vpunpck_test ()
return 0; /* end vpunpck_test */
}
-/* Test if we can record vpbroadcast instructions. */
+/* Test if we can record vpbroadcast and vbroadcast instructions. */
int
vpbroadcast_test ()
{
@@ -268,6 +296,14 @@ vpbroadcast_test ()
asm volatile ("vpbroadcastq %xmm1, %ymm0");
asm volatile ("vpbroadcastq %xmm1, %ymm15");
+ asm volatile ("vbroadcastss %xmm1, %xmm0");
+ asm volatile ("vbroadcastss %xmm1, %ymm15");
+ asm volatile ("vbroadcastss %0, %%ymm0" : : "m" (global_buf0));
+ asm volatile ("vbroadcastss %0, %%xmm15": : "m" (*dyn_buf0));
+ asm volatile ("vbroadcastsd %xmm1, %ymm0");
+ asm volatile ("vbroadcastsd %0, %%ymm15": : "m" (global_buf0));
+ asm volatile ("vbroadcastf128 %0, %%ymm0" : : "m" (*dyn_buf0));
+
/* We have a return statement to deal with
epilogue in different compilers. */
return 0; /* end vpbroadcast_test */
@@ -372,6 +408,7 @@ arith_test ()
/* Using GDB, load these values onto registers for testing.
ymm0.v8_float = {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5}
ymm1.v8_float = {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5}
+ ymm2.v2_int128 = {0x0, 0x0}
ymm15.v2_int128 = {0x0, 0x0}
this way it's easy to confirm we're undoing things correctly. */
asm volatile ("vaddps %xmm0, %xmm1, %xmm15");
@@ -416,9 +453,318 @@ arith_test ()
asm volatile ("vmaxss %xmm0, %xmm1, %xmm15");
asm volatile ("vmaxsd %xmm0, %xmm1, %xmm15");
+ /* Some sanity checks for other arithmetic instructions. */
+ asm volatile ("vpaddb %xmm0, %xmm1, %xmm2");
+ asm volatile ("vpaddw %xmm0, %xmm1, %xmm15");
+ asm volatile ("vpaddd %ymm0, %ymm1, %ymm2");
+ asm volatile ("vpaddq %ymm0, %ymm1, %ymm15");
+
+ asm volatile ("vpmullw %xmm0, %xmm1, %xmm2");
+ asm volatile ("vpmulld %xmm0, %xmm1, %xmm15");
+ asm volatile ("vpmulhw %ymm0, %ymm1, %ymm2");
+ asm volatile ("vpmulhuw %ymm0, %ymm1, %ymm15");
+ asm volatile ("vpmuludq %ymm0, %ymm1, %ymm15");
+
+ asm volatile ("vxorps %xmm0, %xmm1, %xmm2");
+ asm volatile ("vxorpd %ymm0, %ymm1, %ymm2");
+ asm volatile ("vpand %xmm0, %xmm1, %xmm15");
+ asm volatile ("vpandn %ymm0, %ymm1, %ymm15");
+
+ asm volatile ("vpsadbw %xmm0, %xmm1, %xmm2");
+ asm volatile ("vpsadbw %ymm0, %ymm1, %ymm15");
+
return 0; /* end arith_test */
}
+int
+vaddsubpd_test ()
+{
+ /* start vaddsubpd_test */
+ /* YMM test. */
+ asm volatile ("vaddsubpd %ymm15,%ymm1,%ymm0");
+ asm volatile ("vaddsubpd %ymm0,%ymm1,%ymm15");
+ asm volatile ("vaddsubpd %ymm2,%ymm3,%ymm4");
+
+ /* XMM test. */
+ asm volatile ("vaddsubpd %xmm15,%xmm1,%xmm2");
+ asm volatile ("vaddsubpd %xmm0,%xmm1,%xmm10");
+ return 0; /* end vaddsubpd_test */
+}
+
+int
+vaddsubps_test ()
+{
+ /* start vaddsubps_test */
+ /* YMM test. */
+ asm volatile ("vaddsubps %ymm15,%ymm1,%ymm2");
+ asm volatile ("vaddsubps %ymm0,%ymm1,%ymm10");
+ asm volatile ("vaddsubps %ymm2,%ymm3,%ymm4");
+
+ /* XMM test. */
+ asm volatile ("vaddsubps %xmm0,%xmm1,%xmm15");
+ asm volatile ("vaddsubps %xmm15,%xmm1,%xmm0");
+ return 0; /* end vaddsubps_test */
+}
+
+
+/* Test record shifting instructions. */
+int
+shift_test ()
+{
+ /* start shift_test. */
+ /* Using GDB, load these values onto registers for testing.
+ ymm0.v2_int128 = {0, 0}
+ ymm1.v16_int16 = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}
+ xmm2.uint128 = 1
+ ymm15.v2_int128 = {0x0, 0x0}
+ this way it's easy to confirm we're undoing things correctly. */
+
+ asm volatile ("vpsllw $1, %xmm1, %xmm0");
+ asm volatile ("vpsllw %xmm2, %ymm1, %ymm0");
+ asm volatile ("vpslld $3, %ymm1, %ymm15");
+ asm volatile ("vpslld %xmm2, %xmm1, %xmm15");
+ asm volatile ("vpsllq $5, %xmm1, %xmm15");
+ asm volatile ("vpsllq %xmm2, %ymm1, %ymm15");
+
+ asm volatile ("vpsraw $1, %xmm1, %xmm0");
+ asm volatile ("vpsraw %xmm2, %ymm1, %ymm0");
+ asm volatile ("vpsrad $3, %ymm1, %ymm15");
+ asm volatile ("vpsrad %xmm2, %xmm1, %xmm15");
+
+ asm volatile ("vpsrlw $1, %xmm1, %xmm0");
+ asm volatile ("vpsrlw %xmm2, %ymm1, %ymm0");
+ asm volatile ("vpsrld $3, %ymm1, %ymm15");
+ asm volatile ("vpsrld %xmm2, %xmm1, %xmm15");
+ asm volatile ("vpsrlq $5, %xmm1, %xmm15");
+ asm volatile ("vpsrlq %xmm2, %ymm1, %ymm15");
+
+ /* The dq version is treated separately in the manual, so
+ we test it separately just to be sure. */
+ asm volatile ("vpslldq $1, %xmm1, %xmm0");
+ asm volatile ("vpslldq $2, %ymm1, %ymm0");
+ asm volatile ("vpslldq $3, %xmm1, %xmm15");
+ asm volatile ("vpslldq $4, %ymm1, %ymm15");
+
+ asm volatile ("vpsrldq $1, %xmm1, %xmm0");
+ asm volatile ("vpsrldq $2, %ymm1, %ymm0");
+ asm volatile ("vpsrldq $3, %xmm1, %xmm15");
+ asm volatile ("vpsrldq $4, %ymm1, %ymm15");
+
+ return 0; /* end shift_test */
+}
+
+int
+shuffle_test ()
+{
+ /* start shuffle_test. */
+ /* Using GDB, load these values onto registers for testing.
+ ymm0.v2_int128 = {0, 0}
+ ymm1.v16_int16 = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}
+ ymm2.v16_int15 = {17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}
+ ymm15.v2_int128 = {0x0, 0x0}
+ this way it's easy to confirm we're undoing things correctly. */
+
+ asm volatile ("vpshufb %xmm1, %xmm2, %xmm0");
+ asm volatile ("vpshufb %ymm1, %ymm2, %ymm15");
+ asm volatile ("vpshufd $1, %ymm2, %ymm0");
+ asm volatile ("vpshufd $2, %xmm2, %xmm15");
+
+ asm volatile ("vpshufhw $3, %xmm2, %xmm0");
+ asm volatile ("vpshufhw $4, %ymm2, %ymm15");
+ asm volatile ("vpshuflw $5, %ymm2, %ymm0");
+ asm volatile ("vpshuflw $6, %xmm2, %xmm15");
+
+ asm volatile ("vshufps $1, %xmm1, %xmm2, %xmm0");
+ asm volatile ("vshufps $2, %ymm1, %ymm2, %ymm15");
+ asm volatile ("vshufpd $4, %ymm1, %ymm2, %ymm0");
+ asm volatile ("vshufpd $8, %xmm1, %xmm2, %xmm15");
+
+ return 0; /* end shuffle_test */
+}
+
+int
+permute_test ()
+{
+ /* start permute_test. */
+ /* Using GDB, load these values onto registers for testing.
+ ymm0.v2_int128 = {0, 0}
+ ymm1.v16_int16 = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}
+ ymm2.v16_int16 = {17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}
+ ymm15.v2_int128 = {0x0, 0x0}
+ eax = 0
+ this way it's easy to confirm we're undoing things correctly. */
+ asm volatile ("vperm2f128 $1, %ymm1, %ymm2, %ymm0");
+ asm volatile ("vperm2f128 $0, %ymm1, %ymm2, %ymm15");
+ asm volatile ("vperm2i128 $1, %ymm2, %ymm1, %ymm0");
+ asm volatile ("vperm2i128 $0, %ymm2, %ymm1, %ymm15");
+
+ asm volatile ("vpermd %ymm1, %ymm2, %ymm0");
+ asm volatile ("vpermd %ymm1, %ymm2, %ymm15");
+ asm volatile ("vpermq $1, %ymm1, %ymm0");
+ asm volatile ("vpermq $0, %ymm2, %ymm15");
+
+ asm volatile ("vpermilpd %ymm1, %ymm2, %ymm0");
+ asm volatile ("vpermilpd %xmm1, %xmm2, %xmm15");
+ asm volatile ("vpermilpd $1, %ymm2, %ymm15");
+ asm volatile ("vpermilpd $0, %xmm2, %xmm0");
+ asm volatile ("vpermilps %ymm1, %ymm2, %ymm0");
+ asm volatile ("vpermilps %xmm1, %xmm2, %xmm15");
+ asm volatile ("vpermilps $1, %ymm2, %ymm15");
+ asm volatile ("vpermilps $0, %xmm2, %xmm0");
+
+ asm volatile ("vpermpd $0, %ymm1, %ymm15");
+ asm volatile ("vpermpd $0, %ymm2, %ymm0");
+ asm volatile ("vpermps %ymm1, %ymm2, %ymm0");
+ asm volatile ("vpermps %ymm1, %ymm2, %ymm15");
+
+ return 0; /* end permute_test */
+}
+
+int
+extract_insert_test ()
+{
+ /* start extract_insert_test. */
+ /* Using GDB, load these values onto registers for testing.
+ ymm0.v2_int128 = {0, 0}
+ ymm1.v16_int16 = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}
+ xmm2.uint128 = 0xcafe
+ ymm15.v2_int128 = {0x0, 0x0}
+ eax = 0
+ this way it's easy to confirm we're undoing things correctly. */
+
+ asm volatile ("vinserti128 $1, %xmm2, %ymm1, %ymm0");
+ asm volatile ("vinsertf128 $0, %xmm2, %ymm1, %ymm15");
+ asm volatile ("vextracti128 $1, %ymm1, %xmm0");
+ asm volatile ("vextractf128 $0, %ymm1, %xmm15");
+ asm volatile ("vinsertps $16, %xmm2, %xmm1, %xmm0");
+ asm volatile ("vextractps $0, %xmm2, %rax");
+
+ asm volatile ("vpextrb $5, %xmm1, %rax");
+ asm volatile ("vpextrb $4, %%xmm1, %0" : "=m" (global_buf1));
+ asm volatile ("vpextrd $3, %xmm1, %eax");
+ asm volatile ("vpextrd $2, %%xmm1, %0" : "=m" (global_buf1));
+ asm volatile ("vpextrq $1, %xmm1, %rax");
+ asm volatile ("vpextrq $0, %%xmm1, %0" : "=m" (global_buf1));
+
+ asm volatile ("vpinsrb $3, %rax, %xmm2, %xmm0");
+ asm volatile ("vpinsrw $2, %eax, %xmm2, %xmm15");
+ asm volatile ("vpinsrd $1, %eax, %xmm2, %xmm0");
+ asm volatile ("vpinsrq $0, %rax, %xmm2, %xmm15");
+
+ /* vpextrw has completely different mechanics to other vpextr
+ instructions, so separate them for ease of testing later. */
+ asm volatile ("vpextrw $1, %xmm1, %eax");
+ asm volatile ("vpextrw $1, %%xmm1, %0" : "=m" (global_buf1));
+
+ return 0; /* end extract_insert_test */
+}
+
+int
+blend_test ()
+{
+ /* start blend_test. */
+ /* Using GDB, load these values onto registers for testing.
+ ymm0.v2_int128 = {0, 0}
+ ymm1.v16_int16 = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}
+ ymm2.v16_int16 = {17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}
+ ymm15.v2_int128 = {0x0, 0x0}
+ this way it's easy to confirm we're undoing things correctly. */
+
+ asm volatile ("vblendps $5, %xmm1, %xmm2, %xmm0");
+ asm volatile ("vblendpd $10, %ymm1, %ymm2, %ymm15");
+ asm volatile ("vblendvps %ymm15, %ymm1, %ymm2, %ymm0");
+ asm volatile ("vblendvpd %xmm0, %xmm1, %xmm2, %xmm15");
+
+ asm volatile ("vpblendw $94, %ymm1, %ymm2, %ymm15");
+ asm volatile ("vpblendw $47, %xmm1, %xmm2, %xmm0");
+ asm volatile ("vpblendd $22, %ymm1, %ymm2, %ymm0");
+ asm volatile ("vpblendd $11, %xmm1, %xmm2, %xmm15");
+ asm volatile ("vpblendvb %xmm0, %xmm1, %xmm2, %xmm15");
+ asm volatile ("vpblendvb %ymm0, %ymm1, %ymm2, %ymm0");
+
+ return 0; /* end blend_test */
+}
+
+int
+compare_test ()
+{
+ /* start compare_test. */
+ /* Using GDB, load these values onto registers for testing.
+ xmm0.v4_float = {0, 1.5, 2, 0}
+ xmm1.v4_float = {0, 1, 2.5, -1}
+ xmm15.v4_float = {-1, -2, 10, 100}
+ eflags = 2
+ eflags can't be set to some values, if we set it to 0, it'll
+ be reset to 2, so set it to that directly to make results less
+ confusing.
+ this way it's easy to confirm we're undoing things correctly. */
+
+ asm volatile ("vcomisd %xmm0, %xmm1");
+ asm volatile ("vcomiss %xmm15, %xmm1");
+ asm volatile ("vucomiss %xmm1, %xmm15");
+ asm volatile ("vucomisd %xmm15, %xmm0");
+
+ return 0; /* end compare_test */
+}
+
+int
+pack_test ()
+{
+ /* start pack_test. */
+ /* Using GDB, load these values onto registers for testing.
+ xmm0.v4_float = {0, 1.5, 2, 0}
+ xmm1.v4_float = {0, 1, 2.5, -1}
+ xmm2.v4_float = {0, 1, 2.5, -1}
+ xmm15.v4_float = {-1, -2, 10, 100}
+ this way it's easy to confirm we're undoing things correctly. */
+
+ asm volatile ("vpacksswb %xmm1, %xmm2, %xmm0");
+ asm volatile ("vpacksswb %ymm1, %ymm2, %ymm15");
+ asm volatile ("vpackssdw %xmm1, %xmm2, %xmm15");
+ asm volatile ("vpackssdw %ymm1, %ymm2, %ymm0");
+ asm volatile ("vpackuswb %xmm1, %xmm2, %xmm0");
+ asm volatile ("vpackuswb %ymm1, %ymm2, %ymm15");
+ asm volatile ("vpackusdw %xmm1, %xmm2, %xmm15");
+ asm volatile ("vpackusdw %ymm1, %ymm2, %ymm0");
+
+ return 0; /* end pack_test */
+}
+
+int
+convert_test ()
+{
+ /* start convert_test. */
+ /* Using GDB, load these values onto registers for testing.
+ xmm0.v2_int128 = {0, 0}
+ xmm1.v4_float = {0, 1, 2.5, 10}
+ xmm15.v2_int128 = {0, 0}
+ ecx = -1
+ ebx = 0
+ this way it's easy to confirm we're undoing things correctly. */
+
+ asm volatile ("vcvtdq2ps %xmm1, %xmm0");
+ asm volatile ("vcvtdq2pd %xmm1, %xmm15");
+
+ asm volatile ("vcvtps2dq %xmm1, %xmm15");
+ asm volatile ("vcvtps2pd %xmm1, %xmm0");
+ asm volatile ("vcvtpd2ps %xmm1, %xmm15");
+ asm volatile ("vcvtpd2dq %xmm1, %xmm0");
+
+ asm volatile ("vcvtsd2si %xmm1, %rbx");
+ asm volatile ("vcvtsd2ss %xmm0, %xmm1, %xmm15");
+ asm volatile ("vcvtsi2sd %rcx, %xmm1, %xmm0");
+ asm volatile ("vcvtsi2ss %rcx, %xmm1, %xmm15");
+ asm volatile ("vcvtss2sd %xmm15, %xmm1, %xmm0");
+ asm volatile ("vcvtss2si %xmm1, %rbx");
+
+ asm volatile ("vcvttpd2dq %xmm1, %xmm0");
+ asm volatile ("vcvttps2dq %xmm1, %xmm15");
+ asm volatile ("vcvttsd2si %xmm0, %rbx");
+ asm volatile ("vcvttss2si %xmm1, %ecx");
+
+ return 0; /* end convert_test */
+}
+
/* This include is used to allocate the dynamic buffer and have
the pointers aligned to a 32-bit boundary, so we can test instructions
that require aligned memory. */
@@ -442,6 +788,7 @@ main ()
asm volatile ("vmovq %0, %%xmm15": : "m" (global_buf1));
vmov_test ();
+ reset_buffers ();
vpunpck_test ();
vpbroadcast_test ();
vzeroupper_test ();
@@ -449,5 +796,15 @@ main ()
vpcmpeq_test ();
vpmovmskb_test ();
arith_test ();
+ vaddsubpd_test ();
+ vaddsubps_test ();
+ shift_test ();
+ shuffle_test ();
+ permute_test ();
+ extract_insert_test ();
+ blend_test ();
+ compare_test ();
+ pack_test ();
+ convert_test ();
return 0; /* end of main */
}
diff --git a/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp b/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp
index 0ff56dd..fb04260 100644
--- a/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp
@@ -149,6 +149,33 @@ global decimal
if {[record_full_function "vmov"] == true} {
# Now execute backwards, checking all instructions.
+ test_one_register "vmovddup" "ymm0" \
+ "0x3736353433323130c004000000000000, 0x0"
+ test_one_register "vmovddup" "ymm15" \
+ "0x2726252423222120, 0x0"
+ test_one_memory "vmovlpd" "dyn_buf1" \
+ "\\\{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28" \
+ true
+ test_one_register "vmovlpd" "ymm15" \
+ "0x1716151413121110c004000000000000, 0x0"
+ test_one_memory "vmovhpd" "global_buf1" \
+ "\\\{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18"
+ test_one_register "vmovhpd" "ymm15" \
+ "0xc004000000000000c004000000000000, 0x0"
+ test_one_memory "vmovhps" "buf1" \
+ "\\\{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38"
+ test_one_register "vmovhps" "ymm0" \
+ "0xc004000000000000c004000000000000, 0x0"
+
+ test_one_register "vmovlhps" "ymm15" \
+ "0x0, 0x0"
+ test_one_register "vmovlhps" "ymm0" \
+ "0x0, 0x0"
+ test_one_register "vmovhlps" "ymm15" \
+ "0x2f2e2d2c2b2a29280000000000000000, 0x2f2e2d2c2b2a29282726252423222120"
+ test_one_register "vmovhlps" "ymm0" \
+ "0x2f2e2d2c2b2a29282726252423222120, 0x0"
+
# Explicitly test for the start of the array, since the value repeats.
test_one_memory "vmovaps" "dyn_buf1" \
"\\\{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28" true
@@ -365,6 +392,24 @@ gdb_test_no_output "set \$xmm1.v2_int64 = {0x1716151413121110, 0x1f1e1d1c1b1a191
"set xmm1 for vpbroadcast"
gdb_test_no_output "set \$ymm15.v2_int128 = {0x0, 0x0}" "set xmm15 for vpbroadcast"
if {[record_full_function "vpbroadcast"] == true} {
+ test_one_register "vbroadcastf128" "ymm0" \
+ "0x17161514131211101716151413121110, 0x17161514131211101716151413121110"
+ test_one_register "vbroadcastsd" "ymm15" \
+ "0x23222120232221202322212023222120, 0x0"
+ test_one_register "vbroadcastsd" "ymm0" \
+ "0x13121110131211101312111013121110, 0x13121110131211101312111013121110"
+
+ test_one_register "vbroadcastss" "ymm15" \
+ "0x13121110131211101312111013121110, 0x13121110131211101312111013121110" \
+ "broadcast from memory"
+ test_one_register "vbroadcastss" "ymm0" \
+ "0x13121110131211101312111013121110, 0x0" \
+ "broadcast from memory"
+ test_one_register "vbroadcastss" "ymm15" \
+ "0x17161514131211101716151413121110, 0x17161514131211101716151413121110"
+ test_one_register "vbroadcastss" "ymm0" \
+ "0x17161514131211101716151413121110, 0x17161514131211101716151413121110"
+
test_one_register "vpbroadcastq" "ymm15" "0x13121110131211101312111013121110, 0x0"
test_one_register "vpbroadcastq" "ymm0" "0x13121110131211101312111013121110, 0x0"
@@ -397,7 +442,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" \
@@ -527,9 +572,43 @@ gdb_test_no_output \
"set \$ymm0.v8_float = {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5}"
gdb_test_no_output \
"set \$ymm1.v8_float = {0, 1, 2, 3, 4, 5, 6, 7}"
+gdb_test_no_output "set \$ymm2.v2_int128 = {0,0}"
gdb_test_no_output "set \$ymm15.v2_int128 = {0,0}"
if {[record_full_function "arith"] == true} {
+ test_one_register "vpsadbw" "ymm15" \
+ "0x20000000200000004000003f000000, 0x100000001000000010000000100000"
+ test_one_register "vpsadbw" "ymm2" \
+ "0x20000000200000004000003f000000, 0x100000001000000010000000100000"
+ test_one_register "vpandn" "ymm15" \
+ "0x40400000400000003f80000000000000, 0x0"
+ test_one_register "vpand" "ymm15" \
+ "0x10080000000000000000000000000000, 0x10649c00000000001044480000000000"
+ test_one_register "vxorpd" "ymm2" \
+ "0x20000000200000004000003f000000, 0x0"
+ test_one_register "vxorps" "ymm2" \
+ "0x10280000100800000fd0000000000000, 0x10740000106400001054000010440000"
+
+ test_one_register "vpmuludq" "ymm15" \
+ "0x10280000100800000fd0000000000000, 0x10740000106400001054000010440000"
+ test_one_register "vpmulhuw" "ymm15" \
+ "0x0, 0x0"
+ test_one_register "vpmulhw" "ymm2" \
+ "0x18000000000000002000000000000000, 0x0"
+ test_one_register "vpmulld" "ymm15" \
+ "0x80a00000802000007f4000003f000000, 0x81d00000819000008150000081100000"
+ test_one_register "vpmullw" "ymm2" \
+ "0x80a00000802000007f4000003f000000, 0x81d00000819000008150000081100000"
+
+ test_one_register "vpaddq" "ymm15" \
+ "0x80a00000802000007f4000003f000000, 0x0"
+ test_one_register "vpaddd" "ymm2" \
+ "0x80a00000802000007e4000003f000000, 0x0"
+ test_one_register "vpaddw" "ymm15" \
+ "0x40400000400000003fc000003f000000, 0x0"
+ test_one_register "vpaddb" "ymm2" \
+ "0x0, 0x0"
+
test_one_register "vmaxsd" "ymm15" \
"0x40400000400000003f8000003f000000, 0x0" "ymm operation: "
test_one_register "vmaxss" "ymm15" \
@@ -626,3 +705,493 @@ if {[record_full_function "arith"] == true} {
}
gdb_test "finish" "Run till exit from.*arith_test.*" \
"leaving arith"
+
+# Preparation and testing vaddsubpd instructions
+
+gdb_test_no_output "set \$ymm15.v2_int128 = {0xcafeface, 0xcafeface}" \
+ "set ymm15 for vaddsubpd"
+gdb_test_no_output "set \$ymm0.v2_int128 = {0xcafeface, 0xcafeface}" \
+ "set ymm0 for vaddsubpd"
+gdb_test_no_output "set \$xmm2.uint128 = 0xbeef" \
+ "set xmm2 for vaddsubpd"
+gdb_test_no_output "set \$xmm10.uint128 = 0xbeef" \
+ "set xmm10 for vaddsubpd"
+gdb_test_no_output "set \$ymm3.v2_int128 = {0xcafeface, 0xcafeface}" \
+ "set ymm3 for vaddsubpd"
+gdb_test_no_output "set \$ymm4.v2_int128 = {0xcafeface, 0xcafeface}" \
+ "set ymm4 for vaddsubpd"
+
+if {[record_full_function "vaddsubpd"] == true} {
+ test_one_register "vaddsubpd" "xmm10" \
+ "0xbeef" "xmm10:"
+ test_one_register "vaddsubpd" "xmm2" \
+ "0xbeef" "xmm2:"
+ test_one_register "vaddsubpd" "ymm4" \
+ "0xcafeface, 0xcafeface" "ymm4: "
+ test_one_register "vaddsubpd" "ymm15" \
+ "0xcafeface, 0xcafeface" "ymm15: "
+ test_one_register "vaddsubpd" "ymm0" \
+ "0xcafeface, 0xcafeface" "ymm0: "
+
+ gdb_test "record stop" "Process record is stopped.*" \
+ "delete history for vaddsubpd_test"
+} else {
+ untested "couldn't run vaddsubpd tests"
+}
+gdb_test "finish" "Run till exit from.*vaddsubpd_test.*" \
+ "leaving vaddsubpd"
+
+# Preparation and testing vaddsubps instruction
+
+gdb_test_no_output "set \$ymm10.v2_int128 = {0xcafeface, 0xcafeface}" \
+ "set ymm10 for vaddsubps"
+gdb_test_no_output "set \$ymm2.v2_int128 = {0xcafeface, 0xcafeface}" \
+ "set ymm2 for vaddsubps"
+gdb_test_no_output "set \$xmm15.uint128 = 0xbeef" \
+ "set xmm15 for vaddsubps"
+gdb_test_no_output "set \$xmm0.uint128 = 0xbeef" \
+ "set xmm0 for vaddsubps"
+gdb_test_no_output "set \$ymm3.v2_int128 = {0xcafeface, 0xcafeface}" \
+ "set ymm3 for vaddsubps"
+gdb_test_no_output "set \$ymm4.v2_int128 = {0xcafeface, 0xcafeface}" \
+ "set ymm4 for vaddsubps"
+
+if {[record_full_function "vaddsubps"] == true} {
+ test_one_register "vaddsubps" "xmm0" \
+ "0xbeef" "xmm0: "
+ test_one_register "vaddsubps" "xmm15" \
+ "0xbeef" "xmm15: "
+ test_one_register "vaddsubps" "ymm4" \
+ "0xcafeface, 0xcafeface" "ymm4: "
+ test_one_register "vaddsubps" "ymm10" \
+ "0xcafeface, 0xcafeface" "ymm10: "
+ test_one_register "vaddsubps" "ymm2" \
+ "0xcafeface, 0xcafeface" "ymm2: "
+
+ gdb_test "record stop" "Process record is stopped.*" \
+ "delete history for vaddsubps_test"
+} else {
+ untested "couldn't run vaddsubps tests"
+}
+gdb_test "finish" "Run till exit from.*vaddsubps_test.*" \
+ "leaving vaddsubps"
+
+# Preparation and testing shifting instructions.
+gdb_test_no_output \
+ "set \$ymm0.v2_int128 = {0, 0}" "set ymm0 for shift"
+gdb_test_no_output \
+ "set \$ymm1.v16_int16 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}" \
+ "set ymm1 for shift"
+gdb_test_no_output "set \$xmm2.uint128 = 1" "set ymm2 for shift"
+gdb_test_no_output "set \$ymm15.v2_int128 = {0,0}" "set ymm15 for shift"
+
+if {[record_full_function "shift"] == true} {
+ test_one_register "vpsrldq" "ymm15" \
+ "0x80007000600050004000300, 0x0" \
+ "High ymm register: "
+ test_one_register "vpsrldq" "ymm15" \
+ "0x60005000400030002000100000000, 0xe000d000c000b000a000900000000" \
+ "High xmm register: "
+ test_one_register "vpsrldq" "ymm0" \
+ "0x800070006000500040003000200, 0x0" \
+ "Low ymm register: "
+ test_one_register "vpsrldq" "ymm0" \
+ "0x70006000500040003000200010000, 0xf000e000d000c000b000a00090000" \
+ "Low xmm register: "
+
+ test_one_register "vpslldq" "ymm15" \
+ "0x7000600050004000300020001000000, 0x0" \
+ "High ymm register: "
+ test_one_register "vpslldq" "ymm15" \
+ "0x40003800300020002000180010000, 0x80007800700060006000580050004" \
+ "High xmm register: "
+ test_one_register "vpslldq" "ymm0" \
+ "0x8000700060005000400030002000100, 0x0" \
+ "Low ymm register: "
+ test_one_register "vpslldq" "ymm0" \
+ "0x40003000300020002000100010000, 0x80007000700060006000500050004" \
+ "Low xmm register: "
+
+ test_one_register "vpsrlq" "ymm15" \
+ "0x4000380030000000200018001000, 0x0" \
+ "from register: "
+ test_one_register "vpsrlq" "ymm15" \
+ "0x40003000300020002000100010000, 0x0" \
+ "from constant: "
+ test_one_register "vpsrld" "ymm15" \
+ "0x100000000c0000000800000004000, 0x200010001c0010001800100014001" \
+ "from register: "
+ test_one_register "vpsrld" "ymm15" \
+ "0x40003000300020002000100010000, 0x0" \
+ "from constant: "
+ test_one_register "vpsrlw" "ymm0" \
+ "0x40003000300020002000100010000, 0x0" \
+ "from register: "
+ test_one_register "vpsrlw" "ymm0" \
+ "0x40003000300020002000100010000, 0x80007000700060006000500050004" \
+ "from constant: "
+
+ test_one_register "vpsrad" "ymm15" \
+ "0x100000000c0000000800000004000, 0x200010001c0010001800100014001" \
+ "from register: "
+ test_one_register "vpsrad" "ymm15" \
+ "0x10000e000c000a0008000600040002, 0x20001e001c001a0018001600140012" \
+ "from constant: "
+ test_one_register "vpsraw" "ymm0" \
+ "0x40003000300020002000100010000, 0x0" \
+ "from register: "
+ test_one_register "vpsraw" "ymm0" \
+ "0x10000e000c000a0008000600040002, 0x20001e001c001a0018001600140012" \
+ "from constant: "
+
+ test_one_register "vpsllq" "ymm15" \
+ "0x10000e000c000a00080006000400020, 0x0" \
+ "from register: "
+ test_one_register "vpsllq" "ymm15" \
+ "0x10000e000c000a0008000600040002, 0x0" \
+ "from constant: "
+ test_one_register "vpslld" "ymm15" \
+ "0x400038003000280020001800100008, 0x800078007000680060005800500048" \
+ "from register: "
+ test_one_register "vpslld" "ymm15" "0x0, 0x0" "from constant: "
+ test_one_register "vpsllw" "ymm0" \
+ "0x10000e000c000a0008000600040002, 0x0" \
+ "from register: "
+ test_one_register "vpsllw" "ymm0" "0x0, 0x0" "from constant: "
+
+ gdb_test "record stop" "Process record is stopped.*" \
+ "delete history for shift_test"
+} else {
+ untested "couldn't run shift tests"
+}
+gdb_test "finish" "Run till exit from.*shift_test.*" \
+ "leaving shift"
+
+# Preparation and testing shuffling instructions.
+gdb_test_no_output \
+ "set \$ymm0.v2_int128 = {0, 0}" "set ymm0 for shuffle"
+gdb_test_no_output \
+ "set \$ymm1.v16_int16 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}" \
+ "set ymm1 for shuffle"
+gdb_test_no_output "set \$ymm2.v16_int16 = {17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}" \
+ "set ymm2 for shuffle"
+gdb_test_no_output "set \$ymm15.v2_int128 = {0,0}" "set ymm15 for shuffle"
+
+if {[record_full_function "shuffle"] == true} {
+ test_one_register "vshufpd" "ymm15" \
+ "0x20001000200010012001100160015, 0xa0009000a0009001a0019001e001d" \
+ "high register: "
+ test_one_register "vshufpd" "ymm0" \
+ "0x20001000200010012001100140013, 0x0" \
+ "low register: "
+ test_one_register "vshufps" "ymm15" \
+ "0x180017001600150011001100120013, 0x0" \
+ "high register: "
+ test_one_register "vshufps" "ymm0" \
+ "0x180017001600150011001100120012, 0x20001f001e001d00190019001a001a" \
+ "low register: "
+
+ test_one_register "vpshuflw" "ymm15" \
+ "0x150015001600150014001300120011, 0x1d001d001e001d001c001b001a0019" \
+ "high register: "
+ test_one_register "vpshuflw" "ymm0" \
+ "0x150015001500180014001300120011, 0x0" \
+ "low register: "
+ test_one_register "vpshufhw" "ymm15" \
+ "0x120011001200110012001100160015, 0x0" \
+ "high register: "
+ test_one_register "vpshufhw" "ymm0" \
+ "0x120011001200110012001100140013, 0x1a0019001a0019001a0019001c001b" \
+ "low register: "
+
+ test_one_register "vpshufd" "ymm15" \
+ "0x11151100111411001113110011121100, 0x1919190019201900191f1900191e1900" \
+ "high register: "
+ test_one_register "vpshufd" "ymm0" \
+ "0x11151100111411001113110011121100, 0x0" \
+ "low register: "
+ test_one_register "vpshufb" "ymm15" "0x0, 0x0" "high register: "
+ test_one_register "vpshufb" "ymm0" "0x0, 0x0" "low register: "
+
+ gdb_test "record stop" "Process record is stopped.*" \
+ "delete history for shuffle_test"
+} else {
+ untested "couldn't run shuffle tests"
+}
+gdb_test "finish" "Run till exit from.*shuffle_test.*" \
+ "leaving shuffle"
+
+# Preparation and testing permute instructions.
+gdb_test_no_output \
+ "set \$ymm0.v2_int128 = {0, 0}" "set ymm0 for permute"
+gdb_test_no_output \
+ "set \$ymm1.v16_int16 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}" \
+ "set ymm1 for permute"
+gdb_test_no_output "set \$ymm2.v16_int16 = {17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}" \
+ "set ymm2 for permute"
+gdb_test_no_output "set \$ymm15.v2_int128 = {0,0}" "set ymm15 for permute"
+
+if {[record_full_function "permute"] == true} {
+ test_one_register "vpermps" "ymm15" \
+ "0x40003000200010004000300020001, 0x40003000200010004000300020001"
+ test_one_register "vpermps" "ymm0" \
+ "0x140013001200110014001300120011, 0x140013001200110014001300120011"
+ test_one_register "vpermpd" "ymm0" \
+ "0x120011001200110012001100120011, 0x0"
+ test_one_register "vpermpd" "ymm15" \
+ "0x120011001200110012001100140013, 0x1a0019001a0019001a0019001c001b"
+
+ test_one_register "vpermilps" "ymm0" \
+ "0x180017001400130018001700140013, 0x20001f001c001b0020001f001c001b" \
+ "register version"
+ test_one_register "vpermilps" "ymm15" \
+ "0x180017001400130018001700140013, 0x0" \
+ "register version"
+ test_one_register "vpermilps" "ymm15" \
+ "0x140013001200110018001700160015, 0x1c001b001a0019001c001b001a0019" \
+ "immediate version"
+ test_one_register "vpermilps" "ymm0" \
+ "0x140013001200110014001300120011, 0x0" \
+ "immediate version"
+
+ test_one_register "vpermilpd" "ymm0" \
+ "0x140013001200110014001300120011, 0x1c001b001a0019001c001b001a0019" \
+ "register version"
+ test_one_register "vpermilpd" "ymm15" \
+ "0x140013001200110014001300120011, 0x0" \
+ "register version"
+ test_one_register "vpermilpd" "ymm15" \
+ "0x140013001200110014001300120011, 0x140013001200110014001300120011" \
+ "immediate version"
+ test_one_register "vpermilpd" "ymm0" \
+ "0x40003000200010008000700060005, 0x40003000200010004000300020001" \
+ "immediate version"
+
+ test_one_register "vpermq" "ymm15" \
+ "0x10000f000c000b0008000700040003, 0x10000f000c000b0008000700040003"
+ test_one_register "vpermq" "ymm0" \
+ "0x10000f000c000b0008000700040003, 0x10000f000c000b0008000700040003"
+ test_one_register "vpermd" "ymm15" \
+ "0x80007000600050004000300020001, 0x80007000600050004000300020001"
+ test_one_register "vpermd" "ymm0" \
+ "0x10000f000e000d000c000b000a0009, 0x80007000600050004000300020001"
+
+ test_one_register "vperm2i128" "ymm15" \
+ "0x180017001600150014001300120011, 0x180017001600150014001300120011"
+ test_one_register "vperm2i128" "ymm0" \
+ "0x20001f001e001d001c001b001a0019, 0x180017001600150014001300120011"
+ test_one_register "vperm2f128" "ymm15" "0x0, 0x0"
+ test_one_register "vperm2f128" "ymm0" "0x0, 0x0"
+
+ gdb_test "record stop" "Process record is stopped.*" \
+ "delete history for permute_test"
+} else {
+ untested "couldn't run permute tests"
+}
+gdb_test "finish" "Run till exit from.*permute_test.*" \
+ "leaving permute"
+
+# Preparation and testing extract_insert instructions.
+gdb_test_no_output \
+ "set \$ymm0.v2_int128 = {0, 0}" "set ymm0 for extract_insert"
+gdb_test_no_output \
+ "set \$ymm1.v16_int16 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}" \
+ "set ymm1 for extract_insert"
+gdb_test_no_output "set \$xmm2.uint128 = 0xcafe" \
+ "set ymm2 for extract_insert"
+gdb_test_no_output "set \$ymm15.v2_int128 = {0,0}" "set ymm15 for extract_insert"
+gdb_test_no_output "set \$rax = 0" "set eax for extract_insert"
+
+if {[record_full_function "extract_insert"] == true} {
+ test_one_memory "vpextrw" "global_buf1" \
+ "\\\{0x1, 0x0, 0x2, 0x0, 0x3, 0x0, 0x4, 0x0 <repeats 25 times>"
+ test_one_general_register "vpextrw" "rax" "0x8000700060005"
+
+ test_one_register "vpinsrq" "ymm15" \
+ "0x50000cafe, 0x0"
+ test_one_register "vpinsrd" "ymm0" \
+ "0x500cafe, 0x0"
+ test_one_register "vpinsrw" "ymm15" \
+ "0x80007000600050004000300020001, 0x0"
+ test_one_register "vpinsrb" "ymm0" \
+ "0x80007000600050000cafe00020001, 0x0"
+
+ test_one_memory "vpextrq" "global_buf1" \
+ "\\\{0x5, 0x0, 0x6, 0x0 <repeats 29 times>"
+ test_one_general_register "vpextrq" "rax" "0x80007"
+ test_one_memory "vpextrd" "global_buf1" \
+ "\\\{0x3, 0x0 <repeats 31 times>"
+ test_one_general_register "vpextrd" "rax" "0x0"
+ test_one_memory "vpextrb" "global_buf1" \
+ "\\\{0x0 <repeats 32 times>"
+ test_one_general_register "vpextrb" "rax" "0xcafe"
+
+ test_one_general_register "vextractps" "eax" "0x0"
+ test_one_register "vinsertps" "ymm0" \
+ "0x10000f000e000d000c000b000a0009, 0x0"
+ test_one_register "vextractf128" "ymm15" \
+ "0xcafe, 0x10000f000e000d000c000b000a0009"
+ test_one_register "vextracti128" "ymm0" \
+ "0x80007000600050004000300020001, 0xcafe"
+ test_one_register "vinsertf128" "ymm15" \
+ "0x0, 0x0"
+ test_one_register "vinserti128" "ymm0" \
+ "0x0, 0x0"
+
+ gdb_test "record stop" "Process record is stopped.*" \
+ "delete history for extract_insert_test"
+} else {
+ untested "couldn't run extract_insert tests"
+}
+gdb_test "finish" "Run till exit from.*extract_insert_test.*" \
+ "leaving extract_insert"
+
+# Preparation and testing blend instructions.
+gdb_test_no_output \
+ "set \$ymm0.v2_int128 = {0, 0}" "set ymm0 for blend"
+gdb_test_no_output \
+ "set \$ymm1.v16_int16 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}" \
+ "set ymm1 for blend"
+gdb_test_no_output \
+ "set \$ymm2.v16_int16 = {17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}" \
+ "set ymm2 for blend"
+gdb_test_no_output "set \$ymm15.v2_int128 = {0,0}" "set ymm15 for blend"
+
+if {[record_full_function "blend"] == true} {
+ test_one_register "vpblendvb" "ymm0" \
+ "0x180017000600050004000300120011, 0x20001f001e001d001c001b000a0009"
+ test_one_register "vpblendvb" "ymm15" \
+ "0x80007001600150004000300020001, 0x0"
+ test_one_register "vpblendd" "ymm15" \
+ "0x180007001600050004000300020011, 0x20000f001e000d000c000b000a0019"
+ test_one_register "vpblendd" "ymm0" \
+ "0x180017000600150004000300020001, 0x0"
+ test_one_register "vpblendw" "ymm0" \
+ "0x180017001600150014001300120011, 0x20001f001e001d001c001b001a0019"
+ test_one_register "vpblendw" "ymm15" \
+ "0x180017001600150014001300120011, 0x0"
+
+ test_one_register "vblendvpd" "ymm15" \
+ "0x80007000600050014001300120011, 0x10000f000e000d001c001b001a0019"
+ test_one_register "vblendvps" "ymm0" \
+ "0x180017000600050014001300020001, 0x0"
+ test_one_register "vblendpd" "ymm15" "0x0, 0x0"
+ test_one_register "vblendps" "ymm0" "0x0, 0x0"
+
+ gdb_test "record stop" "Process record is stopped.*" \
+ "delete history for blend_test"
+} else {
+ untested "couldn't run blend tests"
+}
+gdb_test "finish" "Run till exit from.*blend_test.*" \
+ "leaving blend"
+
+# Preparation and testing compare instructions.
+gdb_test_no_output \
+ "set \$xmm0.v4_float = {0, 1.5, 2, 0}" "set ymm0 for compare"
+gdb_test_no_output \
+ "set \$xmm1.v4_float = {0, 1, 2.5, -1}" "set ymm1 for compare"
+gdb_test_no_output \
+ "set \$xmm15.v4_float = {-1, -2, 10, 100}" "set ymm15 for compare"
+gdb_test_no_output "set \$eflags = 2"
+
+if {[record_full_function "compare"] == true} {
+ test_one_general_register "vucomisd" "eflags" "0x203"
+ test_one_general_register "vucomiss" "eflags" "0x202"
+ test_one_general_register "vcomiss" "eflags" "0x203"
+ test_one_general_register "vcomisd" "eflags" "0x202"
+
+ gdb_test "record stop" "Process record is stopped.*" \
+ "delete history for compare_test"
+} else {
+ untested "couldn't run compare tests"
+}
+gdb_test "finish" "Run till exit from.*compare_test.*" \
+ "leaving compare"
+
+# Preparation and testing pack instructions.
+gdb_test_no_output \
+ "set \$ymm0.v2_int128 = {0, 0}" "set ymm0 for pack"
+gdb_test_no_output \
+ "set \$ymm1.v16_int16 = {0x1020, 0x1121, 0x1222, 0x1323, 0x1424, 0x1525, 0x1626, 0x1727, 0x1828, 0x1929, 0x1a2a, 0x1b2b, 0x1c2c, 0x1d2d, 0x1e2e, 0x1f2f}" \
+ "set ymm1 for pack"
+gdb_test_no_output \
+ "set \$ymm2.v16_int16 = {0x3040, 0x3141, 0x3242, 0x3343, 0x3444, 0x3545, 0x3646, 0x3747, 0x3848, 0x3949, 0x3a4a, 0x3b4b, 0x3c4c, 0x3d4d, 0x3e4e, 0x3f4f}" \
+ "set ymm2 for pack"
+gdb_test_no_output \
+ "set \$ymm15.v2_int128 = {0, 0}" "set ymm15 for pack"
+
+if {[record_full_function "pack"] == true} {
+ test_one_register "vpackusdw" "ymm0" \
+ "0xffffffffffffffffffffffffffffffff, 0x0"
+ test_one_register "vpackusdw" "ymm15" \
+ "0xffffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffffff"
+ test_one_register "vpackuswb" "ymm15" \
+ "0x7fff7fff7fff7fff7fff7fff7fff7fff, 0x0"
+ test_one_register "vpackuswb" "ymm0" \
+ "0x7fff7fff7fff7fff7fff7fff7fff7fff, 0x7fff7fff7fff7fff7fff7fff7fff7fff"
+ test_one_register "vpackssdw" "ymm0" \
+ "0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f, 0x0"
+ test_one_register "vpackssdw" "ymm15" \
+ "0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f, 0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f"
+ test_one_register "vpacksswb" "ymm15" "0x0, 0x0"
+ test_one_register "vpacksswb" "ymm0" "0x0, 0x0"
+
+ gdb_test "record stop" "Process record is stopped.*" \
+ "delete history for pack_test"
+} else {
+ untested "couldn't run pack tests"
+}
+gdb_test "finish" "Run till exit from.*pack_test.*" \
+ "leaving pack"
+
+# Preparation and testing converting instructions.
+gdb_test_no_output \
+ "set \$ymm0.v2_int128 = {0,0}" \
+ "set ymm0 for convert test"
+gdb_test_no_output \
+ "set \$ymm1.v8_float = {0, 1, 2.5, 10, -1, -2.5, 0}" \
+ "set ymm1 for convert test"
+gdb_test_no_output "set \$ymm15.v2_int128 = {0,0}" \
+ "set ymm15 for convert test"
+gdb_test_no_output "set \$ecx = -1" "set ecx for convert test"
+gdb_test_no_output "set \$ebx = 1" "set ebx for convert test"
+
+if {[record_full_function "convert"] == true} {
+ gdb_test "maint print record-instruction" ".*"
+ test_one_general_register "vcvttss2si" "ecx" "0xffffffff"
+ test_one_general_register "vcvttsd2si" "ebx" "0x0"
+ test_one_register "vcvttps2dq" "ymm15" \
+ "0x41200000402000003f8000004f800000, 0x0"
+ test_one_register "vcvttpd2dq" "ymm0" \
+ "0x412000004020000041f0000000000000, 0x0"
+ test_one_general_register "vcvtss2si" "ebx" "0x0"
+
+ test_one_register "vcvtss2sd" "ymm0" \
+ "0x412000004020000041efffffffe00000, 0x0"
+ test_one_register "vcvtsi2ss" "ymm15" \
+ "0x41200000402000003f80000000000000, 0x0"
+ test_one_register "vcvtsi2sd" "ymm0" \
+ "0x8000000000000, 0x0"
+ test_one_register "vcvtsd2ss" "ymm15" \
+ "0x490000023c000000, 0x0"
+ test_one_general_register "vcvtsd2si" "ebx" "0x1"
+
+ test_one_register "vcvtpd2dq" "ymm0" \
+ "0x3ff00000000000000000000000000000, 0x0"
+ test_one_register "vcvtpd2ps" "ymm15" \
+ "0xa000000020000000100000000, 0x0"
+ test_one_register "vcvtps2pd" "ymm0" \
+ "0x4e8240004e8040004e7e000000000000, 0x0"
+ test_one_register "vcvtps2dq" "ymm15" \
+ "0x41cfc000000000000000000000000000, 0x0"
+ test_one_register "vcvtdq2pd" "ymm15" "0x0, 0x0"
+ test_one_register "vcvtdq2ps" "ymm0" "0x0, 0x0"
+
+ gdb_test "record stop" "Process record is stopped.*" \
+ "delete history for convert_test"
+} else {
+ untested "couldn't run convert tests"
+}
+gdb_test "finish" "Run till exit from.*convert_test.*" \
+ "leaving convert"
diff --git a/gdb/testsuite/gdb.reverse/sigall-precsave.exp b/gdb/testsuite/gdb.reverse/sigall-precsave.exp
index 64869c5..79838a0 100644
--- a/gdb/testsuite/gdb.reverse/sigall-precsave.exp
+++ b/gdb/testsuite/gdb.reverse/sigall-precsave.exp
@@ -138,7 +138,7 @@ proc test_one_sig_reverse {prevsig} {
}
}
-clean_restart $binfile
+clean_restart $::testfile
runto gen_ABRT
diff --git a/gdb/testsuite/gdb.reverse/sigall-reverse.exp b/gdb/testsuite/gdb.reverse/sigall-reverse.exp
index b72e098..82547d8 100644
--- a/gdb/testsuite/gdb.reverse/sigall-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/sigall-reverse.exp
@@ -144,7 +144,7 @@ proc test_one_sig_reverse {prevsig} {
}
}
-clean_restart $binfile
+clean_restart $::testfile
runto gen_ABRT
diff --git a/gdb/testsuite/gdb.reverse/solib-precsave.exp b/gdb/testsuite/gdb.reverse/solib-precsave.exp
index 277e33c..9636167 100644
--- a/gdb/testsuite/gdb.reverse/solib-precsave.exp
+++ b/gdb/testsuite/gdb.reverse/solib-precsave.exp
@@ -60,7 +60,7 @@ if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable \
# and is no longer attempted. Instead, the test does not make assumptions
# about whether the debug info is present or not.
-clean_restart $binfile
+clean_restart $::testfile
gdb_load_shlib $library1
gdb_load_shlib $library2
@@ -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..4efd19f 100644
--- a/gdb/testsuite/gdb.reverse/solib-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/solib-reverse.exp
@@ -52,7 +52,7 @@ if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable $exec_opt
# and is no longer attempted. Instead, the test does not make assumptions
# about whether the debug info is present or not.
-clean_restart $binfile
+clean_restart $::testfile
gdb_load_shlib $library1
gdb_load_shlib $library2
@@ -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/step-precsave.exp b/gdb/testsuite/gdb.reverse/step-precsave.exp
index b49c21b..9a0127a 100644
--- a/gdb/testsuite/gdb.reverse/step-precsave.exp
+++ b/gdb/testsuite/gdb.reverse/step-precsave.exp
@@ -69,7 +69,7 @@ with_timeout_factor 10 {
gdb_test "kill" "" "kill process, prepare to debug log file" \
"Kill the program being debugged\\? \\(y or n\\) " "y"
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test "record restore $precsave" \
"Restored records from core file .*" \
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..e994884
--- /dev/null
+++ b/gdb/testsuite/gdb.rocm/code-object-load-while-breakpoint-hit.exp
@@ -0,0 +1,69 @@
+# 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
+ gdb_load $::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/displaced-stepping.exp b/gdb/testsuite/gdb.rocm/displaced-stepping.exp
index cd50fec..9e8abd4 100644
--- a/gdb/testsuite/gdb.rocm/displaced-stepping.exp
+++ b/gdb/testsuite/gdb.rocm/displaced-stepping.exp
@@ -28,7 +28,8 @@ if {[build_executable "failed to prepare" $testfile $srcfile {hip}]} {
}
proc do_test {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
with_rocm_gpu_lock {
if ![runto_main] {
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..dfd1092 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
@@ -53,7 +54,8 @@ proc do_test { detach-on-fork follow-fork-mode fork_func } {
}
with_rocm_gpu_lock {
- clean_restart ${::binfile}-execer-${fork_func}
+ clean_restart
+ gdb_load ${::binfile}-execer-${fork_func}
gdb_test_no_output "set detach-on-fork ${detach-on-fork}"
gdb_test_no_output "set follow-fork-mode ${follow-fork-mode}"
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..b14e2c7 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
@@ -52,7 +53,8 @@ proc do_test { detach-on-fork follow-fork-mode fork_func } {
}
with_rocm_gpu_lock {
- clean_restart ${::binfile}-execer-${fork_func}
+ clean_restart
+ gdb_load ${::binfile}-execer-${fork_func}
gdb_test_no_output "set detach-on-fork ${detach-on-fork}"
gdb_test_no_output "set follow-fork-mode ${follow-fork-mode}"
diff --git a/gdb/testsuite/gdb.rocm/mi-attach.cpp b/gdb/testsuite/gdb.rocm/mi-attach.cpp
index da7659d..441d460 100644
--- a/gdb/testsuite/gdb.rocm/mi-attach.cpp
+++ b/gdb/testsuite/gdb.rocm/mi-attach.cpp
@@ -15,8 +15,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/>. */
-#include <unistd.h>
#include <hip/hip_runtime.h>
+#include "gdb_watchdog.h"
__global__ void
kern ()
@@ -30,7 +30,7 @@ main ()
{
/* This program will run outside of GDB, make sure that if anything goes
wrong it eventually gets killed. */
- alarm (30);
+ gdb_watchdog (30);
kern<<<1, 1>>> ();
return hipDeviceSynchronize () != hipSuccess;
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/multi-inferior-gpu.exp b/gdb/testsuite/gdb.rocm/multi-inferior-gpu.exp
index 4f55432..0ed11e8 100644
--- a/gdb/testsuite/gdb.rocm/multi-inferior-gpu.exp
+++ b/gdb/testsuite/gdb.rocm/multi-inferior-gpu.exp
@@ -28,7 +28,8 @@ if {[build_executable "failed to prepare" $testfile $srcfile {debug hip}]} {
}
proc do_test {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
gdb_test_no_output "set non-stop on"
gdb_test_no_output "set detach-on-fork off"
gdb_test_no_output "set follow-fork parent"
diff --git a/gdb/testsuite/gdb.rocm/precise-memory-exec.exp b/gdb/testsuite/gdb.rocm/precise-memory-exec.exp
index 506488c..76be078 100644
--- a/gdb/testsuite/gdb.rocm/precise-memory-exec.exp
+++ b/gdb/testsuite/gdb.rocm/precise-memory-exec.exp
@@ -29,7 +29,8 @@ if {[build_executable "failed to prepare $testfile" $testfile $srcfile {debug}]}
}
proc do_test { follow-exec-mode } {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
with_rocm_gpu_lock {
if ![runto_main] {
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-multi-inferiors.exp b/gdb/testsuite/gdb.rocm/precise-memory-multi-inferiors.exp
index c7a78b8..058b085 100644
--- a/gdb/testsuite/gdb.rocm/precise-memory-multi-inferiors.exp
+++ b/gdb/testsuite/gdb.rocm/precise-memory-multi-inferiors.exp
@@ -30,7 +30,7 @@ proc test_per_inferior { } {
gdb_test "show amdgpu precise-memory" \
"AMDGPU precise memory access reporting is off \\(currently disabled\\)." \
"show initial value, inferior 1"
- if $::test_python {
+ if { $::test_python } {
gdb_test "python print(gdb.parameter(\"amdgpu precise-memory\"))" \
"False" \
"show initial value using Python, inferior 1"
@@ -40,7 +40,7 @@ proc test_per_inferior { } {
gdb_test "show amdgpu precise-memory" \
"AMDGPU precise memory access reporting is on \\(currently disabled\\)." \
"show new value, inferior 1"
- if $::test_python {
+ if { $::test_python } {
gdb_test "python print(gdb.parameter(\"amdgpu precise-memory\"))" \
"True" \
"show new value using Python, inferior 1"
@@ -52,7 +52,7 @@ proc test_per_inferior { } {
gdb_test "show amdgpu precise-memory" \
"AMDGPU precise memory access reporting is off \\(currently disabled\\)." \
"show initial value, inferior 2"
- if $::test_python {
+ if { $::test_python } {
gdb_test "python print(gdb.parameter(\"amdgpu precise-memory\"))" \
"False" \
"show initial value using Python, inferior 2"
diff --git a/gdb/testsuite/gdb.rocm/precise-memory-warning-sigsegv.exp b/gdb/testsuite/gdb.rocm/precise-memory-warning-sigsegv.exp
index f855719..da0a95a 100644
--- a/gdb/testsuite/gdb.rocm/precise-memory-warning-sigsegv.exp
+++ b/gdb/testsuite/gdb.rocm/precise-memory-warning-sigsegv.exp
@@ -29,7 +29,8 @@ if {[build_executable "failed to prepare" $testfile $srcfile {debug hip}]} {
}
proc do_test { } {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
with_rocm_gpu_lock {
if ![runto_main] {
diff --git a/gdb/testsuite/gdb.rocm/precise-memory.exp b/gdb/testsuite/gdb.rocm/precise-memory.exp
index fbcb451..8f00559 100644
--- a/gdb/testsuite/gdb.rocm/precise-memory.exp
+++ b/gdb/testsuite/gdb.rocm/precise-memory.exp
@@ -28,7 +28,8 @@ if {[build_executable "failed to prepare" $testfile $srcfile {debug hip}]} {
}
proc do_test { } {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
with_rocm_gpu_lock {
if ![runto_main] {
@@ -59,7 +60,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.rocm/simple.exp b/gdb/testsuite/gdb.rocm/simple.exp
index bc90a0a..8f6ff3e 100644
--- a/gdb/testsuite/gdb.rocm/simple.exp
+++ b/gdb/testsuite/gdb.rocm/simple.exp
@@ -27,7 +27,8 @@ if {[build_executable "failed to prepare" $testfile $srcfile {debug hip}]} {
}
proc do_test {} {
- clean_restart $::binfile
+ clean_restart
+ gdb_load $::binfile
with_rocm_gpu_lock {
if ![runto_main] {
diff --git a/gdb/testsuite/gdb.rust/modules.exp b/gdb/testsuite/gdb.rust/modules.exp
index 5b2e998..0874db3 100644
--- a/gdb/testsuite/gdb.rust/modules.exp
+++ b/gdb/testsuite/gdb.rust/modules.exp
@@ -34,7 +34,7 @@ if {![runto ${srcfile}:$line]} {
# https://github.com/rust-lang/rust/issues/33121
# gdb_test "call f2()" "lambda f2"
-if ![target_info exists gdb,noinferiorio] {
+if { ![target_info exists gdb,noinferiorio] } {
gdb_test_stdio "call f3()" "mod1::inner::innest::f3"
gdb_test_stdio "call self::f2()" "mod1::inner::innest::f2"
gdb_test_stdio "call self::super::f2()" "mod1::inner::f2"
diff --git a/gdb/testsuite/gdb.rust/traits.exp b/gdb/testsuite/gdb.rust/traits.exp
index e5ef015..82fc894 100644
--- a/gdb/testsuite/gdb.rust/traits.exp
+++ b/gdb/testsuite/gdb.rust/traits.exp
@@ -25,7 +25,7 @@ if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug rust}]} {
}
set readelf_program [gdb_find_readelf]
-set result [catch "exec $readelf_program --debug-dump=info $binfile" output]
+set result [catch {exec $readelf_program --debug-dump=info $binfile} output]
if {$result != 0} {
untested "could not read [file tail ${binfile}] with readelf"
return
diff --git a/gdb/testsuite/gdb.server/bkpt-other-inferior.exp b/gdb/testsuite/gdb.server/bkpt-other-inferior.exp
index 893bd72..453be14 100644
--- a/gdb/testsuite/gdb.server/bkpt-other-inferior.exp
+++ b/gdb/testsuite/gdb.server/bkpt-other-inferior.exp
@@ -23,7 +23,7 @@ standard_testfile server.c
require allow_gdbserver_tests
-if { [prepare_for_testing "failed to prepare" ${binfile} "${srcfile}" \
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
{debug pthreads}] } {
return
}
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/connect-stopped-target.exp b/gdb/testsuite/gdb.server/connect-stopped-target.exp
index 021f063..603782c 100644
--- a/gdb/testsuite/gdb.server/connect-stopped-target.exp
+++ b/gdb/testsuite/gdb.server/connect-stopped-target.exp
@@ -34,7 +34,7 @@ proc do_test {nonstop} {
global gdb_prompt
global hex
- clean_restart $binfile
+ clean_restart $::testfile
# 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/connect-with-no-symbol-file.exp b/gdb/testsuite/gdb.server/connect-with-no-symbol-file.exp
index 4e5ee98..01d7e46 100644
--- a/gdb/testsuite/gdb.server/connect-with-no-symbol-file.exp
+++ b/gdb/testsuite/gdb.server/connect-with-no-symbol-file.exp
@@ -69,7 +69,7 @@ proc connect_no_symbol_file { sysroot action } {
} elseif { $action == "permission" } {
remote_exec target "chmod 000 $target_exec"
}
-
+
# Connect to GDBserver.
gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport
}
diff --git a/gdb/testsuite/gdb.server/connect-without-multi-process.exp b/gdb/testsuite/gdb.server/connect-without-multi-process.exp
index 1a7246c..f47e57e 100644
--- a/gdb/testsuite/gdb.server/connect-without-multi-process.exp
+++ b/gdb/testsuite/gdb.server/connect-without-multi-process.exp
@@ -38,7 +38,7 @@ proc do_test {multiprocess} {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart $binfile
+ clean_restart $::testfile
}
# Make sure we're disconnected, in case we're testing with an
diff --git a/gdb/testsuite/gdb.server/exit-multiple-threads.exp b/gdb/testsuite/gdb.server/exit-multiple-threads.exp
index 73e4c32..be29f9e 100644
--- a/gdb/testsuite/gdb.server/exit-multiple-threads.exp
+++ b/gdb/testsuite/gdb.server/exit-multiple-threads.exp
@@ -45,7 +45,8 @@ proc prepare_for_test { executable target_executable disable_multi_process } {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart ${executable}
+ clean_restart
+ gdb_load $executable
}
# Make sure we're disconnected, in case we're testing with an
@@ -69,7 +70,7 @@ proc prepare_for_test { executable target_executable disable_multi_process } {
set gdbserver_protocol [lindex $res 0]
set gdbserver_gdbport [lindex $res 1]
set res [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
- if ![gdb_assert {$res == 0} "connect"] {
+ if { ![gdb_assert {$res == 0} "connect"] } {
return
}
diff --git a/gdb/testsuite/gdb.server/ext-attach.exp b/gdb/testsuite/gdb.server/ext-attach.exp
index bda3ae9..6af2ede 100644
--- a/gdb/testsuite/gdb.server/ext-attach.exp
+++ b/gdb/testsuite/gdb.server/ext-attach.exp
@@ -45,7 +45,7 @@ proc run_test { target_async target_non_stop to_disable } {
set ::GDBFLAGS "$::GDBFLAGS -ex \"set sysroot\""
}
- clean_restart $::binfile
+ clean_restart $::testfile
}
# Make sure we're disconnected, in case we're testing with an
diff --git a/gdb/testsuite/gdb.server/ext-run.exp b/gdb/testsuite/gdb.server/ext-run.exp
index 2286454..f4ff546 100644
--- a/gdb/testsuite/gdb.server/ext-run.exp
+++ b/gdb/testsuite/gdb.server/ext-run.exp
@@ -37,7 +37,7 @@ save_vars { GDBFLAGS } {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart $binfile
+ clean_restart $::testfile
}
# Make sure we're disconnected, in case we're testing with an
diff --git a/gdb/testsuite/gdb.server/extended-remote-restart.exp b/gdb/testsuite/gdb.server/extended-remote-restart.exp
index df722a1..a5ba53c 100644
--- a/gdb/testsuite/gdb.server/extended-remote-restart.exp
+++ b/gdb/testsuite/gdb.server/extended-remote-restart.exp
@@ -58,7 +58,7 @@ proc test_reload { do_kill_p follow_child_p } {
global decimal
global binfile
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if {![runto_main]} {
return 0
@@ -70,7 +70,7 @@ proc test_reload { do_kill_p follow_child_p } {
set live_inf_ptn "process $decimal"
set dead_inf_ptn "<null>"
- if ${follow_child_p} {
+ if { $follow_child_p } {
gdb_test_no_output "set follow-fork child"
set parent_prefix " "
set child_prefix "\\*"
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/inferior-args.c b/gdb/testsuite/gdb.server/inferior-args.c
new file mode 100644
index 0000000..3bc3ff7
--- /dev/null
+++ b/gdb/testsuite/gdb.server/inferior-args.c
@@ -0,0 +1,27 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2023-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>
+
+int
+main (int argc, char **argv)
+{
+ for (int i = 0; i < argc; i++)
+ printf ("[%d] %s\n", i, argv[i]);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.server/inferior-args.exp b/gdb/testsuite/gdb.server/inferior-args.exp
new file mode 100644
index 0000000..9c33874
--- /dev/null
+++ b/gdb/testsuite/gdb.server/inferior-args.exp
@@ -0,0 +1,156 @@
+# Copyright 2023-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 passing inferior arguments on the gdbserver command line. Tests the
+# flags --no-startup-with-shell and --no-escape-args that change how GDB
+# interprets the arguments being passed.
+
+# This test relies on starting gdbserver using the pipe syntax. Not sure
+# how well this will run if part of this test is being run elsewhere.
+require {!is_remote target} {!is_remote host}
+
+load_lib gdbserver-support.exp
+
+standard_testfile
+
+require allow_gdbserver_tests
+
+set gdbserver [find_gdbserver]
+if { $gdbserver == "" } {
+ unsupported "could not find gdbserver"
+ return
+}
+
+standard_testfile
+if {[build_executable "failed to prepare" $testfile $srcfile]} {
+ return -1
+}
+
+# EXTENDED_P is a boolean, when true gdbserver is started with --multi, and
+# GDB connects using extended-remote protocol. Otherwise, no --multi flag
+# is passed, and GDB connects with the remote protocol.
+#
+# WITH_SHELL_P is a boolean, when true gdbserver starts the inferior using a
+# shell, when false gdbserver is passed the --no-startup-with-shell command
+# line option, and should not start the inferior through a shell.
+#
+# ESCAPE_P is a boolean, when true gdbserver applies escapes to the inferior
+# arguments, when false gdbserver is passed the --no-escape-args command
+# line option, and should not apply escaping to the inferior arguments.
+#
+# ARGLIST is a list of inferior arguments to add to the gdbserver command
+# line.
+#
+# RE_LIST is a list of patterns to match, one for each of ARGLIST. Once the
+# inferior is started we check that each argument matches its corresponding
+# entry in RE_LIST.
+proc do_test_inner { extended_p with_shell_p escape_p arglist re_list } {
+
+ clean_restart ${::testfile}
+
+ gdb_test_no_output "set sysroot"
+
+ # Make sure we're disconnected, in case we're testing with an
+ # extended-remote board, therefore already connected.
+ gdb_test "disconnect" ".*"
+
+ if { $extended_p } {
+ set protocol "extended-remote"
+ } else {
+ set protocol "remote"
+ }
+
+ if { $escape_p } {
+ set esc_opt ""
+ } else {
+ set esc_opt "--no-escape-args"
+ }
+
+ if { $with_shell_p } {
+ set shell_opt ""
+ } else {
+ set shell_opt "--no-startup-with-shell"
+ }
+
+ gdb_test "target ${protocol} | ${::gdbserver} --once ${esc_opt} ${shell_opt} - ${::binfile} ${arglist}" \
+ ".*" \
+ "start gdbserver over stdin"
+
+ gdb_breakpoint main
+ gdb_continue_to_breakpoint main
+
+ set expected_len [expr 1 + [llength $re_list]]
+ gdb_test "print argc" \
+ "\\\$$::decimal = $expected_len" "check argc"
+
+ set i 1
+ foreach arg $re_list {
+ gdb_test "print argv\[$i\]" \
+ "\\\$$::decimal = $::hex \"$arg\"" \
+ "check argv\[$i\]"
+ set i [expr $i + 1]
+ }
+}
+
+# Wrapper around do_test_inner. NAME is the name of this test, used to make
+# the test names unique. ARGLIST is the list of inferior arguments to add
+# to the gdbserver command line.
+#
+# The optional RE_ESC_LIST is a list of patterns to match against the
+# inferior arguments once the inferior is started, one pattern for each
+# argument. If RE_ESC_LIST is not given then ARGLIST is reused, which
+# implies the arguments appear unmodified in the test output.
+#
+# The optional RE_NO_ESC_LIST is a list of patterns to match against the
+# inferior arguments when gdbserver is started with --no-escape-args or
+# --no-startup-with-shell. There should be one pattern for each argument.
+# If RE_NO_ESC_LIST is not given then RE_ESC_LIST is reused, which implies
+# there's no difference in how the arguments are printed.
+proc args_test { name arglist {re_esc_list {}} {re_no_esc_list {}} } {
+ if {[llength $re_esc_list] == 0} {
+ set re_esc_list $arglist
+ }
+
+ if {[llength $re_no_esc_list] == 0} {
+ set re_no_esc_list $re_esc_list
+ }
+
+ foreach_with_prefix extended_p { yes no } {
+ foreach_with_prefix startup_with_shell { on off } {
+ foreach_with_prefix escape_p { yes no } {
+ if { $escape_p || !$startup_with_shell } {
+ set re_list $re_esc_list
+ } else {
+ set re_list $re_no_esc_list
+ }
+
+ with_test_prefix "$name" {
+ do_test_inner $extended_p $startup_with_shell \
+ $escape_p $arglist $re_list
+ }
+ }
+ }
+ }
+}
+
+args_test "basic" {a b c}
+args_test "one empty" {1 "" 3}
+args_test "two empty" {1 "" "" 3}
+args_test "one with single quotes" {1 "''" 3}
+args_test "lone double quote" {"1" \" 3} {1 \\\\\" 3}
+save_vars { env(TEST) } {
+ set env(TEST) "ABCD"
+ args_test "shell variable" {\$TEST} {\\$TEST} {ABCD}
+}
diff --git a/gdb/testsuite/gdb.server/monitor-exit-quit.exp b/gdb/testsuite/gdb.server/monitor-exit-quit.exp
index ce63560..74842a0 100644
--- a/gdb/testsuite/gdb.server/monitor-exit-quit.exp
+++ b/gdb/testsuite/gdb.server/monitor-exit-quit.exp
@@ -34,7 +34,7 @@ save_vars { GDBFLAGS } {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart $binfile
+ clean_restart $::testfile
}
# Make sure we're disconnected, in case we're testing with an
@@ -70,7 +70,7 @@ gdb_test_multiple "quit" "" {
# Cleanup, as in default_gdb_exit.
if { $do_cleanup } {
- if ![is_remote host] {
+ if { ![is_remote host] } {
remote_close host
}
unset gdb_spawn_id
diff --git a/gdb/testsuite/gdb.server/non-existing-program.exp b/gdb/testsuite/gdb.server/non-existing-program.exp
index 7119723..ec9c044 100644
--- a/gdb/testsuite/gdb.server/non-existing-program.exp
+++ b/gdb/testsuite/gdb.server/non-existing-program.exp
@@ -34,6 +34,8 @@ if { $gdbserver == "" } {
# to spawn the program before opening the connection.
set spawn_id [remote_spawn target "$gdbserver stdio non-existing-program"]
+set eol {[\r\n]}
+
set msg "gdbserver exits cleanly"
set saw_exiting 0
expect {
@@ -51,7 +53,7 @@ expect {
exp_continue
}
# This is what we get on Windows.
- -re "Error creating process\r\n\r\nExiting\r\n" {
+ -re "Error creating process.*$eol+Exiting$eol+" {
set saw_exiting 1
exp_continue
}
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.server/reconnect-ctrl-c.exp b/gdb/testsuite/gdb.server/reconnect-ctrl-c.exp
index 83869a3..bcab2de 100644
--- a/gdb/testsuite/gdb.server/reconnect-ctrl-c.exp
+++ b/gdb/testsuite/gdb.server/reconnect-ctrl-c.exp
@@ -51,7 +51,7 @@ proc connect_continue_ctrl_c {} {
global gdbserver_protocol gdbserver_gdbport
set res [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
- if ![gdb_assert {$res == 0} "connect"] {
+ if { ![gdb_assert {$res == 0} "connect"] } {
return
}
diff --git a/gdb/testsuite/gdb.server/server-exec-info.exp b/gdb/testsuite/gdb.server/server-exec-info.exp
index fccf075..007290a 100644
--- a/gdb/testsuite/gdb.server/server-exec-info.exp
+++ b/gdb/testsuite/gdb.server/server-exec-info.exp
@@ -21,7 +21,7 @@ load_lib gdbserver-support.exp
require allow_gdbserver_tests allow_shlib_tests
standard_testfile server.c
-if [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] {
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
diff --git a/gdb/testsuite/gdb.server/server-kill.exp b/gdb/testsuite/gdb.server/server-kill.exp
index 0a759ae..a9fcabb 100644
--- a/gdb/testsuite/gdb.server/server-kill.exp
+++ b/gdb/testsuite/gdb.server/server-kill.exp
@@ -43,7 +43,7 @@ proc prepare {} {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart $binfile
+ clean_restart $::testfile
}
# Make sure we're disconnected, in case we're testing with an
diff --git a/gdb/testsuite/gdb.server/server-pipe.exp b/gdb/testsuite/gdb.server/server-pipe.exp
index d786946..20ca0b0 100644
--- a/gdb/testsuite/gdb.server/server-pipe.exp
+++ b/gdb/testsuite/gdb.server/server-pipe.exp
@@ -50,7 +50,7 @@ if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
# the contents of the gdb.TargetConnection.details string.
proc do_test { target } {
global timeout
- clean_restart ${::binfile}
+ clean_restart ${::testfile}
# 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/server-run.exp b/gdb/testsuite/gdb.server/server-run.exp
index 6c9db98..53b3278 100644
--- a/gdb/testsuite/gdb.server/server-run.exp
+++ b/gdb/testsuite/gdb.server/server-run.exp
@@ -34,7 +34,7 @@ save_vars { GDBFLAGS } {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart $binfile
+ clean_restart $::testfile
}
# Make sure we're disconnected, in case we're testing with an
diff --git a/gdb/testsuite/gdb.server/stop-reply-no-thread-multi.exp b/gdb/testsuite/gdb.server/stop-reply-no-thread-multi.exp
index 42608c4..f1c68a5 100644
--- a/gdb/testsuite/gdb.server/stop-reply-no-thread-multi.exp
+++ b/gdb/testsuite/gdb.server/stop-reply-no-thread-multi.exp
@@ -54,7 +54,7 @@ proc run_test { target_non_stop disable_feature } {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
# Make sure we're disconnected, in case we're testing with an
@@ -78,7 +78,7 @@ proc run_test { target_non_stop disable_feature } {
"Support for the 'multiprocess-feature' packet on future remote targets is set to \"off\"."
set res [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
- if ![gdb_assert {$res == 0} "connect"] {
+ if { ![gdb_assert {$res == 0} "connect"] } {
return
}
diff --git a/gdb/testsuite/gdb.server/stop-reply-no-thread.exp b/gdb/testsuite/gdb.server/stop-reply-no-thread.exp
index 38402e8..aa77095 100644
--- a/gdb/testsuite/gdb.server/stop-reply-no-thread.exp
+++ b/gdb/testsuite/gdb.server/stop-reply-no-thread.exp
@@ -42,7 +42,7 @@ proc run_test { disable_feature target_nonstop } {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
# Make sure we're disconnected, in case we're testing with an
@@ -70,7 +70,7 @@ proc run_test { disable_feature target_nonstop } {
gdb_test_no_output "maint set target-non-stop ${target_nonstop}"
set res [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
- if ![gdb_assert {$res == 0} "connect"] {
+ if { ![gdb_assert {$res == 0} "connect"] } {
return
}
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/board-sanity.exp b/gdb/testsuite/gdb.testsuite/board-sanity.exp
index 9c80282..7b9a19e 100644
--- a/gdb/testsuite/gdb.testsuite/board-sanity.exp
+++ b/gdb/testsuite/gdb.testsuite/board-sanity.exp
@@ -44,7 +44,7 @@ proc test_remote { remote host_is_target } {
if { $host_is_target } {
set res [remote_file $other_remote exists $file]
gdb_assert { $res != $exists_ok } \
- "$other_remote copy does not exist"
+ "$other_remote copy does not exist"
}
}
@@ -80,7 +80,7 @@ proc test_remote { remote host_is_target } {
set build_file [remote_upload $remote $file]
gdb_assert { [string equal [file tail $build_file] $file] == 1 } \
"remote_upload returns valid value"
-
+
set res [remote_file $remote delete $file]
gdb_assert { [string equal $res $delete_ok] == 1 } \
"remove $remote copy"
@@ -92,7 +92,7 @@ proc test_remote { remote host_is_target } {
if { $host_is_target } {
set res [remote_file $other_remote exists $file]
gdb_assert { $res != $exists_ok } \
- "$other_remote copy does not exist"
+ "$other_remote copy does not exist"
}
set res [remote_file build exists $file]
diff --git a/gdb/testsuite/gdb.testsuite/gdb-caching-proc-consistency.exp b/gdb/testsuite/gdb.testsuite/gdb-caching-proc-consistency.exp
index 0957dbd..27f905e 100644
--- a/gdb/testsuite/gdb.testsuite/gdb-caching-proc-consistency.exp
+++ b/gdb/testsuite/gdb.testsuite/gdb-caching-proc-consistency.exp
@@ -63,8 +63,8 @@ proc test_file { file } {
set fp [open $file]
while { [gets $fp line] >= 0 } {
- if [regexp -- "^gdb_caching_proc \[ \t\]*(\[^ \t\]*)" $line \
- match procname] {
+ if { [regexp -- "^gdb_caching_proc \[ \t\]*(\[^ \t\]*)" $line \
+ match procname] } {
lappend procnames $procname
}
}
@@ -95,7 +95,8 @@ proc test_file { file } {
}
if { $setup_gdb } {
- clean_restart $obj
+ clean_restart
+ gdb_load $obj
}
test_proc $procname
@@ -113,7 +114,7 @@ if { ![gdb_simple_compile $me $src executable] } {
}
# Test gdb_caching_procs in gdb/testsuite/lib/*.exp
-set files [eval glob -types f $srcdir/lib/*.exp]
+set files [glob -types f $srcdir/lib/*.exp]
set files [lsort $files]
foreach file $files {
test_file $file
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.testsuite/mount-point-map.exp b/gdb/testsuite/gdb.testsuite/mount-point-map.exp
new file mode 100644
index 0000000..9e462bb
--- /dev/null
+++ b/gdb/testsuite/gdb.testsuite/mount-point-map.exp
@@ -0,0 +1,49 @@
+# 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 unix_to_win {
+ /bin C:/msys64/usr/bin
+ /c C:
+ / C:/msys64
+}
+
+# Test that FROM is normalized to TO.
+
+proc test {from to} {
+ set got [host_file_normalize_mingw $from $::unix_to_win]
+ verbose -log "input: $from"
+ verbose -log "expected: $to"
+ verbose -log "got: $got"
+ gdb_assert {$got == $to} $from
+}
+
+# Drive letters always get a '/' suffix, other Windows file names do
+# not.
+test "/" "C:/msys64"
+test "/c" "C:/"
+test "/bin" "C:/msys64/usr/bin"
+
+# A file name that already starts with a drive letter.
+test "C:/msys64" "C:/msys64"
+
+# A subdir/subfile under each mount.
+test "/foo" "C:/msys64/foo"
+test "/c/foo" "C:/foo"
+test "/bin/foo" "C:/msys64/usr/bin/foo"
+
+# Test slash normalization.
+test "//" "C:/msys64"
+test "/c///foo//bar//" "C:/foo/bar"
+# We don't currently handle UNC paths.
+test "//server///" "C:/msys64/server"
diff --git a/gdb/testsuite/gdb.testsuite/with-override.exp b/gdb/testsuite/gdb.testsuite/with-override.exp
index 9180150..1a4ee6a 100644
--- a/gdb/testsuite/gdb.testsuite/with-override.exp
+++ b/gdb/testsuite/gdb.testsuite/with-override.exp
@@ -50,11 +50,11 @@ with_test_prefix no-args {
}
proc foo { {a 0} } {
- return [expr $a + 1]
+ return [expr {$a + 1}]
}
proc foo_plus_1 { {a 0} } {
- return [expr $a + 2]
+ return [expr {$a + 2}]
}
with_test_prefix default-arg {
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..6846b38 100644
--- a/gdb/testsuite/gdb.threads/access-mem-running-thread-exit.exp
+++ b/gdb/testsuite/gdb.threads/access-mem-running-thread-exit.exp
@@ -51,7 +51,7 @@ proc test { non_stop } {
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop $non_stop\""
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
if ![runto setup_done] {
@@ -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/async.exp b/gdb/testsuite/gdb.threads/async.exp
index b1e562a..6347333 100644
--- a/gdb/testsuite/gdb.threads/async.exp
+++ b/gdb/testsuite/gdb.threads/async.exp
@@ -32,7 +32,7 @@ proc test_current_thread {expected_thr} {
global gdb_prompt
global binfile
- clean_restart $binfile
+ clean_restart $::testfile
if {![runto "all_started"]} {
return
diff --git a/gdb/testsuite/gdb.threads/attach-non-stop.exp b/gdb/testsuite/gdb.threads/attach-non-stop.exp
index 9404edd..b8da5b1 100644
--- a/gdb/testsuite/gdb.threads/attach-non-stop.exp
+++ b/gdb/testsuite/gdb.threads/attach-non-stop.exp
@@ -37,7 +37,7 @@ proc test {target_non_stop non_stop cmd} {
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"maint set target-non-stop $target_non_stop\""
append GDBFLAGS " -ex \"set non-stop $non_stop\""
- clean_restart $binfile
+ clean_restart $::testfile
}
set test_spawn_id [spawn_wait_for_attach $binfile]
diff --git a/gdb/testsuite/gdb.threads/attach-stopped.exp b/gdb/testsuite/gdb.threads/attach-stopped.exp
index e628adf..a3926d9 100644
--- a/gdb/testsuite/gdb.threads/attach-stopped.exp
+++ b/gdb/testsuite/gdb.threads/attach-stopped.exp
@@ -43,7 +43,7 @@ proc corefunc { threadtype } {
# Stop the program
remote_exec build "kill -s STOP ${testpid}"
- clean_restart $binfile
+ clean_restart $::testfile
# Verify that we can attach to the stopped process.
diff --git a/gdb/testsuite/gdb.threads/bp_in_thread.exp b/gdb/testsuite/gdb.threads/bp_in_thread.exp
index c63f179..5180c18 100644
--- a/gdb/testsuite/gdb.threads/bp_in_thread.exp
+++ b/gdb/testsuite/gdb.threads/bp_in_thread.exp
@@ -24,7 +24,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
runto_main
diff --git a/gdb/testsuite/gdb.threads/break-while-running.exp b/gdb/testsuite/gdb.threads/break-while-running.exp
index fbc2b59..fb7994d 100644
--- a/gdb/testsuite/gdb.threads/break-while-running.exp
+++ b/gdb/testsuite/gdb.threads/break-while-running.exp
@@ -39,7 +39,7 @@ proc test { update_thread_list always_inserted non_stop } {
global gdb_prompt
global decimal
- clean_restart $binfile
+ clean_restart $::testfile
gdb_test_no_output "set non-stop $non_stop"
gdb_test_no_output "set breakpoint always-inserted $always_inserted"
diff --git a/gdb/testsuite/gdb.threads/check-libthread-db.exp b/gdb/testsuite/gdb.threads/check-libthread-db.exp
index b97ab49..6d63185 100644
--- a/gdb/testsuite/gdb.threads/check-libthread-db.exp
+++ b/gdb/testsuite/gdb.threads/check-libthread-db.exp
@@ -40,7 +40,7 @@ set initial_thread_re "($thread_re1|$thread_re2)"
with_test_prefix "user-initiated check" {
# User-initiated check with libthread_db not loaded.
- clean_restart ${binfile}
+ clean_restart ${::testfile}
gdb_test "maint show check-libthread-db" \
"Whether to check libthread_db at load time is off."
@@ -85,7 +85,7 @@ with_test_prefix "automated load-time check" {
# Automated load-time check with NPTL possibly uninitialized.
with_test_prefix "libpthread.so possibly not initialized" {
- clean_restart ${binfile}
+ clean_restart ${::testfile}
gdb_test_no_output "maint set check-libthread-db 1"
gdb_test_no_output "set debug libthread-db 1"
@@ -104,7 +104,7 @@ with_test_prefix "automated load-time check" {
# Automated load-time check with NPTL fully operational.
if { [can_spawn_for_attach] } {
with_test_prefix "libpthread.so fully initialized" {
- clean_restart ${binfile}
+ clean_restart ${::testfile}
gdb_test_no_output "maint set check-libthread-db 1"
gdb_test_no_output "set debug libthread-db 1"
diff --git a/gdb/testsuite/gdb.threads/corethreads.exp b/gdb/testsuite/gdb.threads/corethreads.exp
index 3b50ae3..0011dc3 100644
--- a/gdb/testsuite/gdb.threads/corethreads.exp
+++ b/gdb/testsuite/gdb.threads/corethreads.exp
@@ -29,6 +29,7 @@ if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executa
set corefile [core_find $binfile]
if {$corefile == ""} {
+ untested "unable to create or find corefile"
return 0
}
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..1767464 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"]
@@ -64,7 +66,7 @@ proc start_gdb_for_test {condition_eval target_non_stop non_stop displaced} {
append ::GDBFLAGS " -ex \"set non-stop $non_stop\""
append ::GDBFLAGS " -ex \"set displaced $displaced\""
append ::GDBFLAGS " -ex \"set schedule-multiple on\""
- clean_restart $::binfile
+ clean_restart $::testfile
}
gdb_test_no_output "set breakpoint condition-evaluation $condition_eval"
diff --git a/gdb/testsuite/gdb.threads/execl.exp b/gdb/testsuite/gdb.threads/execl.exp
index 502d387..a42dce9 100644
--- a/gdb/testsuite/gdb.threads/execl.exp
+++ b/gdb/testsuite/gdb.threads/execl.exp
@@ -31,7 +31,7 @@ if {[gdb_compile "${srcdir}/${subdir}/${srcfile1}" "${binfile1}" executable {deb
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if { [is_remote target] } {
gdb_remote_download target $binfile1
}
diff --git a/gdb/testsuite/gdb.threads/foll-fork-other-thread.exp b/gdb/testsuite/gdb.threads/foll-fork-other-thread.exp
index 5245988..29ec34c 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.
@@ -44,7 +46,7 @@ proc do_test { fork_func follow target-non-stop non-stop displaced-stepping } {
save_vars { ::GDBFLAGS } {
append ::GDBFLAGS " -ex \"maintenance set target-non-stop ${target-non-stop}\""
append ::GDBFLAGS " -ex \"set non-stop ${non-stop}\""
- clean_restart ${::binfile}-${fork_func}
+ clean_restart ${::testfile}-${fork_func}
}
gdb_test_no_output "set displaced-stepping ${displaced-stepping}"
diff --git a/gdb/testsuite/gdb.threads/fork-child-threads.exp b/gdb/testsuite/gdb.threads/fork-child-threads.exp
index abe9769..d1b413c 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
@@ -24,7 +21,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
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..e0e3625 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
@@ -25,7 +21,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
@@ -79,7 +75,7 @@ gdb_test_multiple "info threads" "$test" {
# Start over, but this time, don't switch away from the fork event thread.
-clean_restart $binfile
+clean_restart $::testfile
if {![runto_main]} {
return 0
}
diff --git a/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp b/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp
index 1f76898..d65fe83d 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"]
@@ -35,7 +37,7 @@ proc probe_displaced_stepping_support {} {
global binfile gdb_prompt
with_test_prefix "probe displaced-stepping support" {
- clean_restart $binfile
+ clean_restart $::testfile
gdb_test_no_output "set displaced on"
if {![runto_main]} {
@@ -74,7 +76,7 @@ proc do_test { cond_bp_target detach_on_fork displaced } {
save_vars { GDBFLAGS } {
set GDBFLAGS [concat $GDBFLAGS " -ex \"set non-stop on\""]
- clean_restart $binfile
+ clean_restart $::testfile
}
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.threads/hand-call-in-threads.exp b/gdb/testsuite/gdb.threads/hand-call-in-threads.exp
index d1be1d0..fd934f5 100644
--- a/gdb/testsuite/gdb.threads/hand-call-in-threads.exp
+++ b/gdb/testsuite/gdb.threads/hand-call-in-threads.exp
@@ -44,7 +44,7 @@ proc get_dummy_frame_number { } {
return ""
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if { ![runto_main] } {
return 0
diff --git a/gdb/testsuite/gdb.threads/inf-thr-count.exp b/gdb/testsuite/gdb.threads/inf-thr-count.exp
index d7a7687..5272f5c 100644
--- a/gdb/testsuite/gdb.threads/inf-thr-count.exp
+++ b/gdb/testsuite/gdb.threads/inf-thr-count.exp
@@ -43,8 +43,8 @@ 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\""
- clean_restart $binfile
+ append GDBFLAGS { -ex "set non-stop on"}
+ clean_restart $::testfile
}
if ![runto_main] {
@@ -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/infcall-from-bp-cond-other-thread-event.exp b/gdb/testsuite/gdb.threads/infcall-from-bp-cond-other-thread-event.exp
index 62a183c..35a1fe5 100644
--- a/gdb/testsuite/gdb.threads/infcall-from-bp-cond-other-thread-event.exp
+++ b/gdb/testsuite/gdb.threads/infcall-from-bp-cond-other-thread-event.exp
@@ -53,7 +53,7 @@ proc start_gdb_and_runto_main { target_async target_non_stop } {
append ::GDBFLAGS \
" -ex \"maintenance set target-async ${target_async}\""
- clean_restart ${::binfile}
+ clean_restart ${::testfile}
}
if { ![runto_main] } {
diff --git a/gdb/testsuite/gdb.threads/infcall-from-bp-cond-simple.exp b/gdb/testsuite/gdb.threads/infcall-from-bp-cond-simple.exp
index 0f068c6..ed98998 100644
--- a/gdb/testsuite/gdb.threads/infcall-from-bp-cond-simple.exp
+++ b/gdb/testsuite/gdb.threads/infcall-from-bp-cond-simple.exp
@@ -42,7 +42,7 @@ proc start_gdb_and_runto_main { target_async target_non_stop } {
append ::GDBFLAGS \
" -ex \"maintenance set target-async ${target_async}\""
- clean_restart ${::binfile}
+ clean_restart ${::testfile}
}
if { ![runto_main] } {
diff --git a/gdb/testsuite/gdb.threads/infcall-from-bp-cond-single.exp b/gdb/testsuite/gdb.threads/infcall-from-bp-cond-single.exp
index c404a7d..bc12fb4 100644
--- a/gdb/testsuite/gdb.threads/infcall-from-bp-cond-single.exp
+++ b/gdb/testsuite/gdb.threads/infcall-from-bp-cond-single.exp
@@ -38,7 +38,7 @@ proc start_gdb_and_runto_main { target_async target_non_stop } {
append ::GDBFLAGS \
" -ex \"maintenance set target-async ${target_async}\""
- clean_restart ${::binfile}
+ clean_restart ${::testfile}
}
if { ![runto_main] } {
diff --git a/gdb/testsuite/gdb.threads/infcall-from-bp-cond-timeout.exp b/gdb/testsuite/gdb.threads/infcall-from-bp-cond-timeout.exp
index 9dbaa4f..03c6959 100644
--- a/gdb/testsuite/gdb.threads/infcall-from-bp-cond-timeout.exp
+++ b/gdb/testsuite/gdb.threads/infcall-from-bp-cond-timeout.exp
@@ -52,7 +52,7 @@ proc run_test { target_async target_non_stop non_stop other_thread_bp unwind } {
append ::GDBFLAGS " -ex \"maint non-stop $non_stop\""
append ::GDBFLAGS " -ex \"maintenance set target-async ${target_async}\""
- clean_restart ${::binfile}
+ clean_restart ${::testfile}
}
if {![runto_main]} {
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..e6c68e2
--- /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 $::testfile
+}
+
+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/interrupt-while-step-over.exp b/gdb/testsuite/gdb.threads/interrupt-while-step-over.exp
index 05587eb..44e4d64 100644
--- a/gdb/testsuite/gdb.threads/interrupt-while-step-over.exp
+++ b/gdb/testsuite/gdb.threads/interrupt-while-step-over.exp
@@ -169,7 +169,7 @@ proc testdriver {displaced} {
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop on\""
- clean_restart $binfile
+ clean_restart $::testfile
}
gdb_test_no_output "set displaced-stepping $displaced"
diff --git a/gdb/testsuite/gdb.threads/interrupted-hand-call.exp b/gdb/testsuite/gdb.threads/interrupted-hand-call.exp
index 3a2bc63..15c48b1 100644
--- a/gdb/testsuite/gdb.threads/interrupted-hand-call.exp
+++ b/gdb/testsuite/gdb.threads/interrupted-hand-call.exp
@@ -28,7 +28,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if { ![runto_main] } {
return 0
diff --git a/gdb/testsuite/gdb.threads/killed.exp b/gdb/testsuite/gdb.threads/killed.exp
index b1cec80b0..1fa83af 100644
--- a/gdb/testsuite/gdb.threads/killed.exp
+++ b/gdb/testsuite/gdb.threads/killed.exp
@@ -62,7 +62,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_run_cmd
gdb_test "" "" "run program to completion"
diff --git a/gdb/testsuite/gdb.threads/leader-exit-attach.exp b/gdb/testsuite/gdb.threads/leader-exit-attach.exp
index 641d6b5..2df4a18 100644
--- a/gdb/testsuite/gdb.threads/leader-exit-attach.exp
+++ b/gdb/testsuite/gdb.threads/leader-exit-attach.exp
@@ -31,7 +31,7 @@ set testpid [spawn_id_get_pid $test_spawn_id]
# Wait a bit for the leader thread to exit, before attaching.
sleep 2
-clean_restart ${binfile}
+clean_restart ${::testfile}
# Save this early as we may not be able to talk with GDBserver anymore
# when we need to check it.
diff --git a/gdb/testsuite/gdb.threads/linux-dp.exp b/gdb/testsuite/gdb.threads/linux-dp.exp
index 1652f78..35cc255 100644
--- a/gdb/testsuite/gdb.threads/linux-dp.exp
+++ b/gdb/testsuite/gdb.threads/linux-dp.exp
@@ -44,7 +44,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test_no_output "set print sevenbit-strings"
runto_main
diff --git a/gdb/testsuite/gdb.threads/local-watch-wrong-thread.exp b/gdb/testsuite/gdb.threads/local-watch-wrong-thread.exp
index 3006b83..a63f0be 100644
--- a/gdb/testsuite/gdb.threads/local-watch-wrong-thread.exp
+++ b/gdb/testsuite/gdb.threads/local-watch-wrong-thread.exp
@@ -28,7 +28,7 @@ if {[gdb_compile_pthreads \
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test_no_output "set can-use-hw-watchpoints 1" ""
diff --git a/gdb/testsuite/gdb.threads/main-thread-exit-during-detach.exp b/gdb/testsuite/gdb.threads/main-thread-exit-during-detach.exp
index 20e7bc4..1ce0194 100644
--- a/gdb/testsuite/gdb.threads/main-thread-exit-during-detach.exp
+++ b/gdb/testsuite/gdb.threads/main-thread-exit-during-detach.exp
@@ -50,7 +50,7 @@ if {[build_executable "failed to prepare" $testfile $srcfile \
proc run_test { spawn_inferior } {
save_vars { ::GDBFLAGS } {
append ::GDBFLAGS " -ex \"set non-stop on\""
- clean_restart $::binfile
+ clean_restart $::testfile
}
# Setup the inferior. When complete the main thread (#1) will
diff --git a/gdb/testsuite/gdb.threads/manythreads.exp b/gdb/testsuite/gdb.threads/manythreads.exp
index ae51c5a..2cd296f 100644
--- a/gdb/testsuite/gdb.threads/manythreads.exp
+++ b/gdb/testsuite/gdb.threads/manythreads.exp
@@ -31,7 +31,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test_no_output "set print sevenbit-strings"
runto_main
diff --git a/gdb/testsuite/gdb.threads/multi-create.exp b/gdb/testsuite/gdb.threads/multi-create.exp
index 966d44d..cb86aac 100644
--- a/gdb/testsuite/gdb.threads/multi-create.exp
+++ b/gdb/testsuite/gdb.threads/multi-create.exp
@@ -21,7 +21,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
runto_main
# Run to the beginning of create_function several times. Make sure
diff --git a/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp b/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
index 1aa9253..2694ce5 100644
--- a/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
+++ b/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
@@ -23,7 +23,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
return -1
}
-clean_restart "${binfile}"
+clean_restart "${::testfile}"
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.threads/next-bp-other-thread.exp b/gdb/testsuite/gdb.threads/next-bp-other-thread.exp
index cf8d687..6b696dd 100644
--- a/gdb/testsuite/gdb.threads/next-bp-other-thread.exp
+++ b/gdb/testsuite/gdb.threads/next-bp-other-thread.exp
@@ -28,7 +28,7 @@ if {[build_executable "failed to prepare" $testfile $srcfile \
# Test all "set scheduler-locking" variants.
foreach schedlock {"off" "step" "on" } {
with_test_prefix "schedlock=$schedlock" {
- clean_restart $binfile
+ clean_restart $::testfile
if ![runto_main] {
continue
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..82e85a6 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.
@@ -65,7 +67,7 @@ proc do_test { fork_func target-non-stop non-stop displaced-stepping } {
save_vars { ::GDBFLAGS } {
append ::GDBFLAGS " -ex \"maintenance set target-non-stop ${target-non-stop}\""
append ::GDBFLAGS " -ex \"set non-stop ${non-stop}\""
- clean_restart ${::binfile}-${fork_func}
+ clean_restart ${::testfile}-${fork_func}
}
gdb_test_no_output "set displaced-stepping ${displaced-stepping}"
diff --git a/gdb/testsuite/gdb.threads/next-fork-other-thread.exp b/gdb/testsuite/gdb.threads/next-fork-other-thread.exp
index 183fda6..9349091 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.
@@ -56,7 +58,7 @@ proc do_test { fork_func target-non-stop non-stop displaced-stepping } {
save_vars { ::GDBFLAGS } {
append ::GDBFLAGS " -ex \"maintenance set target-non-stop ${target-non-stop}\""
append ::GDBFLAGS " -ex \"set non-stop ${non-stop}\""
- clean_restart ${::binfile}-${fork_func}
+ clean_restart ${::testfile}-${fork_func}
}
gdb_test_no_output "set displaced-stepping ${displaced-stepping}"
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..9cc4978 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] } {
@@ -50,7 +52,7 @@ proc do_test { } {
save_vars { ::GDBFLAGS } {
append ::GDBFLAGS " -ex \"set non-stop on\""
- clean_restart $::binfile
+ clean_restart $::testfile
}
if { ![runto break_here_first] } {
diff --git a/gdb/testsuite/gdb.threads/pending-fork-event-detach.exp b/gdb/testsuite/gdb.threads/pending-fork-event-detach.exp
index 8e77ab0..fa86488 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
@@ -91,7 +93,8 @@ proc do_test { target-non-stop who_forks fork_function stop_mode } {
save_vars { ::GDBFLAGS } {
append ::GDBFLAGS " -ex \"maintenance set target-non-stop ${target-non-stop}\""
- clean_restart $this_binfile
+ clean_restart
+ gdb_load $this_binfile
}
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.threads/pending-step.exp b/gdb/testsuite/gdb.threads/pending-step.exp
index 1c2422e..d31f879 100644
--- a/gdb/testsuite/gdb.threads/pending-step.exp
+++ b/gdb/testsuite/gdb.threads/pending-step.exp
@@ -54,7 +54,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.threads/print-threads.exp b/gdb/testsuite/gdb.threads/print-threads.exp
index 51a14b2..3d2dc14 100644
--- a/gdb/testsuite/gdb.threads/print-threads.exp
+++ b/gdb/testsuite/gdb.threads/print-threads.exp
@@ -32,7 +32,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
# Now we can proceed with the real testing.
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test_no_output "set print sevenbit-strings"
#gdb_test_no_output "set print address off"
diff --git a/gdb/testsuite/gdb.threads/process-dies-while-detaching.exp b/gdb/testsuite/gdb.threads/process-dies-while-detaching.exp
index 776c08e..6c6a4b1 100644
--- a/gdb/testsuite/gdb.threads/process-dies-while-detaching.exp
+++ b/gdb/testsuite/gdb.threads/process-dies-while-detaching.exp
@@ -43,6 +43,7 @@
# threads are reaped. We test that as well.
standard_testfile
+set testfile_base $testfile
# Test that GDBserver exits.
@@ -214,7 +215,7 @@ proc test_detach {multi_process cmd} {
with_test_prefix "detach" {
global binfile
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if ![runto_main] {
return -1
@@ -242,7 +243,7 @@ proc test_detach_watch {wp multi_process cmd} {
with_test_prefix "watchpoint:$wp" {
global binfile decimal
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if ![runto_main] {
return -1
@@ -290,7 +291,7 @@ proc test_detach_killed_outside {multi_process cmd} {
with_test_prefix "killed outside" {
global binfile
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if ![runto_main] {
return -1
@@ -334,14 +335,15 @@ proc do_test {multi_process cmd} {
return
}
- set binfile [standard_output_file ${testfile}-$multi_process-$cmd]
+ set testfile $::testfile_base-$multi_process-$cmd
+ set binfile [standard_output_file $testfile]
set options {debug pthreads}
if {$multi_process} {
lappend options "additional_flags=-DMULTIPROCESS"
}
if {[build_executable "failed to build" \
- $testfile-$multi_process-$cmd $srcfile $options] == -1} {
+ $testfile $srcfile $options] == -1} {
return -1
}
diff --git a/gdb/testsuite/gdb.threads/process-dies-while-handling-bp.exp b/gdb/testsuite/gdb.threads/process-dies-while-handling-bp.exp
index 26dc8cc..a990dc9 100644
--- a/gdb/testsuite/gdb.threads/process-dies-while-handling-bp.exp
+++ b/gdb/testsuite/gdb.threads/process-dies-while-handling-bp.exp
@@ -42,7 +42,7 @@ proc do_test { non_stop cond_bp_target } {
save_vars { GDBFLAGS } {
set GDBFLAGS [concat $GDBFLAGS " -ex \"set non-stop $non_stop\""]
- clean_restart $binfile
+ clean_restart $::testfile
}
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.threads/pthread_cond_wait.exp b/gdb/testsuite/gdb.threads/pthread_cond_wait.exp
index c1be1cd..e914db0 100644
--- a/gdb/testsuite/gdb.threads/pthread_cond_wait.exp
+++ b/gdb/testsuite/gdb.threads/pthread_cond_wait.exp
@@ -25,7 +25,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
runto_main
gdb_test "break break_me" \
diff --git a/gdb/testsuite/gdb.threads/pthreads.exp b/gdb/testsuite/gdb.threads/pthreads.exp
index 0437e74..04ae91e2 100644
--- a/gdb/testsuite/gdb.threads/pthreads.exp
+++ b/gdb/testsuite/gdb.threads/pthreads.exp
@@ -34,7 +34,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test_no_output "set print sevenbit-strings"
#gdb_test_no_output "set print address off"
diff --git a/gdb/testsuite/gdb.threads/queue-signal.exp b/gdb/testsuite/gdb.threads/queue-signal.exp
index f791ffa..34abc3b 100644
--- a/gdb/testsuite/gdb.threads/queue-signal.exp
+++ b/gdb/testsuite/gdb.threads/queue-signal.exp
@@ -20,7 +20,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if ![runto_main] {
return 0
diff --git a/gdb/testsuite/gdb.threads/schedlock-new-thread.exp b/gdb/testsuite/gdb.threads/schedlock-new-thread.exp
index c398137..5fda4b8 100644
--- a/gdb/testsuite/gdb.threads/schedlock-new-thread.exp
+++ b/gdb/testsuite/gdb.threads/schedlock-new-thread.exp
@@ -31,7 +31,7 @@ proc test {non-stop schedlock} {
save_vars ::GDBFLAGS {
append ::GDBFLAGS " -ex \"set non-stop ${non-stop}\""
set sl [expr $schedlock == "on" ? 1 : 0]
- clean_restart $::binfile-$sl
+ clean_restart $::testfile-$sl
}
set linenum1 [gdb_get_line_number "set break 1 here"]
diff --git a/gdb/testsuite/gdb.threads/schedlock-thread-exit.exp b/gdb/testsuite/gdb.threads/schedlock-thread-exit.exp
index 434b058..137f652 100644
--- a/gdb/testsuite/gdb.threads/schedlock-thread-exit.exp
+++ b/gdb/testsuite/gdb.threads/schedlock-thread-exit.exp
@@ -28,7 +28,7 @@ if { [build_executable "failed to prepare" ${testfile} ${srcfile} \
}
proc do_test { } {
- clean_restart $::binfile
+ clean_restart $::testfile
# One of the launched threads will report a stop on thread_func. Some
# others will also stop on thread_func and have a pending status.
diff --git a/gdb/testsuite/gdb.threads/signal-command-handle-nopass.exp b/gdb/testsuite/gdb.threads/signal-command-handle-nopass.exp
index 2586800..6d344e3 100644
--- a/gdb/testsuite/gdb.threads/signal-command-handle-nopass.exp
+++ b/gdb/testsuite/gdb.threads/signal-command-handle-nopass.exp
@@ -35,7 +35,7 @@ proc test { step_over } {
global srcfile binfile tdlabel_re
with_test_prefix "step-over $step_over" {
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.exp b/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.exp
index 73f88c1..acb018b 100644
--- a/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.exp
+++ b/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.exp
@@ -32,7 +32,7 @@ proc test { schedlock } {
global srcfile binfile tdlabel_re
with_test_prefix "schedlock $schedlock" {
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.threads/signal-delivered-right-thread.exp b/gdb/testsuite/gdb.threads/signal-delivered-right-thread.exp
index 7445cad..9de0908 100644
--- a/gdb/testsuite/gdb.threads/signal-delivered-right-thread.exp
+++ b/gdb/testsuite/gdb.threads/signal-delivered-right-thread.exp
@@ -29,7 +29,7 @@ proc test { command } {
global srcfile binfile tdlabel_re
with_test_prefix "$command" {
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.threads/signal-sigtrap.exp b/gdb/testsuite/gdb.threads/signal-sigtrap.exp
index 8154ddf..849d628 100644
--- a/gdb/testsuite/gdb.threads/signal-sigtrap.exp
+++ b/gdb/testsuite/gdb.threads/signal-sigtrap.exp
@@ -32,7 +32,7 @@ proc test { sigtrap_thread } {
global srcfile binfile tdlabel_re
with_test_prefix "sigtrap thread $sigtrap_thread" {
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if {![runto "thread_function"]} {
return 0
diff --git a/gdb/testsuite/gdb.threads/sigthread.exp b/gdb/testsuite/gdb.threads/sigthread.exp
index 9d2f9b5..dea8eb8 100644
--- a/gdb/testsuite/gdb.threads/sigthread.exp
+++ b/gdb/testsuite/gdb.threads/sigthread.exp
@@ -24,7 +24,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.threads/staticthreads.exp b/gdb/testsuite/gdb.threads/staticthreads.exp
index 0374666..bbe11ab 100644
--- a/gdb/testsuite/gdb.threads/staticthreads.exp
+++ b/gdb/testsuite/gdb.threads/staticthreads.exp
@@ -34,7 +34,7 @@ foreach_with_prefix have_tls { "-DHAVE_TLS" "" } {
}
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test_no_output "set print sevenbit-strings"
@@ -94,7 +94,7 @@ gdb_test_multiple "quit" "$test" {
pass "$test"
}
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if { "$have_tls" != "" } {
diff --git a/gdb/testsuite/gdb.threads/step-N-all-progress.exp b/gdb/testsuite/gdb.threads/step-N-all-progress.exp
index c874d79..031e36a 100644
--- a/gdb/testsuite/gdb.threads/step-N-all-progress.exp
+++ b/gdb/testsuite/gdb.threads/step-N-all-progress.exp
@@ -31,7 +31,7 @@ proc test {non-stop target-non-stop} {
save_vars ::GDBFLAGS {
append ::GDBFLAGS " -ex \"maintenance set target-non-stop ${target-non-stop}\""
append ::GDBFLAGS " -ex \"set non-stop ${non-stop}\""
- clean_restart $::binfile
+ clean_restart $::testfile
}
if { ![runto_main] } {
diff --git a/gdb/testsuite/gdb.threads/step-over-exec.exp b/gdb/testsuite/gdb.threads/step-over-exec.exp
index 7c553f2..b06f3a4 100644
--- a/gdb/testsuite/gdb.threads/step-over-exec.exp
+++ b/gdb/testsuite/gdb.threads/step-over-exec.exp
@@ -71,7 +71,8 @@ proc do_test { execr_thread different_text_segments displaced_stepping } {
return -1
}
- clean_restart ${execr_binfile}
+ clean_restart
+ gdb_load $execr_binfile
gdb_test_no_output "set displaced-stepping $displaced_stepping"
diff --git a/gdb/testsuite/gdb.threads/step-over-thread-exit-while-stop-all-threads.exp b/gdb/testsuite/gdb.threads/step-over-thread-exit-while-stop-all-threads.exp
index cf10bdc..fdd2b27 100644
--- a/gdb/testsuite/gdb.threads/step-over-thread-exit-while-stop-all-threads.exp
+++ b/gdb/testsuite/gdb.threads/step-over-thread-exit-while-stop-all-threads.exp
@@ -29,7 +29,7 @@ if { [build_executable "failed to prepare" $testfile \
proc test {displaced-stepping target-non-stop} {
save_vars ::GDBFLAGS {
append ::GDBFLAGS " -ex \"maintenance set target-non-stop ${target-non-stop}\""
- clean_restart $::binfile
+ clean_restart $::testfile
}
gdb_test_no_output "set displaced-stepping ${displaced-stepping}"
diff --git a/gdb/testsuite/gdb.threads/step-over-thread-exit.exp b/gdb/testsuite/gdb.threads/step-over-thread-exit.exp
index 31037a7..8ed2b21 100644
--- a/gdb/testsuite/gdb.threads/step-over-thread-exit.exp
+++ b/gdb/testsuite/gdb.threads/step-over-thread-exit.exp
@@ -55,7 +55,7 @@ proc test {step_over_mode non-stop target-non-stop schedlock cmd ns_stop_all} {
save_vars ::GDBFLAGS {
append ::GDBFLAGS " -ex \"maintenance set target-non-stop ${target-non-stop}\""
append ::GDBFLAGS " -ex \"set non-stop ${non-stop}\""
- clean_restart $::binfile
+ clean_restart $::testfile
}
if { $step_over_mode == "none" } {
diff --git a/gdb/testsuite/gdb.threads/stepi-over-clone.exp b/gdb/testsuite/gdb.threads/stepi-over-clone.exp
index 5da123e..d6f1680 100644
--- a/gdb/testsuite/gdb.threads/stepi-over-clone.exp
+++ b/gdb/testsuite/gdb.threads/stepi-over-clone.exp
@@ -106,7 +106,7 @@ proc test {non_stop displaced third_thread} {
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop $non_stop\""
append GDBFLAGS " -ex \"set displaced $displaced\""
- clean_restart $binfile
+ clean_restart $::testfile
}
runto_main
diff --git a/gdb/testsuite/gdb.threads/switch-threads.exp b/gdb/testsuite/gdb.threads/switch-threads.exp
index d43603c..1f67a45 100644
--- a/gdb/testsuite/gdb.threads/switch-threads.exp
+++ b/gdb/testsuite/gdb.threads/switch-threads.exp
@@ -29,7 +29,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
runto_main
diff --git a/gdb/testsuite/gdb.threads/thread-bp-deleted.exp b/gdb/testsuite/gdb.threads/thread-bp-deleted.exp
index 2eadd38..8001229 100644
--- a/gdb/testsuite/gdb.threads/thread-bp-deleted.exp
+++ b/gdb/testsuite/gdb.threads/thread-bp-deleted.exp
@@ -38,7 +38,7 @@ set is_remote \
# This test requires background execution, which relies on non-stop mode.
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"maint set target-non-stop on\""
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
if {![runto_main]} {
@@ -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/thread-execl.exp b/gdb/testsuite/gdb.threads/thread-execl.exp
index 04ba518..13a6ef4 100644
--- a/gdb/testsuite/gdb.threads/thread-execl.exp
+++ b/gdb/testsuite/gdb.threads/thread-execl.exp
@@ -35,7 +35,7 @@ proc do_test { schedlock } {
set prefix "schedlock $schedlock"
}
with_test_prefix "$prefix" {
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if {$schedlock == "non-stop"} {
gdb_test_no_output "set non-stop 1"
diff --git a/gdb/testsuite/gdb.threads/thread-find.exp b/gdb/testsuite/gdb.threads/thread-find.exp
index 456f7d3..171b94b 100644
--- a/gdb/testsuite/gdb.threads/thread-find.exp
+++ b/gdb/testsuite/gdb.threads/thread-find.exp
@@ -21,7 +21,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test_no_output "set print sevenbit-strings"
runto_main
diff --git a/gdb/testsuite/gdb.threads/thread-specific-bp.exp b/gdb/testsuite/gdb.threads/thread-specific-bp.exp
index c4858f2..8f48b61 100644
--- a/gdb/testsuite/gdb.threads/thread-specific-bp.exp
+++ b/gdb/testsuite/gdb.threads/thread-specific-bp.exp
@@ -118,7 +118,7 @@ proc check_thread_specific_breakpoint {non_stop} {
foreach_with_prefix non_stop {on off} {
save_vars { GDBFLAGS } {
append GDBFLAGS " -ex \"set non-stop $non_stop\""
- clean_restart $binfile
+ clean_restart $::testfile
}
check_thread_specific_breakpoint $non_stop
diff --git a/gdb/testsuite/gdb.threads/thread-specific.exp b/gdb/testsuite/gdb.threads/thread-specific.exp
index bf9c63b..d1e6f4d 100644
--- a/gdb/testsuite/gdb.threads/thread-specific.exp
+++ b/gdb/testsuite/gdb.threads/thread-specific.exp
@@ -62,7 +62,7 @@ proc get_thread_list { } {
return $thr_list
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test_no_output "set print sevenbit-strings"
gdb_test_no_output "set width 0"
diff --git a/gdb/testsuite/gdb.threads/thread-unwindonsignal.exp b/gdb/testsuite/gdb.threads/thread-unwindonsignal.exp
index 5f4ac1f..dc74714 100644
--- a/gdb/testsuite/gdb.threads/thread-unwindonsignal.exp
+++ b/gdb/testsuite/gdb.threads/thread-unwindonsignal.exp
@@ -28,7 +28,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if { ![runto_main] } {
return 0
diff --git a/gdb/testsuite/gdb.threads/thread_check.exp b/gdb/testsuite/gdb.threads/thread_check.exp
index ee5f35a..9f92066 100644
--- a/gdb/testsuite/gdb.threads/thread_check.exp
+++ b/gdb/testsuite/gdb.threads/thread_check.exp
@@ -39,7 +39,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 1
diff --git a/gdb/testsuite/gdb.threads/threadapply.exp b/gdb/testsuite/gdb.threads/threadapply.exp
index c53db79..34de561 100644
--- a/gdb/testsuite/gdb.threads/threadapply.exp
+++ b/gdb/testsuite/gdb.threads/threadapply.exp
@@ -25,7 +25,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
#
# Run to `main' where we begin our tests.
@@ -73,7 +73,7 @@ proc thr_apply_detach {thread_set} {
global binfile
global break_line
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if ![runto_main] {
return -1
@@ -112,7 +112,7 @@ proc kill_and_remove_inferior {thread_set} {
set any "\[^\r\n\]*"
set ws "\[ \t\]\+"
- clean_restart ${binfile}
+ clean_restart ${::testfile}
with_test_prefix "start inferior 1" {
runto_main
@@ -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/threadcrash.exp b/gdb/testsuite/gdb.threads/threadcrash.exp
index 15d2a20..8df8578 100644
--- a/gdb/testsuite/gdb.threads/threadcrash.exp
+++ b/gdb/testsuite/gdb.threads/threadcrash.exp
@@ -132,8 +132,9 @@ proc do_full_test {} {
set pthread_kill ".*"
}
- for {set i 0} {$i < $thread_count } {incr i} {
- set thread_num [expr [llength $test_list] - $i]
+ set loop_iterations [llength $test_list]
+ for {set i 0} {$i < $loop_iterations } {incr i} {
+ set thread_num [expr $loop_iterations - $i]
set type [lindex $test_list $i]
if { $type == 1 } {
@@ -237,7 +238,7 @@ proc_with_prefix test_corefile {} {
proc_with_prefix test_gcore {} {
- clean_restart "$::binfile"
+ clean_restart "$::testfile"
gdb_test "handle SIGUSR1 nostop print pass" \
".*SIGUSR1.*No.*Yes.*Yes.*User defined signal 1" \
@@ -275,7 +276,7 @@ if [prepare_for_testing "failed to prepare" $testfile $srcfile \
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test_no_output "set backtrace limit unlimited"
diff --git a/gdb/testsuite/gdb.threads/threxit-hop-specific.exp b/gdb/testsuite/gdb.threads/threxit-hop-specific.exp
index ce2df7c..b55e80c 100644
--- a/gdb/testsuite/gdb.threads/threxit-hop-specific.exp
+++ b/gdb/testsuite/gdb.threads/threxit-hop-specific.exp
@@ -23,7 +23,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
runto_main
diff --git a/gdb/testsuite/gdb.threads/tls-core.exp b/gdb/testsuite/gdb.threads/tls-core.exp
index 96b1c6a..587ae61 100644
--- a/gdb/testsuite/gdb.threads/tls-core.exp
+++ b/gdb/testsuite/gdb.threads/tls-core.exp
@@ -27,7 +27,7 @@ set core_supported [expr {$corefile != ""}]
# Generate a core file with "gcore".
-clean_restart ${binfile}
+clean_restart ${::testfile}
runto thread_proc
@@ -43,7 +43,7 @@ proc tls_core_test {supported corefile} {
upvar host_triplet host_triplet
upvar binfile binfile
- clean_restart ${binfile}
+ clean_restart ${::testfile}
set test "load core file"
if {$supported} {
diff --git a/gdb/testsuite/gdb.threads/tls-nodebug-pie.exp b/gdb/testsuite/gdb.threads/tls-nodebug-pie.exp
index 01abcfa..44c12f5 100644
--- a/gdb/testsuite/gdb.threads/tls-nodebug-pie.exp
+++ b/gdb/testsuite/gdb.threads/tls-nodebug-pie.exp
@@ -20,7 +20,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
}
diff --git a/gdb/testsuite/gdb.threads/tls-nodebug.exp b/gdb/testsuite/gdb.threads/tls-nodebug.exp
index ebfa752..971f26c 100644
--- a/gdb/testsuite/gdb.threads/tls-nodebug.exp
+++ b/gdb/testsuite/gdb.threads/tls-nodebug.exp
@@ -26,7 +26,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
if {![runto_main]} {
return 0
}
diff --git a/gdb/testsuite/gdb.threads/tls-shared.exp b/gdb/testsuite/gdb.threads/tls-shared.exp
index 35596bc..b7fa965 100644
--- a/gdb/testsuite/gdb.threads/tls-shared.exp
+++ b/gdb/testsuite/gdb.threads/tls-shared.exp
@@ -29,7 +29,7 @@ if { [gdb_compile_shlib_pthreads ${srcdir}/${subdir}/${srcfile_lib} ${binfile_li
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_load_shlib ${binfile_lib}
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.threads/tls-so_extern.exp b/gdb/testsuite/gdb.threads/tls-so_extern.exp
index 3cef672..a0aa5f8 100644
--- a/gdb/testsuite/gdb.threads/tls-so_extern.exp
+++ b/gdb/testsuite/gdb.threads/tls-so_extern.exp
@@ -28,7 +28,7 @@ if { [gdb_compile_shlib_pthreads ${srcdir}/${subdir}/${srcfile_lib} ${binfile_li
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_load_shlib ${binfile_lib}
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.threads/tls.exp b/gdb/testsuite/gdb.threads/tls.exp
index 73fada7..4b43387 100644
--- a/gdb/testsuite/gdb.threads/tls.exp
+++ b/gdb/testsuite/gdb.threads/tls.exp
@@ -153,7 +153,7 @@ proc check_thread_stack {number spin_threads spin_threads_level} {
}
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test_multiple "print a_thread_local" "" {
-re -wrap "Cannot find thread-local variables on this target" {
diff --git a/gdb/testsuite/gdb.threads/vfork-follow-child-exec.exp b/gdb/testsuite/gdb.threads/vfork-follow-child-exec.exp
index e23db0a..7c2b309 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}]} {
@@ -28,7 +30,7 @@ if {[build_executable "failed to prepare" $testfile $srcfile {debug pthreads}]}
proc test_vfork {detach} {
global binfile
- clean_restart $binfile
+ clean_restart $::testfile
if {![runto_main]} {
return 0
diff --git a/gdb/testsuite/gdb.threads/vfork-follow-child-exit.exp b/gdb/testsuite/gdb.threads/vfork-follow-child-exit.exp
index a6b7f49..a5e7475 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}]} {
@@ -28,7 +30,7 @@ if {[build_executable "failed to prepare" $testfile $srcfile {debug pthreads}]}
proc test_vfork {detach} {
global binfile
- clean_restart $binfile
+ clean_restart $::testfile
if {![runto_main]} {
return 0
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..fce974b 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}] } {
@@ -57,7 +59,7 @@ proc do_test { target-non-stop non-stop follow-fork-mode detach-on-fork schedule
save_vars { ::GDBFLAGS } {
append ::GDBFLAGS " -ex \"maintenance set target-non-stop ${target-non-stop}\""
append ::GDBFLAGS " -ex \"set non-stop ${non-stop}\""
- clean_restart ${::binfile}
+ clean_restart ${::testfile}
}
gdb_test_no_output "set follow-fork-mode ${follow-fork-mode}"
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.threads/watchthreads.exp b/gdb/testsuite/gdb.threads/watchthreads.exp
index 49fc762..f3ec7f4 100644
--- a/gdb/testsuite/gdb.threads/watchthreads.exp
+++ b/gdb/testsuite/gdb.threads/watchthreads.exp
@@ -31,7 +31,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart $binfile
+clean_restart $::testfile
gdb_test_no_output "set can-use-hw-watchpoints 1" ""
#
diff --git a/gdb/testsuite/gdb.threads/watchthreads2.exp b/gdb/testsuite/gdb.threads/watchthreads2.exp
index 2426be4..19a60e4 100644
--- a/gdb/testsuite/gdb.threads/watchthreads2.exp
+++ b/gdb/testsuite/gdb.threads/watchthreads2.exp
@@ -31,7 +31,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
gdb_test_no_output "set can-use-hw-watchpoints 1" ""
diff --git a/gdb/testsuite/gdb.threads/wp-replication.exp b/gdb/testsuite/gdb.threads/wp-replication.exp
index 68f5eb0..8a5f95d 100644
--- a/gdb/testsuite/gdb.threads/wp-replication.exp
+++ b/gdb/testsuite/gdb.threads/wp-replication.exp
@@ -34,7 +34,7 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
return -1
}
-clean_restart ${binfile}
+clean_restart ${::testfile}
# Force hardware watchpoints to be used.
gdb_test_no_output "set can-use-hw-watchpoints 1" ""
diff --git a/gdb/testsuite/gdb.trace/ax.exp b/gdb/testsuite/gdb.trace/ax.exp
index 3380cdf..cc40853 100644
--- a/gdb/testsuite/gdb.trace/ax.exp
+++ b/gdb/testsuite/gdb.trace/ax.exp
@@ -30,7 +30,7 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
return -1
}
-clean_restart $binfile
+clean_restart $testfile
runto_main
gdb_test "maint agent 12" ".*const8 12.*pop.*end.*"
diff --git a/gdb/testsuite/gdb.trace/basic-libipa.exp b/gdb/testsuite/gdb.trace/basic-libipa.exp
index e7612ac..27be96b 100644
--- a/gdb/testsuite/gdb.trace/basic-libipa.exp
+++ b/gdb/testsuite/gdb.trace/basic-libipa.exp
@@ -42,7 +42,7 @@ save_vars { env(ASAN_OPTIONS) } {
# LD_PRELOAD.
append_environment_default ASAN_OPTIONS verify_asan_link_order 0
- clean_restart $binfile
+ clean_restart $testfile
}
if {![runto_main]} {
diff --git a/gdb/testsuite/gdb.trace/entry-values.exp b/gdb/testsuite/gdb.trace/entry-values.exp
index f6bcf66..161496a 100644
--- a/gdb/testsuite/gdb.trace/entry-values.exp
+++ b/gdb/testsuite/gdb.trace/entry-values.exp
@@ -29,7 +29,7 @@ if {[gdb_compile [list ${binfile}1.o] \
return -1
}
-clean_restart ${binfile}1
+clean_restart ${testfile}1
set returned_from_foo ""
@@ -193,7 +193,7 @@ gdb_test_sequence "bt" "bt, 2" {
# Restart GDB and trace.
-clean_restart $binfile
+clean_restart $testfile
load_lib "trace-support.exp"
diff --git a/gdb/testsuite/gdb.trace/ftrace-lock.exp b/gdb/testsuite/gdb.trace/ftrace-lock.exp
index 36a7566..8c9d4aa 100644
--- a/gdb/testsuite/gdb.trace/ftrace-lock.exp
+++ b/gdb/testsuite/gdb.trace/ftrace-lock.exp
@@ -32,7 +32,7 @@ set options [list debug pthreads [gdb_target_symbol_prefix_flags] \
additional_flags=-DNUM_THREADS=$NUM_THREADS]
with_test_prefix "runtime trace support check" {
- if { [prepare_for_testing "prepare for testing" ${binfile}-check \
+ if { [prepare_for_testing "prepare for testing" ${testfile}-check \
$srcfile $options] } {
return
}
@@ -55,7 +55,7 @@ set remote_libipa [gdb_load_shlib $libipa]
lappend options shlib=$libipa
if { [prepare_for_testing "prepare for testing with libipa" \
- $binfile $srcfile $options] } {
+ $testfile $srcfile $options] } {
return
}
diff --git a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
index dd0d785..9b4f053 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
@@ -37,7 +37,7 @@ gdb_exit
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-mi_clean_restart $binfile
+mi_clean_restart $testfile
mi_runto_main
mi_gdb_test "-break-insert end" \
diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
index dde6d8b..dd22046 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
@@ -35,7 +35,7 @@ gdb_exit
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-mi_clean_restart $binfile
+mi_clean_restart $testfile
mi_runto_main
mi_gdb_test "-break-insert marker" \
diff --git a/gdb/testsuite/gdb.trace/mi-traceframe-changed.exp b/gdb/testsuite/gdb.trace/mi-traceframe-changed.exp
index 05c10ed..90a053c 100644
--- a/gdb/testsuite/gdb.trace/mi-traceframe-changed.exp
+++ b/gdb/testsuite/gdb.trace/mi-traceframe-changed.exp
@@ -45,11 +45,10 @@ remote_file target delete $tfile_basic
proc test_tfind_tfile { } {
with_test_prefix "tfile" {
- global binfile
global decimal
global tfile_basic
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
mi_gdb_test "-target-select tfile ${tfile_basic}" \
".*=breakpoint-created,bkpt=\{number=\"${decimal}\",type=\"tracepoint\",disp=\"keep\",enabled=\"y\",.*,func=\"write_basic_trace_file\".*\\^connected" \
@@ -92,8 +91,8 @@ if [generate_tracefile $binfile] {
# Change to a different test case in order to run it on target, and get
# several traceframes.
standard_testfile status-stop.c
-append testfile -1
-append binfile -1
+append testfile "-1"
+append binfile "-1"
set executable $testfile
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
@@ -120,9 +119,8 @@ gdb_exit
proc test_tfind_remote { } {
with_test_prefix "remote" {
global decimal
- global binfile
- mi_clean_restart $binfile
+ mi_clean_restart $::testfile
mi_runto_main
mi_gdb_test "-break-insert end" "\\^done.*" "break end"
diff --git a/gdb/testsuite/gdb.trace/mi-tracepoint-changed.exp b/gdb/testsuite/gdb.trace/mi-tracepoint-changed.exp
index 90654c0..99f7bf9 100644
--- a/gdb/testsuite/gdb.trace/mi-tracepoint-changed.exp
+++ b/gdb/testsuite/gdb.trace/mi-tracepoint-changed.exp
@@ -89,9 +89,7 @@ proc test_reconnect { } {
}
}
- global binfile
-
- if {[mi_clean_restart $binfile]} {
+ if {[mi_clean_restart $::testfile]} {
return
}
@@ -155,11 +153,10 @@ proc test_pending_resolved { } {
with_test_prefix "pending resolved" {
global decimal hex
global executable
- global binfile
global lib_sl1 lib_sl2
global mi_gdb_prompt
- if {[mi_clean_restart $binfile]} {
+ if {[mi_clean_restart $::testfile]} {
return
}
mi_load_shlibs $lib_sl1 $lib_sl2
diff --git a/gdb/testsuite/gdb.trace/mi-tsv-changed.exp b/gdb/testsuite/gdb.trace/mi-tsv-changed.exp
index f90d9a4..6f71e79 100644
--- a/gdb/testsuite/gdb.trace/mi-tsv-changed.exp
+++ b/gdb/testsuite/gdb.trace/mi-tsv-changed.exp
@@ -77,7 +77,7 @@ proc test_create_delete_modify_tsv { } {
}
gdb_exit
- if {[mi_clean_restart $binfile]} {
+ if {[mi_clean_restart $::testfile]} {
return
}
@@ -145,7 +145,7 @@ proc test_upload_tsv { } {
return 0
}
- clean_restart $testfile
+ clean_restart $::testfile
if {![runto_main]} {
return 0
}
@@ -175,8 +175,7 @@ proc test_upload_tsv { } {
}
}
- global binfile
- if {[mi_clean_restart $binfile]} {
+ if {[mi_clean_restart $::testfile]} {
return
}
diff --git a/gdb/testsuite/gdb.trace/packetlen.exp b/gdb/testsuite/gdb.trace/packetlen.exp
index cf9fcc4..52a34b9 100644
--- a/gdb/testsuite/gdb.trace/packetlen.exp
+++ b/gdb/testsuite/gdb.trace/packetlen.exp
@@ -25,7 +25,7 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
return -1
}
-clean_restart $binfile
+clean_restart $testfile
gdb_test "tstop" ".*" ""
gdb_test "tfind none" ".*" ""
runto_main
diff --git a/gdb/testsuite/gdb.trace/passc-dyn.exp b/gdb/testsuite/gdb.trace/passc-dyn.exp
index 0a67df1..b4ec45a 100644
--- a/gdb/testsuite/gdb.trace/passc-dyn.exp
+++ b/gdb/testsuite/gdb.trace/passc-dyn.exp
@@ -25,7 +25,7 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
return -1
}
-clean_restart $binfile
+clean_restart $testfile
runto_main
if {![gdb_target_supports_trace]} {
diff --git a/gdb/testsuite/gdb.trace/report.exp b/gdb/testsuite/gdb.trace/report.exp
index 45857a1..f2a04f7 100644
--- a/gdb/testsuite/gdb.trace/report.exp
+++ b/gdb/testsuite/gdb.trace/report.exp
@@ -24,7 +24,7 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
untested "failed to compile"
return -1
}
-clean_restart $binfile
+clean_restart $testfile
runto_main
if {![gdb_target_supports_trace]} {
diff --git a/gdb/testsuite/gdb.trace/tfile.exp b/gdb/testsuite/gdb.trace/tfile.exp
index 020f4d4..4d156f7 100644
--- a/gdb/testsuite/gdb.trace/tfile.exp
+++ b/gdb/testsuite/gdb.trace/tfile.exp
@@ -61,7 +61,7 @@ if {!$purely_local} {
remote_download host [remote_upload target tfile-error.tf] tfile-error.tf
}
-clean_restart $binfile
+clean_restart $testfile
# Program has presumably exited, now target a trace file it created.
@@ -121,7 +121,7 @@ gdb_test "info registers" "The program has no registers now\." \
# Now start afresh, using only a trace file.
-clean_restart $binfile
+clean_restart $testfile
gdb_test "target tfile $tfile_error" "Created tracepoint.*" \
"target tfile [file tail $tfile_error]"
diff --git a/gdb/testsuite/gdb.trace/tfind.exp b/gdb/testsuite/gdb.trace/tfind.exp
index ae73206..92386e4 100644
--- a/gdb/testsuite/gdb.trace/tfind.exp
+++ b/gdb/testsuite/gdb.trace/tfind.exp
@@ -27,7 +27,7 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" "$binfile" \
return -1
}
-clean_restart $binfile
+clean_restart $testfile
# 6.2 test help tstart
gdb_test "help tstart" \
diff --git a/gdb/testsuite/gdb.trace/trace-mt.exp b/gdb/testsuite/gdb.trace/trace-mt.exp
index 0c6e4e5..092dc6d 100644
--- a/gdb/testsuite/gdb.trace/trace-mt.exp
+++ b/gdb/testsuite/gdb.trace/trace-mt.exp
@@ -22,7 +22,7 @@ set additional_flags [gdb_target_symbol_prefix_flags]
require gdb_trace_common_supports_arch
with_test_prefix "runtime trace support check" {
- if { [prepare_for_testing "prepare for testing" ${binfile} $srcfile \
+ if { [prepare_for_testing "prepare for testing" $testfile $srcfile \
[list debug pthreads $additional_flags]] } {
return
}
@@ -37,13 +37,13 @@ with_test_prefix "runtime trace support check" {
}
}
-proc step_over_tracepoint { binfile trace_type } \
+proc step_over_tracepoint { testfile trace_type } \
{with_test_prefix "step over $trace_type" \
{
global hex
# Start with a fresh gdb.
- clean_restart $binfile
+ clean_restart $testfile
# Make sure inferior is running in all-stop mode.
gdb_test_no_output "set non-stop 0"
@@ -63,13 +63,13 @@ proc step_over_tracepoint { binfile trace_type } \
# Set breakpoint and tracepoint at the same address.
-proc break_trace_same_addr { binfile trace_type option } \
+proc break_trace_same_addr { testfile trace_type option } \
{with_test_prefix "$trace_type $option" \
{
global hex
# Start with a fresh gdb.
- clean_restart $binfile
+ clean_restart $testfile
if ![runto_main] {
return -1
}
@@ -96,10 +96,10 @@ proc break_trace_same_addr { binfile trace_type option } \
}}
foreach break_always_inserted { "on" "off" } {
- break_trace_same_addr $binfile "trace" ${break_always_inserted}
+ break_trace_same_addr $testfile "trace" ${break_always_inserted}
}
-step_over_tracepoint $binfile "trace"
+step_over_tracepoint $testfile "trace"
require allow_shlib_tests
@@ -108,8 +108,8 @@ set libipa [get_in_proc_agent]
set remote_libipa [gdb_load_shlib $libipa]
# Compile test case again with IPA.
-set binfile_ipa ${binfile}-ipa
-if { [prepare_for_testing "prepare for testing" $binfile_ipa $srcfile \
+set testfile_ipa $testfile-ipa
+if { [prepare_for_testing "prepare for testing" $testfile_ipa $srcfile \
[list debug pthreads $additional_flags shlib=$libipa]] } {
return
}
@@ -122,8 +122,8 @@ if { [gdb_test "info sharedlibrary" ".*${remote_libipa}.*" "IPA loaded"] != 0 }
untested "could not find IPA lib loaded"
} else {
foreach break_always_inserted { "on" "off" } {
- break_trace_same_addr $binfile_ipa "ftrace" ${break_always_inserted}
+ break_trace_same_addr $testfile_ipa "ftrace" ${break_always_inserted}
}
- step_over_tracepoint $binfile_ipa "ftrace"
+ step_over_tracepoint $testfile_ipa "ftrace"
}
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.trace/tsv.exp b/gdb/testsuite/gdb.trace/tsv.exp
index 96c7c35..837633d 100644
--- a/gdb/testsuite/gdb.trace/tsv.exp
+++ b/gdb/testsuite/gdb.trace/tsv.exp
@@ -23,7 +23,7 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
return -1
}
-clean_restart $binfile
+clean_restart $testfile
# PR gdb/21352: Command tsave does not support -r argument
gdb_test "tsave -r" "Argument required \\\(file in which to save trace data\\\)\." \
@@ -193,7 +193,7 @@ gdb_test_multiple "target ctf ${tracefile}.ctf" "" {
}
# Restart.
-clean_restart ${binfile}
+clean_restart $testfile
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.trace/while-dyn.exp b/gdb/testsuite/gdb.trace/while-dyn.exp
index 53a8e54..3940ff6 100644
--- a/gdb/testsuite/gdb.trace/while-dyn.exp
+++ b/gdb/testsuite/gdb.trace/while-dyn.exp
@@ -26,7 +26,7 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
return -1
}
-clean_restart $binfile
+clean_restart $testfile
runto_main
if {![gdb_target_supports_trace]} {
diff --git a/gdb/testsuite/gdb.tui/basic.exp b/gdb/testsuite/gdb.tui/basic.exp
index 35c99bd..8ecc91a 100644
--- a/gdb/testsuite/gdb.tui/basic.exp
+++ b/gdb/testsuite/gdb.tui/basic.exp
@@ -112,5 +112,9 @@ set re_noattr "\[^<\]"
set status_window_line 15
set status [Term::get_line_with_attrs $status_window_line]
-gdb_assert { [regexp "^<reverse:1>$re_noattr*<reverse:0>$" $status] == 1} \
+verbose -log "status line: '$status'"
+
+# The status line uses standout, which may translate to different attributes
+# depending on the terminal settings. Just check for at least one attribute.
+gdb_assert { [regexp "^<.*>(exec|extended-r)" $status] == 1 } \
"status window: reverse"
diff --git a/gdb/testsuite/gdb.tui/color-prompt.exp b/gdb/testsuite/gdb.tui/color-prompt.exp
index a95b24a..af6e467 100644
--- a/gdb/testsuite/gdb.tui/color-prompt.exp
+++ b/gdb/testsuite/gdb.tui/color-prompt.exp
@@ -15,18 +15,16 @@
# Check using a prompt with color in TUI.
+require allow_tui_tests
+
tuiterm_env
Term::clean_restart 24 80
-# Set colored prompt.
if {![Term::enter_tui]} {
unsupported "TUI not supported"
return
}
-Term::command "set prompt \\033\[31m(gdb) \\033\[0m"
-
-set line [Term::get_line_with_attrs $Term::_cur_row]
-gdb_assert { [regexp "^<fg:red>$gdb_prompt <fg:default> *$" $line] } \
- "prompt with color"
+set tui 1
+source $srcdir/$subdir/color-prompt.exp.tcl
diff --git a/gdb/testsuite/gdb.tui/color-prompt.exp.tcl b/gdb/testsuite/gdb.tui/color-prompt.exp.tcl
new file mode 100644
index 0000000..e6f4d3b
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/color-prompt.exp.tcl
@@ -0,0 +1,80 @@
+# 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 using a prompt with color in TUI ($tui == 0) or CLI ($tui == 0).
+
+set csi [string cat {\033} "\["]
+set rl_prompt_start_ignore {\001}
+set rl_prompt_end_ignore {\002}
+
+foreach_with_prefix rl_prompt_start_end_ignore { 0 1 } {
+ set color_on [string cat $csi 31m]
+ set color_off [string cat $csi 0m]
+
+ if { $rl_prompt_start_end_ignore } {
+ set color_on \
+ [string cat \
+ $rl_prompt_start_ignore \
+ $color_on \
+ $rl_prompt_end_ignore]
+ set color_off \
+ [string cat \
+ $rl_prompt_start_ignore \
+ $color_off \
+ $rl_prompt_end_ignore]
+ }
+
+ # Set prompt with color.
+ set prompt "${color_on}(gdb) $color_off"
+ Term::command "set prompt $prompt"
+
+ # Check the color.
+ set line [Term::get_line_with_attrs $Term::_cur_row]
+ gdb_assert { [regexp "^<fg:red>$gdb_prompt <fg:default> *$" $line] } \
+ "prompt with color"
+
+ # Type a string.
+ set cmd "some long command"
+ send_gdb $cmd
+ Term::wait_for_line ^[string_to_regexp "(gdb) $cmd"] 23
+
+ # Send ^A, aka C-a, trigger beginning-of-line.
+ send_gdb "\001"
+ if { $tui || $rl_prompt_start_end_ignore } {
+ Term::wait_for_line ^[string_to_regexp "(gdb) $cmd"] 6
+ } else {
+ # Without the markers, readline may get the cursor position wrong, so
+ # match less strict.
+ Term::wait_for_line ^[string_to_regexp "(gdb) $cmd"]
+ }
+ Term::dump_screen
+
+ # Type something else to flush out the effect of the ^A.
+ set prefix "A"
+ send_gdb $prefix
+ if { $tui || $rl_prompt_start_end_ignore } {
+ Term::wait_for_line ^[string_to_regexp "(gdb) $prefix$cmd"] 7
+ } else {
+ # Without the markers, readline may get the cursor position wrong, so
+ # match less strict.
+ Term::wait_for_line [string_to_regexp "$prefix"]
+ }
+
+ # Abort command line editing, and regenerate prompt.
+ send_gdb "\003"
+
+ # Reset prompt to default prompt.
+ Term::command "set prompt (gdb) "
+}
diff --git a/gdb/testsuite/gdb.tui/compact-source.exp b/gdb/testsuite/gdb.tui/compact-source.exp
index b050159..31bc1dc 100644
--- a/gdb/testsuite/gdb.tui/compact-source.exp
+++ b/gdb/testsuite/gdb.tui/compact-source.exp
@@ -41,7 +41,7 @@ if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} {
return -1
}
-Term::clean_restart 24 80 $binfile
+Term::clean_restart 24 80 $testfile
gdb_test_no_output "maint set tui-left-margin-verbose on"
gdb_test_no_output "set tui compact-source on"
@@ -55,9 +55,9 @@ set re_border "\\|"
set max_line_nr_in_source_file [llength $src_list]
# Ensure there are more lines in the window than in the source file.
-set src_window_lines [expr $max_line_nr_in_source_file + 2]
+set src_window_lines [expr {$max_line_nr_in_source_file + 2}]
# Account for border size.
-set src_window_size [expr $src_window_lines + 2]
+set src_window_size [expr {$src_window_lines + 2}]
Term::command "wh src $src_window_size"
set re_left_margin "___4_"
@@ -65,6 +65,6 @@ set re_left_margin "___4_"
Term::check_contents "compact source format" \
"$re_border$re_left_margin$re_line_four *$re_border"
-set re_left_margin "___0*[expr $max_line_nr_in_source_file + 1]_"
+set re_left_margin "___0*[expr {$max_line_nr_in_source_file + 1}]_"
Term::check_contents_not "no surplus line number" \
"$re_border$re_left_margin *$re_border"
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/empty.exp b/gdb/testsuite/gdb.tui/empty.exp
index 33710ff..19196e8 100644
--- a/gdb/testsuite/gdb.tui/empty.exp
+++ b/gdb/testsuite/gdb.tui/empty.exp
@@ -65,7 +65,7 @@ set layouts {
proc check_boxes {boxes} {
set boxno 1
foreach box $boxes {
- eval Term::check_box [list "box $boxno"] $box
+ Term::check_box "box $boxno" {*}$box
incr boxno
}
}
diff --git a/gdb/testsuite/gdb.tui/esc-match.exp b/gdb/testsuite/gdb.tui/esc-match.exp
new file mode 100644
index 0000000..db78ebe
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/esc-match.exp
@@ -0,0 +1,48 @@
+# 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 that the ANSI escape sequence matcher works
+# character-by-character.
+
+load_lib gdb-python.exp
+require allow_python_tests allow_tui_tests
+
+tuiterm_env
+
+Term::clean_restart 24 80
+
+set remote_python_file [gdb_remote_download host \
+ ${srcdir}/${subdir}/esc-match.py]
+gdb_test_no_output "source ${remote_python_file}" \
+ "source esc-match.py"
+
+if {![Term::enter_tui]} {
+ unsupported "TUI not supported"
+ return
+}
+
+Term::command "python print_it()"
+
+Term::dump_screen
+
+set text [Term::get_all_lines]
+# We should not see the control sequence here.
+gdb_assert {![regexp -- "\\\[35;1mOUTPUT\\\[m" $text]} \
+ "output visible without control sequences"
+
+# Also check the styling.
+set text [Term::get_region 0 1 78 23 "\n" true]
+gdb_assert {[regexp -- "<fg:magenta>.*OUTPUT" $text]} \
+ "output is magenta"
diff --git a/gdb/testsuite/gdb.tui/esc-match.py b/gdb/testsuite/gdb.tui/esc-match.py
new file mode 100644
index 0000000..7816002
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/esc-match.py
@@ -0,0 +1,26 @@
+# 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
+
+# Some text to print that includes styling.
+OUT = "\033[35;1mOUTPUT\033[m"
+
+
+def print_it():
+ # Print to stderr avoids any buffering, showing the bug.
+ for c in OUT:
+ print(c, end="", file=sys.stderr)
+ print(file=sys.stderr)
diff --git a/gdb/testsuite/gdb.testsuite/lmap.exp b/gdb/testsuite/gdb.tui/gdb.tcl
index da03722..ca207ed 100644..100755
--- a/gdb/testsuite/gdb.testsuite/lmap.exp
+++ b/gdb/testsuite/gdb.tui/gdb.tcl
@@ -1,4 +1,7 @@
-# Copyright 2023-2025 Free Software Foundation, Inc.
+#!/usr/bin/env tclsh
+
+# 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
@@ -12,9 +15,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-set one 1
-set l1 { $one 2 }
-set res1 [lmap item $l1 {expr $item + 1}]
-gdb_assert { [lindex $res1 0] == 2 }
-gdb_assert { [lindex $res1 1] == 3 }
-gdb_assert { $item == 2 }
+puts "foo\033(%5"
+
+gets stdin
diff --git a/gdb/testsuite/gdb.tui/main-2.exp b/gdb/testsuite/gdb.tui/main-2.exp
index 2b0fb6b..2bc6b8d 100644
--- a/gdb/testsuite/gdb.tui/main-2.exp
+++ b/gdb/testsuite/gdb.tui/main-2.exp
@@ -26,7 +26,7 @@ if { [build_executable "failed to prepare" $testfile $srcfile ] == -1} {
return -1
}
-Term::clean_restart 24 80 $binfile
+Term::clean_restart 24 80 $testfile
if {![runto_main]} {
perror "test suppressed"
@@ -41,7 +41,7 @@ if {![Term::enter_tui]} {
set line " return 0;"
set nr [gdb_get_line_number $line]
-set screen_line [Term::get_line_with_attrs 6]
+set screen_line [Term::get_string_with_attrs 6 11 79]
verbose -log "screen line 6: '$screen_line'"
-gdb_assert { [regexp "$nr <reverse:1>$line<reverse:0>" $screen_line] } \
+gdb_assert { [regexp "<reverse:1>$line<reverse:0>" $screen_line] } \
"highlighted line in middle of source window"
diff --git a/gdb/testsuite/gdb.tui/main.exp b/gdb/testsuite/gdb.tui/main.exp
index d6960c7..e49da35 100644
--- a/gdb/testsuite/gdb.tui/main.exp
+++ b/gdb/testsuite/gdb.tui/main.exp
@@ -43,7 +43,10 @@ if {![Term::enter_tui]} {
}
send_gdb "file [standard_output_file $testfile]\n"
-gdb_assert { [Term::wait_for "Reading symbols from"] } "file command"
+# Matching the output is difficult because it may or may not wrap. Simply
+# match the resulting prompt.
+gdb_assert { [Term::wait_for ""] } "file command"
+
Term::check_contents "show main after file" \
[string_to_regexp "|___[format %06d $nr]_$line"]
diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp
index f517997..6a4c68f 100644
--- a/gdb/testsuite/gdb.tui/new-layout.exp
+++ b/gdb/testsuite/gdb.tui/new-layout.exp
@@ -45,15 +45,12 @@ gdb_test "tui new-layout example src 1 src 1" \
gdb_test "tui new-layout example src 1" \
"New layout does not contain the \"cmd\" window"
-# Avoid unbalanced curly braces problems with tcl 8.5.
-if { [tcl_version_at_least 8 6] } {
- gdb_test "tui new-layout example src 1\}" \
- "Extra '\}' in layout specification"
- gdb_test "tui new-layout example {src 1} 1\}" \
- "Extra '\}' in layout specification"
- gdb_test "tui new-layout example \{src 1" \
- "Missing '\}' in layout specification"
-}
+gdb_test "tui new-layout example src 1\}" \
+ "Extra '\}' in layout specification"
+gdb_test "tui new-layout example {src 1} 1\}" \
+ "Extra '\}' in layout specification"
+gdb_test "tui new-layout example \{src 1" \
+ "Missing '\}' in layout specification"
# Each entry of this list describes a layout, and some associated
# tests. The items within each entry are:
@@ -84,7 +81,7 @@ set layouts \
proc check_boxes {boxes} {
set boxno 1
foreach box $boxes {
- eval Term::check_box [list "box $boxno"] $box
+ Term::check_box "box $boxno" {*}$box
incr boxno
}
}
@@ -150,4 +147,7 @@ Term::check_box "before cmd_only: src box in src layout" 0 0 80 15
Term::command "layout cmd_only"
Term::command "layout src"
+
+# Flush out and check the resulting src box.
+Term::command "print 1"
Term::check_box "after cmd_only: src box in src layout" 0 0 80 15
diff --git a/gdb/testsuite/gdb.tui/pr30056.exp b/gdb/testsuite/gdb.tui/pr30056.exp
index 1123593..dd3b25c 100644
--- a/gdb/testsuite/gdb.tui/pr30056.exp
+++ b/gdb/testsuite/gdb.tui/pr30056.exp
@@ -72,16 +72,15 @@ save_vars { env(LC_ALL) } {
# Send ^C to clear the command line.
send_gdb "\003"
} else {
- # Sending ^C currently doesn't abort the i-search. PR cli/30498 is
- # open about this.
- kfail cli/30498 $test
+ # Sending ^C currently doesn't abort the i-search.
+ fail $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/source-search.c b/gdb/testsuite/gdb.tui/source-search.c
new file mode 100644
index 0000000..2320c5c
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/source-search.c
@@ -0,0 +1,127 @@
+/* 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/>. */
+
+int
+main (void)
+{
+ /* Line 21 */
+ /* Line 22 */
+ /* Line 23 */
+ /* Line 24 */
+ /* Line 25 */
+ /* Line 26 */
+ /* Line 27 */
+ /* Line 28 */
+ /* Line 29 */
+ /* Line 30 */
+ /* Line 31 */
+ /* Line 32 */
+ /* Line 33 */
+ /* Line 34 */
+ /* Line 35 */
+ /* Line 36 */
+ /* Line 37 */
+ /* Line 38 */
+ /* Line 39 */
+ /* Line 40 */
+ /* Line 41 */
+ /* Line 42 */
+ /* Line 43 */
+ /* Line 44 */
+ /* Line 45 */
+ /* Line 46 */
+ /* Line 47 */
+ /* Line 48 */
+ /* Line 49 */
+ /* Line 50 */
+ /* Line 51 */
+ /* Line 52 */
+ /* Line 53 */
+ /* Line 54 */
+ /* Line 55 */
+ /* Line 56 */
+ /* Line 57 */
+ /* Line 58 */
+ /* Line 59 */
+ /* Line 60 */
+ /* Line 61 */
+ /* Line 62 */
+ /* Line 63 */
+ /* Line 64 */
+ /* Line 65 */
+ /* Line 66 */
+ /* Line 67 */
+ /* Line 68 */
+ /* Line 69 */
+ /* Line 70 */
+ /* Line 71 */
+ /* Line 72 */
+ /* Line 73 */
+ /* Line 74 */
+ /* Line 75 */
+ /* Line 76 */
+ /* Line 77 */
+ /* Line 78 */
+ /* Line 79 */
+ /* Line 80 */
+ /* Line 81 */
+ /* Line 82 */
+ /* Line 83 */
+ /* Line 84 */
+ /* Line 85 */
+ /* Line 86 */
+ /* Line 87 */
+ /* Line 88 */
+ /* Line 89 */
+ /* Line 90 */
+ /* Line 91 */
+ /* Line 92 */
+ /* Line 93 */
+ /* Line 94 */
+ /* Line 95 */
+ /* Line 96 */
+ /* Line 97 */
+ /* Line 98 */
+ /* Line 99 */
+ /* Line 100 */
+ /* Line 101 */
+ /* Line 102 */
+ /* Line 103 */
+ /* Line 104 */
+ /* Line 105 */
+ /* Line 106 */
+ /* Line 107 */
+ /* Line 108 */
+ /* Line 109 */
+ /* Line 110 */
+ /* Line 111 */
+ /* Line 112 */
+ /* Line 113 */
+ /* Line 114 */
+ /* Line 115 */
+ /* Line 116 */
+ /* Line 117 */
+ /* Line 118 */
+ /* Line 119 */
+ /* Line 120 */
+ /* Line 121 */
+ /* Line 122 */
+ /* Line 123 */
+ /* Line 124 */
+ /* Line 125 */
+ return 0;
+} /* Last line. */
diff --git a/gdb/testsuite/gdb.tui/source-search.exp b/gdb/testsuite/gdb.tui/source-search.exp
new file mode 100644
index 0000000..4fcdca3
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/source-search.exp
@@ -0,0 +1,72 @@
+# 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 forward-search and reverse-search within the TUI src window.
+
+tuiterm_env
+
+standard_testfile .c
+
+if {[build_executable "failed to build" ${testfile} ${srcfile}] == -1} {
+ return
+}
+
+Term::clean_restart 24 80 $testfile
+if {![Term::enter_tui]} {
+ unsupported "TUI not supported"
+ return
+}
+
+proc check_src_window { testname first_line } {
+ set last_line [expr {$first_line + 12}]
+ Term::check_box_contents $testname 0 0 80 15 \
+ "^\\s+${first_line}\\s+.*\\s+${last_line}\\s+/\\* Line ${last_line} \\*/\\s+$"
+
+}
+
+# Initialise the src window so that it is displaying known contents.
+# Check that the expected contents are displayed.
+Term::command "list 20"
+set first_line 15
+check_src_window "initial src contents" $first_line
+
+# Search forward. Searches are from the last line displayed, so this
+# will move the next source line onto the screen each time.
+for { set i 1 } { $i < 4 } { incr i } {
+ incr first_line
+ Term::command "forward-search Line"
+ check_src_window "src windows after forward-search $i" $first_line
+}
+
+# Reverse search. Like forward-search, but move backward through the
+# source.
+for { set i 1 } { $i < 3 } { incr i } {
+ incr first_line -1
+ Term::command "reverse-search Line"
+ check_src_window "src windows after reverse-search $i" $first_line
+}
+
+# Until there are no matching lines left.
+Term::command "reverse-search Line"
+gdb_assert {[regexp -- "^Expression not found\\s+$" [Term::get_line 22]]} \
+ "check start of source was reached"
+
+Term::command "forward-search Last line"
+Term::check_box_contents "forward-search to end of file" 0 0 80 15 \
+ "^\\s+122\\s+.*/\\* Last line\\. \\*/\\s+$"
+
+Term::command "reverse-search This testcase is part"
+Term::check_box_contents "reverse-search to start of file" 0 0 80 15 \
+ "^\\s+1\\s+.*\\s+13\\s+GNU General Public License for more details\\.\\s+$"
diff --git a/gdb/testsuite/gdb.tui/tui-disasm-long-lines.exp b/gdb/testsuite/gdb.tui/tui-disasm-long-lines.exp
index 35f990d..7a9841f 100644
--- a/gdb/testsuite/gdb.tui/tui-disasm-long-lines.exp
+++ b/gdb/testsuite/gdb.tui/tui-disasm-long-lines.exp
@@ -35,7 +35,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "$binfile" \
}
}
-Term::clean_restart 24 80 $binfile
+Term::clean_restart 24 80 $testfile
if {![Term::prepare_for_tui]} {
unsupported "TUI not supported"
return
diff --git a/gdb/testsuite/gdb.tui/tui-disasm-styling.exp b/gdb/testsuite/gdb.tui/tui-disasm-styling.exp
index 513d787..6859744 100644
--- a/gdb/testsuite/gdb.tui/tui-disasm-styling.exp
+++ b/gdb/testsuite/gdb.tui/tui-disasm-styling.exp
@@ -37,12 +37,15 @@ proc check_asm_output { expect_styled testname } {
$testname
}
-Term::clean_restart 24 80 $binfile
+Term::clean_restart 24 80 $testfile
if {![Term::enter_tui]} {
unsupported "TUI not supported"
return
}
+# Proc enter_tui switches off styling, re-enable it.
+Term::command "set style enabled on"
+
Term::command "layout asm"
Term::check_box "asm box" 0 0 80 15
diff --git a/gdb/testsuite/gdb.tui/tui-focus.exp b/gdb/testsuite/gdb.tui/tui-focus.exp
index 4c9d2a0..50a3315 100644
--- a/gdb/testsuite/gdb.tui/tui-focus.exp
+++ b/gdb/testsuite/gdb.tui/tui-focus.exp
@@ -36,7 +36,7 @@ foreach spec {{src true} {cmd true} {status true} {regs false} \
lassign $spec window valid_p
with_test_prefix "window=$window" {
- Term::clean_restart 24 80 $binfile
+ Term::clean_restart 24 80 $testfile
if {![Term::prepare_for_tui]} {
unsupported "TUI not supported"
return
@@ -73,9 +73,9 @@ 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
+Term::clean_restart 24 80 $testfile
if {[allow_python_tests]} {
# Create a very simple tui window.
gdb_py_test_silent_cmd \
diff --git a/gdb/testsuite/gdb.tui/tui-layout-asm-short-prog.exp b/gdb/testsuite/gdb.tui/tui-layout-asm-short-prog.exp
index 51623e8..47482a2 100644
--- a/gdb/testsuite/gdb.tui/tui-layout-asm-short-prog.exp
+++ b/gdb/testsuite/gdb.tui/tui-layout-asm-short-prog.exp
@@ -20,9 +20,13 @@ tuiterm_env
standard_testfile tui-layout-asm-short-prog.S
-if {[build_executable "failed to prepare" ${testfile} ${srcfile} \
- {debug additional_flags=-nostdlib \
- additional_flags=-nostartfiles}] == -1} {
+set opts {}
+lappend opts debug
+lappend opts additional_flags=-static
+lappend opts additional_flags=-nostdlib
+lappend opts additional_flags=-nostartfiles
+
+if { [build_executable "failed to prepare" $testfile $srcfile $opts] == -1 } {
return -1
}
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.tui/tui-layout.exp b/gdb/testsuite/gdb.tui/tui-layout.exp
index 7bb0ea1..f604871 100644
--- a/gdb/testsuite/gdb.tui/tui-layout.exp
+++ b/gdb/testsuite/gdb.tui/tui-layout.exp
@@ -40,7 +40,7 @@ if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
# happens to be in after a call to clean_restart.
proc test_layout_or_focus {layout_name terminal execution} {
- global binfile gdb_prompt
+ global gdb_prompt
set dumb_terminal [string equal $terminal "dumb"]
@@ -48,9 +48,9 @@ proc test_layout_or_focus {layout_name terminal execution} {
save_vars { env(TERM) } {
setenv TERM $terminal
if {$dumb_terminal} {
- clean_restart $binfile
+ clean_restart $::testfile
} else {
- Term::clean_restart 24 80 $binfile
+ Term::clean_restart 24 80 $::testfile
if {![Term::prepare_for_tui]} {
unsupported "TUI not supported"
return
diff --git a/gdb/testsuite/gdb.tui/tui-missing-src.exp b/gdb/testsuite/gdb.tui/tui-missing-src.exp
index f29ec8c..aca417c 100644
--- a/gdb/testsuite/gdb.tui/tui-missing-src.exp
+++ b/gdb/testsuite/gdb.tui/tui-missing-src.exp
@@ -64,10 +64,8 @@ f2 (int x)
close $fd
# Step 3: Compile the source files.
-if { [gdb_compile "${srcfiles}" "${binfile}" \
- executable {debug additional_flags=-O0}] != "" } {
- untested "failed to compile"
- return -1
+if { [build_executable "failed to prepare" $testfile $srcfiles] == -1 } {
+ return
}
# Step 4: Remove the main.c file.
diff --git a/gdb/testsuite/gdb.tui/tui-mode-switch.exp b/gdb/testsuite/gdb.tui/tui-mode-switch.exp
new file mode 100644
index 0000000..c605962
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/tui-mode-switch.exp
@@ -0,0 +1,57 @@
+require allow_tui_tests
+
+tuiterm_env
+
+if { [ishost *-*-*bsd*] } {
+ # We need support for alternate screen, and xterm doesn't have it.
+ set term xterm-clear
+} else {
+ set term xterm
+}
+
+Term::with_term $term {
+ Term::clean_restart 12 40
+}
+
+if {![Term::prepare_for_tui]} {
+ unsupported "TUI not supported"
+ return 0
+}
+
+# Generate prompt.
+Term::gen_prompt
+
+# Move to last line.
+for { set i 1 } { $i <= 11 } { incr i } {
+ send_gdb "\n"
+ Term::wait_for ""
+}
+
+# Type "foo".
+send_gdb "foo"
+set line { 0 11 40 1 }
+gdb_assert { [Term::wait_for_region_contents {*}$line "^$gdb_prompt foo"] } \
+ "type foo"
+
+# Enter TUI.
+send_gdb "\030\001"
+gdb_assert { [Term::wait_for ""] } "enter TUI"
+
+# Exit TUI.
+send_gdb "\030\001"
+gdb_assert { [Term::wait_for ""] } "exit TUI"
+
+# Type b.
+send_gdb "b"
+gdb_assert { [Term::wait_for_region_contents {*}$line "^$gdb_prompt b"] } \
+ "type b"
+
+# Check that we don't see "boo".
+gdb_assert { ![Term::check_region_contents_p {*}$line "^$gdb_prompt boo"] } \
+ "no boo"
+Term::dump_screen
+
+# We need an empty prompt here, to deal with the "monitor exit" that
+# native-extended-gdbserver will send. Send a backspace.
+send_gdb "\010"
+Term::wait_for ""
diff --git a/gdb/testsuite/gdb.tui/tuiterm-2.exp b/gdb/testsuite/gdb.tui/tuiterm-2.exp
index 5992271..a451834 100644
--- a/gdb/testsuite/gdb.tui/tuiterm-2.exp
+++ b/gdb/testsuite/gdb.tui/tuiterm-2.exp
@@ -106,6 +106,76 @@ with_override Term::accept_gdb_output test_accept_gdb_output {
}
gdb_assert { [Term::wait_for ""] }
}
+
+ with_test_prefix "Term::wait_for 2" {
+ Term::_setup 4 20
+ set send_cnt 0
+ set expect_send {}
+ set action_cnt 0
+ set actions {
+ {
+ Term::_move_cursor 0 0
+
+ Term::_insert "${::border}(gdb) "
+ set pos $Term::_cur_col
+
+ Term::_insert "foo"
+
+ Term::_move_cursor 19 0
+ Term::_insert "$::border"
+
+ Term::_move_cursor $pos 0
+ }
+ {
+ Term::_move_cursor 0 1
+
+ Term::_insert "${::border}(gdb) "
+ set pos $Term::_cur_col
+
+ Term::_move_cursor 19 1
+ Term::_insert "$::border"
+
+ Term::_move_cursor $pos 1
+ }
+ }
+
+ # Wait for a prompt.
+ gdb_assert { [Term::wait_for ""] }
+
+ # The first action sets the cursor after the prompt on the
+ # first line. The second action sets the cursor after the
+ # prompt on the second line. Check that wait_for returns
+ # after the second action, not the first.
+ gdb_assert { $Term::_cur_row == 1 }
+ }
}
}
}
+
+with_test_prefix "Unrecognized escape sequence" {
+ spawn $srcdir/$subdir/gdb.tcl
+ switch_gdb_spawn_id $spawn_id
+
+ Term::_setup 4 20
+
+ save_vars timeout {
+ set timeout 1
+
+ set line { 0 0 20 1 }
+
+ # Parse "foo".
+ gdb_assert { [Term::wait_for_region_contents \
+ {*}$line \
+ [string_to_regexp "foo"]] } \
+ "foo"
+
+ # Parse "\033(%5".
+ gdb_assert { ![Term::accept_gdb_output 0] } \
+ "fail to parse escape sequence"
+ gdb_assert { [Term::wait_for_region_contents \
+ {*}$line \
+ [string_to_regexp "^\[(%5"]] } \
+ "echoed escape sequence"
+ }
+ Term::dump_screen
+}
diff --git a/gdb/testsuite/gdb.tui/tuiterm.exp b/gdb/testsuite/gdb.tui/tuiterm.exp
index 9dc2402..ed9478a 100644
--- a/gdb/testsuite/gdb.tui/tuiterm.exp
+++ b/gdb/testsuite/gdb.tui/tuiterm.exp
@@ -102,7 +102,7 @@ proc test_backspace {} {
Term::_move_cursor 1 2
- Term::_ctl_0x08
+ Term::_ctl_0x08 0
check "backspace one" {
"abcdefgh"
"ijklmnop"
@@ -111,13 +111,22 @@ proc test_backspace {} {
} 0 2
# Cursor should not move if it is already at column 0.
- Term::_ctl_0x08
+ Term::_ctl_0x08 0
check "backspace 2" {
"abcdefgh"
"ijklmnop"
"qrstuvwx"
"yz01234 "
} 0 2
+
+ # Cursor should wrap to previous line.
+ Term::_ctl_0x08 1
+ check "backspace 3" {
+ "abcdefgh"
+ "ijklmnop"
+ "qrstuvwx"
+ "yz01234 "
+ } 7 1
}
proc test_linefeed { } {
@@ -435,6 +444,30 @@ proc test_horizontal_absolute { } {
"qrstuvwx"
"yz01234 "
} 3 2
+
+ Term::_csi_G 8
+ check "cursor horizontal absolute 3" {
+ "abcdefgh"
+ "ijklmnop"
+ "qrstuvwx"
+ "yz01234 "
+ } 7 2
+
+ Term::_csi_G 9
+ check "cursor horizontal absolute 4" {
+ "abcdefgh"
+ "ijklmnop"
+ "qrstuvwx"
+ "yz01234 "
+ } 7 2
+
+ Term::_csi_`
+ check "horizontal position absolute 1" {
+ "abcdefgh"
+ "ijklmnop"
+ "qrstuvwx"
+ "yz01234 "
+ } 0 2
}
proc test_cursor_position { } {
@@ -620,13 +653,21 @@ proc test_cursor_backward_tabulation { } {
}
proc test_repeat { } {
- Term::_move_cursor 2 1
- set Term::_last_char X
+ Term::_move_cursor 0 1
- Term::_csi_b 3
+ Term::_insert "xxX"
+ gdb_assert { $Term::_last_char == "X" }
+ check "insert" {
+ "abcdefgh"
+ "xxXlmnop"
+ "qrstuvwx"
+ "yz01234 "
+ } 3 1
+
+ Term::_csi_b 2
check "repeat" {
"abcdefgh"
- "ijXXXnop"
+ "xxXXXnop"
"qrstuvwx"
"yz01234 "
} 5 1
@@ -750,6 +791,15 @@ proc test_attrs {} {
set line [Term::get_line_with_attrs 0]
gdb_assert { [regexp $re $line] } "attribute: $attr"
}
+
+ # Regression test: Check that _csi_m works without arguments.
+ setup_terminal 4 1
+ Term::_csi_m 7
+ Term::_insert "a"
+ Term::_csi_m
+ Term::_insert "a"
+ set line [Term::get_line_with_attrs 0]
+ gdb_assert { [string equal $line "<reverse:1>a<reverse:0>a "] }
}
# Run proc TEST_PROC_NAME with a "small" terminal.
diff --git a/gdb/testsuite/gdb.tui/wrap-line.exp b/gdb/testsuite/gdb.tui/wrap-line.exp
index aa2b1c6..a1ba706 100644
--- a/gdb/testsuite/gdb.tui/wrap-line.exp
+++ b/gdb/testsuite/gdb.tui/wrap-line.exp
@@ -37,11 +37,11 @@ proc fill_line { width } {
# Take into account that the prompt also takes space.
set prefix [string length "(gdb) "]
- set start [expr $prefix + 1]
+ set start [expr {$prefix + 1}]
# Print chars.
for { set i $start } { $i <= $width } { incr i } {
- set c [expr $i % 10]
+ set c [expr {$i % 10}]
send_gdb $c
append res $c
}
@@ -59,7 +59,7 @@ proc test_wrap { wrap_width tui } {
set str [fill_line $wrap_width]
# Remaining space on line.
- set space [string repeat " " [expr $::cols - $wrap_width]]
+ set space [string repeat " " [expr {$::cols - $wrap_width}]]
# Now print the first char we expect to wrap.
send_gdb "W"
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/ada.exp b/gdb/testsuite/lib/ada.exp
index 37bed85..50067eb 100644
--- a/gdb/testsuite/lib/ada.exp
+++ b/gdb/testsuite/lib/ada.exp
@@ -220,7 +220,8 @@ proc gnat_runtime_has_debug_info_1 { shared } {
return 0
}
- clean_restart $dst
+ clean_restart
+ gdb_load $dst
if { ! [runto "GNAT_Debug_Info_Test"] } {
return 0
diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index 7e8778a..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\""
@@ -3385,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/future.exp b/gdb/testsuite/lib/future.exp
index 161c31c..6643187 100644
--- a/gdb/testsuite/lib/future.exp
+++ b/gdb/testsuite/lib/future.exp
@@ -749,19 +749,6 @@ if { [array size use_gdb_compile] != 0 } {
rename gdb_default_target_compile ""
}
-
-# Provide 'lreverse' missing in Tcl before 7.5.
-
-if {[info procs lreverse] == ""} {
- proc lreverse { arg } {
- set retval {}
- while { [llength $retval] < [llength $arg] } {
- lappend retval [lindex $arg end-[llength $retval]]
- }
- return $retval
- }
-}
-
# Various ccache versions provide incorrect debug info such as ignoring
# different current directory, breaking GDB testsuite.
set env(CCACHE_DISABLE) 1
diff --git a/gdb/testsuite/lib/gdb-utils.exp b/gdb/testsuite/lib/gdb-utils.exp
index fe2cfca..c24e7ed 100644
--- a/gdb/testsuite/lib/gdb-utils.exp
+++ b/gdb/testsuite/lib/gdb-utils.exp
@@ -70,6 +70,8 @@ proc style {str style} {
set fg 39
set bg 49
set intensity 22
+ set italic 23
+ set underline 24
set reverse 27
switch -exact -- $style {
title { set intensity 1 }
@@ -84,7 +86,7 @@ proc style {str style} {
line-number { set intensity 2 }
none { return $str }
}
- return "\033\\\[${fg};${bg};${intensity};${reverse}m${str}\033\\\[m"
+ return "\033\\\[${fg};${bg};${intensity};${italic};${underline};${reverse}m${str}\033\\\[m"
}
# gdb_get_bp_addr num
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index ead14bd..930462f 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -15,6 +15,8 @@
# This file was written by Fred Fish. (fnf@cygnus.com)
+package require Tcl 8.6.2
+
# Generic gdb subroutines that should work for any target. If these
# need to be modified for any target, it can be done with a variable
# or by passing arguments.
@@ -269,6 +271,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.
@@ -280,10 +289,13 @@ if {![info exists gdb_prompt]} {
set gdb_prompt "\\(gdb\\)"
}
-# A regexp that matches the pagination prompt.
-set pagination_prompt \
+# The pagination prompt.
+set pagination_prompt_str \
"--Type <RET> for more, q to quit, c to continue without paging--"
+# A regexp that matches the pagination prompt.
+set pagination_prompt [string_to_regexp $pagination_prompt_str]
+
# The variable fullname_syntax_POSIX is a regexp which matches a POSIX
# absolute path ie. /foo/
set fullname_syntax_POSIX {/[^\n]*/}
@@ -1026,7 +1038,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 +1139,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 +1149,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 +1408,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"
}
@@ -1663,76 +1680,9 @@ proc python_version_at_least { major minor } {
# Return 1 if tcl version used is at least MAJOR.MINOR.PATCHLEVEL.
proc tcl_version_at_least { major minor {patchlevel 0} } {
- global tcl_patchLevel
- regexp {^([0-9]+)\.([0-9]+)\.([0-9]+)$} \
- $tcl_patchLevel dummy \
- tcl_version_major tcl_version_minor tcl_version_patchlevel
- return \
- [version_compare \
- [list \
- $major \
- $minor \
- $patchlevel] \
- <= \
- [list \
- $tcl_version_major \
- $tcl_version_minor \
- $tcl_version_patchlevel]]
-}
-
-if { [tcl_version_at_least 8 5] == 0 } {
- # lrepeat was added in tcl 8.5. Only add if missing.
- proc lrepeat { n element } {
- if { [string is integer -strict $n] == 0 } {
- error "expected integer but got \"$n\""
- }
- if { $n < 0 } {
- error "bad count \"$n\": must be integer >= 0"
- }
- set res [list]
- for {set i 0} {$i < $n} {incr i} {
- lappend res $element
- }
- return $res
- }
-}
-
-if { [tcl_version_at_least 8 6] == 0 } {
- # lmap was added in tcl 8.6. Only add if missing.
-
- # Note that we only implement the simple variant for now.
- proc lmap { varname list body } {
- set res {}
- foreach val $list {
- uplevel 1 "set $varname $val"
- lappend res [uplevel 1 $body]
- }
-
- return $res
- }
-
- # ::tcl_platform(pathSeparator) was added in 8.6.
- switch $::tcl_platform(platform) {
- windows {
- set ::tcl_platform(pathSeparator) ;
- }
- default {
- set ::tcl_platform(pathSeparator) :
- }
- }
-}
-
-if { [tcl_version_at_least 8 6 2] == 0 } {
- # string cat was added in tcl 8.6.2. Only add if missing.
-
- rename string tcl_proc_string
-
- proc string { what args } {
- if { $what == "cat" } {
- return [join $args ""]
- }
- return [tcl_proc_string $what {*}$args]
- }
+ set current_version [package require Tcl]
+ set min_version "$major.$minor.$patchlevel"
+ return [expr {[package vcompare $current_version $min_version] >= 0}]
}
# gdb_test_no_output [-prompt PROMPT_REGEXP] [-nopass] COMMAND [MESSAGE]
@@ -2237,6 +2187,209 @@ proc gdb_assert { condition {message ""} } {
return $res
}
+# Comparison command for "lsort -command". Sorts two strings by
+# descending file name length.
+
+proc compare_length_desc {a b} {
+ expr {[string length $b] - [string length $a]}
+}
+
+# Fill in and return the global cache for Windows <=> Unix mount point
+# mappings, for Windows.
+#
+# Calling external processes on MSYS2/Cygwin is expensive so instead
+# of calling "cygpath -ua $FILENAME" or "cygpath -ma $FILENAME" for
+# every file name, we extract the Windows and Unix file names of each
+# mount point using the 'mount' command output, and cache the
+# mappings, for both directions.
+
+gdb_caching_proc get_mount_point_map {} {
+ array set win_to_unix {}
+ array set unix_to_win {}
+
+ # The 'mount' command provides all mappings. The general format
+ # is: 'WindowsFileName on UnixFileName type ...'
+ #
+ # For example:
+ # 'C:/msys64 on / type ntfs (binary,auto)'
+ # 'C: on /c type ntfs (binary,posix=0,user,noumount,auto)'
+ set mount_output [exec mount]
+
+ foreach line [split $mount_output \n] {
+ if {[regexp {^(.+) on (.+) type } $line -> win_filename unix_filename]} {
+ set win_to_unix($win_filename) $unix_filename
+ set unix_to_win($unix_filename) $win_filename
+ }
+ }
+
+ # Sort each mapping's keys by descending file name length,
+ # otherwise we wouldn't be able to look for '/foo' in '/' (for
+ # example).
+
+ set sorted_win {}
+ foreach k [lsort -command compare_length_desc [array names win_to_unix]] {
+ lappend sorted_win $k $win_to_unix($k)
+ }
+
+ set sorted_unix {}
+ foreach k [lsort -command compare_length_desc [array names unix_to_win]] {
+ lappend sorted_unix $k $unix_to_win($k)
+ }
+
+ # Return both sorted lists: {win => unix} {unix => win}
+ return [list $sorted_win $sorted_unix]
+}
+
+# Normalize backward slashes to forward slashes.
+
+proc normalize_slashes {filename} {
+ return [string map {\\ /} $filename]
+}
+
+# Sanitize a host file name, without making it absolute or resolving
+# symlinks. On native Windows, this normalizes slashes to forward
+# slashes, and makes sure that if the file name starts with a drive
+# letter, it is upper case. On other systems, it just returns the
+# file name unmodified.
+
+proc host_file_sanitize {filename} {
+ if {[ishost *-*-mingw*]} {
+ set filename [normalize_slashes $filename]
+
+ # If the file name starts with a drive letter, uppercase it.
+ if {[regexp {^([a-zA-Z]):(/.*)?} $filename -> drive rest]} {
+ set filename "[string toupper $drive]:$rest"
+ }
+ }
+
+ return $filename
+}
+
+# Normalize a file name for the build machine. If running native
+# Windows GDB, this converts a Windows file name to the corresponding
+# Unix filename, per the mount table. For example, this replaces
+# 'c:/foo' with '/c/foo' (on MSYS2) or '/cygdrive/c/foo' (on Cygwin).
+# On other systems, it just wraps "file normalize".
+
+proc build_file_normalize {filename} {
+ if {[ishost *-*-mingw*]} {
+ set filename [host_file_sanitize $filename]
+
+ # Handle Windows => Unix mount point conversion. We assume
+ # there are no symlinks to resolve, which is a reasonable
+ # assumption for native Windows testing.
+
+ # Get Windows => Unix map.
+ lassign [get_mount_point_map] win_to_unix _
+
+ foreach {win_filename unix_filename} $win_to_unix {
+ if {[string equal -length [string length $win_filename] \
+ $win_filename $filename]} {
+ set rest [string range $filename \
+ [string length $win_filename] end]
+ return "${unix_filename}$rest"
+ }
+ }
+ }
+
+ return [file normalize $filename]
+}
+
+# Normalize a file name for the host machine and native Windows GDB.
+# This converts a Unix file name to a Windows filename,
+# per the mount table. E.g., '/c/foo' (on MSYS2) or '/cygdrive/c/foo'
+# (on Cygwin) is converted to 'c:/foo'.
+
+proc host_file_normalize_mingw {filename unix_to_win} {
+ set filename [host_file_sanitize $filename]
+
+ # If the file name already starts with a drive letter (e.g.,
+ # C:/foo), we're done. Don't let it fallthrough to "file
+ # normalize", which would misinterpret it as a relative file
+ # name.
+ if {[regexp {^[A-Z]:/} $filename]} {
+ return $filename
+ }
+
+ # Collapse all repeated forward slashes.
+ set filename [regsub -all {//+} $filename {/}]
+
+ # Strip trailing slash, except for root.
+ if {$filename ne "/" && [string match */ $filename]} {
+ set filename [string range $filename 0 end-1]
+ }
+
+ foreach {unix_filename win_filename} $unix_to_win {
+ set mount_len [string length $unix_filename]
+ if {[string equal -length $mount_len $unix_filename $filename]} {
+ if {$unix_filename eq "/"} {
+ if {$filename eq "/"} {
+ return "$win_filename"
+ } else {
+ return "$win_filename$filename"
+ }
+ } elseif {[string length $filename] == $mount_len} {
+ # Like "cygpath -ma" if the file name resolves to a
+ # drive letter, append a slash, to make it unambiguous
+ # that we resolved to the root of the drive and not
+ # the drive's current directory.
+ if {[string match {[A-Za-z]:} $win_filename]} {
+ return "$win_filename/"
+ } else {
+ return "$win_filename"
+ }
+ } elseif {[string index $filename $mount_len] eq "/"} {
+ set rest [string range $filename $mount_len end]
+ return "$win_filename$rest"
+ }
+ }
+ }
+
+ return [file normalize $filename]
+}
+
+# Normalize a file name for the host machine. If running native
+# Windows GDB, this converts a Unix file name to a Windows filename,
+# per the mount table. E.g., '/c/foo' (on MSYS2) or '/cygdrive/c/foo'
+# (on Cygwin) is converted to 'c:/foo'.
+
+proc host_file_normalize {filename} {
+ if {[ishost *-*-mingw*]} {
+ # Get Unix => Windows map.
+ lassign [get_mount_point_map] _ unix_to_win
+ return [host_file_normalize_mingw $filename $unix_to_win]
+ }
+
+ return [file normalize $filename]
+}
+
+# Wrapper around "file join" that handles host-specific details.
+#
+# For Cygwin/MSYS2's Tcl, file names that start with a drive letter
+# are not considered absolute file names, thus 'file join "c:/" "d:/"'
+# returns "c:/d:". This procedure thus detects absolute Windows-style
+# file names, and treats them as absolute, bypassing "file join".
+
+proc host_file_join {args} {
+ if {[isbuild *-*-mingw*]} {
+ set result ""
+ foreach filename $args {
+ set filename [host_file_sanitize $filename]
+
+ # If the file name starts with drive letter and colon
+ # (e.g., "C:/"), treat it as absolute.
+ if {[regexp {^[A-Z]:/} $filename]} {
+ set result $filename
+ } else {
+ set result [file join $result $filename]
+ }
+ }
+ return $result
+ } else {
+ return [file join {*}$args]
+ }
+}
+
proc gdb_reinitialize_dir { subdir } {
global gdb_prompt
@@ -2251,7 +2404,8 @@ proc gdb_reinitialize_dir { subdir } {
}
gdb_expect 60 {
-re "Source directories searched.*$gdb_prompt $" {
- send_gdb "dir $subdir\n"
+ set dir [host_file_normalize $subdir]
+ send_gdb "dir $dir\n"
gdb_expect 60 {
-re "Source directories searched.*$gdb_prompt $" {
verbose "Dir set to $subdir"
@@ -2301,7 +2455,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 +2469,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 +2734,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
@@ -2823,11 +2991,6 @@ gdb_caching_proc allow_dap_tests {} {
return 0
}
- # ton.tcl uses "string is entier", supported starting tcl 8.6.
- if { ![tcl_version_at_least 8 6] } {
- return 0
- }
-
# With set auto-connect-native-target off, we run into:
# +++ run
# Traceback (most recent call last):
@@ -4265,6 +4428,76 @@ gdb_caching_proc allow_tsx_tests {} {
return $allow_tsx_tests
}
+# Run a test on the target to check if it supports x86 shadow stack. Return 1
+# if shadow stack is enabled, 0 otherwise.
+
+gdb_caching_proc allow_ssp_tests {} {
+ global srcdir subdir gdb_prompt hex
+
+ set me "allow_ssp_tests"
+
+ if { ![istarget i?86-*-*] && ![istarget x86_64-*-* ] } {
+ verbose "$me: target known to not support shadow stack."
+ return 0
+ }
+
+ # There is no need to check the actual HW in addition to ptrace support.
+ # We need both checks and ptrace will tell us about the HW state.
+ set compile_flags "{additional_flags=-fcf-protection=return}"
+ set src { int main() { return 0; } }
+ if {![gdb_simple_compile $me $src executable $compile_flags]} {
+ return 0
+ }
+
+ save_vars { ::env(GLIBC_TUNABLES) } {
+
+ append_environment GLIBC_TUNABLES "glibc.cpu.hwcaps" "SHSTK"
+
+ # No error message, compilation succeeded so now run it via gdb.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $obj
+ if {![runto_main]} {
+ remote_file build delete $obj
+ return 0
+ }
+ set shadow_stack_disabled_re "(<unavailable>)"
+ if {[istarget *-*-linux*]} {
+ # Starting with v6.6, the Linux kernel supports CET shadow stack.
+ # Dependent on the target we can see a nullptr or "<unavailable>"
+ # when shadow stack is supported by HW and the Linux kernel but
+ # not enabled for the current thread (for example due to a lack
+ # of compiler or glibc support for -fcf-protection).
+ set shadow_stack_disabled_re "$shadow_stack_disabled_re|(.*0x0)"
+ }
+
+ set allow_ssp_tests 0
+ gdb_test_multiple "print \$pl3_ssp" "test shadow stack support" {
+ -re -wrap "(.*$hex)((?!(.*0x0)).)" {
+ verbose -log "$me: Shadow stack support detected."
+ set allow_ssp_tests 1
+ }
+ -re -wrap $shadow_stack_disabled_re {
+ # In case shadow stack is not enabled (for example due to a
+ # lack of compiler or glibc support for -fcf-protection).
+ verbose -log "$me: Shadow stack is not enabled."
+ }
+ -re -wrap "void" {
+ # In case we don't have hardware or kernel support.
+ verbose -log "$me: No shadow stack support."
+ }
+ }
+
+ gdb_exit
+ }
+
+ remote_file build delete $obj
+
+ verbose "$me: returning $allow_ssp_tests" 2
+ return $allow_ssp_tests
+}
+
# Run a test on the target to see if it supports avx512bf16. Return 1 if so,
# 0 if it does not. Based on 'check_vmx_hw_available' from the GCC testsuite.
@@ -4407,7 +4640,8 @@ gdb_caching_proc allow_lam_tests {} {
# No error message, compilation succeeded so now run it via gdb.
set allow_lam_tests 0
- clean_restart $obj
+ clean_restart
+ gdb_load $obj
gdb_run_cmd
gdb_expect {
-re ".*$inferior_exited_re with code.*${gdb_prompt} $" {
@@ -4690,7 +4924,8 @@ gdb_caching_proc allow_aarch64_sve_tests {} {
}
# Compilation succeeded so now run it via gdb.
- clean_restart $obj
+ clean_restart
+ gdb_load $obj
gdb_run_cmd
gdb_expect {
-re ".*Illegal instruction.*${gdb_prompt} $" {
@@ -4750,7 +4985,8 @@ gdb_caching_proc aarch64_initialize_sve_information { } {
return [array get supported_vl]
}
- clean_restart $test_exec
+ clean_restart
+ gdb_load $test_exec
if {![runto_main]} {
return [array get supported_vl]
@@ -4847,7 +5083,8 @@ gdb_caching_proc allow_aarch64_sme_tests {} {
}
# Compilation succeeded so now run it via gdb.
- clean_restart $obj
+ clean_restart
+ gdb_load $obj
gdb_run_cmd
gdb_expect {
-re ".*Illegal instruction.*${gdb_prompt} $" {
@@ -4907,7 +5144,8 @@ gdb_caching_proc aarch64_initialize_sme_information { } {
return [array get supported_svl]
}
- clean_restart $test_exec
+ clean_restart
+ gdb_load $test_exec
if {![runto_main]} {
return [array get supported_svl]
@@ -5001,7 +5239,8 @@ gdb_caching_proc allow_aarch64_mops_tests {} {
}
# Compilation succeeded so now run it via gdb.
- clean_restart $obj
+ clean_restart
+ gdb_load $obj
gdb_run_cmd
gdb_expect {
-re ".*$inferior_exited_re with code 01.*${gdb_prompt} $" {
@@ -5024,6 +5263,61 @@ gdb_caching_proc allow_aarch64_mops_tests {} {
return $allow_mops_tests
}
+# Run a test on the target to see if it supports AArch64 GCS extensions.
+# Return 1 if so, 0 if it does not. Note this causes a restart of GDB.
+
+gdb_caching_proc allow_aarch64_gcs_tests {} {
+ global srcdir subdir gdb_prompt inferior_exited_re
+
+ set me "allow_aarch64_gcs_tests"
+
+ if { ![is_aarch64_target]} {
+ return 0
+ }
+
+ # Compile a program that tests the GCS feature.
+ set src {
+ #include <stdbool.h>
+ #include <sys/auxv.h>
+
+ /* Feature check for Guarded Control Stack. */
+ #ifndef HWCAP_GCS
+ #define HWCAP_GCS (1ULL << 32)
+ #endif
+
+ int main (void) {
+ bool gcs_supported = getauxval (AT_HWCAP) & HWCAP_GCS;
+
+ /* Return success if GCS is supported. */
+ return !gcs_supported;
+ }
+ }
+
+ if {![gdb_simple_compile $me $src executable]} {
+ return 0
+ }
+
+ # Compilation succeeded so now run it via gdb.
+ set allow_gcs_tests 0
+ clean_restart
+ gdb_load $obj
+ gdb_run_cmd
+ gdb_expect {
+ -re ".*$inferior_exited_re normally.*${gdb_prompt} $" {
+ verbose -log "\n$me: gcs support detected"
+ set allow_gcs_tests 1
+ }
+ -re ".*$inferior_exited_re with code 01.*${gdb_prompt} $" {
+ verbose -log "\n$me: gcs support not detected"
+ }
+ }
+ gdb_exit
+ remote_file build delete $obj
+
+ verbose "$me: returning $allow_gcs_tests" 2
+ return $allow_gcs_tests
+}
+
# A helper that compiles a test case to see if __int128 is supported.
proc gdb_int128_helper {lang} {
return [gdb_can_simple_compile "i128-for-$lang" {
@@ -5087,6 +5381,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 {} {
@@ -5666,6 +5994,10 @@ proc gdb_simple_compile {name code {type object} {compile_flags {}} {object obj}
set ext "d"
break
}
+ if { "$flag" eq "rust" } {
+ set ext "rs"
+ break
+ }
}
set src [standard_temp_file $name.$ext]
set obj [standard_temp_file $name.$postfix]
@@ -6244,6 +6576,9 @@ proc gdb_compile {source dest type options} {
}
}
+ # Automatically handle includes in testsuite/lib/.
+ auto_lappend_include_files options $source
+
cond_wrap [expr $pie != -1 || $nopie != -1] \
with_PIE_multilib_flags_filtered {
set result [target_compile $source $dest $type $options]
@@ -6779,7 +7114,20 @@ gdb_caching_proc can_spawn_for_attach {} {
set me "can_spawn_for_attach"
set src {
- #include <unistd.h>
+ #ifdef _WIN32
+ # include <windows.h>
+ #else
+ # include <unistd.h>
+ #endif
+
+ #ifdef _WIN32
+ unsigned
+ sleep (unsigned seconds)
+ {
+ Sleep (seconds * 1000);
+ return 0;
+ }
+ #endif
int
main (void)
@@ -6920,7 +7268,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; }" ]
@@ -7007,6 +7355,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
@@ -7372,13 +7738,13 @@ proc clean_standard_output_dir {} {
}
# Directory containing the standard output files.
- set standard_output_dir [file normalize [standard_output_file ""]]
+ set standard_output_dir [build_standard_output_file ""]
# Ensure that standard_output_dir is clean, or only contains
# gdb.log / gdb.sum.
set log_file_info [split [log_file -info]]
set log_file [file normalize [lindex $log_file_info end]]
- if { $log_file == [file normalize [standard_output_file gdb.log]] } {
+ if { $log_file == [file normalize [build_standard_output_file gdb.log]] } {
# Dir already contains active gdb.log. Don't remove the dir, but
# check that it's clean otherwise.
set res [glob -directory $standard_output_dir -tails *]
@@ -7471,6 +7837,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
@@ -7617,22 +7999,39 @@ proc make_gdb_parallel_path { args } {
}
# Turn BASENAME into a full file name in the standard output
-# directory. It is ok if BASENAME is the empty string; in this case
-# the directory is returned.
+# directory, as seen from the build machine. I.e., as seen from the
+# system driving DejaGnu. (E.g., if DejaGnu is being driven by MSYS2
+# to test native Windows GDB, the "build" file names should be file
+# names TCL understands, i.e., Unix file names.) It is OK if BASENAME
+# is the empty string; in this case the directory is returned.
-proc standard_output_file {basename} {
+proc build_standard_output_file {basename} {
global objdir subdir gdb_test_file_name
set dir [make_gdb_parallel_path outputs $subdir $gdb_test_file_name]
file mkdir $dir
- # If running on MinGW, replace /c/foo with c:/foo
- if { [ishost *-*-mingw*] } {
- set dir [exec sh -c "cd ${dir} && pwd -W"]
- }
return [file join $dir $basename]
}
-# Turn BASENAME into a file name on host.
+# Turn BASENAME into a full file name in the standard output
+# directory, as seen from a non-remote host. I.e., assuming the build
+# and the host share the filesystem. E.g., if DejaGnu is being driven
+# by MSYS2 to test native Windows GDB, the "host" file names should be
+# file names GDB understands, i.e., Windows file names. It is OK if
+# BASENAME is the empty string; in this case the directory is
+# returned.
+
+proc standard_output_file {basename} {
+ global objdir subdir gdb_test_file_name
+
+ set dir [make_gdb_parallel_path outputs $subdir $gdb_test_file_name]
+ file mkdir $dir
+ set dir [host_file_normalize $dir]
+ return [host_file_join $dir $basename]
+}
+
+# Like standard_output_file, but handles remote hosts. Turn BASENAME
+# into a file name on (potentially remote) host.
proc host_standard_output_file { basename } {
if { [is_remote host] } {
@@ -8886,6 +9285,10 @@ proc clean_restart {{executable ""}} {
gdb_reinitialize_dir $srcdir/$subdir
if {$executable != ""} {
+ if { [file pathtype $executable] == "absolute" } {
+ error "absolute path used"
+ }
+
set binfile [standard_output_file ${executable}]
return [gdb_load ${binfile}]
}
@@ -9136,7 +9539,8 @@ gdb_caching_proc target_endianness {} {
return 0
}
- clean_restart $obj
+ clean_restart
+ gdb_load $obj
if ![runto_main] {
return 0
}
@@ -9262,7 +9666,13 @@ proc remove_core {pid {test ""}} {
}
}
-proc core_find {binfile {deletefiles {}} {arg ""}} {
+# Runs ${binfile} expecting it to crash and generate a core file.
+# If DELETEFILES is provided, remove these files after running the program.
+# If ARG is provided, pass it as a command line argument to the program.
+# If OUTPUT_FILE is provided, save the program output to it.
+# Returns the name of the core dump, or empty string if not found.
+
+proc core_find {binfile {deletefiles {}} {arg ""} {output_file "/dev/null"}} {
global objdir subdir
set destcore "$binfile.core"
@@ -9284,9 +9694,14 @@ proc core_find {binfile {deletefiles {}} {arg ""}} {
set found 0
set coredir [standard_output_file coredir.[getpid]]
file mkdir $coredir
- catch "system \"(cd ${coredir}; ulimit -c unlimited; ${binfile} ${arg}; true) >/dev/null 2>&1\""
+ catch "system \"(cd ${coredir}; ulimit -c unlimited; ${binfile} ${arg}; true) >${output_file} 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
@@ -9370,7 +9785,8 @@ gdb_caching_proc target_supports_scheduler_locking {} {
return 0
}
- clean_restart $obj
+ clean_restart
+ gdb_load $obj
if ![runto_main] {
return 0
}
@@ -9891,6 +10307,10 @@ proc gdb_stdin_log_init { } {
set logfile [standard_output_file_with_gdb_instance gdb.in]
set in_file [open $logfile w]
+
+ verbose -log ""
+ verbose -log "Starting logfile: $logfile"
+ verbose -log ""
}
# Write to the file for logging gdb input.
@@ -10324,7 +10744,11 @@ proc with_override { name override body } {
proc with_ansi_styling_terminal { body } {
save_vars { ::env(TERM) ::env(NO_COLOR) ::env(COLORTERM) } {
# Set environment variables to allow styling.
- setenv TERM ansi
+ if { [ishost *-*-*bsd*] } {
+ setenv TERM ansiw
+ } else {
+ setenv TERM ansi
+ }
unset -nocomplain ::env(NO_COLOR)
unset -nocomplain ::env(COLORTERM)
@@ -10857,7 +11281,8 @@ gdb_caching_proc have_epilogue_line_info {} {
return False
}
- clean_restart $obj
+ clean_restart
+ gdb_load $obj
gdb_test_multiple "info line 6" "epilogue test" {
-re -wrap ".*starts at address.*and ends at.*" {
@@ -11000,6 +11425,66 @@ proc lappend_include_file { flags file } {
}
}
+# Helper for auto_lappend_include_files that handles one source file,
+# and tracks the list of already-visited files.
+
+proc auto_lappend_include_files_1 {flags source {visited {}}} {
+ upvar $flags up_flags
+ upvar $visited up_visited
+ global srcdir
+
+ set ext [string tolower [file extension $source]]
+ if {$ext ni {".c" ".cpp" ".cc" ".h" ".s"}} {
+ return
+ }
+
+ if {[catch {open $source r} fh err]} {
+ error "Failed to open file '$source': $err"
+ }
+ set contents [read $fh]
+ close $fh
+
+ lappend up_visited $source
+
+ # Match lines like:
+ # #include "gdb_foo.h"
+ set re "^\\s*#include\\s+\"(.*)\""
+
+ foreach line [split $contents "\n"] {
+ if {[regexp $re $line -> basename]} {
+ set lib_file "$srcdir/lib/$basename"
+
+ # If already processed, skip.
+ if {[lsearch -exact $up_visited $lib_file] != -1} {
+ continue
+ }
+
+ if {![file exists $lib_file]} {
+ continue
+ }
+
+ # Append to include list, and recurse into the included
+ # file.
+ lappend_include_file up_flags $lib_file
+ auto_lappend_include_files_1 up_flags $lib_file up_visited
+ }
+ }
+}
+
+# Automatically handle includes under gdb/testsuite/lib/.
+#
+# For each source file in SOURCES, look for #include directives
+# including files that live in testsuite/lib/. For each such included
+# file, call lappend_include_file for it.
+
+proc auto_lappend_include_files {flags sources} {
+ upvar $flags up_flags
+ set visited {}
+ foreach src $sources {
+ auto_lappend_include_files_1 up_flags $src visited
+ }
+}
+
# Return a list of supported host locales.
gdb_caching_proc host_locales { } {
@@ -11111,5 +11596,46 @@ gdb_caching_proc have_builtin_trap {} {
} executable]
}
+# Return 1 if there is a startup shell. Return -1 if there's no startup shell.
+# Return -1 otherwise.
+
+gdb_caching_proc have_startup_shell {} {
+ if { [is_remote target] } {
+ # For remote debugging targets, there is no guarantee that a "shell"
+ # is used.
+ return -1
+ }
+
+
+ gdb_exit
+ gdb_start
+
+ set re_on \
+ [string_to_regexp "Use of shell to start subprocesses is on."]
+ set re_off \
+ [string_to_regexp "Use of shell to start subprocesses is off."]
+ set re_cmd_unsupported \
+ [string_to_regexp \
+ {Undefined show command: "startup-with-shell". Try "help show".}]
+
+ set supported -1
+ gdb_test_multiple "show startup-with-shell" "" {
+ -re -wrap $re_on {
+ set supported 1
+ }
+ -re -wrap $re_off {
+ set supported 0
+ }
+ -re -wrap $re_cmd_unsupported {
+ }
+ -re -wrap "" {
+ }
+ }
+
+ gdb_exit
+
+ return $supported
+}
+
# Always load compatibility stuff.
load_lib future.exp
diff --git a/gdb/testsuite/lib/gdb_watchdog.h b/gdb/testsuite/lib/gdb_watchdog.h
new file mode 100644
index 0000000..15d63e7
--- /dev/null
+++ b/gdb/testsuite/lib/gdb_watchdog.h
@@ -0,0 +1,75 @@
+/* This file 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/>. */
+
+/* Set a watchdog that aborts the testcase after a timeout. */
+
+#ifndef GDB_WATCHDOG_H
+#define GDB_WATCHDOG_H
+
+/* Forward declaration to make sure the definitions have the right
+ prototype, at least in C. */
+static void gdb_watchdog (unsigned int seconds);
+
+static const char _gdb_watchdog_msg[]
+ = "gdb_watchdog: timeout expired - aborting test\n";
+
+#ifdef _WIN32
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+static VOID CALLBACK
+_gdb_watchdog_timer_routine (PVOID lpParam, BOOLEAN TimerOrWaitFired)
+{
+ fputs (_gdb_watchdog_msg, stderr);
+ abort ();
+}
+
+static void
+gdb_watchdog (unsigned int seconds)
+{
+ HANDLE timer;
+
+ if (!CreateTimerQueueTimer (&timer, NULL,
+ _gdb_watchdog_timer_routine, NULL,
+ seconds * 1000, 0, 0))
+ abort ();
+}
+
+#else /* POSIX systems */
+
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+
+static void
+_gdb_sigalrm_handler (int signo)
+{
+ write (2, _gdb_watchdog_msg, sizeof (_gdb_watchdog_msg) - 1);
+ abort ();
+}
+
+static void
+gdb_watchdog (unsigned int seconds)
+{
+ signal (SIGALRM, _gdb_sigalrm_handler);
+ alarm (seconds);
+}
+
+#endif
+
+#endif /* GDB_WATCHDOG_H */
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/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index aba13a2..a3ae648 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -1044,6 +1044,9 @@ proc mi_clean_restart {{executable ""} {flags {}}} {
mi_gdb_reinitialize_dir $srcdir/$subdir
if {$executable != ""} {
+ if { [file pathtype $executable] == "absolute" } {
+ error "absolute path used"
+ }
set binfile [standard_output_file ${executable}]
return [mi_gdb_load ${binfile}]
}
diff --git a/gdb/testsuite/lib/selftest-support.exp b/gdb/testsuite/lib/selftest-support.exp
index e037664..af8ec6f 100644
--- a/gdb/testsuite/lib/selftest-support.exp
+++ b/gdb/testsuite/lib/selftest-support.exp
@@ -16,7 +16,7 @@
# Find a pathname to a file that we would execute if the shell was asked
# to run $arg using the current PATH.
-proc find_gdb { arg } {
+proc _selftest_find_gdb { arg } {
# If the arg directly specifies an existing executable file, then
# simply use it.
@@ -36,65 +36,163 @@ proc find_gdb { arg } {
return $arg
}
-# A helper proc that sets up for self-testing.
-# EXECUTABLE is the gdb to use.
-# FUNCTION is the function to break in, either captured_main
-# or captured_command_loop.
-# Return 0 in case of success, -1 in case of failure, and -2 in case of
-# skipping the test-case.
+# Return true if the GDB under test is installed (as opposed to a GDB in its
+# build directory).
-proc selftest_setup { executable function } {
- global gdb_prompt
- global INTERNAL_GDBFLAGS
+proc _selftest_gdb_is_installed {} {
+ # If GDB_DATA_DIRECTORY is empty, assume that it is an installed GDB. It is
+ # not a perfectly accurate check, but should be good enough.
+ return [expr {"$::GDB_DATA_DIRECTORY" == ""}]
+}
+
+# Return true if the libtool binary is present on the host.
+
+proc _selftest_has_libtool {} {
+ lassign [remote_exec host "sh -c \"command -v libtool\""] status output
+ return [expr {$status == 0}]
+}
+
+# If GDB is executed from a build tree, run libtool to obtain the real
+# executable path for EXECUTABLE, which may be a libtool wrapper. Return
+# the path on success. On failure, issue an UNTESTED test result and return
+# an empty string.
+#
+# If GDB is executed from an installed location, return EXECUTABLE unchanged.
+#
+# If libtool is not present on the host system, return EXECUTABLE unchanged.
+# The test might still work, because the GDB binary is not always a libtool
+# wrapper.
+
+proc selftest_libtool_get_real_gdb_executable { executable } {
+ if [_selftest_gdb_is_installed] {
+ return $executable
+ }
- # load yourself into the debugger
+ if ![_selftest_has_libtool] {
+ return $executable
+ }
+
+ lassign [remote_exec host libtool "--mode=execute echo -n $executable"] \
+ status executable
+
+ if { $status != 0 } {
+ untested "failed to run libtool"
+ return ""
+ }
- global gdb_file_cmd_debug_info
- set gdb_file_cmd_debug_info "unset"
+ return $executable
+}
+
+# Return true if EXECUTABLE has debug info.
+#
+# If it doesn't, or if it's not possible to determine, issue an UNTESTED test
+# result and return false.
+
+proc _selftest_check_executable_debug_info { executable } {
+ set ::gdb_file_cmd_debug_info "unset"
+ set result true
+
+ # On Cygwin (at least), gdb/gdb.exe is a libtool wrapper (which happens to
+ # be a PE executable). The real binary is gdb/.libs/gdb.exe. If we load
+ # gdb/gdb.exe, we won't see any debug info and conclude that we can't run
+ # the test. Obtain the real executable path using libtool.
+ #
+ # At the time of writing, we don't see a libtool wrapper generated on Linux.
+ # But if there was one, it would be a shell script, and it would not be
+ # possible to load it in gdb. This conversion would therefore also be
+ # necessary.
+ #
+ # If testing against an installed GDB, then there won't be a libtool
+ # wrapper, no need to convert.
+ set executable [selftest_libtool_get_real_gdb_executable $executable]
+
+ if { $executable == "" } {
+ # selftest_libtool_get_real_gdb_executable already records an UNTESTED
+ # on failure.
+ return false
+ }
- set result [gdb_load $executable]
+ gdb_start
- if {$result != 0} {
- return -1
+ if {[gdb_load $executable] != 0} {
+ untested "failed to load executable when checking for debug info"
+ set result false
}
- if {$gdb_file_cmd_debug_info != "debug"} {
+ if {$::gdb_file_cmd_debug_info != "debug"} {
untested "no debug information, skipping testcase."
- return -2
+ set result false
}
- # Set a breakpoint at $function.
+ gdb_exit
+
+ return $result
+}
+
+# A helper proc that sets up for self-testing.
+#
+# Assumes that the inferior GDB is already loaded in the top-level GDB.
+#
+# Return 0 in case of success, -1 in case of failure, and -2 in case of
+# skipping the test-case.
+
+proc _selftest_setup { } {
+ global gdb_prompt
+ global INTERNAL_GDBFLAGS
+
+ # Set a breakpoint at main
+ set function main
if { [gdb_breakpoint $function "no-message"] != 1 } {
untested "Cannot set breakpoint at $function, skipping testcase."
return -2
}
+ # Debugging on Windows shows random threads starting and exiting,
+ # interfering with the tests. Disable them, since they are not useful here.
+ gdb_test_no_output "set print thread-events off"
+
# run yourself
set description "run until breakpoint at $function"
+ set re_hs {[^\r\n]+}
+ set re_args [string cat \
+ [string_to_regexp "("] \
+ $re_hs \
+ [string_to_regexp ")"]]
+ set re_pass \
+ [multi_line \
+ "Starting program: $re_hs" \
+ ".*" \
+ [string cat "Breakpoint $::decimal, $function $re_args at" \
+ " ${re_hs}gdb.c:$re_hs"] \
+ ".*"]
+ set re_xfail \
+ [multi_line \
+ "Starting program: $re_hs" \
+ ".*" \
+ "Breakpoint $::decimal, $function $re_args$re_hs" \
+ ".*"]
gdb_test_multiple "run $INTERNAL_GDBFLAGS" "$description" {
- -re "Starting program.*Breakpoint \[0-9\]+,.*$function \\(.*\\).* at .*main.c:.*$gdb_prompt $" {
- pass "$description"
- }
- -re "Starting program.*Breakpoint \[0-9\]+,.*$function \\(.*\\).*$gdb_prompt $" {
- xfail "$description (line numbers scrambled?)"
- }
- -re "vfork: No more processes.*$gdb_prompt $" {
- fail "$description (out of virtual memory)"
- return -1
- }
- -re ".*$gdb_prompt $" {
- fail "$description"
- return -1
- }
+ -re -wrap $re_pass {
+ pass $description
+ }
+ -re -wrap $re_xfail {
+ xfail "$description (line numbers scrambled?)"
+ }
+ -re -wrap "vfork: No more processes.*" {
+ fail "$description (out of virtual memory)"
+ return -1
+ }
+ -re -wrap "" {
+ fail $description
+ return -1
+ }
}
return 0
}
-# Prepare for running a self-test by moving the GDB executable to a
-# location where we can use it as the inferior. Return the filename
-# of the new location.
+# Return the location of the gdb executable to test.
#
# If the current testing setup is not suitable for running a
# self-test, then return an empty string.
@@ -114,52 +212,54 @@ proc selftest_prepare {} {
# ... or with a stub-like server? I.e., gdbserver + "target
# remote"? In that case we won't be able to pass command line
- # arguments to GDB, and selftest_setup wants to do exactly that.
+ # arguments to GDB, and _selftest_setup wants to do exactly that.
if [use_gdb_stub] {
return
}
- # Run the test with self. Copy the file executable file in case
- # this OS doesn't like to edit its own text space.
-
- set gdb_fullpath [find_gdb $::GDB]
-
- if {[is_remote host]} {
- set xgdb x$::tool
- } else {
- set xgdb [standard_output_file x$::tool]
- }
-
- # Remove any old copy lying around.
- remote_file host delete $xgdb
-
- set filename [remote_download host $gdb_fullpath $xgdb]
-
- return $filename
+ return [_selftest_find_gdb $::GDB]
}
# A simple way to run some self-tests.
-proc do_self_tests {function body} {
+proc do_self_tests {body} {
set file [selftest_prepare]
if { $file eq "" } {
return
}
- gdb_start
+ # Check if the gdb executable has debug info.
+ if { ![_selftest_check_executable_debug_info $file] } {
+ return
+ }
+
+ # FILE might be a libtool wrapper. In order to debug the real thing, pass
+ # FILE on the command-line of the top-level gdb, and run under
+ # `libtool --mode=execute. libtool will replace FILE with the path to the
+ # real executable and set any path required for it to find its dependent
+ # libraries.
+ #
+ # If testing against an installed GDB, there won't be a libtool wrapper.
+ save_vars { ::GDB ::GDBFLAGS } {
+ if { ![_selftest_gdb_is_installed] && [_selftest_has_libtool] } {
+ set ::GDB "libtool --mode=execute $::GDB"
+ }
+
+ set ::GDBFLAGS "$::GDBFLAGS $file"
+ gdb_start
+ }
# When debugging GDB with GDB, some operations can take a relatively long
# time, especially if the build is non-optimized. Bump the timeout for the
# duration of the test.
with_timeout_factor 10 {
- set result [selftest_setup $file $function]
+ set result [_selftest_setup]
if {$result == 0} {
set result [uplevel $body]
}
}
gdb_exit
- catch "remote_file host delete $file"
if {$result == -1} {
warning "Couldn't test self"
diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp
index a0cd199..97017c7 100644
--- a/gdb/testsuite/lib/tuiterm.exp
+++ b/gdb/testsuite/lib/tuiterm.exp
@@ -33,1264 +33,1690 @@ namespace eval Term {
variable _resize_count
- proc _log { what } {
- verbose "+++ $what"
- }
+ variable _TERM
+ set _TERM ""
- # Call BODY, then log WHAT along with the original and new cursor position.
- proc _log_cur { what body } {
- variable _cur_row
- variable _cur_col
+ variable _alternate
+ variable _alternate_setup
+ set _alternate 0
+ set _alternate_setup 0
+}
+
+proc Term::_log { what } {
+ verbose "+++ $what"
+}
- set orig_cur_row $_cur_row
- set orig_cur_col $_cur_col
+# Call BODY, then log WHAT along with the original and new cursor position.
+proc Term::_log_cur { what body } {
+ variable _cur_row
+ variable _cur_col
- uplevel $body
+ set orig_cur_row $_cur_row
+ set orig_cur_col $_cur_col
+
+ set code [catch {uplevel $body} result]
- _log "$what, cursor: ($orig_cur_row, $orig_cur_col) -> ($_cur_row, $_cur_col)"
+ _log "$what, cursor: ($orig_cur_row, $orig_cur_col) -> ($_cur_row, $_cur_col)"
+
+ if { $code == 1 } {
+ global errorInfo errorCode
+ return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
+ } else {
+ return -code $code $result
}
+}
- # If ARG is empty, return DEF: otherwise ARG. This is useful for
- # defaulting arguments in CSIs.
- proc _default {arg def} {
- if {$arg == ""} {
- return $def
- }
- return $arg
+# If ARG is empty, return DEF: otherwise ARG. This is useful for
+# defaulting arguments in CSIs.
+proc Term::_default {arg def} {
+ if {$arg == ""} {
+ return $def
}
+ return $arg
+}
- # Erase in the line Y from SX to just before EX.
- proc _clear_in_line {sx ex y} {
- variable _attrs
- variable _chars
- set lattr [array get _attrs]
- while {$sx < $ex} {
- set _chars($sx,$y) [list " " $lattr]
- incr sx
- }
+# Erase in the line Y from SX to just before EX.
+proc Term::_clear_in_line {sx ex y} {
+ variable _attrs
+ variable _chars
+ set lattr [array get _attrs]
+ while {$sx < $ex} {
+ set _chars($sx,$y) [list " " $lattr]
+ incr sx
}
+}
- # Erase the lines from SY to just before EY.
- proc _clear_lines {sy ey} {
- variable _cols
- while {$sy < $ey} {
- _clear_in_line 0 $_cols $sy
- incr sy
- }
+# Erase the lines from SY to just before EY.
+proc Term::_clear_lines {sy ey} {
+ variable _cols
+ while {$sy < $ey} {
+ _clear_in_line 0 $_cols $sy
+ incr sy
}
+}
+
+# Beep.
+proc Term::_ctl_0x07 {} {
+}
+
+# Return 1 if tuiterm has the bw/auto_left_margin enabled.
+proc Term::_have_bw {} {
+ return [expr \
+ { [string equal $Term::_TERM "ansiw"] \
+ || [string equal $Term::_TERM "ansis"] }]
+}
- # Beep.
- proc _ctl_0x07 {} {
+# Backspace.
+proc Term::_ctl_0x08 { {bw -1} } {
+ if { $bw == -1 } {
+ set bw [_have_bw]
}
+ _log_cur "Backspace, bw == $bw" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
- # Backspace.
- proc _ctl_0x08 {} {
- _log_cur "Backspace" {
- variable _cur_col
+ if { $_cur_col > 0 } {
+ # No wrapping needed.
+ incr _cur_col -1
+ return
+ }
- if {$_cur_col > 0} {
- incr _cur_col -1
- }
+ if { ! $bw } {
+ # Wrapping not enabled.
+ return
}
+
+ if { $_cur_row == 0 } {
+ # Can't wrap.
+ return
+ }
+
+ # Wrap to previous line.
+ set _cur_col [expr $_cols - 1]
+ incr _cur_row -1
}
+}
- # Linefeed.
- proc _ctl_0x0a {} {
- _log_cur "Line feed" {
- variable _cur_row
- variable _rows
- variable _cols
- variable _chars
-
- incr _cur_row 1
- while {$_cur_row >= $_rows} {
- # Scroll the display contents. We scroll one line at
- # a time here; as _cur_row was only increased by one,
- # a single line scroll should be enough to put the
- # cursor back on the screen. But we wrap the
- # scrolling inside a while loop just to be on the safe
- # side.
- for {set y 0} {$y < [expr $_rows - 1]} {incr y} {
- set next_y [expr $y + 1]
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$y) $_chars($x,$next_y)
- }
- }
+# Linefeed.
+proc Term::_ctl_0x0a {} {
+ _log_cur "Line feed" {
+ variable _cur_row
+ variable _rows
+ variable _cols
+ variable _chars
- incr _cur_row -1
+ incr _cur_row 1
+ while {$_cur_row >= $_rows} {
+ # Scroll the display contents. We scroll one line at
+ # a time here; as _cur_row was only increased by one,
+ # a single line scroll should be enough to put the
+ # cursor back on the screen. But we wrap the
+ # scrolling inside a while loop just to be on the safe
+ # side.
+ for {set y 0} {$y < [expr $_rows - 1]} {incr y} {
+ set next_y [expr $y + 1]
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$y) $_chars($x,$next_y)
+ }
}
+
+ incr _cur_row -1
}
}
+}
- # Carriage return.
- proc _ctl_0x0d {} {
- _log_cur "Carriage return" {
- variable _cur_col
+# Carriage return.
+proc Term::_ctl_0x0d {} {
+ _log_cur "Carriage return" {
+ variable _cur_col
- set _cur_col 0
- }
+ set _cur_col 0
}
+}
- # Insert Character.
- #
- # https://vt100.net/docs/vt510-rm/ICH.html
- proc _csi_@ {args} {
- set n [_default [lindex $args 0] 1]
+# Designate G0 Character Set, USASCII (ESC ( B)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html (see "ESC ( C", case C = B)
+proc Term::_esc_0x28_B {} {
+ _log "ignored: G0: USASCII"
+}
- _log_cur "Insert Character ($n)" {
- variable _cur_col
- variable _cur_row
- variable _cols
- variable _chars
+# Designate G0 Character Set, DEC Special Character and Line Drawing Set (ESC ( 0)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html (see "ESC ( C", case C = 0)
+proc Term::_esc_0x28_0 {} {
+ _log "ignored: G0: DEC Special Character and Line Drawing Set"
+}
- # Move characters right of the cursor right by N positions,
- # starting with the rightmost one.
- for {set in_col [expr $_cols - $n - 1]} {$in_col >= $_cur_col} {incr in_col -1} {
- set out_col [expr $in_col + $n]
- set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row)
- }
+# DECKPAM (Application Keypad, ESC =)
+#
+# https://vt100.net/docs/vt510-rm/DECKPAM.html
+proc Term::_esc_0x3d {} {
+ _log "ignored: Application Keypad"
+}
+
+# DECKPNM (Normal Keypad, ESC >)
+#
+# https://vt100.net/docs/vt510-rm/DECKPNM.html
+proc Term::_esc_0x3e {} {
+ _log "ignored: Normal Keypad"
+}
- # Write N blank spaces starting from the cursor.
- _clear_in_line $_cur_col [expr $_cur_col + $n] $_cur_row
+# Insert Character.
+#
+# https://vt100.net/docs/vt510-rm/ICH.html
+proc Term::_csi_@ {args} {
+ set n [_default [lindex $args 0] 1]
+
+ _log_cur "Insert Character ($n)" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
+ variable _chars
+
+ # Move characters right of the cursor right by N positions,
+ # starting with the rightmost one.
+ for {set in_col [expr $_cols - $n - 1]} {$in_col >= $_cur_col} {incr in_col -1} {
+ set out_col [expr $in_col + $n]
+ set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row)
}
+
+ # Write N blank spaces starting from the cursor.
+ _clear_in_line $_cur_col [expr $_cur_col + $n] $_cur_row
}
+}
- # Cursor Up.
- #
- # https://vt100.net/docs/vt510-rm/CUU.html
- proc _csi_A {args} {
- set arg [_default [lindex $args 0] 1]
+# Horizontal Position Absolute.
+#
+# https://vt100.net/docs/vt510-rm/HPA.html
+proc Term::_csi_` {args} {
+ # Same as Cursor Horizontal Absolute.
+ return [Term::_csi_G {*}$args]
+}
- _log_cur "Cursor Up ($arg)" {
- variable _cur_row
+# Cursor Up.
+#
+# https://vt100.net/docs/vt510-rm/CUU.html
+proc Term::_csi_A {args} {
+ set arg [_default [lindex $args 0] 1]
- set _cur_row [expr {max ($_cur_row - $arg, 0)}]
- }
+ _log_cur "Cursor Up ($arg)" {
+ variable _cur_row
+
+ set _cur_row [expr {max ($_cur_row - $arg, 0)}]
}
+}
- # Cursor Down.
- #
- # https://vt100.net/docs/vt510-rm/CUD.html
- proc _csi_B {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Down.
+#
+# https://vt100.net/docs/vt510-rm/CUD.html
+proc Term::_csi_B {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Down ($arg)" {
- variable _cur_row
- variable _rows
+ _log_cur "Cursor Down ($arg)" {
+ variable _cur_row
+ variable _rows
- set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}]
- }
+ set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}]
}
+}
- # Cursor Forward.
- #
- # https://vt100.net/docs/vt510-rm/CUF.html
- proc _csi_C {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Forward.
+#
+# https://vt100.net/docs/vt510-rm/CUF.html
+proc Term::_csi_C {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Forward ($arg)" {
- variable _cur_col
- variable _cols
+ _log_cur "Cursor Forward ($arg)" {
+ variable _cur_col
+ variable _cols
- set _cur_col [expr {min ($_cur_col + $arg, $_cols - 1)}]
- }
+ set _cur_col [expr {min ($_cur_col + $arg, $_cols - 1)}]
}
+}
- # Cursor Backward.
- #
- # https://vt100.net/docs/vt510-rm/CUB.html
- proc _csi_D {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Backward.
+#
+# https://vt100.net/docs/vt510-rm/CUB.html
+proc Term::_csi_D {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Backward ($arg)" {
- variable _cur_col
+ _log_cur "Cursor Backward ($arg)" {
+ variable _cur_col
- set _cur_col [expr {max ($_cur_col - $arg, 0)}]
- }
+ set _cur_col [expr {max ($_cur_col - $arg, 0)}]
}
+}
- # Cursor Next Line.
- #
- # https://vt100.net/docs/vt510-rm/CNL.html
- proc _csi_E {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Next Line.
+#
+# https://vt100.net/docs/vt510-rm/CNL.html
+proc Term::_csi_E {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Next Line ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _rows
+ _log_cur "Cursor Next Line ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _rows
- set _cur_col 0
- set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}]
- }
+ set _cur_col 0
+ set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}]
}
+}
- # Cursor Previous Line.
- #
- # https://vt100.net/docs/vt510-rm/CPL.html
- proc _csi_F {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Previous Line.
+#
+# https://vt100.net/docs/vt510-rm/CPL.html
+proc Term::_csi_F {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Previous Line ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _rows
+ _log_cur "Cursor Previous Line ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _rows
- set _cur_col 0
- set _cur_row [expr {max ($_cur_row - $arg, 0)}]
- }
+ set _cur_col 0
+ set _cur_row [expr {max ($_cur_row - $arg, 0)}]
}
+}
- # Cursor Horizontal Absolute.
- #
- # https://vt100.net/docs/vt510-rm/CHA.html
- proc _csi_G {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Horizontal Absolute.
+#
+# https://vt100.net/docs/vt510-rm/CHA.html
+proc Term::_csi_G {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Horizontal Absolute ($arg)" {
- variable _cur_col
- variable _cols
+ _log_cur "Cursor Horizontal Absolute ($arg)" {
+ variable _cur_col
+ variable _cols
- set _cur_col [expr {min ($arg - 1, $_cols)}]
- }
+ set _cur_col [expr {min ($arg, $_cols)} - 1]
}
+}
- # Cursor Position.
- #
- # https://vt100.net/docs/vt510-rm/CUP.html
- proc _csi_H {args} {
- set row [_default [lindex $args 0] 1]
- set col [_default [lindex $args 1] 1]
+# Cursor Position.
+#
+# https://vt100.net/docs/vt510-rm/CUP.html
+proc Term::_csi_H {args} {
+ set row [_default [lindex $args 0] 1]
+ set col [_default [lindex $args 1] 1]
- _log_cur "Cursor Position ($row, $col)" {
- variable _cur_col
- variable _cur_row
+ _log_cur "Cursor Position ($row, $col)" {
+ variable _cur_col
+ variable _cur_row
- set _cur_row [expr {$row - 1}]
- set _cur_col [expr {$col - 1}]
- }
+ set _cur_row [expr {$row - 1}]
+ set _cur_col [expr {$col - 1}]
}
+}
- # Cursor Horizontal Forward Tabulation.
- #
- # https://vt100.net/docs/vt510-rm/CHT.html
- proc _csi_I {args} {
- set n [_default [lindex $args 0] 1]
+# Cursor Horizontal Forward Tabulation.
+#
+# https://vt100.net/docs/vt510-rm/CHT.html
+proc Term::_csi_I {args} {
+ set n [_default [lindex $args 0] 1]
- _log_cur "Cursor Horizontal Forward Tabulation ($n)" {
- variable _cur_col
- variable _cols
+ _log_cur "Cursor Horizontal Forward Tabulation ($n)" {
+ variable _cur_col
+ variable _cols
- incr _cur_col [expr {$n * 8 - $_cur_col % 8}]
- if {$_cur_col >= $_cols} {
- set _cur_col [expr {$_cols - 1}]
- }
+ incr _cur_col [expr {$n * 8 - $_cur_col % 8}]
+ if {$_cur_col >= $_cols} {
+ set _cur_col [expr {$_cols - 1}]
}
}
+}
- # Erase in Display.
- #
- # https://vt100.net/docs/vt510-rm/ED.html
- proc _csi_J {args} {
- set arg [_default [lindex $args 0] 0]
-
- _log_cur "Erase in Display ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _rows
- variable _cols
-
- if {$arg == 0} {
- # Cursor (inclusive) to end of display.
- _clear_in_line $_cur_col $_cols $_cur_row
- _clear_lines [expr {$_cur_row + 1}] $_rows
- } elseif {$arg == 1} {
- # Beginning of display to cursor (inclusive).
- _clear_lines 0 $_cur_row
- _clear_in_line 0 [expr $_cur_col + 1] $_cur_row
- } elseif {$arg == 2} {
- # Entire display.
- _clear_lines 0 $_rows
- }
+# Erase in Display.
+#
+# https://vt100.net/docs/vt510-rm/ED.html
+proc Term::_csi_J {args} {
+ set arg [_default [lindex $args 0] 0]
+
+ _log_cur "Erase in Display ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _rows
+ variable _cols
+
+ if {$arg == 0} {
+ # Cursor (inclusive) to end of display.
+ _clear_in_line $_cur_col $_cols $_cur_row
+ _clear_lines [expr {$_cur_row + 1}] $_rows
+ } elseif {$arg == 1} {
+ # Beginning of display to cursor (inclusive).
+ _clear_lines 0 $_cur_row
+ _clear_in_line 0 [expr $_cur_col + 1] $_cur_row
+ } elseif {$arg == 2} {
+ # Entire display.
+ _clear_lines 0 $_rows
}
}
+}
- # Erase in Line.
- #
- # https://vt100.net/docs/vt510-rm/EL.html
- proc _csi_K {args} {
- set arg [_default [lindex $args 0] 0]
+# Erase in Line.
+#
+# https://vt100.net/docs/vt510-rm/EL.html
+proc Term::_csi_K {args} {
+ set arg [_default [lindex $args 0] 0]
- _log_cur "Erase in Line ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _cols
+ _log_cur "Erase in Line ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
- if {$arg == 0} {
- # Cursor (inclusive) to end of line.
- _clear_in_line $_cur_col $_cols $_cur_row
- } elseif {$arg == 1} {
- # Beginning of line to cursor (inclusive).
- _clear_in_line 0 [expr $_cur_col + 1] $_cur_row
- } elseif {$arg == 2} {
- # Entire line.
- _clear_in_line 0 $_cols $_cur_row
- }
+ if {$arg == 0} {
+ # Cursor (inclusive) to end of line.
+ _clear_in_line $_cur_col $_cols $_cur_row
+ } elseif {$arg == 1} {
+ # Beginning of line to cursor (inclusive).
+ _clear_in_line 0 [expr $_cur_col + 1] $_cur_row
+ } elseif {$arg == 2} {
+ # Entire line.
+ _clear_in_line 0 $_cols $_cur_row
}
}
+}
- # Insert Line
- #
- # https://vt100.net/docs/vt510-rm/IL.html
- proc _csi_L {args} {
- set arg [_default [lindex $args 0] 1]
+# Insert Line
+#
+# https://vt100.net/docs/vt510-rm/IL.html
+proc Term::_csi_L {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Insert Line ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _rows
- variable _cols
- variable _chars
+ _log_cur "Insert Line ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _rows
+ variable _cols
+ variable _chars
- set y [expr $_rows - 2]
- set next_y [expr $y + $arg]
- while {$y >= $_cur_row} {
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$next_y) $_chars($x,$y)
- }
- incr y -1
- incr next_y -1
+ set y [expr $_rows - 2]
+ set next_y [expr $y + $arg]
+ while {$y >= $_cur_row} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$next_y) $_chars($x,$y)
}
-
- _clear_lines $_cur_row [expr $_cur_row + $arg]
+ incr y -1
+ incr next_y -1
}
+
+ _clear_lines $_cur_row [expr $_cur_row + $arg]
}
+}
- # Delete line.
- #
- # https://vt100.net/docs/vt510-rm/DL.html
- proc _csi_M {args} {
- set count [_default [lindex $args 0] 1]
+# Delete line.
+#
+# https://vt100.net/docs/vt510-rm/DL.html
+proc Term::_csi_M {args} {
+ set count [_default [lindex $args 0] 1]
- _log_cur "Delete line ($count)" {
- variable _cur_row
- variable _rows
- variable _cols
- variable _chars
+ _log_cur "Delete line ($count)" {
+ variable _cur_row
+ variable _rows
+ variable _cols
+ variable _chars
- set y $_cur_row
- set next_y [expr {$y + $count}]
- while {$next_y < $_rows} {
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$y) $_chars($x,$next_y)
- }
- incr y
- incr next_y
+ set y $_cur_row
+ set next_y [expr {$y + $count}]
+ while {$next_y < $_rows} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$y) $_chars($x,$next_y)
}
- _clear_lines $y $_rows
+ incr y
+ incr next_y
}
+ _clear_lines $y $_rows
}
+}
- # Delete Character.
- #
- # https://vt100.net/docs/vt510-rm/DCH.html
- proc _csi_P {args} {
- set count [_default [lindex $args 0] 1]
-
- _log_cur "Delete character ($count)" {
- variable _cur_row
- variable _cur_col
- variable _chars
- variable _cols
+# Delete Character.
+#
+# https://vt100.net/docs/vt510-rm/DCH.html
+proc Term::_csi_P {args} {
+ set count [_default [lindex $args 0] 1]
- # Move all characters right of the cursor N positions left.
- set out_col [expr $_cur_col]
- set in_col [expr $_cur_col + $count]
+ _log_cur "Delete character ($count)" {
+ variable _cur_row
+ variable _cur_col
+ variable _chars
+ variable _cols
- while {$in_col < $_cols} {
- set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row)
- incr in_col
- incr out_col
- }
+ # Move all characters right of the cursor N positions left.
+ set out_col [expr $_cur_col]
+ set in_col [expr $_cur_col + $count]
- # Clear the rest of the line.
- _clear_in_line $out_col $_cols $_cur_row
+ while {$in_col < $_cols} {
+ set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row)
+ incr in_col
+ incr out_col
}
+
+ # Clear the rest of the line.
+ _clear_in_line $out_col $_cols $_cur_row
}
+}
- # Pan Down
- #
- # https://vt100.net/docs/vt510-rm/SU.html
- proc _csi_S {args} {
- set count [_default [lindex $args 0] 1]
+# Pan Down
+#
+# https://vt100.net/docs/vt510-rm/SU.html
+proc Term::_csi_S {args} {
+ set count [_default [lindex $args 0] 1]
- _log_cur "Pan Down ($count)" {
- variable _cur_col
- variable _cur_row
- variable _cols
- variable _rows
- variable _chars
+ _log_cur "Pan Down ($count)" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
+ variable _rows
+ variable _chars
- # The following code is written without consideration for
- # the scroll margins. At this time this comment was
- # written the tuiterm library doesn't support the scroll
- # margins. If/when that changes, then the following will
- # need to be updated.
+ # The following code is written without consideration for
+ # the scroll margins. At this time this comment was
+ # written the tuiterm library doesn't support the scroll
+ # margins. If/when that changes, then the following will
+ # need to be updated.
- set dy 0
- set y $count
+ set dy 0
+ set y $count
- while {$y < $_rows} {
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$dy) $_chars($x,$y)
- }
- incr y 1
- incr dy 1
+ while {$y < $_rows} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$dy) $_chars($x,$y)
}
-
- _clear_lines $dy $_rows
+ incr y 1
+ incr dy 1
}
+
+ _clear_lines $dy $_rows
}
+}
- # Pan Up
- #
- # https://vt100.net/docs/vt510-rm/SD.html
- proc _csi_T {args} {
- set count [_default [lindex $args 0] 1]
+# Pan Up
+#
+# https://vt100.net/docs/vt510-rm/SD.html
+proc Term::_csi_T {args} {
+ set count [_default [lindex $args 0] 1]
- _log_cur "Pan Up ($count)" {
- variable _cur_col
- variable _cur_row
- variable _cols
- variable _rows
- variable _chars
+ _log_cur "Pan Up ($count)" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
+ variable _rows
+ variable _chars
- # The following code is written without consideration for
- # the scroll margins. At this time this comment was
- # written the tuiterm library doesn't support the scroll
- # margins. If/when that changes, then the following will
- # need to be updated.
+ # The following code is written without consideration for
+ # the scroll margins. At this time this comment was
+ # written the tuiterm library doesn't support the scroll
+ # margins. If/when that changes, then the following will
+ # need to be updated.
- set y [expr $_rows - $count]
- set dy $_rows
+ set y [expr $_rows - $count]
+ set dy $_rows
- while {$dy >= $count} {
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$dy) $_chars($x,$y)
- }
- incr y -1
- incr dy -1
+ while {$dy >= $count} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$dy) $_chars($x,$y)
}
-
- _clear_lines 0 $count
+ incr y -1
+ incr dy -1
}
+
+ _clear_lines 0 $count
}
+}
- # Erase chars.
- #
- # https://vt100.net/docs/vt510-rm/ECH.html
- proc _csi_X {args} {
- set n [_default [lindex $args 0] 1]
+# Erase chars.
+#
+# https://vt100.net/docs/vt510-rm/ECH.html
+proc Term::_csi_X {args} {
+ set n [_default [lindex $args 0] 1]
- _log_cur "Erase chars ($n)" {
- # Erase characters but don't move cursor.
- variable _cur_col
- variable _cur_row
- variable _attrs
- variable _chars
+ _log_cur "Erase chars ($n)" {
+ # Erase characters but don't move cursor.
+ variable _cur_col
+ variable _cur_row
+ variable _attrs
+ variable _chars
- set lattr [array get _attrs]
- set x $_cur_col
- for {set i 0} {$i < $n} {incr i} {
- set _chars($x,$_cur_row) [list " " $lattr]
- incr x
- }
+ set lattr [array get _attrs]
+ set x $_cur_col
+ for {set i 0} {$i < $n} {incr i} {
+ set _chars($x,$_cur_row) [list " " $lattr]
+ incr x
}
}
+}
- # Cursor Backward Tabulation.
- #
- # https://vt100.net/docs/vt510-rm/CBT.html
- proc _csi_Z {args} {
- set n [_default [lindex $args 0] 1]
+# Cursor Backward Tabulation.
+#
+# https://vt100.net/docs/vt510-rm/CBT.html
+proc Term::_csi_Z {args} {
+ set n [_default [lindex $args 0] 1]
- _log_cur "Cursor Backward Tabulation ($n)" {
- variable _cur_col
+ _log_cur "Cursor Backward Tabulation ($n)" {
+ variable _cur_col
- set _cur_col [expr {max (int (($_cur_col - 1) / 8) * 8 - ($n - 1) * 8, 0)}]
- }
+ set _cur_col [expr {max (int (($_cur_col - 1) / 8) * 8 - ($n - 1) * 8, 0)}]
}
+}
- # Repeat.
- #
- # https://www.xfree86.org/current/ctlseqs.html (See `(REP)`)
- proc _csi_b {args} {
- set n [_default [lindex $args 0] 1]
+# Repeat.
+#
+# https://www.xfree86.org/current/ctlseqs.html (See `(REP)`)
+proc Term::_csi_b {args} {
+ set n [_default [lindex $args 0] 1]
- _log_cur "Repeat ($n)" {
- variable _last_char
+ _log_cur "Repeat ($n)" {
+ variable _last_char
- _insert [string repeat $_last_char $n]
- }
+ _insert [string repeat $_last_char $n]
}
+}
- # Vertical Line Position Absolute.
- #
- # https://vt100.net/docs/vt510-rm/VPA.html
- proc _csi_d {args} {
- set row [_default [lindex $args 0] 1]
+# Vertical Line Position Absolute.
+#
+# https://vt100.net/docs/vt510-rm/VPA.html
+proc Term::_csi_d {args} {
+ set row [_default [lindex $args 0] 1]
- _log_cur "Vertical Line Position Absolute ($row)" {
- variable _cur_row
- variable _rows
+ _log_cur "Vertical Line Position Absolute ($row)" {
+ variable _cur_row
+ variable _rows
- set _cur_row [expr min ($row - 1, $_rows - 1)]
- }
+ set _cur_row [expr min ($row - 1, $_rows - 1)]
}
+}
- # Reset the attributes in attributes array UPVAR_NAME to the default values.
- proc _reset_attrs { upvar_name } {
- upvar $upvar_name var
- array set var {
- intensity normal
- fg default
- bg default
- underline 0
- reverse 0
- invisible 0
- blinking 0
+# Set Mode (SM, CSI h)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+proc Term::_csi_h { args } {
+ foreach item $args {
+ switch -exact -- $item {
+ 4 {
+ # Insert Mode (IRM)
+ _log "ignored: insert mode"
+ }
+ default {
+ error unsupported
+ }
}
}
+}
- # Translate the color numbers as used in proc _csi_m to a name.
- proc _color_attr { n } {
- switch -exact -- $n {
- 0 {
- return black
+# Reset Mode (RM, CSI l)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+proc Term::_csi_l { args } {
+ foreach item $args {
+ switch -exact -- $item {
+ 4 {
+ # Replace Mode (IRM)
+ _log "ignored: replace mode"
+ }
+ default {
+ error unsupported
}
+ }
+ }
+}
+
+# Set Scrolling Region (DECSTBM, CSI Ps ; Ps r)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+proc Term::_csi_r { top bottom } {
+ _log "ignored: set scrolling region"
+}
+
+# Window manipulation (XTWINOPS, CSI Ps ; Ps ; Ps t)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+proc Term::_csi_t { arg1 arg2 arg3 } {
+ if { $arg1 == 22 && $arg2 == 0 && $arg3 == 0 } {
+ _log "ignored: Save xterm icon and window title on stack"
+ return
+ }
+
+ if { $arg1 == 23 && $arg2 == 0 && $arg3 == 0 } {
+ _log "ignored: Restore xterm icon and window title from stack"
+ return
+ }
+
+ error unsupported
+}
+
+# DECSET (CSI ? h)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
+proc Term::_csi_0x3f_h { args } {
+ foreach item $args {
+ switch -exact -- $item {
1 {
- return red
+ _log "ignored: Application Cursor Keys"
}
- 2 {
- return green
+ 7 {
+ _log "ignored: autowrap mode"
}
- 3 {
- return yellow
+ 1000 {
+ _log "ignored: Send Mouse X & Y on button press and release"
}
- 4 {
- return blue
+ 1006 {
+ _log "ignored: Enable SGR Mouse Mode"
}
- 5 {
- return magenta
+ 1049 {
+ _log "switch to alternate screen"
+ _set_alternate 1
}
- 6 {
- return cyan
+ default {
+ error unsupported
+ }
+ }
+ }
+}
+
+# DECRST (CSI ? l)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
+proc Term::_csi_0x3f_l { args } {
+ foreach item $args {
+ switch -exact -- $item {
+ 1 {
+ _log "ignored: Normal Cursor Keys"
}
7 {
- return white
+ _log "ignored: no autowrap mode"
+ }
+ 1000 {
+ _log "ignored: Don't send Mouse X & Y on button press and release"
+ }
+ 1006 {
+ _log "ignored: Disable SGR Mouse Mode"
+ }
+ 1049 {
+ _log "switch from alternate screen"
+ _set_alternate 0
+ }
+ default {
+ error "unsupported"
}
- default { error "unsupported color number: $n" }
}
}
+}
- # Select Graphic Rendition.
- #
- # https://vt100.net/docs/vt510-rm/SGR.html
- proc _csi_m {args} {
- _log_cur "Select Graphic Rendition ([join $args {, }])" {
- variable _attrs
+# Reset the attributes in attributes array UPVAR_NAME to the default values.
+proc Term::_reset_attrs { upvar_name } {
+ upvar $upvar_name var
+ array set var {
+ intensity normal
+ fg default
+ bg default
+ underline 0
+ reverse 0
+ invisible 0
+ blinking 0
+ }
+}
- foreach item $args {
- switch -exact -- $item {
- "" - 0 {
- _reset_attrs _attrs
- }
- 1 {
- set _attrs(intensity) bold
- }
- 2 {
- set _attrs(intensity) dim
- }
- 4 {
- set _attrs(underline) 1
- }
- 5 {
- set _attrs(blinking) 1
- }
- 7 {
- set _attrs(reverse) 1
- }
- 8 {
- set _attrs(invisible) 1
- }
- 22 {
- set _attrs(intensity) normal
- }
- 24 {
- set _attrs(underline) 0
- }
- 25 {
- set _attrs(blinking) 0
- }
- 27 {
- set _attrs(reverse) 0
- }
- 28 {
- set _attrs(invisible) 0
- }
- 30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 {
- set _attrs(fg) [_color_attr [expr $item - 30]]
- }
- 39 {
- set _attrs(fg) default
- }
- 40 - 41 - 42 - 43 - 44 - 45 - 46 - 47 {
- set _attrs(bg) [_color_attr [expr $item - 40]]
- }
- 49 {
- set _attrs(bg) default
- }
+# Translate the color numbers as used in proc _csi_m to a name.
+proc Term::_color_attr { n } {
+ switch -exact -- $n {
+ 0 {
+ return black
+ }
+ 1 {
+ return red
+ }
+ 2 {
+ return green
+ }
+ 3 {
+ return yellow
+ }
+ 4 {
+ return blue
+ }
+ 5 {
+ return magenta
+ }
+ 6 {
+ return cyan
+ }
+ 7 {
+ return white
+ }
+ default { error "unsupported color number: $n" }
+ }
+}
+
+# Select Graphic Rendition.
+#
+# https://vt100.net/docs/vt510-rm/SGR.html
+proc Term::_csi_m {args} {
+ if { [llength $args] == 0 } {
+ # Apply default.
+ set args [list 0]
+ }
+
+ _log_cur "Select Graphic Rendition ([join $args {, }])" {
+ variable _attrs
+
+ foreach item $args {
+ switch -exact -- $item {
+ "" - 0 {
+ _reset_attrs _attrs
+ }
+ 1 {
+ set _attrs(intensity) bold
+ }
+ 2 {
+ set _attrs(intensity) dim
+ }
+ 4 {
+ set _attrs(underline) 1
+ }
+ 5 {
+ set _attrs(blinking) 1
+ }
+ 7 {
+ set _attrs(reverse) 1
+ }
+ 8 {
+ set _attrs(invisible) 1
+ }
+ 22 {
+ set _attrs(intensity) normal
+ }
+ 24 {
+ set _attrs(underline) 0
+ }
+ 25 {
+ set _attrs(blinking) 0
+ }
+ 27 {
+ set _attrs(reverse) 0
+ }
+ 28 {
+ set _attrs(invisible) 0
+ }
+ 30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 {
+ set _attrs(fg) [_color_attr [expr $item - 30]]
+ }
+ 39 {
+ set _attrs(fg) default
+ }
+ 40 - 41 - 42 - 43 - 44 - 45 - 46 - 47 {
+ set _attrs(bg) [_color_attr [expr $item - 40]]
+ }
+ 49 {
+ set _attrs(bg) default
}
}
}
}
+}
- # Insert string at the cursor location.
- proc _insert {str} {
- _log_cur "Inserted string '$str'" {
- _log "Inserting string '$str'"
-
- variable _cur_col
- variable _cur_row
- variable _rows
- variable _cols
- variable _attrs
- variable _chars
- set lattr [array get _attrs]
- foreach char [split $str {}] {
- _log_cur " Inserted char '$char'" {
- set _chars($_cur_col,$_cur_row) [list $char $lattr]
- incr _cur_col
- if {$_cur_col >= $_cols} {
- set _cur_col 0
- incr _cur_row
- if {$_cur_row >= $_rows} {
- error "FIXME scroll"
- }
+# Request Terminal Parameters (DECREQTPARM)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+# https://vt100.net/docs/vt100-ug/chapter3.html
+proc Term::_csi_x {} {
+ # Ignore.
+}
+
+# Insert string at the cursor location.
+proc Term::_insert {str} {
+ _log_cur "Inserted string '$str'" {
+ _log "Inserting string '$str'"
+
+ variable _cur_col
+ variable _cur_row
+ variable _rows
+ variable _cols
+ variable _attrs
+ variable _chars
+ set lattr [array get _attrs]
+ foreach char [split $str {}] {
+ _log_cur " Inserted char '$char'" {
+ set _chars($_cur_col,$_cur_row) [list $char $lattr]
+ incr _cur_col
+ if {$_cur_col >= $_cols} {
+ set _cur_col 0
+ incr _cur_row
+ if {$_cur_row >= $_rows} {
+ error "FIXME scroll"
}
}
}
}
+
+ variable _last_char
+ set _last_char [string index $str end]
}
+}
- # Move the cursor to the (0-based) COL and ROW positions.
- proc _move_cursor { col row } {
- variable _cols
- variable _rows
- variable _cur_col
- variable _cur_row
+# Move the cursor to the (0-based) COL and ROW positions.
+proc Term::_move_cursor { col row } {
+ variable _cols
+ variable _rows
+ variable _cur_col
+ variable _cur_row
- if { $col < 0 || $col >= $_cols } {
- error "_move_cursor: invalid col value: $col"
- }
+ if { $col < 0 || $col >= $_cols } {
+ error "_move_cursor: invalid col value: $col"
+ }
+
+ if { $row < 0 || $row >= $_rows } {
+ error "_move_cursor: invalid row value: $row"
+ }
- if { $row < 0 || $row >= $_rows } {
- error "_move_cursor: invalid row value: $row"
- }
+ set _cur_col $col
+ set _cur_row $row
+}
- set _cur_col $col
- set _cur_row $row
+# Enable or disable alternate screen.
+proc Term::_set_alternate { enable } {
+ variable _alternate
+ if { $enable == $_alternate } {
+ return
}
+ set _alternate $enable
- # Initialize.
- proc _setup {rows cols} {
- global stty_init
- set stty_init "rows $rows columns $cols"
+ variable _attrs
+ variable _chars
+ variable _cur_col
+ variable _cur_row
- variable _rows
- variable _cols
- variable _cur_col
- variable _cur_row
- variable _attrs
- variable _resize_count
+ variable _save_attrs
+ variable _save_chars
+ variable _save_cur_col
+ variable _save_cur_row
- set _rows $rows
- set _cols $cols
- set _cur_col 0
- set _cur_row 0
- set _resize_count 0
- _reset_attrs _attrs
-
- _clear_lines 0 $_rows
- }
-
- # Accept some output from gdb and update the screen.
- # Return 1 if successful, or 0 if a timeout occurred.
- proc accept_gdb_output { } {
- global expect_out
- gdb_expect {
- -re "^\[\x07\x08\x0a\x0d\]" {
- scan $expect_out(0,string) %c val
- set hexval [format "%02x" $val]
- _log "wait_for: _ctl_0x${hexval}"
- _ctl_0x${hexval}
- }
- -re "^\x1b(\[0-9a-zA-Z\])" {
- _log "wait_for: unsupported escape"
- error "unsupported escape"
- }
- -re "^\x1b\\\[(\[0-9;\]*)(\[a-zA-Z@\])" {
- set cmd $expect_out(2,string)
- set params [split $expect_out(1,string) ";"]
- _log "wait_for: _csi_$cmd <<<$expect_out(1,string)>>>"
- eval _csi_$cmd $params
- }
- -re "^\[^\x07\x08\x0a\x0d\x1b\]+" {
- _insert $expect_out(0,string)
- variable _last_char
- set _last_char [string index $expect_out(0,string) end]
- }
+ variable _alternate_setup
- timeout {
- # Assume a timeout means we somehow missed the
- # expected result, and carry on.
- warning "timeout in accept_gdb_output"
- dump_screen
- return 0
- }
- }
+ if { $_alternate_setup } {
+ set tmp $_save_chars
+ }
+ set _save_chars [array get _chars]
+ if { $_alternate_setup } {
+ array set _chars $tmp
+ }
- return 1
+ if { $_alternate_setup } {
+ set tmp $_save_attrs
+ }
+ set _save_attrs [array get _attrs]
+ if { $_alternate_setup } {
+ array set _attrs $tmp
}
- # Print arg using "verbose -log" if DEBUG_TUI_MATCHING == 1.
- proc debug_tui_matching { arg } {
- set debug 0
- if { [info exists ::DEBUG_TUI_MATCHING] } {
- set debug $::DEBUG_TUI_MATCHING
- }
+ if { $_alternate_setup } {
+ set tmp $_save_cur_col
+ }
+ set _save_cur_col $_cur_col
+ if { $_alternate_setup } {
+ set _cur_col $tmp
+ }
- if { ! $debug } {
- return
- }
+ if { $_alternate_setup } {
+ set tmp $_save_cur_row
+ }
+ set _save_cur_row $_cur_row
+ if { $_alternate_setup } {
+ set _cur_row $tmp
+ }
- verbose -log "$arg"
+ if { ! $_alternate_setup } {
+ variable _rows
+ variable _cols
+ _setup $_rows $_cols
+ set _alternate_setup 1
}
+}
- # Accept some output from gdb and update the screen. WAIT_FOR is
- # a regexp matching the line to wait for. Return 0 on timeout, 1
- # on success.
- proc wait_for {wait_for} {
- global gdb_prompt
- variable _cur_col
- variable _cur_row
+# Initialize.
+proc Term::_setup {rows cols} {
+ global stty_init
+ set stty_init "rows $rows columns $cols"
+
+ variable _rows
+ variable _cols
+ variable _cur_col
+ variable _cur_row
+ variable _attrs
+ variable _resize_count
+
+ set _rows $rows
+ set _cols $cols
+ set _cur_col 0
+ set _cur_row 0
+ set _resize_count 0
+ _reset_attrs _attrs
- set fn "wait_for"
+ _clear_lines 0 $_rows
+}
- set prompt_wait_for "(^|\\|)$gdb_prompt \$"
- if { $wait_for == "" } {
- set wait_for $prompt_wait_for
+# Accept some output from gdb and update the screen.
+# Return 1 if successful, or 0 if a timeout occurred.
+proc Term::accept_gdb_output { {warn 1} } {
+ global expect_out
+
+ set ctls "\x07\x08\x0a\x0d"
+ set esc "\x1b"
+ set re_ctls "\[$ctls\]"
+ set re_others "\[^$esc$ctls\]"
+ set have_esc 0
+ gdb_expect {
+ -re ^$re_ctls {
+ scan $expect_out(0,string) %c val
+ set hexval [format "%02x" $val]
+ _log "wait_for: _ctl_0x${hexval}"
+ _ctl_0x${hexval}
+ }
+ -re "^$esc" {
+ _log "wait_for: ESC"
+ set have_esc 1
+ }
+ -re "^$re_others+" {
+ _insert $expect_out(0,string)
+ }
+
+ timeout {
+ # Assume a timeout means we somehow missed the
+ # expected result, and carry on.
+ warning "timeout in accept_gdb_output"
+ dump_screen
+ return 0
}
+ }
- debug_tui_matching "$fn: regexp: '$wait_for'"
+ if { !$have_esc } {
+ return 1
+ }
- while 1 {
- if { [accept_gdb_output] == 0 } {
- return 0
- }
+ set re_csi [string_to_regexp "\["]
+ set have_csi 0
+ gdb_expect {
+ -re "^(\[0-9a-zA-Z\])" {
+ _log "wait_for: unsupported escape"
+ error "unsupported escape"
+ }
+ -re "^(\[\\(\])(\[a-zA-Z\])" {
+ scan $expect_out(1,string) %c val
+ set hexval [format "%02x" $val]
+ set cmd $expect_out(2,string)
+ eval _esc_0x${hexval}_$cmd
+ }
+ -re "^(\[=>\])" {
+ scan $expect_out(1,string) %c val
+ set hexval [format "%02x" $val]
+ _esc_0x$hexval
+ }
+ -re "^$re_csi" {
+ _log "wait_for: CSI"
+ set have_csi 1
+ }
- # If the cursor appears just after the prompt, return. It
- # isn't reliable to check this only after an insertion,
- # because curses may make "unusual" redrawing decisions.
- if {$wait_for == "$prompt_wait_for"} {
- set prev [get_line $_cur_row $_cur_col]
- } else {
- set prev [get_line $_cur_row]
- }
- if {[regexp -- $wait_for $prev]} {
- debug_tui_matching "$fn: match: '$prev'"
- if {$wait_for == "$prompt_wait_for"} {
- break
- }
- set wait_for $prompt_wait_for
- debug_tui_matching "$fn: regexp prompt: '$wait_for'"
- } else {
- debug_tui_matching "$fn: mismatch: '$prev'"
+ timeout {
+ # Assume a timeout means we somehow missed the
+ # expected result, and carry on.
+ if { $warn } {
+ warning "timeout in accept_gdb_output following ESC"
+ dump_screen
}
+ _insert "^\["
+ return 0
}
+ }
+ if { !$have_csi } {
return 1
}
- # Accept some output from gdb and update the screen. Wait for the screen
- # region X/Y/WIDTH/HEIGTH to matches REGEXP. Return 0 on timeout, 1 on
- # success.
- proc wait_for_region_contents {x y width height regexp} {
- while 1 {
- if { [accept_gdb_output] == 0 } {
- return 0
- }
-
- if { [check_region_contents_p $x $y $width $height $regexp] } {
- break
+ set re_csi_prefix {[?]}
+ set re_csi_args {[0-9;]}
+ set re_csi_cmd {[a-zA-Z@`]}
+ gdb_expect {
+ -re "^($re_csi_cmd)" {
+ set cmd $expect_out(1,string)
+ _log "wait_for: _csi_$cmd"
+ eval _csi_$cmd
+ }
+ -re "^($re_csi_args*)($re_csi_cmd)" {
+ set params [split $expect_out(1,string) ";"]
+ set cmd $expect_out(2,string)
+ _log "wait_for: _csi_$cmd <<<$params>>>"
+ eval _csi_$cmd $params
+ }
+ -re "^($re_csi_prefix?)($re_csi_args*)($re_csi_cmd)" {
+ set prefix $expect_out(1,string)
+ set params [split $expect_out(2,string) ";"]
+ set cmd $expect_out(3,string)
+ scan $prefix %c val
+ set hexval [format "%02x" $val]
+ _log "wait_for: _csi_0x${hexval}_$cmd <<<$expect_out(1,string)>>>"
+ eval _csi_0x${hexval}_$cmd $params
+ }
+
+ timeout {
+ # Assume a timeout means we somehow missed the
+ # expected result, and carry on.
+ if { $warn } {
+ warning "timeout in accept_gdb_output following CSI"
+ dump_screen
}
+ _insert "^\[\["
+ return 0
}
+ }
- return 1
+ return 1
+}
+
+# Print arg using "verbose -log" if DEBUG_TUI_MATCHING == 1.
+proc Term::debug_tui_matching { arg } {
+ set debug 0
+ if { [info exists ::DEBUG_TUI_MATCHING] } {
+ set debug $::DEBUG_TUI_MATCHING
}
- # Setup the terminal with dimensions ROWSxCOLS, TERM=ansi, and execute
- # BODY.
- proc with_tuiterm {rows cols body} {
- global env stty_init
- save_vars {env(TERM) env(NO_COLOR) stty_init} {
- setenv TERM ansi
- setenv NO_COLOR ""
- _setup $rows $cols
+ if { ! $debug } {
+ return
+ }
- uplevel $body
- }
+ verbose -log "$arg"
+}
+
+# Accept some output from gdb and update the screen. WAIT_FOR is
+# a regexp matching the line to wait for. Return 0 on timeout, 1
+# on success.
+proc Term::wait_for {wait_for} {
+ global gdb_prompt
+ variable _cur_col
+ variable _cur_row
+
+ set fn "wait_for"
+
+ set prompt_wait_for "(^|\\|)$gdb_prompt \$"
+ if { $wait_for == "" } {
+ set wait_for $prompt_wait_for
}
- # Like ::clean_restart, but ensures that gdb starts in an
- # environment where the TUI can work. ROWS and COLS are the size
- # of the terminal. EXECUTABLE, if given, is passed to
- # clean_restart.
- proc clean_restart {rows cols {executable {}}} {
- with_tuiterm $rows $cols {
- save_vars { ::GDBFLAGS } {
- # Make GDB not print the directory names. Use this setting to
- # remove the differences in test runs due to varying directory
- # names.
- append ::GDBFLAGS " -ex \"set filename-display basename\""
+ debug_tui_matching "$fn: regexp: '$wait_for'"
- if {$executable == ""} {
- ::clean_restart
- } else {
- ::clean_restart $executable
- }
- }
+ while 1 {
+ if { [accept_gdb_output] == 0 } {
+ return 0
+ }
- ::gdb_test_no_output "set pagination off"
+ # If the cursor appears just after the prompt, return. It
+ # isn't reliable to check this only after an insertion,
+ # because curses may make "unusual" redrawing decisions.
+ if {$wait_for == "$prompt_wait_for"} {
+ set prev [get_line $_cur_row $_cur_col]
+ } else {
+ set prev [get_line $_cur_row]
}
- }
- # Generate prompt on TUIterm.
- proc gen_prompt {} {
- # Generate a prompt.
- send_gdb "echo\n"
+ if { ![regexp -- $wait_for $prev] } {
+ debug_tui_matching "$fn: mismatch: '$prev'"
+ continue
+ }
- # Drain the output before the prompt.
- gdb_expect {
- -re "echo\r\n" {
+ if {$wait_for == "$prompt_wait_for"} {
+ # We've detected that the cursor is just after the prompt.
+ # Now check that there's nothing else on the line.
+ set prev [get_line $_cur_row]
+ if { ![regexp -- "(^|\\|)$gdb_prompt +($|\\||\\+)" $prev] } {
+ debug_tui_matching "$fn: mismatch: '$prev'"
+ continue
}
}
- # Interpret prompt using TUIterm.
- wait_for ""
- }
+ debug_tui_matching "$fn: match: '$prev'"
- # Setup ready for starting the tui, but don't actually start it.
- # Returns 1 on success, 0 if TUI tests should be skipped.
- proc prepare_for_tui {} {
- if { [is_remote host] } {
- # In clean_restart, we're using "setenv TERM ansi", which has
- # effect on build. If we have [is_remote host] == 0, so
- # build == host, then it also has effect on host. But for
- # [is_remote host] == 1, it has no effect on host.
- return 0
+ if {$wait_for == "$prompt_wait_for"} {
+ # Matched the prompt, we're done.
+ break
}
- if {![allow_tui_tests]} {
+ # Now try to match the prompt.
+ set wait_for $prompt_wait_for
+ debug_tui_matching "$fn: regexp prompt: '$wait_for'"
+ }
+
+ return 1
+}
+
+# Accept some output from gdb and update the screen. Wait for the screen
+# region X/Y/WIDTH/HEIGTH to matches REGEXP. Return 0 on timeout, 1 on
+# success.
+proc Term::wait_for_region_contents {x y width height regexp} {
+ while 1 {
+ if { [accept_gdb_output] == 0 } {
return 0
}
- gdb_test_no_output "set tui border-kind ascii"
- gdb_test_no_output "maint set tui-resize-message on"
- return 1
+ if { [check_region_contents_p $x $y $width $height $regexp] } {
+ break
+ }
}
- # Start the TUI. Returns 1 on success, 0 if TUI tests should be
- # skipped.
- proc enter_tui {} {
- if {![prepare_for_tui]} {
+ return 1
+}
+
+# Accept some output from gdb and update the screen. Wait for the current
+# screen line to match REGEXP and cursor position POS, unless POS is empty.
+# Return 0 on timeout, 1 on success.
+proc Term::wait_for_line { regexp {pos ""} } {
+ variable _cur_row
+ variable _cur_col
+ variable _cols
+
+ while 1 {
+ if { [accept_gdb_output] == 0 } {
return 0
}
- command_no_prompt_prefix "tui enable"
- return 1
- }
+ if { ![check_region_contents_p 0 $_cur_row $_cols 1 $regexp] } {
+ continue
+ }
- # Send the command CMD to gdb, then wait for a gdb prompt to be
- # seen in the TUI. CMD should not end with a newline -- that will
- # be supplied by this function.
- proc command {cmd} {
- global gdb_prompt
- send_gdb "$cmd\n"
- set str [string_to_regexp $cmd]
- set str "(^|\\|)$gdb_prompt $str"
- wait_for $str
- }
-
- # As proc command, but don't wait for an initial prompt. This is used for
- # initial terminal commands, where there's no prompt yet.
- proc command_no_prompt_prefix {cmd} {
- gen_prompt
- command $cmd
- }
-
- # Apply the attribute list in ATTRS to attributes array UPVAR_NAME.
- # Return a string annotating the changed attributes.
- proc apply_attrs { upvar_name attrs } {
- set res ""
- upvar $upvar_name var
- foreach { attr val } $attrs {
- if { $var($attr) != $val } {
- append res "<$attr:$val>"
- set var($attr) $val
- }
+ if { $pos == "" || $_cur_col == $pos } {
+ break
}
+ }
- return $res
+ return 1
+}
+
+# In BODY, when using Term::with_tuiterm, use TERM instead of the default.
+
+proc Term::with_term { term body } {
+ save_vars { Term::_TERM } {
+ set Term::_TERM $term
+ uplevel $body
}
+}
- # Return the text of screen line N. Lines are 0-based. If C is given,
- # stop before column C. Columns are also zero-based. If ATTRS, annotate
- # with attributes.
- proc get_line_1 {n c attrs} {
- variable _rows
- # This can happen during resizing, if the cursor seems to
- # temporarily be off-screen.
- if {$n >= $_rows} {
- return ""
+# Setup the terminal with dimensions ROWSxCOLS, TERM=ansi, and execute
+# BODY.
+proc Term::with_tuiterm {rows cols body} {
+ global env stty_init
+ variable _TERM
+ save_vars {env(TERM) env(NO_COLOR) stty_init} {
+ if { $Term::_TERM != "" } {
+ setenv TERM $Term::_TERM
+ } elseif { [ishost *-*-*bsd*] } {
+ setenv TERM ansiw
+ } else {
+ setenv TERM ansi
}
+ # Save active TERM variable.
+ set Term::_TERM $env(TERM)
- set result ""
- variable _cols
- variable _chars
- set c [_default $c $_cols]
- set x 0
- if { $attrs } {
- _reset_attrs line_attrs
- }
- while {$x < $c} {
- if { $attrs } {
- set char_attrs [lindex $_chars($x,$n) 1]
- append result [apply_attrs line_attrs $char_attrs]
+ setenv NO_COLOR ""
+ _setup $rows $cols
+
+ uplevel $body
+ }
+}
+
+# Like ::clean_restart, but ensures that gdb starts in an
+# environment where the TUI can work. ROWS and COLS are the size
+# of the terminal. EXECUTABLE, if given, is passed to
+# clean_restart.
+proc Term::clean_restart {rows cols {executable {}}} {
+ with_tuiterm $rows $cols {
+ save_vars { ::GDBFLAGS } {
+ # Make GDB not print the directory names. Use this setting to
+ # remove the differences in test runs due to varying directory
+ # names.
+ append ::GDBFLAGS " -ex \"set filename-display basename\""
+
+ if {$executable == ""} {
+ ::clean_restart
+ } else {
+ ::clean_restart $executable
}
- append result [lindex $_chars($x,$n) 0]
- incr x
}
- if { $attrs } {
- _reset_attrs zero_attrs
- set char_attrs [array get zero_attrs]
- append result [apply_attrs line_attrs $char_attrs]
+
+ ::gdb_test_no_output "set pagination off"
+ }
+}
+
+# Generate prompt on TUIterm.
+proc Term::gen_prompt {} {
+ # Generate a prompt.
+ send_gdb "echo\n"
+
+ # Drain the output before the prompt.
+ gdb_expect {
+ -re "echo\r\n" {
}
- return $result
}
- # Return the text of screen line N, without attributes. Lines are
- # 0-based. If C is given, stop before column C. Columns are also
- # zero-based.
- proc get_line {n {c ""} } {
- return [get_line_1 $n $c 0]
+ # Interpret prompt using TUIterm.
+ wait_for ""
+}
+
+# Setup ready for starting the tui, but don't actually start it.
+# Returns 1 on success, 0 if TUI tests should be skipped.
+proc Term::prepare_for_tui {} {
+ if { [is_remote host] } {
+ # In clean_restart, we're using "setenv TERM ansi", which has
+ # effect on build. If we have [is_remote host] == 0, so
+ # build == host, then it also has effect on host. But for
+ # [is_remote host] == 1, it has no effect on host.
+ return 0
}
- # As get_line, but annotate with attributes.
- proc get_line_with_attrs {n {c ""}} {
- return [get_line_1 $n $c 1]
+ if {![allow_tui_tests]} {
+ return 0
}
- # Get just the character at (X, Y).
- proc get_char {x y} {
- variable _chars
- return [lindex $_chars($x,$y) 0]
+ gdb_test_no_output "set tui border-kind ascii"
+ gdb_test_no_output "maint set tui-resize-message on"
+ # When matching GDB output using Term::wait_for, the number of
+ # matching attempts in wait_for can be influenced by CLI styling.
+ # Disable it by default to avoid this.
+ gdb_test_no_output "set style enabled off"
+ return 1
+}
+
+# Start the TUI. Returns 1 on success, 0 if TUI tests should be
+# skipped.
+proc Term::enter_tui {} {
+ if {![prepare_for_tui]} {
+ return 0
}
- # Get the entire screen as a string.
- proc get_all_lines {} {
- variable _rows
- variable _cols
- variable _chars
+ command_no_prompt_prefix "tui enable"
+ return 1
+}
- set result ""
- for {set y 0} {$y < $_rows} {incr y} {
- for {set x 0} {$x < $_cols} {incr x} {
- append result [lindex $_chars($x,$y) 0]
- }
- append result "\n"
+# Send the command CMD to gdb, then wait for a gdb prompt to be
+# seen in the TUI. CMD should not end with a newline -- that will
+# be supplied by this function.
+proc Term::command {cmd} {
+ global gdb_prompt
+ send_gdb "$cmd\n"
+ set str [string_to_regexp $cmd]
+ set str "(^|\\|)$gdb_prompt $str"
+ wait_for $str
+}
+
+# As proc command, but don't wait for an initial prompt. This is used for
+# initial terminal commands, where there's no prompt yet.
+proc Term::command_no_prompt_prefix {cmd} {
+ gen_prompt
+ command $cmd
+}
+
+# Apply the attribute list in ATTRS to attributes array UPVAR_NAME.
+# Return a string annotating the changed attributes.
+proc Term::apply_attrs { upvar_name attrs } {
+ set res ""
+ upvar $upvar_name var
+ foreach { attr val } $attrs {
+ if { $var($attr) != $val } {
+ append res "<$attr:$val>"
+ set var($attr) $val
}
+ }
- return $result
+ return $res
+}
+
+# Return the text of screen line N. Lines are 0-based. Start at column
+# X. If C is non-empty, stop before column C. Columns are also
+# zero-based. If ATTRS, annotate with attributes.
+proc Term::get_string {n x c {attrs 0}} {
+ variable _rows
+ # This can happen during resizing, if the cursor seems to
+ # temporarily be off-screen.
+ if {$n >= $_rows} {
+ return ""
}
- # Get the text just before the cursor.
- proc get_current_line {} {
- variable _cur_col
- variable _cur_row
- return [get_line $_cur_row $_cur_col]
+ set result ""
+ variable _cols
+ variable _chars
+ set c [_default $c $_cols]
+ if { $attrs } {
+ _reset_attrs line_attrs
}
+ while {$x < $c} {
+ if { $attrs } {
+ set char_attrs [lindex $_chars($x,$n) 1]
+ append result [apply_attrs line_attrs $char_attrs]
+ }
+ append result [lindex $_chars($x,$n) 0]
+ incr x
+ }
+ if { $attrs } {
+ _reset_attrs zero_attrs
+ set char_attrs [array get zero_attrs]
+ append result [apply_attrs line_attrs $char_attrs]
+ }
+ return $result
+}
- # Helper function for check_box. Returns empty string if the box
- # is found, description of why not otherwise.
- proc _check_box {x y width height} {
- set x2 [expr {$x + $width - 1}]
- set y2 [expr {$y + $height - 1}]
+# Return the text of screen line N. Lines are 0-based. Start at column
+# X. If C is non-empty, stop before column C. Columns are also
+# zero-based. Annotate with attributes.
+proc Term::get_string_with_attrs { n x c } {
+ return [get_string $n $x $c 1]
+}
- verbose -log "_check_box x=$x, y=$y, x2=$x2, y2=$y2, width=$width, height=$height"
+# Return the text of screen line N. Lines are 0-based. If C is
+# non-empty, stop before column C. Columns are also zero-based. If
+# ATTRS, annotate with attributes.
+proc Term::get_line_1 {n c attrs} {
+ return [get_string $n 0 $c $attrs]
+}
- set c [get_char $x $y]
- if {$c != "+"} {
- return "ul corner is $c, not +"
- }
+# Return the text of screen line N, without attributes. Lines are
+# 0-based. If C is given, stop before column C. Columns are also
+# zero-based.
+proc Term::get_line {n {c ""} } {
+ return [get_line_1 $n $c 0]
+}
- set c [get_char $x $y2]
- if {$c != "+"} {
- return "ll corner is $c, not +"
- }
+# As get_line, but annotate with attributes.
+proc Term::get_line_with_attrs {n {c ""}} {
+ return [get_line_1 $n $c 1]
+}
- set c [get_char $x2 $y]
- if {$c != "+"} {
- return "ur corner is $c, not +"
- }
+# Get just the character at (X, Y).
+proc Term::get_char {x y} {
+ variable _chars
+ return [lindex $_chars($x,$y) 0]
+}
- set c [get_char $x2 $y2]
- if {$c != "+"} {
- return "lr corner is $c, not +"
- }
+# Get the entire screen as a string.
+proc Term::get_all_lines {} {
+ variable _rows
+ variable _cols
+ variable _chars
- # Note we do not check the full horizonal borders of the box.
- # The top will contain a title, and the bottom may as well, if
- # it is overlapped by some other border. However, at most a
- # title should appear as '+-VERY LONG TITLE-+', so we can
- # check for the '+-' on the left, and '-+' on the right.
- set c [get_char [expr {$x + 1}] $y]
- if {$c != "-"} {
- return "ul title padding is $c, not -"
+ set result ""
+ for {set y 0} {$y < $_rows} {incr y} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ append result [lindex $_chars($x,$y) 0]
}
+ append result "\n"
+ }
- set c [get_char [expr {$x2 - 1}] $y]
- if {$c != "-"} {
- return "ul title padding is $c, not -"
- }
+ return $result
+}
- # Now check the vertical borders.
- for {set i [expr {$y + 1}]} {$i < $y2 - 1} {incr i} {
- set c [get_char $x $i]
- if {$c != "|"} {
- return "left side $i is $c, not |"
- }
+# Get the text just before the cursor.
+proc Term::get_current_line {} {
+ variable _cur_col
+ variable _cur_row
+ return [get_line $_cur_row $_cur_col]
+}
- set c [get_char $x2 $i]
- if {$c != "|"} {
- return "right side $i is $c, not |"
- }
- }
+# Helper function for check_box. Returns empty string if the box
+# is found, description of why not otherwise.
+proc Term::_check_box {x y width height} {
+ set x2 [expr {$x + $width - 1}]
+ set y2 [expr {$y + $height - 1}]
- return ""
+ verbose -log "_check_box x=$x, y=$y, x2=$x2, y2=$y2, width=$width, height=$height"
+
+ set c [get_char $x $y]
+ if {$c != "+"} {
+ return "ul corner is $c, not +"
}
- # Check for a box at the given coordinates.
- proc check_box {test_name x y width height} {
- dump_box $x $y $width $height
- set why [_check_box $x $y $width $height]
- if {$why == ""} {
- pass $test_name
- } else {
- fail "$test_name ($why)"
- }
+ set c [get_char $x $y2]
+ if {$c != "+"} {
+ return "ll corner is $c, not +"
}
- # Wait until a box appears at the given coordinates.
- proc wait_for_box {test_name x y width height} {
- while 1 {
- if { [accept_gdb_output] == 0 } {
- return 0
- }
+ set c [get_char $x2 $y]
+ if {$c != "+"} {
+ return "ur corner is $c, not +"
+ }
- set why [_check_box $x $y $width $height]
- if {$why == ""} {
- pass $test_name
- break
- }
- }
+ set c [get_char $x2 $y2]
+ if {$c != "+"} {
+ return "lr corner is $c, not +"
}
- # Check whether the text contents of the terminal match the
- # regular expression. Note that text styling is not considered.
- proc check_contents {test_name regexp} {
- dump_screen
- set contents [get_all_lines]
- gdb_assert {[regexp -- $regexp $contents]} $test_name
+ # Note we do not check the full horizonal borders of the box.
+ # The top will contain a title, and the bottom may as well, if
+ # it is overlapped by some other border. However, at most a
+ # title should appear as '+-VERY LONG TITLE-+', so we can
+ # check for the '+-' on the left, and '-+' on the right.
+ set c [get_char [expr {$x + 1}] $y]
+ if {$c != "-"} {
+ return "ul title padding is $c, not -"
}
- # As check_contents, but check that the text contents of the terminal does
- # not match the regular expression.
- proc check_contents_not {test_name regexp} {
- dump_screen
- set contents [get_all_lines]
- gdb_assert {![regexp -- $regexp $contents]} $test_name
+ set c [get_char [expr {$x2 - 1}] $y]
+ if {$c != "-"} {
+ return "ul title padding is $c, not -"
}
- # Get the region of the screen described by X, Y, WIDTH, and
- # HEIGHT, and separate the lines using SEP. If ATTRS is true then
- # include attribute information in the output.
- proc get_region { x y width height sep { attrs false } } {
- variable _chars
+ # Now check the vertical borders.
+ for {set i [expr {$y + 1}]} {$i < $y2 - 1} {incr i} {
+ set c [get_char $x $i]
+ if {$c != "|"} {
+ return "left side $i is $c, not |"
+ }
- if { $attrs } {
- _reset_attrs region_attrs
+ set c [get_char $x2 $i]
+ if {$c != "|"} {
+ return "right side $i is $c, not |"
}
+ }
- # Grab the contents of the box, join each line together
- # using $sep.
- set result ""
- for {set yy $y} {$yy < [expr {$y + $height}]} {incr yy} {
- if {$yy > $y} {
- # Add the end of line sequence only if this isn't the
- # first line.
- append result $sep
- }
- for {set xx $x} {$xx < [expr {$x + $width}]} {incr xx} {
- if { $attrs } {
- set char_attrs [lindex $_chars($xx,$yy) 1]
- append result [apply_attrs region_attrs $char_attrs]
- }
+ return ""
+}
- append result [get_char $xx $yy]
- }
+# Check for a box at the given coordinates.
+proc Term::check_box {test_name x y width height} {
+ dump_box $x $y $width $height
+ set why [_check_box $x $y $width $height]
+ if {$why == ""} {
+ pass $test_name
+ } else {
+ fail "$test_name ($why)"
+ }
+}
+
+# Wait until a box appears at the given coordinates.
+proc Term::wait_for_box {test_name x y width height} {
+ while 1 {
+ if { [accept_gdb_output] == 0 } {
+ return 0
}
- if { $attrs } {
- _reset_attrs zero_attrs
- set char_attrs [array get zero_attrs]
- append result [apply_attrs region_attrs $char_attrs]
+
+ set why [_check_box $x $y $width $height]
+ if {$why == ""} {
+ pass $test_name
+ break
}
- return $result
}
+}
- # Check that the region of the screen described by X, Y, WIDTH,
- # and HEIGHT match REGEXP. This is like check_contents except
- # only part of the screen is checked. This can be used to check
- # the contents within a box (though check_box_contents is a better
- # choice for boxes with a border). Return 1 if check succeeded.
- proc check_region_contents_p { x y width height regexp } {
- variable _chars
- dump_box $x $y $width $height
+# Check whether the text contents of the terminal match the
+# regular expression. Note that text styling is not considered.
+proc Term::check_contents {test_name regexp} {
+ dump_screen
+ set contents [get_all_lines]
+ gdb_assert {[regexp -- $regexp $contents]} $test_name
+}
- # Now grab the contents of the box, join each line together
- # with a '\r\n' sequence and match against REGEXP.
- set result [get_region $x $y $width $height "\r\n"]
- return [regexp -- $regexp $result]
- }
+# As check_contents, but check that the text contents of the terminal does
+# not match the regular expression.
+proc Term::check_contents_not {test_name regexp} {
+ dump_screen
+ set contents [get_all_lines]
+ gdb_assert {![regexp -- $regexp $contents]} $test_name
+}
- # Check that the region of the screen described by X, Y, WIDTH,
- # and HEIGHT match REGEXP. As check_region_contents_p, but produce
- # a pass/fail message.
- proc check_region_contents { test_name x y width height regexp } {
- set ok [check_region_contents_p $x $y $width $height $regexp]
- gdb_assert {$ok} $test_name
- }
+# Get the region of the screen described by X, Y, WIDTH, and
+# HEIGHT, and separate the lines using SEP. If ATTRS is true then
+# include attribute information in the output.
+proc Term::get_region { x y width height sep { attrs false } } {
+ variable _chars
- # Check the contents of a box on the screen. This is a little
- # like check_contents, but doesn't check the whole screen
- # contents, only the contents of a single box. This procedure
- # includes (effectively) a call to check_box to ensure there is a
- # box where expected, if there is then the contents of the box are
- # matched against REGEXP.
- proc check_box_contents {test_name x y width height regexp} {
- variable _chars
+ if { $attrs } {
+ _reset_attrs region_attrs
+ }
- dump_box $x $y $width $height
- set why [_check_box $x $y $width $height]
- if {$why != ""} {
- fail "$test_name (box check: $why)"
- return
+ # Grab the contents of the box, join each line together
+ # using $sep.
+ set result ""
+ for {set yy $y} {$yy < $y + $height} {incr yy} {
+ if {$yy > $y} {
+ # Add the end of line sequence only if this isn't the
+ # first line.
+ append result $sep
}
+ for {set xx $x} {$xx < $x + $width} {incr xx} {
+ if { $attrs } {
+ set char_attrs [lindex $_chars($xx,$yy) 1]
+ append result [apply_attrs region_attrs $char_attrs]
+ }
- check_region_contents $test_name [expr {$x + 1}] [expr {$y + 1}] \
- [expr {$width - 2}] [expr {$height - 2}] $regexp
+ append result [get_char $xx $yy]
+ }
+ }
+ if { $attrs } {
+ _reset_attrs zero_attrs
+ set char_attrs [array get zero_attrs]
+ append result [apply_attrs region_attrs $char_attrs]
}
+ return $result
+}
- # A debugging function to dump the current screen, with line
- # numbers. If ATTRS, annotate with attributes.
- proc dump_screen { {attrs 0} } {
- variable _rows
- variable _cols
- variable _cur_row
- variable _cur_col
+# Check that the region of the screen described by X, Y, WIDTH,
+# and HEIGHT match REGEXP. This is like check_contents except
+# only part of the screen is checked. This can be used to check
+# the contents within a box (though check_box_contents is a better
+# choice for boxes with a border). Return 1 if check succeeded.
+proc Term::check_region_contents_p { x y width height regexp } {
+ variable _chars
+ dump_box $x $y $width $height
- verbose -log "Screen Dump (size $_cols columns x $_rows rows, cursor at column $_cur_col, row $_cur_row):"
+ # Now grab the contents of the box, join each line together
+ # with a '\r\n' sequence and match against REGEXP.
+ set result [get_region $x $y $width $height "\r\n"]
+ return [regexp -- $regexp $result]
+}
- for {set y 0} {$y < $_rows} {incr y} {
- set fmt [format %5d $y]
- verbose -log "$fmt [get_line_1 $y "" $attrs]"
- }
+# Check that the region of the screen described by X, Y, WIDTH,
+# and HEIGHT match REGEXP. As check_region_contents_p, but produce
+# a pass/fail message.
+proc Term::check_region_contents { test_name x y width height regexp } {
+ set ok [check_region_contents_p $x $y $width $height $regexp]
+ gdb_assert {$ok} $test_name
+}
+
+# Check the contents of a box on the screen. This is a little
+# like check_contents, but doesn't check the whole screen
+# contents, only the contents of a single box. This procedure
+# includes (effectively) a call to check_box to ensure there is a
+# box where expected, if there is then the contents of the box are
+# matched against REGEXP.
+proc Term::check_box_contents {test_name x y width height regexp} {
+ variable _chars
+
+ dump_box $x $y $width $height
+ set why [_check_box $x $y $width $height]
+ if {$why != ""} {
+ fail "$test_name (box check: $why)"
+ return
}
- # As dump_screen, but with attributes annotation.
- proc dump_screen_with_attrs {} {
- return [dump_screen 1]
+ check_region_contents $test_name [expr {$x + 1}] [expr {$y + 1}] \
+ [expr {$width - 2}] [expr {$height - 2}] $regexp
+}
+
+# A debugging function to dump the current screen, with line
+# numbers. If ATTRS, annotate with attributes.
+proc Term::dump_screen { {attrs 0} } {
+ variable _rows
+ variable _cols
+ variable _cur_row
+ variable _cur_col
+
+ verbose -log "Screen Dump (size $_cols columns x $_rows rows, cursor at column $_cur_col, row $_cur_row):"
+
+ for {set y 0} {$y < $_rows} {incr y} {
+ set fmt [format %5d $y]
+ verbose -log "$fmt [get_line_1 $y {} $attrs]"
}
+}
- # A debugging function to dump a box from the current screen, with line
- # numbers.
- proc dump_box { x y width height } {
- verbose -log "Box Dump ($width x $height) @ ($x, $y):"
- set region [get_region $x $y $width $height "\n"]
- set lines [split $region "\n"]
- set nr $y
- foreach line $lines {
- set fmt [format %5d $nr]
- verbose -log "$fmt $line"
- incr nr
- }
+# As dump_screen, but with attributes annotation.
+proc Term::dump_screen_with_attrs {} {
+ return [dump_screen 1]
+}
+
+# A debugging function to dump a box from the current screen, with line
+# numbers.
+proc Term::dump_box { x y width height } {
+ verbose -log "Box Dump ($width x $height) @ ($x, $y):"
+ set region [get_region $x $y $width $height "\n"]
+ set lines [split $region "\n"]
+ set nr $y
+ foreach line $lines {
+ set fmt [format %5d $nr]
+ verbose -log "$fmt $line"
+ incr nr
}
+}
- # Resize the terminal.
- proc _do_resize {rows cols} {
- variable _chars
- variable _rows
- variable _cols
+# Resize the terminal.
+proc Term::_do_resize {rows cols} {
+ variable _chars
+ variable _rows
+ variable _cols
- set old_rows [expr {min ($_rows, $rows)}]
- set old_cols [expr {min ($_cols, $cols)}]
+ set old_rows [expr {min ($_rows, $rows)}]
+ set old_cols [expr {min ($_cols, $cols)}]
- # Copy locally.
- array set local_chars [array get _chars]
- unset _chars
+ # Copy locally.
+ array set local_chars [array get _chars]
+ unset _chars
- set _rows $rows
- set _cols $cols
- _clear_lines 0 $_rows
+ set _rows $rows
+ set _cols $cols
+ _clear_lines 0 $_rows
- for {set x 0} {$x < $old_cols} {incr x} {
- for {set y 0} {$y < $old_rows} {incr y} {
- set _chars($x,$y) $local_chars($x,$y)
- }
+ for {set x 0} {$x < $old_cols} {incr x} {
+ for {set y 0} {$y < $old_rows} {incr y} {
+ set _chars($x,$y) $local_chars($x,$y)
}
}
+}
- proc resize {rows cols {wait_for_msg 1}} {
- variable _rows
- variable _cols
- variable _resize_count
+proc Term::resize {rows cols {wait_for_msg 1}} {
+ variable _rows
+ variable _cols
+ variable _resize_count
- # expect handles each argument to stty separately. This means
- # that gdb will see SIGWINCH twice. Rather than rely on this
- # behavior (which, after all, could be changed), we make it
- # explicit here. This also simplifies waiting for the redraw.
- _do_resize $rows $_cols
- stty rows $_rows < $::gdb_tty_name
- if { $wait_for_msg } {
- wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}"
- }
- incr _resize_count
- _do_resize $_rows $cols
- stty columns $_cols < $::gdb_tty_name
- if { $wait_for_msg } {
- wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}"
- }
- incr _resize_count
- }
+ # expect handles each argument to stty separately. This means
+ # that gdb will see SIGWINCH twice. Rather than rely on this
+ # behavior (which, after all, could be changed), we make it
+ # explicit here. This also simplifies waiting for the redraw.
+ _do_resize $rows $_cols
+ stty rows $_rows < $::gdb_tty_name
+ if { $wait_for_msg } {
+ wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}"
+ }
+ incr _resize_count
+ _do_resize $_rows $cols
+ stty columns $_cols < $::gdb_tty_name
+ if { $wait_for_msg } {
+ wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}"
+ }
+ incr _resize_count
}
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
}
diff --git a/gdb/thread.c b/gdb/thread.c
index b659463..b6c19f9 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -33,7 +33,6 @@
#include "regcache.h"
#include "btrace.h"
-#include <ctype.h>
#include <sys/types.h>
#include <signal.h>
#include "ui-out.h"
@@ -1038,6 +1037,37 @@ pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread)
&& pc < thread->control.step_range_end);
}
+/* The options for the "info threads" command. */
+
+struct info_threads_opts
+{
+ /* For "-gid". */
+ bool show_global_ids = false;
+ /* For "-running". */
+ bool show_running_threads = false;
+ /* For "-stopped". */
+ bool show_stopped_threads = false;
+};
+
+static const gdb::option::option_def info_threads_option_defs[] = {
+
+ gdb::option::flag_option_def<info_threads_opts> {
+ "gid",
+ [] (info_threads_opts *opts) { return &opts->show_global_ids; },
+ N_("Show global thread IDs."),
+ },
+ gdb::option::flag_option_def<info_threads_opts> {
+ "running",
+ [] (info_threads_opts *opts) { return &opts->show_running_threads; },
+ N_("Show running threads only."),
+ },
+ gdb::option::flag_option_def<info_threads_opts> {
+ "stopped",
+ [] (info_threads_opts *opts) { return &opts->show_stopped_threads; },
+ N_("Show stopped threads only."),
+ },
+};
+
/* Helper for print_thread_info. Returns true if THR should be
printed. If REQUESTED_THREADS, a list of GDB ids/ranges, is not
NULL, only print THR if its ID is included in the list. GLOBAL_IDS
@@ -1046,11 +1076,13 @@ pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread)
is a thread from the process PID. Otherwise, threads from all
attached PIDs are printed. If both REQUESTED_THREADS is not NULL
and PID is not -1, then the thread is printed if it belongs to the
- specified process. Otherwise, an error is raised. */
+ specified process. Otherwise, an error is raised. OPTS is the
+ options of the "info threads" command. */
static bool
-should_print_thread (const char *requested_threads, int default_inf_num,
- int global_ids, int pid, struct thread_info *thr)
+should_print_thread (const char *requested_threads,
+ const info_threads_opts &opts, int default_inf_num,
+ int global_ids, int pid, thread_info *thr)
{
if (requested_threads != NULL && *requested_threads != '\0')
{
@@ -1075,7 +1107,17 @@ should_print_thread (const char *requested_threads, int default_inf_num,
if (thr->state == THREAD_EXITED)
return false;
- return true;
+ bool is_stopped = (thr->state == THREAD_STOPPED);
+ if (opts.show_stopped_threads && is_stopped)
+ return true;
+
+ bool is_running = (thr->state == THREAD_RUNNING);
+ if (opts.show_running_threads && is_running)
+ return true;
+
+ /* If the user did not pass a filter flag, show the thread. */
+ return (!opts.show_stopped_threads
+ && !opts.show_running_threads);
}
/* Return the string to display in "info threads"'s "Target Id"
@@ -1104,8 +1146,8 @@ thread_target_id_str (thread_info *tp)
static void
do_print_thread (ui_out *uiout, const char *requested_threads,
- int global_ids, int pid, int show_global_ids,
- int default_inf_num, thread_info *tp,
+ const info_threads_opts &opts, int global_ids,
+ int pid, int default_inf_num, thread_info *tp,
thread_info *current_thread)
{
int core;
@@ -1114,7 +1156,7 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
if (current_thread != nullptr)
switch_to_thread (current_thread);
- if (!should_print_thread (requested_threads, default_inf_num,
+ if (!should_print_thread (requested_threads, opts, default_inf_num,
global_ids, pid, tp))
return;
@@ -1130,7 +1172,7 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
uiout->field_string ("id-in-tg", print_thread_id (tp));
}
- if (show_global_ids || uiout->is_mi_like_p ())
+ if (opts.show_global_ids || uiout->is_mi_like_p ())
uiout->field_signed ("id", tp->global_num);
/* Switch to the thread (and inferior / target). */
@@ -1191,23 +1233,22 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
static void
print_thread (ui_out *uiout, const char *requested_threads,
- int global_ids, int pid, int show_global_ids,
+ const info_threads_opts &opts, int global_ids, int pid,
int default_inf_num, thread_info *tp, thread_info *current_thread)
{
do_with_buffered_output (do_print_thread, uiout, requested_threads,
- global_ids, pid, show_global_ids,
- default_inf_num, tp, current_thread);
+ opts, global_ids, pid, default_inf_num, tp,
+ current_thread);
}
/* Like print_thread_info, but in addition, GLOBAL_IDS indicates
whether REQUESTED_THREADS is a list of global or per-inferior
- thread ids. */
+ thread ids. OPTS is the options of the "info threads" command. */
static void
print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
- int global_ids, int pid,
- int show_global_ids)
+ const info_threads_opts &opts, int global_ids, int pid)
{
int default_inf_num = current_inferior ()->num;
@@ -1235,19 +1276,21 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
list_emitter.emplace (uiout, "threads");
else
{
- int n_threads = 0;
+ int n_matching_threads = 0;
/* The width of the "Target Id" column. Grown below to
accommodate the largest entry. */
size_t target_id_col_width = 17;
for (thread_info *tp : all_threads ())
{
+ any_thread = true;
+
/* In case REQUESTED_THREADS contains $_thread. */
if (current_thread != nullptr)
switch_to_thread (current_thread);
- if (!should_print_thread (requested_threads, default_inf_num,
- global_ids, pid, tp))
+ if (!should_print_thread (requested_threads, opts,
+ default_inf_num, global_ids, pid, tp))
continue;
/* Switch inferiors so we're looking at the right
@@ -1258,25 +1301,24 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
= std::max (target_id_col_width,
thread_target_id_str (tp).size ());
- ++n_threads;
+ ++n_matching_threads;
}
- if (n_threads == 0)
+ if (n_matching_threads == 0)
{
- if (requested_threads == NULL || *requested_threads == '\0')
+ if (!any_thread)
uiout->message (_("No threads.\n"));
else
- uiout->message (_("No threads match '%s'.\n"),
- requested_threads);
+ uiout->message (_("No threads matched.\n"));
return;
}
- table_emitter.emplace (uiout, show_global_ids ? 5 : 4,
- n_threads, "threads");
+ table_emitter.emplace (uiout, opts.show_global_ids ? 5 : 4,
+ n_matching_threads, "threads");
uiout->table_header (1, ui_left, "current", "");
uiout->table_header (4, ui_left, "id-in-tg", "Id");
- if (show_global_ids)
+ if (opts.show_global_ids)
uiout->table_header (4, ui_left, "id", "GId");
uiout->table_header (target_id_col_width, ui_left,
"target-id", "Target Id");
@@ -1287,13 +1329,11 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
for (inferior *inf : all_inferiors ())
for (thread_info *tp : inf->threads ())
{
- any_thread = true;
-
if (tp == current_thread && tp->state == THREAD_EXITED)
current_exited = true;
- print_thread (uiout, requested_threads, global_ids, pid,
- show_global_ids, default_inf_num, tp, current_thread);
+ print_thread (uiout, requested_threads, opts, global_ids, pid,
+ default_inf_num, tp, current_thread);
}
/* This end scope restores the current thread and the frame
@@ -1322,27 +1362,10 @@ void
print_thread_info (struct ui_out *uiout, const char *requested_threads,
int pid)
{
- print_thread_info_1 (uiout, requested_threads, 1, pid, 0);
+ info_threads_opts opts;
+ print_thread_info_1 (uiout, requested_threads, opts, 1, pid);
}
-/* The options for the "info threads" command. */
-
-struct info_threads_opts
-{
- /* For "-gid". */
- bool show_global_ids = false;
-};
-
-static const gdb::option::option_def info_threads_option_defs[] = {
-
- gdb::option::flag_option_def<info_threads_opts> {
- "gid",
- [] (info_threads_opts *opts) { return &opts->show_global_ids; },
- N_("Show global thread IDs."),
- },
-
-};
-
/* Create an option_def_group for the "info threads" options, with
IT_OPTS as context. */
@@ -1367,7 +1390,7 @@ info_threads_command (const char *arg, int from_tty)
gdb::option::process_options
(&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp);
- print_thread_info_1 (current_uiout, arg, 0, -1, it_opts.show_global_ids);
+ print_thread_info_1 (current_uiout, arg, it_opts, 0, -1);
}
/* Completer for the "info threads" command. */
@@ -1784,7 +1807,7 @@ thread_apply_command_completer (cmd_list_element *ignore,
/* Check if we're past a valid thread ID list already. */
if (parser.finished ()
- && cmd > text && !isspace (cmd[-1]))
+ && cmd > text && !c_isspace (cmd[-1]))
return;
/* We're past the thread ID list, advance word point. */
@@ -1847,7 +1870,7 @@ thread_apply_command (const char *tidlist, int from_tty)
if (*cmd == '\0')
error (_("Please specify a command following the thread ID list"));
- if (tidlist == cmd || isdigit (cmd[0]))
+ if (tidlist == cmd || c_isdigit (cmd[0]))
invalid_thread_id_error (cmd);
scoped_restore_current_thread restore_thread;
@@ -2287,9 +2310,7 @@ static const struct internalvar_funcs inferior_thread_count_funcs =
NULL,
};
-void _initialize_thread ();
-void
-_initialize_thread ()
+INIT_GDB_FILE (thread)
{
static struct cmd_list_element *thread_apply_list = NULL;
cmd_list_element *c;
diff --git a/gdb/tic6x-linux-tdep.c b/gdb/tic6x-linux-tdep.c
index 280d46d..5b3d402 100644
--- a/gdb/tic6x-linux-tdep.c
+++ b/gdb/tic6x-linux-tdep.c
@@ -169,7 +169,7 @@ tic6x_uclinux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
linux_init_abi (info, gdbarch, 0);
/* Shared library handling. */
- set_gdbarch_so_ops (gdbarch, &dsbt_so_ops);
+ set_gdbarch_make_solib_ops (gdbarch, make_dsbt_solib_ops);
tdep->syscall_next_pc = tic6x_linux_syscall_next_pc;
@@ -203,9 +203,7 @@ tic6x_uclinux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
&tic6x_linux_rt_sigreturn_tramp_frame);
}
-void _initialize_tic6x_linux_tdep ();
-void
-_initialize_tic6x_linux_tdep ()
+INIT_GDB_FILE (tic6x_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_tic6x, 0, GDB_OSABI_LINUX,
tic6x_uclinux_init_abi);
diff --git a/gdb/tic6x-tdep.c b/gdb/tic6x-tdep.c
index 062a974..56d3098 100644
--- a/gdb/tic6x-tdep.c
+++ b/gdb/tic6x-tdep.c
@@ -1267,7 +1267,7 @@ tic6x_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
dwarf2_frame_set_init_reg (gdbarch, tic6x_dwarf2_frame_init_reg);
/* Single stepping. */
- set_gdbarch_software_single_step (gdbarch, tic6x_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, tic6x_software_single_step);
/* Call dummy code. */
set_gdbarch_frame_align (gdbarch, tic6x_frame_align);
@@ -1293,9 +1293,7 @@ tic6x_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_tic6x_tdep ();
-void
-_initialize_tic6x_tdep ()
+INIT_GDB_FILE (tic6x_tdep)
{
gdbarch_register (bfd_arch_tic6x, tic6x_gdbarch_init);
}
diff --git a/gdb/tid-parse.c b/gdb/tid-parse.c
index 4e45798..9f79fba 100644
--- a/gdb/tid-parse.c
+++ b/gdb/tid-parse.c
@@ -20,7 +20,6 @@
#include "tid-parse.h"
#include "inferior.h"
#include "gdbthread.h"
-#include <ctype.h>
/* See tid-parse.h. */
@@ -184,7 +183,7 @@ tid_range_parser::finished () const
or we are not in a range and not in front of an integer, negative
integer, convenience var or negative convenience var. */
return (*m_cur_tok == '\0'
- || !(isdigit (*m_cur_tok)
+ || !(c_isdigit (*m_cur_tok)
|| *m_cur_tok == '$'
|| *m_cur_tok == '*'));
case STATE_THREAD_RANGE:
@@ -261,7 +260,7 @@ tid_range_parser::get_tid_or_range (int *inf_num,
m_qualified = true;
p = dot + 1;
- if (isspace (*p))
+ if (c_isspace (*p))
return false;
}
else
@@ -272,7 +271,7 @@ tid_range_parser::get_tid_or_range (int *inf_num,
}
m_range_parser.init (p);
- if (p[0] == '*' && (p[1] == '\0' || isspace (p[1])))
+ if (p[0] == '*' && (p[1] == '\0' || c_isspace (p[1])))
{
/* Setup the number range parser to return numbers in the
whole [1,INT_MAX] range. */
diff --git a/gdb/tilegx-linux-nat.c b/gdb/tilegx-linux-nat.c
index bd077b2..99f2cc4 100644
--- a/gdb/tilegx-linux-nat.c
+++ b/gdb/tilegx-linux-nat.c
@@ -163,9 +163,7 @@ tilegx_linux_nat_target::store_registers (struct regcache *regcache,
perror_with_name (_("Couldn't write registers"));
}
-void _initialize_tile_linux_nat ();
-void
-_initialize_tile_linux_nat ()
+INIT_GDB_FILE (tile_linux_nat)
{
linux_target = &the_tilegx_linux_nat_target;
add_inf_child_target (&the_tilegx_linux_nat_target);
diff --git a/gdb/tilegx-linux-tdep.c b/gdb/tilegx-linux-tdep.c
index a0e6954..f54e280 100644
--- a/gdb/tilegx-linux-tdep.c
+++ b/gdb/tilegx-linux-tdep.c
@@ -19,6 +19,7 @@
#include "osabi.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "glibc-tdep.h"
#include "solib-svr4.h"
#include "symtab.h"
@@ -119,11 +120,9 @@ tilegx_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* GNU/Linux uses SVR4-style shared libraries. */
if (arch_size == 32)
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
else
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- linux_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_lp64_svr4_solib_ops);
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
@@ -134,9 +133,7 @@ tilegx_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
}
-void _initialize_tilegx_linux_tdep ();
-void
-_initialize_tilegx_linux_tdep ()
+INIT_GDB_FILE (tilegx_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_tilegx, bfd_mach_tilegx, GDB_OSABI_LINUX,
tilegx_linux_init_abi);
diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c
index 4922fff..a153f65 100644
--- a/gdb/tilegx-tdep.c
+++ b/gdb/tilegx-tdep.c
@@ -1021,9 +1021,7 @@ tilegx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_tilegx_tdep ();
-void
-_initialize_tilegx_tdep ()
+INIT_GDB_FILE (tilegx_tdep)
{
gdbarch_register (bfd_arch_tilegx, tilegx_gdbarch_init);
}
diff --git a/gdb/top.c b/gdb/top.c
index 6adef46..f5b9fdc 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -34,6 +34,7 @@
#include "value.h"
#include "language.h"
#include "terminal.h"
+#include "gdbsupport/cleanups.h"
#include "gdbsupport/job-control.h"
#include "annotate.h"
#include "completer.h"
@@ -68,7 +69,6 @@
#include "event-top.h"
#include <sys/stat.h>
-#include <ctype.h>
#include "ui-out.h"
#include "cli-out.h"
#include "tracepoint.h"
@@ -415,7 +415,7 @@ wait_sync_command_done (void)
point. */
scoped_enable_commit_resumed enable ("sync wait");
- while (gdb_do_one_event () >= 0)
+ while (current_interpreter ()->do_one_event () >= 0)
if (ui->prompt_state != PROMPT_BLOCKED)
break;
}
@@ -1031,7 +1031,7 @@ gdb_readline_wrapper (const char *prompt)
(*after_char_processing_hook) ();
gdb_assert (after_char_processing_hook == NULL);
- while (gdb_do_one_event () >= 0)
+ while (current_interpreter ()->do_one_event () >= 0)
if (gdb_readline_wrapper_done)
break;
@@ -1311,7 +1311,7 @@ print_gdb_version (struct ui_file *stream, bool interactive)
/* Second line is a copyright notice. */
gdb_printf (stream,
- "Copyright (C) 2024 Free Software Foundation, Inc.\n");
+ "Copyright (C) 2025 Free Software Foundation, Inc.\n");
/* Following the copyright is a brief statement that the program is
free software, that users are free to copy and change it on
@@ -1595,6 +1595,11 @@ This GDB was configured as follows:\n\
--with-system-gdbinit-dir=%s%s\n\
"), SYSTEM_GDBINIT_DIR, SYSTEM_GDBINIT_DIR_RELOCATABLE ? " (relocatable)" : "");
+#ifdef SUPPORTED_BINARY_FILE_FORMATS
+ gdb_printf (stream, _("\
+ --enable-binary-file-formats=%s\n"), SUPPORTED_BINARY_FILE_FORMATS);
+#endif
+
/* We assume "relocatable" will be printed at least once, thus we always
print this text. It's a reasonably safe assumption for now. */
gdb_printf (stream, _("\n\
@@ -2347,9 +2352,7 @@ gdb_init ()
init_colorsupport_var ();
}
-void _initialize_top ();
-void
-_initialize_top ()
+INIT_GDB_FILE (top)
{
/* Determine a default value for the history filename. */
const char *tmpenv = getenv ("GDBHISTFILE");
diff --git a/gdb/tracectf.c b/gdb/tracectf.c
index 1650e67..c2231ff 100644
--- a/gdb/tracectf.c
+++ b/gdb/tracectf.c
@@ -28,7 +28,6 @@
#include "inferior.h"
#include "gdbthread.h"
#include "tracefile.h"
-#include <ctype.h>
#include <algorithm>
#include "gdbsupport/filestuff.h"
#include "gdbarch.h"
@@ -1174,7 +1173,7 @@ ctf_target_open (const char *args, int from_tty)
merge_uploaded_trace_state_variables (&uploaded_tsvs);
merge_uploaded_tracepoints (&uploaded_tps);
- post_create_inferior (from_tty);
+ post_create_inferior (from_tty, true);
}
/* This is the implementation of target_ops method to_close. Destroy
@@ -1717,9 +1716,7 @@ ctf_target::traceframe_info ()
/* module initialization */
-void _initialize_ctf ();
-void
-_initialize_ctf ()
+INIT_GDB_FILE (ctf)
{
#if HAVE_LIBBABELTRACE
add_target (ctf_target_info, ctf_target_open,
diff --git a/gdb/tracefile-tfile.c b/gdb/tracefile-tfile.c
index c2b5e3b..a45001c 100644
--- a/gdb/tracefile-tfile.c
+++ b/gdb/tracefile-tfile.c
@@ -194,12 +194,12 @@ tfile_write_status (struct trace_file_writer *self,
if (ts->start_time)
{
fprintf (writer->fp, ";starttime:%s",
- phex_nz (ts->start_time, sizeof (ts->start_time)));
+ phex_nz (ts->start_time));
}
if (ts->stop_time)
{
fprintf (writer->fp, ";stoptime:%s",
- phex_nz (ts->stop_time, sizeof (ts->stop_time)));
+ phex_nz (ts->stop_time));
}
if (ts->notes != NULL)
{
@@ -254,7 +254,7 @@ tfile_write_uploaded_tp (struct trace_file_writer *self,
char buf[MAX_TRACE_UPLOAD];
fprintf (writer->fp, "tp T%x:%s:%c:%x:%x",
- utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
+ utp->number, phex_nz (utp->addr),
(utp->enabled ? 'E' : 'D'), utp->step, utp->pass);
if (utp->type == bp_fast_tracepoint)
fprintf (writer->fp, ":F%x", utp->orig_size);
@@ -265,10 +265,10 @@ tfile_write_uploaded_tp (struct trace_file_writer *self,
fprintf (writer->fp, "\n");
for (const auto &act : utp->actions)
fprintf (writer->fp, "tp A%x:%s:%s\n",
- utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act.get ());
+ utp->number, phex_nz (utp->addr), act.get ());
for (const auto &act : utp->step_actions)
fprintf (writer->fp, "tp S%x:%s:%s\n",
- utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act.get ());
+ utp->number, phex_nz (utp->addr), act.get ());
if (utp->at_string)
{
encode_source_string (utp->number, utp->addr,
@@ -290,7 +290,7 @@ tfile_write_uploaded_tp (struct trace_file_writer *self,
fprintf (writer->fp, "tp Z%s\n", buf);
}
fprintf (writer->fp, "tp V%x:%s:%x:%s\n",
- utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
+ utp->number, phex_nz (utp->addr),
utp->hit_count,
phex_nz (utp->traceframe_usage,
sizeof (utp->traceframe_usage)));
@@ -567,7 +567,7 @@ tfile_target_open (const char *arg, int from_tty)
merge_uploaded_tracepoints (&uploaded_tps);
- post_create_inferior (from_tty);
+ post_create_inferior (from_tty, true);
}
/* Interpret the given line from the definitions part of the trace
@@ -1116,9 +1116,7 @@ tfile_append_tdesc_line (const char *line)
trace_tdesc += "\n";
}
-void _initialize_tracefile_tfile ();
-void
-_initialize_tracefile_tfile ()
+INIT_GDB_FILE (tracefile_tfile)
{
add_target (tfile_target_info, tfile_target_open,
filename_maybe_quoted_completer);
diff --git a/gdb/tracefile.c b/gdb/tracefile.c
index dac2eb7..19b4d1e 100644
--- a/gdb/tracefile.c
+++ b/gdb/tracefile.c
@@ -473,9 +473,7 @@ tracefile_target::get_trace_status (struct trace_status *ts)
return -1;
}
-void _initialize_tracefile ();
-void
-_initialize_tracefile ()
+INIT_GDB_FILE (tracefile)
{
add_com ("tsave", class_trace, tsave_command, _("\
Save the trace data to a file.\n\
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index a2f1a75..879e4a6 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -208,16 +208,16 @@ set_tracepoint_num (int num)
static void
set_traceframe_context (const frame_info_ptr &trace_frame)
{
- CORE_ADDR trace_pc;
+ std::optional<CORE_ADDR> trace_pc;
struct symbol *traceframe_fun;
symtab_and_line traceframe_sal;
/* Save as globals for internal use. */
if (trace_frame != NULL
- && get_frame_pc_if_available (trace_frame, &trace_pc))
+ && (trace_pc = get_frame_pc_if_available (trace_frame)))
{
- traceframe_sal = find_pc_line (trace_pc, 0);
- traceframe_fun = find_pc_function (trace_pc);
+ traceframe_sal = find_pc_line (*trace_pc, 0);
+ traceframe_fun = find_pc_function (*trace_pc);
/* Save linenumber as "$trace_line", a debugger variable visible to
users. */
@@ -308,12 +308,12 @@ validate_trace_state_variable_name (const char *name)
/* All digits in the name is reserved for value history
references. */
- for (p = name; isdigit (*p); p++)
+ for (p = name; c_isdigit (*p); p++)
;
if (*p == '\0')
error (_("$%s is not a valid trace state variable name"), name);
- for (p = name; isalnum (*p) || *p == '_'; p++)
+ for (p = name; c_isalnum (*p) || *p == '_'; p++)
;
if (*p != '\0')
error (_("$%s is not a valid trace state variable name"), name);
@@ -339,7 +339,7 @@ trace_variable_command (const char *args, int from_tty)
error (_("Name of trace variable should start with '$'"));
name_start = p;
- while (isalnum (*p) || *p == '_')
+ while (c_isalnum (*p) || *p == '_')
p++;
std::string name (name_start, p - name_start);
@@ -689,14 +689,14 @@ validate_actionline (const char *line, tracepoint *t)
(exp->op.get ()));
sym = vvop->get_symbol ();
- if (sym->aclass () == LOC_CONST)
+ if (sym->loc_class () == LOC_CONST)
{
error (_("constant `%s' (value %s) "
"will not be collected."),
sym->print_name (),
plongest (sym->value_longest ()));
}
- else if (sym->aclass () == LOC_OPTIMIZED_OUT)
+ else if (sym->loc_class () == LOC_OPTIMIZED_OUT)
{
error (_("`%s' is optimized away "
"and cannot be collected."),
@@ -916,11 +916,11 @@ collection_list::collect_symbol (struct symbol *sym,
int treat_as_expr = 0;
len = check_typedef (sym->type ())->length ();
- switch (sym->aclass ())
+ switch (sym->loc_class ())
{
default:
gdb_printf ("%s: don't know symbol class %d\n",
- sym->print_name (), sym->aclass ());
+ sym->print_name (), sym->loc_class ());
break;
case LOC_CONST:
gdb_printf ("constant %s (value %s) will not be collected.\n",
@@ -2508,12 +2508,12 @@ info_scope_command (const char *args_in, int from_tty)
gdb_stdout);
else
{
- switch (sym->aclass ())
+ switch (sym->loc_class ())
{
default:
case LOC_UNDEF: /* Messed up symbol? */
gdb_printf ("a bogus symbol, class %d.\n",
- sym->aclass ());
+ sym->loc_class ());
count--; /* Don't count this one. */
continue;
case LOC_CONST:
@@ -2818,7 +2818,7 @@ encode_source_string (int tpnum, ULONGEST addr,
if (80 + strlen (srctype) > buf_size)
error (_("Buffer too small for source encoding"));
sprintf (buf, "%x:%s:%s:%x:%x:",
- tpnum, phex_nz (addr, sizeof (addr)),
+ tpnum, phex_nz (addr),
srctype, 0, (int) strlen (src));
if (strlen (buf) + strlen (src) * 2 >= buf_size)
error (_("Source string too long for buffer"));
@@ -3919,9 +3919,7 @@ static const struct internalvar_funcs sdata_funcs =
cmd_list_element *while_stepping_cmd_element = nullptr;
/* module initialization */
-void _initialize_tracepoint ();
-void
-_initialize_tracepoint ()
+INIT_GDB_FILE (tracepoint)
{
struct cmd_list_element *c;
diff --git a/gdb/tui/tui-disasm.c b/gdb/tui/tui-disasm.c
index 5488760..07453b4 100644
--- a/gdb/tui/tui-disasm.c
+++ b/gdb/tui/tui-disasm.c
@@ -100,6 +100,9 @@ tui_disassemble (struct gdbarch *gdbarch,
{
bool term_out = disassembler_styling && gdb_stdout->can_emit_style_escape ();
string_file gdb_dis_out (term_out);
+ struct ui_file *stream = (addr_size == nullptr
+ ? (decltype (stream))&null_stream
+ : (decltype (stream))&gdb_dis_out);
/* Must start with an empty list. */
asm_lines.clear ();
@@ -108,11 +111,13 @@ tui_disassemble (struct gdbarch *gdbarch,
for (int i = 0; i < count; ++i)
{
tui_asm_line tal;
- CORE_ADDR orig_pc = pc;
+
+ /* Save the instruction address. */
+ tal.addr = pc;
try
{
- pc = pc + gdb_print_insn (gdbarch, pc, &gdb_dis_out, NULL);
+ pc += gdb_print_insn (gdbarch, pc, stream, NULL);
}
catch (const gdb_exception_error &except)
{
@@ -124,25 +129,24 @@ tui_disassemble (struct gdbarch *gdbarch,
return pc;
}
+ /* If that's all we need, continue. */
+ if (addr_size == nullptr)
+ {
+ asm_lines.push_back (std::move (tal));
+ continue;
+ }
+
/* Capture the disassembled instruction. */
tal.insn = gdb_dis_out.release ();
/* And capture the address the instruction is at. */
- tal.addr = orig_pc;
- print_address (gdbarch, orig_pc, &gdb_dis_out);
+ print_address (gdbarch, tal.addr, &gdb_dis_out);
tal.addr_string = gdb_dis_out.release ();
+ tal.addr_size = (term_out
+ ? len_without_escapes (tal.addr_string)
+ : tal.addr_string.size ());
- if (addr_size != nullptr)
- {
- size_t new_size;
-
- if (term_out)
- new_size = len_without_escapes (tal.addr_string);
- else
- new_size = tal.addr_string.size ();
- *addr_size = std::max (*addr_size, new_size);
- tal.addr_size = new_size;
- }
+ *addr_size = std::max (*addr_size, tal.addr_size);
asm_lines.push_back (std::move (tal));
}
@@ -546,9 +550,7 @@ run_tests ()
} /* namespace selftests */
#endif /* GDB_SELF_TEST */
-void _initialize_tui_disasm ();
-void
-_initialize_tui_disasm ()
+INIT_GDB_FILE (tui_disasm)
{
#if GDB_SELF_TEST
selftests::register_test ("tui-disasm", selftests::tui::disasm::run_tests);
diff --git a/gdb/tui/tui-file.c b/gdb/tui/tui-file.c
index 39aee9f..df6f503 100644
--- a/gdb/tui/tui-file.c
+++ b/gdb/tui/tui-file.c
@@ -21,7 +21,7 @@
#include "tui/tui-command.h"
void
-tui_file::puts (const char *linebuffer)
+tui_file::do_puts (const char *linebuffer)
{
tui_puts (linebuffer);
if (!m_buffered)
@@ -29,7 +29,7 @@ tui_file::puts (const char *linebuffer)
}
void
-tui_file::write (const char *buf, long length_buf)
+tui_file::do_write (const char *buf, long length_buf)
{
tui_write (buf, length_buf);
if (!m_buffered)
@@ -41,5 +41,5 @@ tui_file::flush ()
{
if (m_buffered)
tui_cmd_win ()->refresh_window ();
- stdio_file::flush ();
+ escape_buffering_file::flush ();
}
diff --git a/gdb/tui/tui-file.h b/gdb/tui/tui-file.h
index dbd6fa9..b6dc058 100644
--- a/gdb/tui/tui-file.h
+++ b/gdb/tui/tui-file.h
@@ -23,18 +23,21 @@
/* A STDIO-like output stream for the TUI. */
-class tui_file : public stdio_file
+class tui_file : public escape_buffering_file
{
public:
tui_file (FILE *stream, bool buffered)
- : stdio_file (stream),
+ : escape_buffering_file (stream),
m_buffered (buffered)
{}
- void write (const char *buf, long length_buf) override;
- void puts (const char *) override;
void flush () override;
+protected:
+
+ void do_write (const char *buf, long length_buf) override;
+ void do_puts (const char *) override;
+
private:
/* True if this stream is buffered. */
diff --git a/gdb/tui/tui-hooks.c b/gdb/tui/tui-hooks.c
index 814ddac..024fedd 100644
--- a/gdb/tui/tui-hooks.c
+++ b/gdb/tui/tui-hooks.c
@@ -262,9 +262,7 @@ tui_remove_hooks (void)
tui_attach_detach_observers (false);
}
-void _initialize_tui_hooks ();
-void
-_initialize_tui_hooks ()
+INIT_GDB_FILE (tui_hooks)
{
/* Install the permanent hooks. */
gdb::observers::new_objfile.attach (tui_new_objfile_hook, "tui-hooks");
diff --git a/gdb/tui/tui-interp.c b/gdb/tui/tui-interp.c
index 53acf82..3d0e152 100644
--- a/gdb/tui/tui-interp.c
+++ b/gdb/tui/tui-interp.c
@@ -161,9 +161,7 @@ tui_interp_factory (const char *name)
return new tui_interp (name);
}
-void _initialize_tui_interp ();
-void
-_initialize_tui_interp ()
+INIT_GDB_FILE (tui_interp)
{
interp_factory_register (INTERP_TUI, tui_interp_factory);
diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c
index 1b4cc82..84cad93 100644
--- a/gdb/tui/tui-io.c
+++ b/gdb/tui/tui-io.c
@@ -319,6 +319,10 @@ tui_apply_style (WINDOW *w, ui_file_style style)
wattron (w, A_NORMAL);
wattroff (w, A_BOLD);
wattroff (w, A_DIM);
+#ifdef A_ITALIC
+ wattroff (w, A_ITALIC);
+#endif
+ wattroff (w, A_UNDERLINE);
wattroff (w, A_REVERSE);
if (last_color_pair != -1)
wattroff (w, COLOR_PAIR (last_color_pair));
@@ -366,6 +370,14 @@ tui_apply_style (WINDOW *w, ui_file_style style)
gdb_assert_not_reached ("invalid intensity");
}
+#ifdef A_ITALIC
+ if (style.is_italic ())
+ wattron (w, A_ITALIC);
+#endif
+
+ if (style.is_underline ())
+ wattron (w, A_UNDERLINE);
+
if (style.is_reverse ())
wattron (w, A_REVERSE);
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 73ba0c6..95d20fb 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -37,7 +37,6 @@
#include "tui/tui-layout.h"
#include "tui/tui-source.h"
#include "gdb_curses.h"
-#include "gdbsupport/gdb-safe-ctype.h"
/* The layouts. */
static std::vector<std::unique_ptr<tui_layout_split>> layouts;
@@ -381,14 +380,14 @@ tui_register_window (const char *name, window_factory &&factory)
for (const char &c : name_copy)
{
- if (ISSPACE (c))
+ if (c_isspace (c))
error (_("invalid whitespace character in window name"));
- if (!ISALNUM (c) && strchr ("-_.", c) == nullptr)
+ if (!c_isalnum (c) && strchr ("-_.", c) == nullptr)
error (_("invalid character '%c' in window name"), c);
}
- if (!ISALPHA (name_copy[0]))
+ if (!c_isalpha (name_copy[0]))
error (_("window name must start with a letter, not '%c'"), name_copy[0]);
/* We already check above for all the builtin window names. If we get
@@ -1294,9 +1293,7 @@ tui_new_layout_command (const char *spec, int from_tty)
/* Function to initialize gdb commands, for tui window layout
manipulation. */
-void _initialize_tui_layout ();
-void
-_initialize_tui_layout ()
+INIT_GDB_FILE (tui_layout)
{
struct cmd_list_element *layout_cmd
= add_basic_prefix_cmd ("layout", class_tui, _("\
diff --git a/gdb/tui/tui-regs.c b/gdb/tui/tui-regs.c
index 0b8cb85..ac2757a 100644
--- a/gdb/tui/tui-regs.c
+++ b/gdb/tui/tui-regs.c
@@ -566,9 +566,7 @@ tui_reggroup_completer (struct cmd_list_element *ignore,
complete_on_enum (tracker, extra, text, word);
}
-void _initialize_tui_regs ();
-void
-_initialize_tui_regs ()
+INIT_GDB_FILE (tui_regs)
{
struct cmd_list_element **tuicmd, *cmd;
diff --git a/gdb/tui/tui-status.c b/gdb/tui/tui-status.c
index 484f4e5..1e09975 100644
--- a/gdb/tui/tui-status.c
+++ b/gdb/tui/tui-status.c
@@ -271,10 +271,14 @@ tui_show_frame_info (const frame_info_ptr &fi)
symtab_and_line sal = find_frame_sal (fi);
const char *func_name;
+ std::optional<CORE_ADDR> tmp_pc = get_frame_pc_if_available (fi);
/* find_frame_sal does not always set PC, but we want to ensure
that it is available in the SAL. */
- if (get_frame_pc_if_available (fi, &sal.pc))
- func_name = tui_get_function_from_frame (fi);
+ if (tmp_pc.has_value ())
+ {
+ sal.pc = *tmp_pc;
+ func_name = tui_get_function_from_frame (fi);
+ }
else
func_name = _("<unavailable>");
@@ -325,9 +329,7 @@ tui_update_command (const char *arg, int from_tty)
/* Function to initialize gdb commands, for tui window stack
manipulation. */
-void _initialize_tui_stack ();
-void
-_initialize_tui_stack ()
+INIT_GDB_FILE (tui_stack)
{
add_com ("update", class_tui, tui_update_command,
_("\
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index f44600d..b411d07 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -45,7 +45,6 @@
#include "tui/tui-win.h"
#include "gdb_curses.h"
-#include <ctype.h>
#include "readline/readline.h"
#include <signal.h>
#include <string_view>
@@ -1041,7 +1040,7 @@ parse_scrolling_args (const char *arg,
/* Process the number of lines to scroll. */
std::string copy = arg;
buf_ptr = &copy[0];
- if (isdigit (*buf_ptr))
+ if (c_isdigit (*buf_ptr))
{
char *num_str;
@@ -1091,9 +1090,7 @@ bool tui_left_margin_verbose = false;
/* Function to initialize gdb commands, for tui window
manipulation. */
-void _initialize_tui_win ();
-void
-_initialize_tui_win ()
+INIT_GDB_FILE (tui_win)
{
static struct cmd_list_element *tui_setlist;
static struct cmd_list_element *tui_showlist;
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
index a545c48..2fe4914 100644
--- a/gdb/tui/tui-winsource.c
+++ b/gdb/tui/tui-winsource.c
@@ -26,7 +26,6 @@
#include "value.h"
#include "source.h"
#include "objfiles.h"
-#include "gdbsupport/gdb-safe-ctype.h"
#include "tui/tui.h"
#include "tui/tui-data.h"
@@ -109,7 +108,7 @@ tui_copy_source_line (const char **ptr, int *length)
}
else if (c == '\t')
process_tab ();
- else if (ISCNTRL (c))
+ else if (c_iscntrl (c))
{
result.push_back ('^');
result.push_back (c + 0100);
@@ -461,7 +460,9 @@ tui_source_window_base::rerender ()
/* find_frame_sal does not always set SAL.PC, but we want to ensure
that it is available in the SAL before updating the window. */
- get_frame_pc_if_available (frame, &sal.pc);
+ std::optional<CORE_ADDR> tmp_pc = get_frame_pc_if_available (frame);
+ if (tmp_pc.has_value ())
+ sal.pc = *tmp_pc;
maybe_update (get_frame_arch (frame), sal);
update_exec_info (false);
diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
index 2c7a6a0..01aee2f 100644
--- a/gdb/tui/tui.c
+++ b/gdb/tui/tui.c
@@ -125,6 +125,19 @@ tui_rl_switch_mode (int notused1, int notused2)
}
else
{
+ /* If we type "foo", entering it into the readline buffer
+
+ (gdb) foo
+ ^
+ and then switch to TUI and back, we may get back
+
+ (gdb) foo
+ ^
+ which is confusing because "foo" is no longer part of the
+ readline buffer. Fix this by clearing it before switching to
+ TUI. */
+ rl_clear_visible_line ();
+
/* If tui_enable throws, we'll re-prep below. */
rl_deprep_terminal ();
tui_enable ();
@@ -618,9 +631,7 @@ tui_get_command_dimension (unsigned int *width,
return true;
}
-void _initialize_tui ();
-void
-_initialize_tui ()
+INIT_GDB_FILE (tui)
{
struct cmd_list_element **tuicmd;
diff --git a/gdb/type-stack.c b/gdb/type-stack.c
index fc12e5e..b9266b8 100644
--- a/gdb/type-stack.c
+++ b/gdb/type-stack.c
@@ -20,7 +20,6 @@
#include "type-stack.h"
#include "gdbtypes.h"
-#include "parser-defs.h"
/* See type-stack.h. */
@@ -51,7 +50,7 @@ type_stack::insert (enum type_pieces tp)
/* See type-stack.h. */
void
-type_stack::insert (struct expr_builder *pstate, const char *string)
+type_stack::insert (struct gdbarch *gdbarch, const char *string)
{
union type_stack_elt element;
int slot;
@@ -67,8 +66,7 @@ type_stack::insert (struct expr_builder *pstate, const char *string)
element.piece = tp_space_identifier;
insert_into (slot, element);
element.int_val
- = address_space_name_to_type_instance_flags (pstate->gdbarch (),
- string);
+ = address_space_name_to_type_instance_flags (gdbarch, string);
insert_into (slot, element);
}
diff --git a/gdb/type-stack.h b/gdb/type-stack.h
index af5a89d..eeb2f35 100644
--- a/gdb/type-stack.h
+++ b/gdb/type-stack.h
@@ -26,34 +26,49 @@
struct type;
struct expr_builder;
-/* For parsing of complicated types.
- An array should be preceded in the list by the size of the array. */
+/* The kind of element on the stack of types and qualifiers, used for
+ parsing complicated types. */
enum type_pieces
- {
- tp_end = -1,
- tp_pointer,
- tp_reference,
- tp_rvalue_reference,
- tp_array,
- tp_function,
- tp_function_with_arguments,
- tp_const,
- tp_volatile,
- tp_space_identifier,
- tp_atomic,
- tp_restrict,
- tp_type_stack,
- tp_kind
- };
-
-/* The stack can contain either an enum type_pieces or an int. */
+{
+ /* This is returned by pop() to indicate that the stack is empty.
+ Note that it may not be pushed by the user. */
+ tp_end = -1,
+ tp_pointer,
+ tp_reference,
+ tp_rvalue_reference,
+ /* An array type, where the dimension is pushed on the stack as
+ well. */
+ tp_array,
+ tp_function,
+ /* A function with argument types; the types are also pushed on the
+ stack. */
+ tp_function_with_arguments,
+ tp_const,
+ tp_volatile,
+ /* An address space identifier. The address space is also pushed on
+ the stack. */
+ tp_space_identifier,
+ tp_atomic,
+ tp_restrict,
+ /* A separate type stack, which is also pushed onto this type
+ stack. */
+ tp_type_stack,
+ /* Fortran-specific, specifies the kind. */
+ tp_kind,
+};
+
+/* Items on the type stack. */
union type_stack_elt
- {
- enum type_pieces piece;
- int int_val;
- struct type_stack *stack_val;
- std::vector<struct type *> *typelist_val;
- };
+{
+ /* An ordinary type qualifier. */
+ enum type_pieces piece;
+ /* An integer value. Currently only used for address spaces. */
+ int int_val;
+ /* Another type stack. */
+ struct type_stack *stack_val;
+ /* A list of types. */
+ std::vector<struct type *> *typelist_val;
+};
/* The type stack is an instance of this structure. */
@@ -80,18 +95,31 @@ public:
void insert (enum type_pieces tp);
+ /* Push an ordinary element on the type stack. This can be used for
+ any element that doesn't require any extra data. */
void push (enum type_pieces tp)
{
+ /* tp_end can only be returned by this class, not pushed. The
+ others require a payload on the stack and so can only be pushed
+ by the appropriate method. */
+ gdb_assert (tp != tp_end);
+ gdb_assert (!requires_payload (tp));
type_stack_elt elt;
elt.piece = tp;
m_elements.push_back (elt);
}
- void push (int n)
+ /* Push an element and an integer value onto the stack. The integer
+ value is pushed first, followed by TP. Only piece kinds that
+ accept an integer argument are allowed. */
+ void push (enum type_pieces tp, int n)
{
+ gdb_assert (tp == tp_array || tp == tp_space_identifier || tp == tp_kind);
type_stack_elt elt;
elt.int_val = n;
m_elements.push_back (elt);
+ elt.piece = tp;
+ m_elements.push_back (elt);
}
/* Push the type stack STACK as an element on this type stack. */
@@ -101,11 +129,12 @@ public:
type_stack_elt elt;
elt.stack_val = stack;
m_elements.push_back (elt);
- push (tp_type_stack);
+ elt.piece = tp_type_stack;
+ m_elements.push_back (elt);
}
- /* Push a function type with arguments onto the global type stack.
- LIST holds the argument types. If the final item in LIST is NULL,
+ /* Push a function type with arguments onto this type stack. LIST
+ holds the argument types. If the final item in LIST is NULL,
then the function will be varargs. */
void push (std::vector<struct type *> *list)
@@ -113,35 +142,51 @@ public:
type_stack_elt elt;
elt.typelist_val = list;
m_elements.push_back (elt);
- push (tp_function_with_arguments);
+ elt.piece = tp_function_with_arguments;
+ m_elements.push_back (elt);
}
+ /* Pop the topmost element of the stack and return it.
+
+ If the stack is empty, tp_end is returned.
+
+ If the topmost element requires a payload -- for example,
+ tp_array takes an integer parameter -- then the value is returned
+ but *not* popped from the stack. Instead the appropriate
+ payload-specific pop_* method (e.g., pop_int) must then be
+ called. This somewhat odd approach ensures that the stack can't
+ be put into an invalid state. */
enum type_pieces pop ()
{
if (m_elements.empty ())
return tp_end;
type_stack_elt elt = m_elements.back ();
- m_elements.pop_back ();
+ if (!requires_payload (elt.piece))
+ m_elements.pop_back ();
return elt.piece;
}
int pop_int ()
{
- if (m_elements.empty ())
- {
- /* "Can't happen". */
- return 0;
- }
+ gdb_assert (m_elements.size () >= 2);
type_stack_elt elt = m_elements.back ();
m_elements.pop_back ();
+ type_pieces tp = elt.piece;
+ gdb_assert (tp == tp_array || tp == tp_space_identifier || tp == tp_kind);
+ elt = m_elements.back ();
+ m_elements.pop_back ();
return elt.int_val;
}
std::vector<struct type *> *pop_typelist ()
{
- gdb_assert (!m_elements.empty ());
+ gdb_assert (m_elements.size () >= 2);
type_stack_elt elt = m_elements.back ();
m_elements.pop_back ();
+ type_pieces tp = elt.piece;
+ gdb_assert (tp == tp_function_with_arguments);
+ elt = m_elements.back ();
+ m_elements.pop_back ();
return elt.typelist_val;
}
@@ -149,9 +194,13 @@ public:
struct type_stack *pop_type_stack ()
{
- gdb_assert (!m_elements.empty ());
+ gdb_assert (m_elements.size () >= 2);
type_stack_elt elt = m_elements.back ();
m_elements.pop_back ();
+ type_pieces tp = elt.piece;
+ gdb_assert (tp == tp_type_stack);
+ elt = m_elements.back ();
+ m_elements.pop_back ();
return elt.stack_val;
}
@@ -163,7 +212,7 @@ public:
stack is a tp_pointer, and the new values are inserted above the
first item. */
- void insert (struct expr_builder *pstate, const char *string);
+ void insert (struct gdbarch *gdbarch, const char *string);
/* Append the elements of the type stack FROM to the type stack
THIS. Always returns THIS. */
@@ -188,9 +237,9 @@ public:
private:
- /* A helper function for insert_type and insert_type_address_space.
- This does work of expanding the type stack and inserting the new
- element, ELEMENT, into the stack at location SLOT. */
+ /* A helper function for the insert methods. This does work of
+ expanding the type stack and inserting the new element, ELEMENT,
+ into the stack at location SLOT. */
void insert_into (int slot, union type_stack_elt element)
{
@@ -198,6 +247,14 @@ private:
m_elements.insert (m_elements.begin () + slot, element);
}
+ /* Return true if TP requires some payload element. */
+ bool requires_payload (type_pieces tp) const
+ {
+ return (tp == tp_array || tp == tp_kind || tp == tp_type_stack
+ || tp == tp_function_with_arguments
+ || tp == tp_space_identifier);
+ }
+
/* Elements on the stack. */
std::vector<union type_stack_elt> m_elements;
diff --git a/gdb/typeprint.c b/gdb/typeprint.c
index 4bc5947..42fbf38 100644
--- a/gdb/typeprint.c
+++ b/gdb/typeprint.c
@@ -31,7 +31,6 @@
#include "cp-abi.h"
#include "typeprint.h"
#include "valprint.h"
-#include <ctype.h>
#include "cli/cli-utils.h"
#include "extension.h"
#include "completer.h"
@@ -219,7 +218,7 @@ typedef_hash_table::add_template_parameters (struct type *t)
struct decl_field *tf;
/* We only want type-valued template parameters in the hash. */
- if (TYPE_TEMPLATE_ARGUMENT (t, i)->aclass () != LOC_TYPEDEF)
+ if (TYPE_TEMPLATE_ARGUMENT (t, i)->loc_class () != LOC_TYPEDEF)
continue;
tf = XOBNEW (&m_storage, struct decl_field);
@@ -367,7 +366,7 @@ whatis_exp (const char *exp, int show)
{
int seen_one = 0;
- for (++exp; *exp && !isspace (*exp); ++exp)
+ for (++exp; *exp && !c_isspace (*exp); ++exp)
{
switch (*exp)
{
@@ -413,7 +412,7 @@ whatis_exp (const char *exp, int show)
if (!*exp && !seen_one)
error (_("flag expected"));
- if (!isspace (*exp))
+ if (!c_isspace (*exp))
error (_("expected space after format"));
exp = skip_spaces (exp);
}
@@ -735,9 +734,7 @@ Display of struct members offsets and sizes in hexadecimal is %s\n"),
value);
}
-void _initialize_typeprint ();
-void
-_initialize_typeprint ()
+INIT_GDB_FILE (typeprint)
{
struct cmd_list_element *c;
diff --git a/gdb/ui-file.c b/gdb/ui-file.c
index f86b6b1..2e5c06f 100644
--- a/gdb/ui-file.c
+++ b/gdb/ui-file.c
@@ -408,7 +408,7 @@ tee_file::can_emit_style_escape ()
/* See ui-file.h. */
void
-no_terminal_escape_file::write (const char *buf, long length_buf)
+escape_buffering_file::write (const char *buf, long length_buf)
{
std::string copy (buf, length_buf);
this->puts (copy.c_str ());
@@ -417,7 +417,60 @@ no_terminal_escape_file::write (const char *buf, long length_buf)
/* See ui-file.h. */
void
-no_terminal_escape_file::puts (const char *buf)
+escape_buffering_file::puts (const char *buf)
+{
+ std::string local_buffer;
+ if (!m_buffer.empty ())
+ {
+ gdb_assert (m_buffer[0] == '\033');
+ m_buffer += buf;
+ /* If we need to keep buffering, we'll handle that below. */
+ local_buffer = std::move (m_buffer);
+ buf = local_buffer.c_str ();
+ }
+
+ while (*buf != '\0')
+ {
+ const char *esc = strchr (buf, '\033');
+ if (esc == nullptr)
+ break;
+
+ /* First, write out any prefix. */
+ if (esc > buf)
+ {
+ do_write (buf, esc - buf);
+ buf = esc;
+ }
+
+ int n_read = 0;
+ ansi_escape_result seen = examine_ansi_escape (esc, &n_read);
+ if (seen == ansi_escape_result::INCOMPLETE)
+ {
+ /* Start buffering. */
+ m_buffer = buf;
+ return;
+ }
+ else if (seen == ansi_escape_result::NO_MATCH)
+ {
+ /* Just emit the ESC . */
+ n_read = 1;
+ }
+ else
+ gdb_assert (seen == ansi_escape_result::MATCHED);
+
+ do_write (esc, n_read);
+ buf += n_read;
+ }
+
+ /* If there is any data remaining in BUF, we can flush it now. */
+ if (*buf != '\0')
+ do_puts (buf);
+}
+
+/* See ui-file.h. */
+
+void
+no_terminal_escape_file::do_puts (const char *buf)
{
while (*buf != '\0')
{
@@ -438,6 +491,13 @@ no_terminal_escape_file::puts (const char *buf)
}
void
+no_terminal_escape_file::do_write (const char *buf, long len)
+{
+ std::string copy (buf, len);
+ do_puts (copy.c_str ());
+}
+
+void
timestamped_file::write (const char *buf, long len)
{
if (debug_timestamp)
diff --git a/gdb/ui-file.h b/gdb/ui-file.h
index 3919e52..1219bde 100644
--- a/gdb/ui-file.h
+++ b/gdb/ui-file.h
@@ -362,24 +362,58 @@ private:
ui_file *m_two;
};
+/* A ui_file implementation that buffers terminal escape sequences.
+ Note that this does not buffer in general -- it only buffers when
+ an incomplete but potentially recognizable escape sequence is
+ started. */
+
+class escape_buffering_file : public stdio_file
+{
+public:
+ using stdio_file::stdio_file;
+
+ /* Like the stdio_file methods but these forward to do_write and
+ do_puts, respectively. */
+ void write (const char *buf, long length_buf) override final;
+ void puts (const char *linebuffer) override final;
+
+ /* This class does not override 'flush'. While it does have an
+ internal buffer, it does not really make sense to flush the
+ buffer until an escape sequence has been fully processed. */
+
+protected:
+
+ /* Called to output some text. If the text contains a recognizable
+ terminal escape sequence, then it is guaranteed to be complete.
+ "Recognizable" here means that examine_ansi_escape did not return
+ INCOMPLETE. */
+ virtual void do_puts (const char *buf) = 0;
+ virtual void do_write (const char *buf, long len) = 0;
+
+private:
+
+ /* Buffer used only for incomplete escape sequences. */
+ std::string m_buffer;
+};
+
/* A ui_file implementation that filters out terminal escape
sequences. */
-class no_terminal_escape_file : public stdio_file
+class no_terminal_escape_file : public escape_buffering_file
{
public:
no_terminal_escape_file ()
{
}
- /* Like the stdio_file methods, but these filter out terminal escape
- sequences. */
- void write (const char *buf, long length_buf) override;
- void puts (const char *linebuffer) override;
-
void emit_style_escape (const ui_file_style &style) override
{
}
+
+protected:
+
+ void do_puts (const char *linebuffer) override;
+ void do_write (const char *buf, long len) override;
};
/* A base class for ui_file types that wrap another ui_file. */
diff --git a/gdb/ui-style.c b/gdb/ui-style.c
index b8d73ab..d450c3e 100644
--- a/gdb/ui-style.c
+++ b/gdb/ui-style.c
@@ -21,12 +21,14 @@
#include "gdbsupport/gdb_regex.h"
/* A regular expression that is used for matching ANSI terminal escape
- sequences. */
+ sequences. Note that this will actually match any prefix of such a
+ sequence. This property is used so that other code can buffer
+ incomplete sequences as needed. */
static const char ansi_regex_text[] =
- /* Introduction. */
- "^\033\\["
-#define DATA_SUBEXP 1
+ /* Introduction. Only the escape character is truly required. */
+ "^\033(\\["
+#define DATA_SUBEXP 2
/* Capture parameter and intermediate bytes. */
"("
/* Parameter bytes. */
@@ -36,12 +38,12 @@ static const char ansi_regex_text[] =
/* End the first capture. */
")"
/* The final byte. */
-#define FINAL_SUBEXP 2
- "([\x40-\x7e])";
+#define FINAL_SUBEXP 3
+ "([\x40-\x7e]))?";
/* The number of subexpressions to allocate space for, including the
"0th" whole match subexpression. */
-#define NUM_SUBEXPRESSIONS 3
+#define NUM_SUBEXPRESSIONS 4
/* The compiled form of ansi_regex_text. */
@@ -288,6 +290,16 @@ ui_file_style::to_ansi () const
else
result.append (std::to_string (m_intensity));
result.push_back (';');
+ if (m_italic)
+ result.append ("3");
+ else
+ result.append ("23");
+ result.push_back (';');
+ if (m_underline)
+ result.append ("4");
+ else
+ result.append ("24");
+ result.push_back (';');
if (m_reverse)
result.push_back ('7');
else
@@ -371,6 +383,15 @@ ui_file_style::parse (const char *buf, size_t *n_read)
*n_read = 0;
return false;
}
+
+ /* If the final subexpression did not match, then that means there
+ was an incomplete sequence. These are ignored here. */
+ if (subexps[FINAL_SUBEXP].rm_so == -1)
+ {
+ *n_read = 0;
+ return false;
+ }
+
/* Other failures mean the regexp is broken. */
gdb_assert (match == 0);
/* The regexp is anchored. */
@@ -424,6 +445,14 @@ ui_file_style::parse (const char *buf, size_t *n_read)
/* Dim. */
m_intensity = DIM;
break;
+ case 3:
+ /* Italic. */
+ m_italic = true;
+ break;
+ case 4:
+ /* Underline. */
+ m_underline = true;
+ break;
case 7:
/* Reverse. */
m_reverse = true;
@@ -435,6 +464,14 @@ ui_file_style::parse (const char *buf, size_t *n_read)
/* Normal. */
m_intensity = NORMAL;
break;
+ case 23:
+ /* Non-italic. */
+ m_italic = false;
+ break;
+ case 24:
+ /* Non-underline. */
+ m_underline = false;
+ break;
case 27:
/* Inverse off. */
m_reverse = false;
@@ -527,17 +564,25 @@ ui_file_style::parse (const char *buf, size_t *n_read)
/* See ui-style.h. */
-bool
-skip_ansi_escape (const char *buf, int *n_read)
+ansi_escape_result
+examine_ansi_escape (const char *buf, int *n_read)
{
+ gdb_assert (*buf == '\033');
+
regmatch_t subexps[NUM_SUBEXPRESSIONS];
int match = ansi_regex.exec (buf, ARRAY_SIZE (subexps), subexps, 0);
- if (match == REG_NOMATCH || buf[subexps[FINAL_SUBEXP].rm_so] != 'm')
- return false;
+ if (match == REG_NOMATCH)
+ return ansi_escape_result::NO_MATCH;
+
+ if (subexps[FINAL_SUBEXP].rm_so == -1)
+ return ansi_escape_result::INCOMPLETE;
+
+ if (buf[subexps[FINAL_SUBEXP].rm_so] != 'm')
+ return ansi_escape_result::NO_MATCH;
*n_read = subexps[FINAL_SUBEXP].rm_eo;
- return true;
+ return ansi_escape_result::MATCHED;
}
/* See ui-style.h. */
@@ -549,7 +594,11 @@ colorsupport ()
{
std::vector<color_space> result = {color_space::MONOCHROME};
- int colors = tgetnum ("Co");
+ /* ncurses versions prior to 6.1 (and other curses
+ implementations) declare the tgetnum argument to be
+ 'char *', so we need the const_cast, since C++ will not
+ implicitly convert. */
+ int colors = tgetnum (const_cast<char*> ("Co"));
if (colors >= 8)
result.push_back (color_space::ANSI_8COLOR);
if (colors >= 16)
diff --git a/gdb/ui-style.h b/gdb/ui-style.h
index 77a175d..1ea3556 100644
--- a/gdb/ui-style.h
+++ b/gdb/ui-style.h
@@ -266,7 +266,9 @@ struct ui_file_style
return (m_foreground == other.m_foreground
&& m_background == other.m_background
&& m_intensity == other.m_intensity
- && m_reverse == other.m_reverse);
+ && m_reverse == other.m_reverse
+ && m_italic == other.m_italic
+ && m_underline == other.m_underline);
}
bool operator!= (const ui_file_style &other) const
@@ -284,7 +286,9 @@ struct ui_file_style
return (m_foreground == NONE
&& m_background == NONE
&& m_intensity == NORMAL
- && !m_reverse);
+ && !m_reverse
+ && !m_italic
+ && !m_underline);
}
/* Return true if this style specified reverse display; false
@@ -330,6 +334,32 @@ struct ui_file_style
return m_intensity;
}
+ /* Return true if this style specified italic display; false
+ otherwise. */
+ bool is_italic () const
+ {
+ return m_italic;
+ }
+
+ /* Set/clear the italic display flag. */
+ void set_italic (bool italic)
+ {
+ m_italic = italic;
+ }
+
+ /* Return true if this style specified underline display; false
+ otherwise. */
+ bool is_underline () const
+ {
+ return m_underline;
+ }
+
+ /* Set/clear the underline display flag. */
+ void set_underline (bool underline)
+ {
+ m_underline = underline;
+ }
+
/* Parse an ANSI escape sequence in BUF, modifying this style. BUF
must begin with an ESC character. Return true if an escape
sequence was successfully parsed; false otherwise. In either
@@ -351,14 +381,40 @@ private:
color m_foreground = NONE;
color m_background = NONE;
intensity m_intensity = NORMAL;
+ bool m_italic = false;
+ bool m_underline = false;
bool m_reverse = false;
};
+/* Possible results for checking an ANSI escape sequence. */
+enum class ansi_escape_result
+{
+ /* The escape sequence is definitely not recognizable. */
+ NO_MATCH,
+
+ /* The escape sequence might be recognizable with more input. */
+ INCOMPLETE,
+
+ /* The escape sequence is definitely recognizable. */
+ MATCHED,
+};
+
+/* Examine an ANSI escape sequence in BUF. BUF must begin with an ESC
+ character. Return a value indicating whether the sequence was
+ recognizable. If MATCHED is returned, then N_READ is updated to
+ reflect the number of chars read from BUF. */
+
+extern ansi_escape_result examine_ansi_escape (const char *buf, int *n_read);
+
/* Skip an ANSI escape sequence in BUF. BUF must begin with an ESC
character. Return true if an escape sequence was successfully
skipped; false otherwise. If an escape sequence was skipped,
N_READ is updated to reflect the number of chars read from BUF. */
-extern bool skip_ansi_escape (const char *buf, int *n_read);
+static inline bool
+skip_ansi_escape (const char *buf, int *n_read)
+{
+ return examine_ansi_escape (buf, n_read) == ansi_escape_result::MATCHED;
+}
#endif /* GDB_UI_STYLE_H */
diff --git a/gdb/ui.c b/gdb/ui.c
index d67ab2c..cd23399 100644
--- a/gdb/ui.c
+++ b/gdb/ui.c
@@ -237,9 +237,7 @@ new_ui_command (const char *args, int from_tty)
gdb_printf ("New UI allocated\n");
}
-void _initialize_ui ();
-void
-_initialize_ui ()
+INIT_GDB_FILE (ui)
{
cmd_list_element *c = add_cmd ("new-ui", class_support, new_ui_command, _("\
Create a new UI.\n\
diff --git a/gdb/unittests/array-view-selftests.c b/gdb/unittests/array-view-selftests.c
index fa96d3b..914800a 100644
--- a/gdb/unittests/array-view-selftests.c
+++ b/gdb/unittests/array-view-selftests.c
@@ -695,9 +695,7 @@ run_copy_tests ()
} /* namespace array_view_tests */
} /* namespace selftests */
-void _initialize_array_view_selftests ();
-void
-_initialize_array_view_selftests ()
+INIT_GDB_FILE (array_view_selftests)
{
selftests::register_test ("array_view",
selftests::array_view_tests::run_tests);
diff --git a/gdb/unittests/child-path-selftests.c b/gdb/unittests/child-path-selftests.c
index 0f29f7d..95b2c34 100644
--- a/gdb/unittests/child-path-selftests.c
+++ b/gdb/unittests/child-path-selftests.c
@@ -58,9 +58,7 @@ test ()
}
}
-void _initialize_child_path_selftests ();
-void
-_initialize_child_path_selftests ()
+INIT_GDB_FILE (child_path_selftests)
{
selftests::register_test ("child_path",
selftests::child_path::test);
diff --git a/gdb/unittests/cli-utils-selftests.c b/gdb/unittests/cli-utils-selftests.c
index e6c64a9..1382ca6 100644
--- a/gdb/unittests/cli-utils-selftests.c
+++ b/gdb/unittests/cli-utils-selftests.c
@@ -109,9 +109,7 @@ test_cli_utils ()
}
}
-void _initialize_cli_utils_selftests ();
-void
-_initialize_cli_utils_selftests ()
+INIT_GDB_FILE (cli_utils_selftests)
{
selftests::register_test ("cli_utils",
selftests::cli_utils::test_cli_utils);
diff --git a/gdb/unittests/command-def-selftests.c b/gdb/unittests/command-def-selftests.c
index 6f169f5..095b57f 100644
--- a/gdb/unittests/command-def-selftests.c
+++ b/gdb/unittests/command-def-selftests.c
@@ -72,7 +72,7 @@ check_doc (struct cmd_list_element *commandlist, const char *prefix)
"first line is not terminated with a '.' character");
/* Checks the doc is not terminated with a new line. */
- if (isspace (c->doc[strlen (c->doc) - 1]))
+ if (c_isspace (c->doc[strlen (c->doc) - 1]))
broken_doc_invariant
(prefix, c->name,
"has superfluous trailing whitespace");
@@ -87,7 +87,7 @@ check_doc (struct cmd_list_element *commandlist, const char *prefix)
else
{
/* \n\n is ok, so we check that explicitly here. */
- if (isspace (nl[-1]) && nl[-1] != '\n')
+ if (c_isspace (nl[-1]) && nl[-1] != '\n')
broken_doc_invariant (prefix, c->name,
"has whitespace before a newline");
}
@@ -219,9 +219,7 @@ command_structure_invariants_tests ()
} /* namespace selftests */
-void _initialize_command_def_selftests ();
-void
-_initialize_command_def_selftests ()
+INIT_GDB_FILE (command_def_selftests)
{
selftests::register_test
("help_doc_invariants",
diff --git a/gdb/unittests/common-utils-selftests.c b/gdb/unittests/common-utils-selftests.c
index fab9cd1..ecc4769 100644
--- a/gdb/unittests/common-utils-selftests.c
+++ b/gdb/unittests/common-utils-selftests.c
@@ -127,9 +127,7 @@ string_vappendf_tests ()
} /* namespace selftests */
-void _initialize_common_utils_selftests ();
-void
-_initialize_common_utils_selftests ()
+INIT_GDB_FILE (common_utils_selftests)
{
selftests::register_test ("string_printf", selftests::string_printf_tests);
selftests::register_test ("string_vprintf", selftests::string_vprintf_tests);
diff --git a/gdb/unittests/copy_bitwise-selftests.c b/gdb/unittests/copy_bitwise-selftests.c
index 8798cbd..6fcdcd7 100644
--- a/gdb/unittests/copy_bitwise-selftests.c
+++ b/gdb/unittests/copy_bitwise-selftests.c
@@ -151,9 +151,7 @@ copy_bitwise_tests (void)
} /* namespace selftests */
-void _initialize_copy_bitwise_utils_selftests ();
-void
-_initialize_copy_bitwise_utils_selftests ()
+INIT_GDB_FILE (copy_bitwise_utils_selftests)
{
selftests::register_test ("copy_bitwise", selftests::copy_bitwise_tests);
}
diff --git a/gdb/unittests/enum-flags-selftests.c b/gdb/unittests/enum-flags-selftests.c
index bb55019..3eb0f52 100644
--- a/gdb/unittests/enum-flags-selftests.c
+++ b/gdb/unittests/enum-flags-selftests.c
@@ -607,10 +607,7 @@ self_test ()
} /* namespace enum_flags_tests */
} /* namespace selftests */
-void _initialize_enum_flags_selftests ();
-
-void
-_initialize_enum_flags_selftests ()
+INIT_GDB_FILE (enum_flags_selftests)
{
selftests::register_test ("enum-flags",
selftests::enum_flags_tests::self_test);
diff --git a/gdb/unittests/environ-selftests.c b/gdb/unittests/environ-selftests.c
index 79bffed..5ac3384 100644
--- a/gdb/unittests/environ-selftests.c
+++ b/gdb/unittests/environ-selftests.c
@@ -297,9 +297,7 @@ run_tests ()
} /* namespace gdb_environ */
} /* namespace selftests */
-void _initialize_environ_selftests ();
-void
-_initialize_environ_selftests ()
+INIT_GDB_FILE (environ_selftests)
{
selftests::register_test ("gdb_environ",
selftests::gdb_environ_tests::run_tests);
diff --git a/gdb/unittests/filtered_iterator-selftests.c b/gdb/unittests/filtered_iterator-selftests.c
index b3ec70b..c04cae4 100644
--- a/gdb/unittests/filtered_iterator-selftests.c
+++ b/gdb/unittests/filtered_iterator-selftests.c
@@ -125,6 +125,26 @@ test_filtered_iterator ()
SELF_CHECK (even_ints == expected_even_ints);
}
+/* Same as the above, but using pointers as the iterator base type. */
+
+static void
+test_filtered_iterator_ptr ()
+{
+ int array[] = { 4, 4, 5, 6, 7, 8, 9 };
+ std::vector<int> even_ints;
+ const std::vector<int> expected_even_ints { 4, 4, 6, 8 };
+
+ filtered_iterator<int *, even_numbers_only> iter
+ (array, array + ARRAY_SIZE (array));
+ filtered_iterator<int *, even_numbers_only> end
+ (array + ARRAY_SIZE (array), array + ARRAY_SIZE (array));
+
+ for (; iter != end; ++iter)
+ even_ints.push_back (*iter);
+
+ SELF_CHECK (even_ints == expected_even_ints);
+}
+
/* Test operator== and operator!=. */
static void
@@ -152,14 +172,44 @@ test_filtered_iterator_eq ()
SELF_CHECK (!(iter1 != iter2));
}
+
+/* Same as the above, but using pointers as the iterator base type. */
+
+static void
+test_filtered_iterator_eq_ptr ()
+{
+ int array[] = { 4, 4, 5, 6, 7, 8, 9 };
+
+ filtered_iterator<int *, even_numbers_only> iter1
+ (array, array + ARRAY_SIZE(array));
+ filtered_iterator<int *, even_numbers_only> iter2
+ (array, array + ARRAY_SIZE(array));
+
+ /* They start equal. */
+ SELF_CHECK (iter1 == iter2);
+ SELF_CHECK (!(iter1 != iter2));
+
+ /* Advance 1, now they aren't equal (despite pointing to equal values). */
+ ++iter1;
+ SELF_CHECK (!(iter1 == iter2));
+ SELF_CHECK (iter1 != iter2);
+
+ /* Advance 2, now they are equal again. */
+ ++iter2;
+ SELF_CHECK (iter1 == iter2);
+ SELF_CHECK (!(iter1 != iter2));
+}
+
} /* namespace selftests */
-void _initialize_filtered_iterator_selftests ();
-void
-_initialize_filtered_iterator_selftests ()
+INIT_GDB_FILE (filtered_iterator_selftests)
{
selftests::register_test ("filtered_iterator",
selftests::test_filtered_iterator);
selftests::register_test ("filtered_iterator_eq",
selftests::test_filtered_iterator_eq);
+ selftests::register_test ("filtered_iterator_ptr",
+ selftests::test_filtered_iterator_ptr);
+ selftests::register_test ("filtered_iterator_eq_ptr",
+ selftests::test_filtered_iterator_eq_ptr);
}
diff --git a/gdb/unittests/format_pieces-selftests.c b/gdb/unittests/format_pieces-selftests.c
index 473d690..c7d8ff0 100644
--- a/gdb/unittests/format_pieces-selftests.c
+++ b/gdb/unittests/format_pieces-selftests.c
@@ -147,9 +147,7 @@ run_tests ()
} /* namespace format_pieces */
} /* namespace selftests */
-void _initialize_format_pieces_selftests ();
-void
-_initialize_format_pieces_selftests ()
+INIT_GDB_FILE (format_pieces_selftests)
{
selftests::register_test ("format_pieces",
selftests::format_pieces::run_tests);
diff --git a/gdb/unittests/frame_info_ptr-selftests.c b/gdb/unittests/frame_info_ptr-selftests.c
index c9eb4f4..d518482 100644
--- a/gdb/unittests/frame_info_ptr-selftests.c
+++ b/gdb/unittests/frame_info_ptr-selftests.c
@@ -66,9 +66,7 @@ test_user_created_frame ()
} /* namespace selftests */
-void _initialize_frame_info_ptr_selftests ();
-void
-_initialize_frame_info_ptr_selftests ()
+INIT_GDB_FILE (frame_info_ptr_selftests)
{
selftests::register_test ("frame_info_ptr_user",
selftests::test_user_created_frame);
diff --git a/gdb/unittests/function-view-selftests.c b/gdb/unittests/function-view-selftests.c
index 036c7f9..21838f1 100644
--- a/gdb/unittests/function-view-selftests.c
+++ b/gdb/unittests/function-view-selftests.c
@@ -250,9 +250,7 @@ run_tests ()
} /* namespace function_view */
} /* namespace selftests */
-void _initialize_function_view_selftests ();
-void
-_initialize_function_view_selftests ()
+INIT_GDB_FILE (function_view_selftests)
{
selftests::register_test ("function_view",
selftests::function_view::run_tests);
diff --git a/gdb/unittests/gdb_tilde_expand-selftests.c b/gdb/unittests/gdb_tilde_expand-selftests.c
index b0b7027..28c759f 100644
--- a/gdb/unittests/gdb_tilde_expand-selftests.c
+++ b/gdb/unittests/gdb_tilde_expand-selftests.c
@@ -84,9 +84,7 @@ do_test ()
} /* namespace gdb_tilde_expand_tests */
} /* namespace selftests */
-void _initialize_gdb_tilde_expand_selftests ();
-void
-_initialize_gdb_tilde_expand_selftests ()
+INIT_GDB_FILE (gdb_tilde_expand_selftests)
{
selftests::register_test
("gdb_tilde_expand", selftests::gdb_tilde_expand_tests::do_test);
diff --git a/gdb/unittests/gmp-utils-selftests.c b/gdb/unittests/gmp-utils-selftests.c
index 495947af..9843fcb 100644
--- a/gdb/unittests/gmp-utils-selftests.c
+++ b/gdb/unittests/gmp-utils-selftests.c
@@ -498,10 +498,7 @@ gdb_mpq_write_fixed_point ()
}
-void _initialize_gmp_utils_selftests ();
-
-void
-_initialize_gmp_utils_selftests ()
+INIT_GDB_FILE (gmp_utils_selftests)
{
selftests::register_test ("gdb_mpz_as_integer",
selftests::gdb_mpz_as_integer);
diff --git a/gdb/unittests/intrusive_list-selftests.c b/gdb/unittests/intrusive_list-selftests.c
index eaffbba..2dd1298 100644
--- a/gdb/unittests/intrusive_list-selftests.c
+++ b/gdb/unittests/intrusive_list-selftests.c
@@ -1648,10 +1648,7 @@ test_intrusive_list ()
test_node_is_linked ();
}
-void _initialize_intrusive_list_selftests ();
-
-void
-_initialize_intrusive_list_selftests ()
+INIT_GDB_FILE (intrusive_list_selftests)
{
selftests::register_test ("intrusive_list", test_intrusive_list);
}
diff --git a/gdb/unittests/lookup_name_info-selftests.c b/gdb/unittests/lookup_name_info-selftests.c
index 3e8440b..dc0d307 100644
--- a/gdb/unittests/lookup_name_info-selftests.c
+++ b/gdb/unittests/lookup_name_info-selftests.c
@@ -105,9 +105,7 @@ run_tests ()
}} /* namespace selftests::lookup_name */
-void _initialize_lookup_name_info_selftests ();
-void
-_initialize_lookup_name_info_selftests ()
+INIT_GDB_FILE (lookup_name_info_selftests)
{
selftests::register_test ("lookup_name_info",
selftests::lookup_name::run_tests);
diff --git a/gdb/unittests/main-thread-selftests.c b/gdb/unittests/main-thread-selftests.c
index 5f3d790..77adf47 100644
--- a/gdb/unittests/main-thread-selftests.c
+++ b/gdb/unittests/main-thread-selftests.c
@@ -73,9 +73,7 @@ run_tests ()
}
}
-void _initialize_main_thread_selftests ();
-void
-_initialize_main_thread_selftests ()
+INIT_GDB_FILE (main_thread_selftests)
{
#if CXX_STD_THREAD
selftests::register_test ("run_on_main_thread",
diff --git a/gdb/unittests/memory-map-selftests.c b/gdb/unittests/memory-map-selftests.c
index 6872d5a..c014c4d 100644
--- a/gdb/unittests/memory-map-selftests.c
+++ b/gdb/unittests/memory-map-selftests.c
@@ -75,9 +75,7 @@ parse_memory_map_tests ()
#endif /* HAVE_LIBEXPAT */
-void _initialize_memory_map_selftests ();
-void
-_initialize_memory_map_selftests ()
+INIT_GDB_FILE (memory_map_selftests)
{
#if defined(HAVE_LIBEXPAT)
selftests::register_test
diff --git a/gdb/unittests/memrange-selftests.c b/gdb/unittests/memrange-selftests.c
index 1433105..17e08e8 100644
--- a/gdb/unittests/memrange-selftests.c
+++ b/gdb/unittests/memrange-selftests.c
@@ -105,9 +105,7 @@ normalize_mem_ranges_tests ()
} /* namespace memrange_tests */
} /* namespace selftests */
-void _initialize_memrange_selftests ();
-void
-_initialize_memrange_selftests ()
+INIT_GDB_FILE (memrange_selftests)
{
selftests::register_test
("normalize_mem_ranges",
diff --git a/gdb/unittests/mkdir-recursive-selftests.c b/gdb/unittests/mkdir-recursive-selftests.c
index 764fe1a..b2ae383 100644
--- a/gdb/unittests/mkdir-recursive-selftests.c
+++ b/gdb/unittests/mkdir-recursive-selftests.c
@@ -80,9 +80,7 @@ test ()
}
}
-void _initialize_mkdir_recursive_selftests ();
-void
-_initialize_mkdir_recursive_selftests ()
+INIT_GDB_FILE (mkdir_recursive_selftests)
{
selftests::register_test ("mkdir_recursive",
selftests::mkdir_recursive::test);
diff --git a/gdb/unittests/observable-selftests.c b/gdb/unittests/observable-selftests.c
index 90d7392..0934249 100644
--- a/gdb/unittests/observable-selftests.c
+++ b/gdb/unittests/observable-selftests.c
@@ -237,9 +237,7 @@ run_tests ()
} /* namespace observers */
} /* namespace selftests */
-void _initialize_observer_selftest ();
-void
-_initialize_observer_selftest ()
+INIT_GDB_FILE (observer_selftest)
{
selftests::register_test ("gdb::observers",
selftests::observers::run_tests);
diff --git a/gdb/unittests/offset-type-selftests.c b/gdb/unittests/offset-type-selftests.c
index 1623f0d..2cba4e1 100644
--- a/gdb/unittests/offset-type-selftests.c
+++ b/gdb/unittests/offset-type-selftests.c
@@ -170,9 +170,7 @@ run_tests ()
} /* namespace offset_type */
} /* namespace selftests */
-void _initialize_offset_type_selftests ();
-void
-_initialize_offset_type_selftests ()
+INIT_GDB_FILE (offset_type_selftests)
{
selftests::register_test ("offset_type", selftests::offset_type::run_tests);
}
diff --git a/gdb/unittests/packed-selftests.c b/gdb/unittests/packed-selftests.c
index daa8036..5a91b29 100644
--- a/gdb/unittests/packed-selftests.c
+++ b/gdb/unittests/packed-selftests.c
@@ -119,9 +119,7 @@ run_tests ()
} /* namespace packed_tests */
} /* namespace selftests */
-void _initialize_packed_selftests ();
-void
-_initialize_packed_selftests ()
+INIT_GDB_FILE (packed_selftests)
{
selftests::register_test ("packed", selftests::packed_tests::run_tests);
}
diff --git a/gdb/unittests/parallel-for-selftests.c b/gdb/unittests/parallel-for-selftests.c
index 841d914..f545614 100644
--- a/gdb/unittests/parallel-for-selftests.c
+++ b/gdb/unittests/parallel-for-selftests.c
@@ -17,13 +17,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-/* This file is divided in two parts:
- - FOR_EACH-undefined, and
- - FOR_EACH-defined.
- The former includes the latter, more than once, with different values for
- FOR_EACH. The FOR_EACH-defined part reads like a regular function. */
-#ifndef FOR_EACH
-
#include "gdbsupport/selftest.h"
#include "gdbsupport/parallel-for.h"
@@ -49,97 +42,77 @@ struct save_restore_n_threads
int n_threads;
};
-/* Define test_par using TEST in the FOR_EACH-defined part. */
-#define TEST test_par
-#define FOR_EACH gdb::parallel_for_each
-#include "parallel-for-selftests.c"
-#undef FOR_EACH
-#undef TEST
-
-/* Define test_seq using TEST in the FOR_EACH-defined part. */
-#define TEST test_seq
-#define FOR_EACH gdb::sequential_for_each
-#include "parallel-for-selftests.c"
-#undef FOR_EACH
-#undef TEST
+using foreach_callback_t = gdb::function_view<void (int first, int last)>;
+using do_foreach_t = gdb::function_view<void (int first, int last,
+ foreach_callback_t)>;
static void
-test (int n_threads)
+test_one (int n_threads, do_foreach_t do_foreach)
{
- test_par (n_threads);
- test_seq (n_threads);
+ save_restore_n_threads saver;
+ gdb::thread_pool::g_thread_pool->set_thread_count (n_threads);
+
+ {
+ constexpr int upper_bound = 1000;
+ std::atomic<int> counter (0);
+ do_foreach (0, upper_bound,
+ [&] (int start, int end) { counter += end - start; });
+ SELF_CHECK (counter == upper_bound);
+ }
+
+ {
+ std::atomic<int> counter (0);
+ do_foreach (0, 0, [&] (int start, int end) { counter += end - start; });
+ SELF_CHECK (counter == 0);
+ }
+
+ {
+ /* Check that if there are fewer tasks than threads, then we won't
+ end up with a null result. */
+ std::vector<std::unique_ptr<int>> intresults;
+ std::atomic<bool> any_empty_tasks (false);
+
+ do_foreach (0, 1,
+ [&] (int start, int end)
+ {
+ if (start == end)
+ any_empty_tasks = true;
+
+ return std::make_unique<int> (end - start);
+ });
+
+ SELF_CHECK (!any_empty_tasks);
+ SELF_CHECK (std::all_of (intresults.begin (), intresults.end (),
+ [] (const std::unique_ptr<int> &entry)
+ { return entry != nullptr; }));
+ }
}
static void
-test_n_threads ()
+test_parallel_for_each ()
{
- test (0);
- test (1);
- test (3);
+ const std::vector<do_foreach_t> for_each_functions
+ {
+ [] (int start, int end, foreach_callback_t callback)
+ { gdb::parallel_for_each<1> (start, end, callback); },
+ [] (int start, int end, foreach_callback_t callback)
+ { gdb::sequential_for_each (start, end, callback);}
+ };
+
+ for (int n_threads : { 0, 1, 3 })
+ for (const auto &for_each_function : for_each_functions)
+ test_one (n_threads, for_each_function);
}
-}
-}
+} /* namespace parallel_for */
+} /* namespace selftests */
#endif /* CXX_STD_THREAD */
-void _initialize_parallel_for_selftests ();
-void
-_initialize_parallel_for_selftests ()
+INIT_GDB_FILE (parallel_for_selftests)
{
#ifdef CXX_STD_THREAD
selftests::register_test ("parallel_for",
- selftests::parallel_for::test_n_threads);
+ selftests::parallel_for::test_parallel_for_each);
#endif /* CXX_STD_THREAD */
}
-
-#else /* FOR_EACH */
-
-static void
-TEST (int n_threads)
-{
- save_restore_n_threads saver;
- gdb::thread_pool::g_thread_pool->set_thread_count (n_threads);
-
-#define NUMBER 10000
-
- std::atomic<int> counter (0);
- FOR_EACH (1, 0, NUMBER,
- [&] (int start, int end)
- {
- counter += end - start;
- });
- SELF_CHECK (counter == NUMBER);
-
- counter = 0;
- FOR_EACH (1, 0, 0,
- [&] (int start, int end)
- {
- counter += end - start;
- });
- SELF_CHECK (counter == 0);
-
-#undef NUMBER
-
- /* Check that if there are fewer tasks than threads, then we won't
- end up with a null result. */
- std::vector<std::unique_ptr<int>> intresults;
- std::atomic<bool> any_empty_tasks (false);
-
- FOR_EACH (1, 0, 1,
- [&] (int start, int end)
- {
- if (start == end)
- any_empty_tasks = true;
- return std::make_unique<int> (end - start);
- });
- SELF_CHECK (!any_empty_tasks);
- SELF_CHECK (std::all_of (intresults.begin (),
- intresults.end (),
- [] (const std::unique_ptr<int> &entry)
- {
- return entry != nullptr;
- }));
-}
-
-#endif /* FOR_EACH */
diff --git a/gdb/unittests/parse-connection-spec-selftests.c b/gdb/unittests/parse-connection-spec-selftests.c
index 7104272..ce2da35 100644
--- a/gdb/unittests/parse-connection-spec-selftests.c
+++ b/gdb/unittests/parse-connection-spec-selftests.c
@@ -238,9 +238,7 @@ run_tests ()
} /* namespace parse_connection_spec_tests */
} /* namespace selftests */
-void _initialize_parse_connection_spec_selftests ();
-void
-_initialize_parse_connection_spec_selftests ()
+INIT_GDB_FILE (parse_connection_spec_selftests)
{
selftests::register_test ("parse_connection_spec",
selftests::parse_connection_spec_tests::run_tests);
diff --git a/gdb/unittests/path-join-selftests.c b/gdb/unittests/path-join-selftests.c
index a4003f0..8bc5a91 100644
--- a/gdb/unittests/path-join-selftests.c
+++ b/gdb/unittests/path-join-selftests.c
@@ -63,9 +63,7 @@ test ()
}
}
-void _initialize_path_join_selftests ();
-void
-_initialize_path_join_selftests ()
+INIT_GDB_FILE (path_join_selftests)
{
selftests::register_test ("path_join",
selftests::path_join::test);
diff --git a/gdb/unittests/remote-arg-selftests.c b/gdb/unittests/remote-arg-selftests.c
index 70f8a39..17b8d1d 100644
--- a/gdb/unittests/remote-arg-selftests.c
+++ b/gdb/unittests/remote-arg-selftests.c
@@ -156,10 +156,7 @@ self_test ()
} /* namespace remote_args_tests */
} /* namespace selftests */
-void _initialize_remote_arg_selftests ();
-
-void
-_initialize_remote_arg_selftests ()
+INIT_GDB_FILE (remote_arg_selftests)
{
selftests::register_test ("remote-args",
selftests::remote_args_tests::self_test);
diff --git a/gdb/unittests/rsp-low-selftests.c b/gdb/unittests/rsp-low-selftests.c
index 7a1b2de..d0002ae 100644
--- a/gdb/unittests/rsp-low-selftests.c
+++ b/gdb/unittests/rsp-low-selftests.c
@@ -60,9 +60,7 @@ static void test_hex2str ()
} /* namespace rsp_low */
} /* namespace selftests */
-void _initialize_rsp_low_selftests ();
-void
-_initialize_rsp_low_selftests ()
+INIT_GDB_FILE (rsp_low_selftests)
{
selftests::register_test ("hex2bin_byte_vector",
selftests::rsp_low::test_hex2bin_byte_vector);
diff --git a/gdb/unittests/scoped_fd-selftests.c b/gdb/unittests/scoped_fd-selftests.c
index 7abbbd8..da59a18 100644
--- a/gdb/unittests/scoped_fd-selftests.c
+++ b/gdb/unittests/scoped_fd-selftests.c
@@ -92,9 +92,7 @@ run_tests ()
} /* namespace scoped_fd */
} /* namespace selftests */
-void _initialize_scoped_fd_selftests ();
-void
-_initialize_scoped_fd_selftests ()
+INIT_GDB_FILE (scoped_fd_selftests)
{
selftests::register_test ("scoped_fd",
selftests::scoped_fd::run_tests);
diff --git a/gdb/unittests/scoped_ignore_signal-selftests.c b/gdb/unittests/scoped_ignore_signal-selftests.c
index fdfaca3..86c5031 100644
--- a/gdb/unittests/scoped_ignore_signal-selftests.c
+++ b/gdb/unittests/scoped_ignore_signal-selftests.c
@@ -114,9 +114,7 @@ test_sigpipe ()
} /* namespace scoped_ignore_sig */
} /* namespace selftests */
-void _initialize_scoped_ignore_signal_selftests ();
-void
-_initialize_scoped_ignore_signal_selftests ()
+INIT_GDB_FILE (scoped_ignore_signal_selftests)
{
#ifdef SIGPIPE
selftests::register_test ("scoped_ignore_sigpipe",
diff --git a/gdb/unittests/scoped_mmap-selftests.c b/gdb/unittests/scoped_mmap-selftests.c
index 695ed1e..f752b9a 100644
--- a/gdb/unittests/scoped_mmap-selftests.c
+++ b/gdb/unittests/scoped_mmap-selftests.c
@@ -41,7 +41,7 @@ test_destroy ()
errno = 0;
{
::scoped_mmap smmap (nullptr, sysconf (_SC_PAGESIZE), PROT_WRITE,
- MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
mem = smmap.get ();
SELF_CHECK (mem != nullptr);
@@ -59,7 +59,7 @@ test_release ()
errno = 0;
{
::scoped_mmap smmap (nullptr, sysconf (_SC_PAGESIZE), PROT_WRITE,
- MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
mem = smmap.release ();
SELF_CHECK (mem != nullptr);
@@ -135,9 +135,7 @@ run_tests ()
#endif /* !defined(HAVE_SYS_MMAN_H) */
-void _initialize_scoped_mmap_selftests ();
-void
-_initialize_scoped_mmap_selftests ()
+INIT_GDB_FILE (scoped_mmap_selftests)
{
#if defined(HAVE_SYS_MMAN_H)
selftests::register_test ("scoped_mmap",
diff --git a/gdb/unittests/scoped_restore-selftests.c b/gdb/unittests/scoped_restore-selftests.c
index 18d898b..4396046 100644
--- a/gdb/unittests/scoped_restore-selftests.c
+++ b/gdb/unittests/scoped_restore-selftests.c
@@ -102,9 +102,7 @@ run_tests ()
} /* namespace scoped_restore_tests */
} /* namespace selftests */
-void _initialize_scoped_restore_selftests ();
-void
-_initialize_scoped_restore_selftests ()
+INIT_GDB_FILE (scoped_restore_selftests)
{
selftests::register_test ("scoped_restore",
selftests::scoped_restore_tests::run_tests);
diff --git a/gdb/unittests/search-memory-selftests.c b/gdb/unittests/search-memory-selftests.c
index 0e82d6c..c1942fc 100644
--- a/gdb/unittests/search-memory-selftests.c
+++ b/gdb/unittests/search-memory-selftests.c
@@ -89,9 +89,7 @@ run_tests ()
} /* namespace selftests */
-void _initialize_search_memory_selftests ();
-void
-_initialize_search_memory_selftests ()
+INIT_GDB_FILE (search_memory_selftests)
{
selftests::register_test ("search_memory",
selftests::search_memory_tests::run_tests);
diff --git a/gdb/unittests/style-selftests.c b/gdb/unittests/style-selftests.c
index 2cbe194..7cb42a1 100644
--- a/gdb/unittests/style-selftests.c
+++ b/gdb/unittests/style-selftests.c
@@ -38,6 +38,8 @@ run_tests ()
SELF_CHECK (style.get_foreground ().is_none ());
SELF_CHECK (style.get_background ().is_none ());
SELF_CHECK (style.get_intensity () == ui_file_style::NORMAL);
+ SELF_CHECK (!style.is_italic ());
+ SELF_CHECK (!style.is_underline ());
SELF_CHECK (!style.is_reverse ());
SELF_CHECK (style.to_ansi () == "\033[m");
@@ -47,6 +49,8 @@ run_tests ()
SELF_CHECK (style.get_foreground ().is_none ());
SELF_CHECK (style.get_background ().is_none ());
SELF_CHECK (style.get_intensity () == ui_file_style::NORMAL);
+ SELF_CHECK (!style.is_italic ());
+ SELF_CHECK (!style.is_underline ());
SELF_CHECK (!style.is_reverse ());
/* This particular case does not round-trip identically, but the
difference is unimportant. */
@@ -57,8 +61,10 @@ run_tests ()
SELF_CHECK (style.get_foreground ().is_none ());
SELF_CHECK (style.get_background ().is_none ());
SELF_CHECK (style.get_intensity () == ui_file_style::NORMAL);
+ SELF_CHECK (!style.is_italic ());
+ SELF_CHECK (!style.is_underline ());
SELF_CHECK (style.is_reverse ());
- SELF_CHECK (style.to_ansi () == "\033[39;49;22;7m");
+ SELF_CHECK (style.to_ansi () == "\033[39;49;22;23;24;7m");
style = ui_file_style ();
SELF_CHECK (style.parse ("\033[32;1m", &n_read));
@@ -67,8 +73,22 @@ run_tests ()
SELF_CHECK (style.get_foreground ().get_value () == ui_file_style::GREEN);
SELF_CHECK (style.get_background ().is_none ());
SELF_CHECK (style.get_intensity () == ui_file_style::BOLD);
+ SELF_CHECK (!style.is_italic ());
+ SELF_CHECK (!style.is_underline ());
SELF_CHECK (!style.is_reverse ());
- SELF_CHECK (style.to_ansi () == "\033[32;49;1;27m");
+ SELF_CHECK (style.to_ansi () == "\033[32;49;1;23;24;27m");
+
+ style = ui_file_style ();
+ SELF_CHECK (style.parse ("\033[32;2;3;4m", &n_read));
+ SELF_CHECK (n_read == 11);
+ SELF_CHECK (style.get_foreground ().is_basic ());
+ SELF_CHECK (style.get_foreground ().get_value () == ui_file_style::GREEN);
+ SELF_CHECK (style.get_background ().is_none ());
+ SELF_CHECK (style.get_intensity () == ui_file_style::DIM);
+ SELF_CHECK (style.is_italic ());
+ SELF_CHECK (style.is_underline ());
+ SELF_CHECK (!style.is_reverse ());
+ SELF_CHECK (style.to_ansi () == "\033[32;49;2;3;4;27m");
style = ui_file_style ();
SELF_CHECK (style.parse ("\033[38;5;112;48;5;249m", &n_read));
@@ -80,8 +100,10 @@ run_tests ()
style.get_background ().get_rgb (rgb);
CHECK_RGB (0xb2, 0xb2, 0xb2);
SELF_CHECK (style.get_intensity () == ui_file_style::NORMAL);
+ SELF_CHECK (!style.is_italic ());
+ SELF_CHECK (!style.is_underline ());
SELF_CHECK (!style.is_reverse ());
- SELF_CHECK (style.to_ansi () == "\033[38;5;112;48;5;249;22;27m");
+ SELF_CHECK (style.to_ansi () == "\033[38;5;112;48;5;249;22;23;24;27m");
style = ui_file_style ();
SELF_CHECK (style.parse ("\033[38;2;83;84;85;48;2;0;1;254;2;7m", &n_read));
@@ -93,16 +115,16 @@ run_tests ()
style.get_background ().get_rgb (rgb);
CHECK_RGB (0, 1, 254);
SELF_CHECK (style.get_intensity () == ui_file_style::DIM);
+ SELF_CHECK (!style.is_italic ());
+ SELF_CHECK (!style.is_underline ());
SELF_CHECK (style.is_reverse ());
- SELF_CHECK (style.to_ansi () == "\033[38;2;83;84;85;48;2;0;1;254;2;7m");
+ SELF_CHECK (style.to_ansi () == "\033[38;2;83;84;85;48;2;0;1;254;2;23;24;7m");
}
} /* namespace style */
} /* namespace selftests */
-void _initialize_style_selftest ();
-void
-_initialize_style_selftest ()
+INIT_GDB_FILE (style_selftest)
{
selftests::register_test ("style",
selftests::style::run_tests);
diff --git a/gdb/unittests/tracepoint-selftests.c b/gdb/unittests/tracepoint-selftests.c
index 235dd1e..bef51ae 100644
--- a/gdb/unittests/tracepoint-selftests.c
+++ b/gdb/unittests/tracepoint-selftests.c
@@ -60,9 +60,7 @@ test_parse_static_tracepoint_marker_definition ()
} /* namespace tracepoint_tests */
} /* namespace selftests */
-void _initialize_tracepoint_selftests ();
-void
-_initialize_tracepoint_selftests ()
+INIT_GDB_FILE (tracepoint_selftests)
{
selftests::register_test
("parse_static_tracepoint_marker_definition",
diff --git a/gdb/unittests/tui-selftests.c b/gdb/unittests/tui-selftests.c
index e61b0db..5235a07 100644
--- a/gdb/unittests/tui-selftests.c
+++ b/gdb/unittests/tui-selftests.c
@@ -45,9 +45,7 @@ run_tests ()
#endif /* TUI */
-void _initialize_tui_selftest ();
-void
-_initialize_tui_selftest ()
+INIT_GDB_FILE (tui_selftest)
{
#ifdef TUI
selftests::register_test ("tui", selftests::tui::run_tests);
diff --git a/gdb/unittests/ui-file-selftests.c b/gdb/unittests/ui-file-selftests.c
index b62fd4f..d78c6b0 100644
--- a/gdb/unittests/ui-file-selftests.c
+++ b/gdb/unittests/ui-file-selftests.c
@@ -53,9 +53,7 @@ run_tests ()
} /* namespace file*/
} /* namespace selftests */
-void _initialize_ui_file_selftest ();
-void
-_initialize_ui_file_selftest ()
+INIT_GDB_FILE (ui_file_selftest)
{
selftests::register_test ("ui-file",
selftests::file::run_tests);
diff --git a/gdb/unittests/unique_xmalloc_ptr_char.c b/gdb/unittests/unique_xmalloc_ptr_char.c
index 984f692..7f61c06 100644
--- a/gdb/unittests/unique_xmalloc_ptr_char.c
+++ b/gdb/unittests/unique_xmalloc_ptr_char.c
@@ -47,9 +47,7 @@ unique_xmalloc_ptr_char ()
}
}
-void _initialize_unique_xmalloc_ptr_char ();
-void
-_initialize_unique_xmalloc_ptr_char ()
+INIT_GDB_FILE (unique_xmalloc_ptr_char)
{
selftests::register_test ("unique_xmalloc_ptr_char",
selftests::unpack::unique_xmalloc_ptr_char);
diff --git a/gdb/unittests/unpack-selftests.c b/gdb/unittests/unpack-selftests.c
index 54af777..fccf7a2 100644
--- a/gdb/unittests/unpack-selftests.c
+++ b/gdb/unittests/unpack-selftests.c
@@ -52,9 +52,7 @@ unpack_field_as_long_tests (struct gdbarch *arch)
}
}
-void _initialize_unpack_selftests ();
-void
-_initialize_unpack_selftests ()
+INIT_GDB_FILE (unpack_selftests)
{
selftests::register_test_foreach_arch
("unpack_field_as_long", selftests::unpack::unpack_field_as_long_tests);
diff --git a/gdb/unittests/utils-selftests.c b/gdb/unittests/utils-selftests.c
deleted file mode 100644
index b1c457c..0000000
--- a/gdb/unittests/utils-selftests.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Unit tests for the utils.c file.
-
- Copyright (C) 2018-2025 Free Software Foundation, Inc.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "utils.h"
-#include "gdbsupport/selftest.h"
-
-namespace selftests {
-namespace utils {
-
-static void
-test_substitute_path_component ()
-{
- auto test = [] (std::string s, const char *from, const char *to,
- const char *expected)
- {
- char *temp = xstrdup (s.c_str ());
- substitute_path_component (&temp, from, to);
- SELF_CHECK (strcmp (temp, expected) == 0);
- xfree (temp);
- };
-
- test ("/abc/$def/g", "abc", "xyz", "/xyz/$def/g");
- test ("abc/$def/g", "abc", "xyz", "xyz/$def/g");
- test ("/abc/$def/g", "$def", "xyz", "/abc/xyz/g");
- test ("/abc/$def/g", "g", "xyz", "/abc/$def/xyz");
- test ("/abc/$def/g", "ab", "xyz", "/abc/$def/g");
- test ("/abc/$def/g", "def", "xyz", "/abc/$def/g");
- test ("/abc/$def/g", "abc", "abc", "/abc/$def/g");
- test ("/abc/$def/g", "abc", "", "//$def/g");
- test ("/abc/$def/g", "abc/$def", "xyz", "/xyz/g");
- test ("/abc/$def/abc", "abc", "xyz", "/xyz/$def/xyz");
-}
-
-}
-}
-
-void _initialize_utils_selftests ();
-void
-_initialize_utils_selftests ()
-{
- selftests::register_test ("substitute_path_component",
- selftests::utils::test_substitute_path_component);
-}
diff --git a/gdb/unittests/vec-utils-selftests.c b/gdb/unittests/vec-utils-selftests.c
index 4be0b86..11fad31 100644
--- a/gdb/unittests/vec-utils-selftests.c
+++ b/gdb/unittests/vec-utils-selftests.c
@@ -65,9 +65,7 @@ unordered_remove_tests ()
} /* namespace vector_utils_tests */
} /* namespace selftests */
-void _initialize_vec_utils_selftests ();
-void
-_initialize_vec_utils_selftests ()
+INIT_GDB_FILE (vec_utils_selftests)
{
selftests::register_test
("unordered_remove",
diff --git a/gdb/unittests/xml-utils-selftests.c b/gdb/unittests/xml-utils-selftests.c
index 5884faa..f4a637b 100644
--- a/gdb/unittests/xml-utils-selftests.c
+++ b/gdb/unittests/xml-utils-selftests.c
@@ -47,9 +47,7 @@ static void test_xml_escape_text_append ()
}
}
-void _initialize_xml_utils ();
-void
-_initialize_xml_utils ()
+INIT_GDB_FILE (xml_utils)
{
selftests::register_test ("xml_escape_text",
selftests::xml_utils::test_xml_escape_text);
diff --git a/gdb/user-regs.c b/gdb/user-regs.c
index 5860d7d..7170cda 100644
--- a/gdb/user-regs.c
+++ b/gdb/user-regs.c
@@ -237,9 +237,7 @@ maintenance_print_user_registers (const char *args, int from_tty)
}
}
-void _initialize_user_regs ();
-void
-_initialize_user_regs ()
+INIT_GDB_FILE (user_regs)
{
add_cmd ("user-registers", class_maintenance,
maintenance_print_user_registers,
diff --git a/gdb/utils.c b/gdb/utils.c
index ce3c26e..57c739e 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -17,7 +17,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include <ctype.h>
#include "gdbsupport/gdb_wait.h"
#include "gdbsupport/scoped_signal_handler.h"
#include "event-top.h"
@@ -54,7 +53,6 @@
#include "top.h"
#include "ui.h"
#include "main.h"
-#include "solist.h"
#include "inferior.h"
@@ -76,7 +74,6 @@
#include "gdbsupport/scope-exit.h"
#include "gdbarch.h"
#include "cli-out.h"
-#include "gdbsupport/gdb-safe-ctype.h"
#include "bt-utils.h"
#include "gdbsupport/buildargv.h"
#include "pager.h"
@@ -177,6 +174,7 @@ vwarning (const char *string, va_list args)
target_terminal::ours_for_output ();
}
gdb_puts (warning_pre_print, gdb_stderr);
+ print_warning_prefix (gdb_stderr);
gdb_puts (_("warning: "), gdb_stderr);
gdb_vprintf (gdb_stderr, string, args);
gdb_printf (gdb_stderr, "\n");
@@ -1008,7 +1006,7 @@ parse_escape (struct gdbarch *gdbarch, const char **string_ptr)
while (++count < 3)
{
c = (**string_ptr);
- if (ISDIGIT (c) && c != '8' && c != '9')
+ if (c_isdigit (c) && c != '8' && c != '9')
{
(*string_ptr)++;
i *= 8;
@@ -1401,7 +1399,26 @@ pager_file::emit_style_escape (const ui_file_style &style)
{
m_applied_style = style;
if (m_paging)
- m_stream->emit_style_escape (style);
+ {
+ /* Previous style changes will have been sent to m_stream via
+ escape sequences encoded in the m_wrap_buffer. As a result,
+ the m_stream->m_applied_style will not have been updated.
+
+ If we now use m_stream->emit_style_escape, then the required
+ style might not actually be emitted as the requested style
+ might happen to match the out of date value in
+ m_stream->m_applied_style.
+
+ Instead, send the style change directly using m_stream->puts.
+
+ However, we track what style is currently applied to the
+ underlying stream in m_stream_style, this is updated whenever
+ m_wrap_buffer is flushed to the underlying stream. And so, if
+ the style we are applying matches what we know is currently
+ applied to the underlying stream, then we can skip sending
+ this style to the stream. */
+ this->set_stream_style (m_applied_style);
+ }
else
m_wrap_buffer.append (style.to_ansi ());
}
@@ -1424,8 +1441,8 @@ pager_file::prompt_for_continue ()
scoped_restore save_paging = make_scoped_restore (&m_paging, true);
- /* Clear the current styling. */
- m_stream->emit_style_escape (ui_file_style ());
+ /* Clear the current styling on ourselves and the managed stream. */
+ this->emit_style_escape (ui_file_style ());
if (annotation_level > 1)
m_stream->puts (("\n\032\032pre-prompt-for-continue\n"));
@@ -1508,6 +1525,7 @@ pager_file::flush_wrap_buffer ()
if (!m_paging && !m_wrap_buffer.empty ())
{
m_stream->puts (m_wrap_buffer.c_str ());
+ m_stream_style = m_applied_style;
m_wrap_buffer.clear ();
}
}
@@ -1682,10 +1700,25 @@ pager_file::puts (const char *linebuffer)
else if (*linebuffer == '\033'
&& skip_ansi_escape (linebuffer, &skip_bytes))
{
- m_wrap_buffer.append (linebuffer, skip_bytes);
- /* Note that we don't consider this a character, so we
+ /* We don't consider escape sequences as characters, so we
don't increment chars_printed here. */
- linebuffer += skip_bytes;
+
+ size_t style_len;
+ ui_file_style style;
+ if (style.parse (linebuffer, &style_len)
+ && style_len <= skip_bytes)
+ {
+ this->emit_style_escape (style);
+
+ linebuffer += style_len;
+ skip_bytes -= style_len;
+ }
+
+ if (skip_bytes > 0)
+ {
+ m_wrap_buffer.append (linebuffer, skip_bytes);
+ linebuffer += skip_bytes;
+ }
}
else if (*linebuffer == '\r')
{
@@ -1724,7 +1757,8 @@ pager_file::puts (const char *linebuffer)
current applied style to how it was at the WRAP_COLUMN
location. */
m_applied_style = m_wrap_style;
- m_stream->emit_style_escape (ui_file_style ());
+ this->set_stream_style (ui_file_style ());
+
/* If we aren't actually wrapping, don't output
newline -- if chars_per_line is right, we
probably just overflowed anyway; if it's wrong,
@@ -1752,7 +1786,7 @@ pager_file::puts (const char *linebuffer)
/* Having finished inserting the wrapping we should
restore the style as it was at the WRAP_COLUMN. */
- m_stream->emit_style_escape (m_wrap_style);
+ this->set_stream_style (m_wrap_style);
/* The WRAP_BUFFER will still contain content, and that
content might set some alternative style. Restore
@@ -1767,7 +1801,7 @@ pager_file::puts (const char *linebuffer)
m_wrap_column = 0; /* And disable fancy wrap */
}
else if (did_paginate)
- m_stream->emit_style_escape (save_style);
+ this->emit_style_escape (save_style);
}
}
@@ -1788,7 +1822,7 @@ void
pager_file::write (const char *buf, long length_buf)
{
/* We have to make a string here because the pager uses
- skip_ansi_escape, which requires NUL-termination. */
+ examine_ansi_escape, which requires NUL-termination. */
std::string str (buf, length_buf);
this->puts (str.c_str ());
}
@@ -2032,7 +2066,7 @@ fprintf_symbol (struct ui_file *stream, const char *name,
static bool
valid_identifier_name_char (int ch)
{
- return (ISALNUM (ch) || ch == '_');
+ return (c_isalnum (ch) || ch == '_');
}
/* Skip to end of token, or to END, whatever comes first. Input is
@@ -2042,7 +2076,7 @@ static const char *
cp_skip_operator_token (const char *token, const char *end)
{
const char *p = token;
- while (p != end && !ISSPACE (*p) && *p != '(')
+ while (p != end && !c_isspace (*p) && *p != '(')
{
if (valid_identifier_name_char (*p))
{
@@ -2096,9 +2130,9 @@ cp_skip_operator_token (const char *token, const char *end)
static void
skip_ws (const char *&string1, const char *&string2, const char *end_str2)
{
- while (ISSPACE (*string1))
+ while (c_isspace (*string1))
string1++;
- while (string2 < end_str2 && ISSPACE (*string2))
+ while (string2 < end_str2 && c_isspace (*string2))
string2++;
}
@@ -2162,7 +2196,7 @@ skip_template_parameter_list (const char **name)
/* Skip any whitespace that might occur after the closing of the
parameter list, but only if it is the end of parameter list. */
const char *q = p;
- while (ISSPACE (*q))
+ while (c_isspace (*q))
++q;
if (*q == '>')
p = q;
@@ -2194,8 +2228,8 @@ strncmp_iw_with_mode (const char *string1, const char *string2,
while (1)
{
if (skip_spaces
- || ((ISSPACE (*string1) && !valid_identifier_name_char (*string2))
- || (ISSPACE (*string2) && !valid_identifier_name_char (*string1))))
+ || ((c_isspace (*string1) && !valid_identifier_name_char (*string2))
+ || (c_isspace (*string2) && !valid_identifier_name_char (*string1))))
{
skip_ws (string1, string2, end_str2);
skip_spaces = false;
@@ -2228,7 +2262,7 @@ strncmp_iw_with_mode (const char *string1, const char *string2,
if (match_for_lcd != NULL && abi_start != string1)
match_for_lcd->mark_ignored_range (abi_start, string1);
- while (ISSPACE (*string1))
+ while (c_isspace (*string1))
string1++;
}
@@ -2295,9 +2329,9 @@ strncmp_iw_with_mode (const char *string1, const char *string2,
string1++;
string2++;
- while (ISSPACE (*string1))
+ while (c_isspace (*string1))
string1++;
- while (string2 < end_str2 && ISSPACE (*string2))
+ while (string2 < end_str2 && c_isspace (*string2))
string2++;
continue;
}
@@ -2397,14 +2431,13 @@ strncmp_iw_with_mode (const char *string1, const char *string2,
if (case_sensitivity == case_sensitive_on && *string1 != *string2)
break;
if (case_sensitivity == case_sensitive_off
- && (TOLOWER ((unsigned char) *string1)
- != TOLOWER ((unsigned char) *string2)))
+ && c_tolower (*string1) != c_tolower (*string2))
break;
/* If we see any non-whitespace, non-identifier-name character
(any of "()<>*&" etc.), then skip spaces the next time
around. */
- if (!ISSPACE (*string1) && !valid_identifier_name_char (*string1))
+ if (!c_isspace (*string1) && !valid_identifier_name_char (*string1))
skip_spaces = true;
string1++;
@@ -3117,16 +3150,16 @@ strcmp_iw_ordered (const char *string1, const char *string2)
while (*string1 != '\0' && *string2 != '\0')
{
- while (ISSPACE (*string1))
+ while (c_isspace (*string1))
string1++;
- while (ISSPACE (*string2))
+ while (c_isspace (*string2))
string2++;
switch (case_pass)
{
case case_sensitive_off:
- c1 = TOLOWER ((unsigned char) *string1);
- c2 = TOLOWER ((unsigned char) *string2);
+ c1 = c_tolower (*string1);
+ c2 = c_tolower (*string2);
break;
case case_sensitive_on:
c1 = *string1;
@@ -3235,17 +3268,17 @@ string_to_core_addr (const char *my_string)
{
CORE_ADDR addr = 0;
- if (my_string[0] == '0' && TOLOWER (my_string[1]) == 'x')
+ if (my_string[0] == '0' && c_tolower (my_string[1]) == 'x')
{
/* Assume that it is in hex. */
int i;
for (i = 2; my_string[i] != '\0'; i++)
{
- if (ISDIGIT (my_string[i]))
+ if (c_isdigit (my_string[i]))
addr = (my_string[i] - '0') + (addr * 16);
- else if (ISXDIGIT (my_string[i]))
- addr = (TOLOWER (my_string[i]) - 'a' + 0xa) + (addr * 16);
+ else if (c_isxdigit (my_string[i]))
+ addr = (c_tolower (my_string[i]) - 'a' + 0xa) + (addr * 16);
else
error (_("invalid hex \"%s\""), my_string);
}
@@ -3257,7 +3290,7 @@ string_to_core_addr (const char *my_string)
for (i = 0; my_string[i] != '\0'; i++)
{
- if (ISDIGIT (my_string[i]))
+ if (c_isdigit (my_string[i]))
addr = (my_string[i] - '0') + (addr * 10);
else
error (_("invalid decimal \"%s\""), my_string);
@@ -3332,7 +3365,7 @@ gdb_argv_as_array_view_test ()
argument. */
std::string
-ldirname (const char *filename)
+gdb_ldirname (const char *filename)
{
std::string dirname;
const char *base = lbasename (filename);
@@ -3374,51 +3407,6 @@ parse_pid_to_attach (const char *args)
return pid;
}
-/* Substitute all occurrences of string FROM by string TO in *STRINGP. *STRINGP
- must come from xrealloc-compatible allocator and it may be updated. FROM
- needs to be delimited by IS_DIR_SEPARATOR or DIRNAME_SEPARATOR (or be
- located at the start or end of *STRINGP. */
-
-void
-substitute_path_component (char **stringp, const char *from, const char *to)
-{
- char *string = *stringp, *s;
- const size_t from_len = strlen (from);
- const size_t to_len = strlen (to);
-
- for (s = string;;)
- {
- s = strstr (s, from);
- if (s == NULL)
- break;
-
- if ((s == string || IS_DIR_SEPARATOR (s[-1])
- || s[-1] == DIRNAME_SEPARATOR)
- && (s[from_len] == '\0' || IS_DIR_SEPARATOR (s[from_len])
- || s[from_len] == DIRNAME_SEPARATOR))
- {
- char *string_new;
-
- string_new
- = (char *) xrealloc (string, (strlen (string) + to_len + 1));
-
- /* Relocate the current S pointer. */
- s = s - string + string_new;
- string = string_new;
-
- /* Replace from by to. */
- memmove (&s[to_len], &s[from_len], strlen (&s[from_len]) + 1);
- memcpy (s, to, to_len);
-
- s += to_len;
- }
- else
- s++;
- }
-
- *stringp = string;
-}
-
#ifdef HAVE_WAITPID
#ifdef SIGALRM
@@ -3740,9 +3728,7 @@ test_assign_set_return_if_changed ()
}
#endif
-void _initialize_utils ();
-void
-_initialize_utils ()
+INIT_GDB_FILE (utils)
{
add_setshow_uinteger_cmd ("width", class_support, &chars_per_line, _("\
Set number of characters where GDB should wrap lines of its output."), _("\
diff --git a/gdb/utils.h b/gdb/utils.h
index bc8c2ef..b37e8f7 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -133,10 +133,7 @@ private:
extern int gdb_filename_fnmatch (const char *pattern, const char *string,
int flags);
-extern void substitute_path_component (char **stringp, const char *from,
- const char *to);
-
-std::string ldirname (const char *filename);
+std::string gdb_ldirname (const char *filename);
extern int count_path_elements (const char *path);
diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c
index e9ec858..d592344 100644
--- a/gdb/v850-tdep.c
+++ b/gdb/v850-tdep.c
@@ -1461,9 +1461,7 @@ v850_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
-void _initialize_v850_tdep ();
-void
-_initialize_v850_tdep ()
+INIT_GDB_FILE (v850_tdep)
{
gdbarch_register (bfd_arch_v850, v850_gdbarch_init);
gdbarch_register (bfd_arch_v850_rh850, v850_gdbarch_init);
diff --git a/gdb/valops.c b/gdb/valops.c
index 94f908d..fa87546 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -45,9 +45,6 @@
/* Local functions. */
-static int typecmp (bool staticp, bool varargs, int nargs,
- struct field t1[], const gdb::array_view<value *> t2);
-
static struct value *search_struct_field (const char *, struct value *,
struct type *, int);
@@ -1766,7 +1763,7 @@ value_string (const gdb_byte *ptr, ssize_t count, struct type *char_type)
/* See if we can pass arguments in T2 to a function which takes arguments
- of types T1. T1 is a list of NARGS arguments, and T2 is an array_view
+ of types T1. T1 is an array_view of arguments, and T2 is an array_view
of the values we're trying to pass. If some arguments need coercion of
some sort, then the coerced values are written into T2. Return value is
0 if the arguments could be matched, or the position at which they
@@ -1783,8 +1780,8 @@ value_string (const gdb_byte *ptr, ssize_t count, struct type *char_type)
requested operation is type secure, shouldn't we? FIXME. */
static int
-typecmp (bool staticp, bool varargs, int nargs,
- struct field t1[], gdb::array_view<value *> t2)
+typecmp (bool staticp, bool varargs,
+ gdb::array_view<struct field> t1, gdb::array_view<value *> t2)
{
int i;
@@ -1794,7 +1791,7 @@ typecmp (bool staticp, bool varargs, int nargs,
t2 = t2.slice (1);
for (i = 0;
- (i < nargs) && t1[i].type ()->code () != TYPE_CODE_VOID;
+ (i < t1.size ()) && t1[i].type ()->code () != TYPE_CODE_VOID;
i++)
{
struct type *tt1, *tt2;
@@ -2227,7 +2224,6 @@ search_struct_method (const char *name, struct value **arg1p,
gdb_assert (args.has_value ());
if (!typecmp (TYPE_FN_FIELD_STATIC_P (f, j),
TYPE_FN_FIELD_TYPE (f, j)->has_varargs (),
- TYPE_FN_FIELD_TYPE (f, j)->num_fields (),
TYPE_FN_FIELD_ARGS (f, j), *args))
{
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
@@ -3826,7 +3822,7 @@ value_maybe_namespace_elt (const struct type *curtype,
if (sym.symbol == NULL)
return NULL;
else if ((noside == EVAL_AVOID_SIDE_EFFECTS)
- && (sym.symbol->aclass () == LOC_TYPEDEF))
+ && (sym.symbol->loc_class () == LOC_TYPEDEF))
result = value::allocate (sym.symbol->type ());
else
result = value_of_variable (sym.symbol, sym.block);
@@ -4024,7 +4020,7 @@ value_of_this_silent (const struct language_defn *lang)
bound as the original ARRAY. */
struct value *
-value_slice (struct value *array, int lowbound, int length)
+value_slice (struct value *array, LONGEST lowbound, LONGEST length)
{
struct type *slice_range_type, *slice_type, *range_type;
LONGEST lowerbound, upperbound;
@@ -4162,9 +4158,7 @@ cast_into_complex (struct type *type, struct value *val)
error (_("cannot cast non-number to complex"));
}
-void _initialize_valops ();
-void
-_initialize_valops ()
+INIT_GDB_FILE (valops)
{
add_setshow_boolean_cmd ("overload-resolution", class_support,
&overload_resolution, _("\
diff --git a/gdb/valprint.c b/gdb/valprint.c
index ed03f6d..b8c1c06 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -34,7 +34,6 @@
#include "gdbsupport/gdb_obstack.h"
#include "charset.h"
#include "typeprint.h"
-#include <ctype.h>
#include <algorithm>
#include "gdbsupport/byte-vector.h"
#include "cli/cli-option.h"
@@ -3194,9 +3193,7 @@ test_print_flags (gdbarch *arch)
#endif
-void _initialize_valprint ();
-void
-_initialize_valprint ()
+INIT_GDB_FILE (valprint)
{
#if GDB_SELF_TEST
selftests::register_test_foreach_arch ("print-flags", test_print_flags);
diff --git a/gdb/value.c b/gdb/value.c
index 0f1be2e..c78bb98 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -35,7 +35,6 @@
#include "valprint.h"
#include "cli/cli-decode.h"
#include "extension.h"
-#include <ctype.h>
#include "tracepoint.h"
#include "cp-abi.h"
#include "user-regs.h"
@@ -45,6 +44,7 @@
#include <utility>
#include <vector>
#include "completer.h"
+#include "gdbsupport/cleanups.h"
#include "gdbsupport/selftest.h"
#include "gdbsupport/array-view.h"
#include "cli/cli-style.h"
@@ -3266,6 +3266,9 @@ unpack_bits_as_long (struct type *field_type, const gdb_byte *valaddr,
}
}
+ if (field_type->code () == TYPE_CODE_RANGE)
+ val += field_type->bounds ()->bias;
+
return val;
}
@@ -3296,21 +3299,28 @@ unpack_value_field_as_long (struct type *type, const gdb_byte *valaddr,
return 1;
}
-/* Unpack a field FIELDNO of the specified TYPE, from the anonymous
- object at VALADDR. See unpack_bits_as_long for more details. */
+/* See value.h. */
LONGEST
-unpack_field_as_long (struct type *type, const gdb_byte *valaddr, int fieldno)
+unpack_field_as_long (const gdb_byte *valaddr, struct field *field)
{
- int bitpos = type->field (fieldno).loc_bitpos ();
- int bitsize = type->field (fieldno).bitsize ();
- struct type *field_type = type->field (fieldno).type ();
+ int bitpos = field->loc_bitpos ();
+ int bitsize = field->bitsize ();
+ struct type *field_type = field->type ();
return unpack_bits_as_long (field_type, valaddr, bitpos, bitsize);
}
/* See value.h. */
+LONGEST
+unpack_field_as_long (struct type *type, const gdb_byte *valaddr, int fieldno)
+{
+ return unpack_field_as_long (valaddr, &type->field (fieldno));
+}
+
+/* See value.h. */
+
void
value::unpack_bitfield (struct value *dest_val,
LONGEST bitpos, LONGEST bitsize,
@@ -3712,11 +3722,11 @@ value_from_history_ref (const char *h, const char **endp)
len = 2;
/* Find length of numeral string. */
- for (; isdigit (h[len]); len++)
+ for (; c_isdigit (h[len]); len++)
;
/* Make sure numeral string is not part of an identifier. */
- if (h[len] == '_' || isalpha (h[len]))
+ if (h[len] == '_' || c_isalpha (h[len]))
return NULL;
/* Now collect the index value. */
@@ -4486,9 +4496,7 @@ test_value_copy ()
} /* namespace selftests */
#endif /* GDB_SELF_TEST */
-void _initialize_values ();
-void
-_initialize_values ()
+INIT_GDB_FILE (values)
{
cmd_list_element *show_convenience_cmd
= add_cmd ("convenience", no_class, show_convenience, _("\
diff --git a/gdb/value.h b/gdb/value.h
index 71d0ba1..b9d2809 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -1058,10 +1058,19 @@ extern gdb_mpz value_as_mpz (struct value *val);
extern LONGEST unpack_long (struct type *type, const gdb_byte *valaddr);
extern CORE_ADDR unpack_pointer (struct type *type, const gdb_byte *valaddr);
+/* Unpack a field FIELDNO of the specified TYPE, from the anonymous
+ object at VALADDR. See unpack_bits_as_long for more details. */
+
extern LONGEST unpack_field_as_long (struct type *type,
const gdb_byte *valaddr,
int fieldno);
+/* Unpack a field, FIELD, from the anonymous object at VALADDR. See
+ unpack_bits_as_long for more details. */
+
+extern LONGEST unpack_field_as_long (const gdb_byte *valaddr,
+ struct field *field);
+
/* Unpack a bitfield of the specified FIELD_TYPE, from the object at
VALADDR, and store the result in *RESULT.
The bitfield starts at BITPOS bits and contains BITSIZE bits; if
@@ -1147,9 +1156,12 @@ extern struct value *address_of_variable (struct symbol *var,
extern value *value_of_register (int regnum, const frame_info_ptr &next_frame);
-/* Same as the above, but the value is not fetched. */
+/* Same as the above, but the value is not fetched. If TYPE is
+ non-nullptr, use it as the value type. Otherwise, 'register_type'
+ will be used to obtain the type. */
-extern value *value_of_register_lazy (const frame_info_ptr &next_frame, int regnum);
+extern value *value_of_register_lazy (const frame_info_ptr &next_frame,
+ int regnum, struct type *type = nullptr);
/* Return the symbol's reading requirement. */
@@ -1577,7 +1589,7 @@ extern struct value *make_cv_value (int, int, struct value *);
extern struct value *varying_to_slice (struct value *);
-extern struct value *value_slice (struct value *, int, int);
+extern struct value *value_slice (struct value *, LONGEST, LONGEST);
/* Create a complex number. The type is the complex type; the values
are cast to the underlying scalar type before the complex number is
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 8dc7a30..4dc986a 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -2424,9 +2424,7 @@ eq_varobj_and_string (const void *a, const void *b)
return obj->obj_name == name;
}
-void _initialize_varobj ();
-void
-_initialize_varobj ()
+INIT_GDB_FILE (varobj)
{
varobj_table = htab_create_alloc (5, hash_varobj, eq_varobj_and_string,
nullptr, xcalloc, xfree);
diff --git a/gdb/vax-bsd-nat.c b/gdb/vax-bsd-nat.c
index 6d8bb54..717314e 100644
--- a/gdb/vax-bsd-nat.c
+++ b/gdb/vax-bsd-nat.c
@@ -136,9 +136,7 @@ vaxbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
return 1;
}
-void _initialize_vaxbsd_nat ();
-void
-_initialize_vaxbsd_nat ()
+INIT_GDB_FILE (vaxbsd_nat)
{
add_inf_child_target (&the_vax_bsd_nat_target);
diff --git a/gdb/vax-netbsd-tdep.c b/gdb/vax-netbsd-tdep.c
index 34a9150..7781264 100644
--- a/gdb/vax-netbsd-tdep.c
+++ b/gdb/vax-netbsd-tdep.c
@@ -32,13 +32,10 @@ vaxnbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
nbsd_init_abi (info, gdbarch);
/* NetBSD ELF uses SVR4-style shared libraries. */
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
}
-void _initialize_vaxnbsd_tdep ();
-void
-_initialize_vaxnbsd_tdep ()
+INIT_GDB_FILE (vaxnbsd_tdep)
{
gdbarch_register_osabi (bfd_arch_vax, 0, GDB_OSABI_NETBSD,
vaxnbsd_elf_init_abi);
diff --git a/gdb/vax-tdep.c b/gdb/vax-tdep.c
index 94dc308..0a83f4f 100644
--- a/gdb/vax-tdep.c
+++ b/gdb/vax-tdep.c
@@ -506,9 +506,7 @@ vax_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return (gdbarch);
}
-void _initialize_vax_tdep ();
-void
-_initialize_vax_tdep ()
+INIT_GDB_FILE (vax_tdep)
{
gdbarch_register (bfd_arch_vax, vax_gdbarch_init, NULL);
}
diff --git a/gdb/version.in b/gdb/version.in
index 75e06a8..85ad8ec 100644
--- a/gdb/version.in
+++ b/gdb/version.in
@@ -1 +1 @@
-17.0.50.DATE-git \ No newline at end of file
+18.0.50.DATE-git \ No newline at end of file
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 0fee4ad..f74ea0c 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -56,7 +56,6 @@
#include "cli/cli-style.h"
#include <unistd.h>
#include "exec.h"
-#include "solist.h"
#include "solib.h"
#include "xml-support.h"
#include "inttypes.h"
@@ -433,7 +432,12 @@ wait_for_single (HANDLE handle, DWORD howlong)
{
while (true)
{
- DWORD r = WaitForSingleObject (handle, howlong);
+ /* Using an INFINITE argument to WaitForSingleObject may cause a system
+ deadlock. Avoid it by waiting for a bit in a loop instead. */
+ DWORD milliseconds = howlong == INFINITE ? 100 : howlong;
+ DWORD r = WaitForSingleObject (handle, milliseconds);
+ if (howlong == INFINITE && r == WAIT_TIMEOUT)
+ continue;
if (r == WAIT_OBJECT_0)
return;
if (r == WAIT_FAILED)
@@ -2422,7 +2426,7 @@ redir_set_redirection (const char *s, int *inp, int *out, int *err)
/* cmd.exe recognizes "&N" only immediately after the redirection symbol. */
if (*s != '&')
{
- while (isspace (*s)) /* skip whitespace before file name */
+ while (c_isspace (*s)) /* skip whitespace before file name */
s++;
*d++ = ' '; /* separate file name with a single space */
}
@@ -2449,7 +2453,7 @@ redir_set_redirection (const char *s, int *inp, int *out, int *err)
s++;
*d++ = *s++;
}
- else if (isspace (*s) && !quote)
+ else if (c_isspace (*s) && !quote)
break;
else
*d++ = *s++;
@@ -2485,7 +2489,7 @@ redirect_inferior_handles (const char *cmd_orig, char *cmd,
int quote = 0;
bool retval = false;
- while (isspace (*s))
+ while (c_isspace (*s))
*d++ = *s++;
while (*s)
@@ -3089,9 +3093,7 @@ windows_nat_target::thread_name (struct thread_info *thr)
}
-void _initialize_windows_nat ();
-void
-_initialize_windows_nat ()
+INIT_GDB_FILE (windows_nat)
{
x86_dr_low.set_control = cygwin_set_dr7;
x86_dr_low.set_addr = cygwin_set_dr;
@@ -3265,9 +3267,7 @@ windows_nat_target::thread_alive (ptid_t ptid)
return WaitForSingleObject (th->h, 0) != WAIT_OBJECT_0;
}
-void _initialize_check_for_gdb_ini ();
-void
-_initialize_check_for_gdb_ini ()
+INIT_GDB_FILE (check_for_gdb_ini)
{
char *homedir;
if (inhibit_gdbinit)
diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
index 0ba1472..c6f5803 100644
--- a/gdb/windows-tdep.c
+++ b/gdb/windows-tdep.c
@@ -36,7 +36,6 @@
#include "gdbcore.h"
#include "coff/internal.h"
#include "libcoff.h"
-#include "solist.h"
#define CYGWIN_DLL_NAME "cygwin1.dll"
@@ -551,43 +550,6 @@ windows_xfer_shared_library (const char* so_name, CORE_ADDR load_addr,
xml += "\"/></library>";
}
-/* Implement the "iterate_over_objfiles_in_search_order" gdbarch
- method. It searches all objfiles, starting with CURRENT_OBJFILE
- first (if not NULL).
-
- On Windows, the system behaves a little differently when two
- objfiles each define a global symbol using the same name, compared
- to other platforms such as GNU/Linux for instance. On GNU/Linux,
- all instances of the symbol effectively get merged into a single
- one, but on Windows, they remain distinct.
-
- As a result, it usually makes sense to start global symbol searches
- with the current objfile before expanding it to all other objfiles.
- This helps for instance when a user debugs some code in a DLL that
- refers to a global variable defined inside that DLL. When trying
- to print the value of that global variable, it would be unhelpful
- to print the value of another global variable defined with the same
- name, but in a different DLL. */
-
-static void
-windows_iterate_over_objfiles_in_search_order
- (gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb,
- objfile *current_objfile)
-{
- if (current_objfile)
- {
- if (cb (current_objfile))
- return;
- }
-
- for (objfile *objfile : current_program_space->objfiles ())
- if (objfile != current_objfile)
- {
- if (cb (objfile))
- return;
- }
-}
-
static void
show_maint_show_all_tib (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
@@ -863,10 +825,30 @@ windows_get_siginfo_type (struct gdbarch *gdbarch)
return siginfo_type;
}
+/* solib_ops for Windows systems. */
+
+struct windows_solib_ops : target_solib_ops
+{
+ using target_solib_ops::target_solib_ops;
+
+ void create_inferior_hook (int from_tty) const override;
+ void iterate_over_objfiles_in_search_order
+ (iterate_over_objfiles_in_search_order_cb_ftype cb,
+ objfile *current_objfile) const override;
+};
+
+/* Return a new solib_ops for Windows systems. */
+
+static solib_ops_up
+make_windows_solib_ops (program_space *pspace)
+{
+ return std::make_unique<windows_solib_ops> (pspace);
+}
+
/* Implement the "solib_create_inferior_hook" solib_ops method. */
-static void
-windows_solib_create_inferior_hook (int from_tty)
+void
+windows_solib_ops::create_inferior_hook (int from_tty) const
{
CORE_ADDR exec_base = 0;
@@ -911,7 +893,42 @@ windows_solib_create_inferior_hook (int from_tty)
}
}
-static solib_ops windows_so_ops;
+/* Implement the "iterate_over_objfiles_in_search_order" gdbarch
+ method. It searches all objfiles, starting with CURRENT_OBJFILE
+ first (if not NULL).
+
+ On Windows, the system behaves a little differently when two
+ objfiles each define a global symbol using the same name, compared
+ to other platforms such as GNU/Linux for instance. On GNU/Linux,
+ all instances of the symbol effectively get merged into a single
+ one, but on Windows, they remain distinct.
+
+ As a result, it usually makes sense to start global symbol searches
+ with the current objfile before expanding it to all other objfiles.
+ This helps for instance when a user debugs some code in a DLL that
+ refers to a global variable defined inside that DLL. When trying
+ to print the value of that global variable, it would be unhelpful
+ to print the value of another global variable defined with the same
+ name, but in a different DLL. */
+
+void
+windows_solib_ops::iterate_over_objfiles_in_search_order
+ (iterate_over_objfiles_in_search_order_cb_ftype cb,
+ objfile *current_objfile) const
+{
+ if (current_objfile)
+ {
+ if (cb (current_objfile))
+ return;
+ }
+
+ for (objfile *objfile : m_pspace->objfiles ())
+ if (objfile != current_objfile)
+ {
+ if (cb (objfile))
+ return;
+ }
+}
/* Common parts for gdbarch initialization for the Windows and Cygwin OS
ABIs. */
@@ -926,13 +943,7 @@ windows_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch)
`c:\Program Files\Foo App\mydll.dll', for example. */
set_gdbarch_has_dos_based_file_system (gdbarch, 1);
- set_gdbarch_iterate_over_objfiles_in_search_order
- (gdbarch, windows_iterate_over_objfiles_in_search_order);
-
- windows_so_ops = solib_target_so_ops;
- windows_so_ops.solib_create_inferior_hook
- = windows_solib_create_inferior_hook;
- set_gdbarch_so_ops (gdbarch, &windows_so_ops);
+ set_gdbarch_make_solib_ops (gdbarch, make_windows_solib_ops);
set_gdbarch_get_siginfo_type (gdbarch, windows_get_siginfo_type);
}
@@ -1151,13 +1162,11 @@ core_process_module_section (bfd *abfd, asection *sect, void *obj)
ULONGEST
windows_core_xfer_shared_libraries (struct gdbarch *gdbarch,
- gdb_byte *readbuf,
+ struct bfd &cbfd, gdb_byte *readbuf,
ULONGEST offset, ULONGEST len)
{
cpms_data data { gdbarch, "<library-list>\n", 0 };
- bfd_map_over_sections (current_program_space->core_bfd (),
- core_process_module_section,
- &data);
+ bfd_map_over_sections (&cbfd, core_process_module_section, &data);
data.xml += "</library-list>\n";
ULONGEST len_avail = data.xml.length ();
@@ -1183,9 +1192,7 @@ windows_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid)
return normal_pid_to_str (ptid);
}
-void _initialize_windows_tdep ();
-void
-_initialize_windows_tdep ()
+INIT_GDB_FILE (windows_tdep)
{
init_w32_command_list ();
cmd_list_element *info_w32_thread_information_block_cmd
diff --git a/gdb/windows-tdep.h b/gdb/windows-tdep.h
index 87a618e..4d8e6bc 100644
--- a/gdb/windows-tdep.h
+++ b/gdb/windows-tdep.h
@@ -33,6 +33,7 @@ extern void windows_xfer_shared_library (const char* so_name,
std::string &xml);
extern ULONGEST windows_core_xfer_shared_libraries (struct gdbarch *gdbarch,
+ struct bfd &cbfd,
gdb_byte *readbuf,
ULONGEST offset,
ULONGEST len);
diff --git a/gdb/x86-bsd-nat.c b/gdb/x86-bsd-nat.c
index 0c9ddfd..37376bb 100644
--- a/gdb/x86-bsd-nat.c
+++ b/gdb/x86-bsd-nat.c
@@ -128,9 +128,7 @@ x86bsd_dr_get_control (void)
#endif /* PT_GETDBREGS */
-void _initialize_x86_bsd_nat ();
-void
-_initialize_x86_bsd_nat ()
+INIT_GDB_FILE (x86_bsd_nat)
{
#ifdef HAVE_PT_GETDBREGS
x86_dr_low.set_control = x86bsd_dr_set_control;
diff --git a/gdb/x86-gnu-nat.c b/gdb/x86-gnu-nat.c
index b9ba95b..e088189 100644
--- a/gdb/x86-gnu-nat.c
+++ b/gdb/x86-gnu-nat.c
@@ -491,9 +491,7 @@ x86_gnu_dr_get_control (void)
}
#endif /* i386_DEBUG_STATE */
-void _initialize_x86_gnu_nat ();
-void
-_initialize_x86_gnu_nat ()
+INIT_GDB_FILE (x86_gnu_nat)
{
#ifdef i386_DEBUG_STATE
x86_dr_low.set_control = x86_gnu_dr_set_control;
diff --git a/gdb/x86-linux-nat.c b/gdb/x86-linux-nat.c
index fc7c5f6..660a906 100644
--- a/gdb/x86-linux-nat.c
+++ b/gdb/x86-linux-nat.c
@@ -41,6 +41,7 @@
#include "nat/x86-linux.h"
#include "nat/x86-linux-dregs.h"
#include "nat/linux-ptrace.h"
+#include "x86-tdep.h"
#include "nat/x86-linux-tdesc.h"
/* linux_nat_target::low_new_fork implementation. */
@@ -97,15 +98,19 @@ const struct target_desc *
x86_linux_nat_target::read_description ()
{
/* The x86_linux_tdesc_for_tid call only reads xcr0 the first time it is
- called, the xcr0 value is stored here and reused on subsequent calls. */
- static uint64_t xcr0_storage;
+ called. Also it checks the enablement state of features which are
+ not configured in xcr0, such as CET shadow stack. Once the supported
+ features are identified, the XSTATE_BV_STORAGE value is configured
+ accordingly and preserved for subsequent calls of this function. */
+ static uint64_t xstate_bv_storage;
if (inferior_ptid == null_ptid)
return this->beneath ()->read_description ();
int tid = inferior_ptid.pid ();
- return x86_linux_tdesc_for_tid (tid, &xcr0_storage, &this->m_xsave_layout);
+ return x86_linux_tdesc_for_tid (tid, &xstate_bv_storage,
+ &this->m_xsave_layout);
}
@@ -210,9 +215,46 @@ x86_linux_get_thread_area (pid_t pid, void *addr, unsigned int *base_addr)
}
-void _initialize_x86_linux_nat ();
+/* See x86-linux-nat.h. */
+
void
-_initialize_x86_linux_nat ()
+x86_linux_fetch_ssp (regcache *regcache, const int tid)
+{
+ uint64_t ssp = 0x0;
+ iovec iov {&ssp, sizeof (ssp)};
+
+ /* The shadow stack may be enabled and disabled at runtime. Reading the
+ ssp might fail as shadow stack was not activated for the current
+ thread. We don't want to show a warning but silently return. The
+ register will be shown as unavailable for the user. */
+ if (ptrace (PTRACE_GETREGSET, tid, NT_X86_SHSTK, &iov) != 0)
+ return;
+
+ x86_supply_ssp (regcache, ssp);
+}
+
+/* See x86-linux-nat.h. */
+
+void
+x86_linux_store_ssp (const regcache *regcache, const int tid)
+{
+ uint64_t ssp = 0x0;
+ iovec iov {&ssp, sizeof (ssp)};
+ x86_collect_ssp (regcache, ssp);
+
+ /* Dependent on the target the ssp register can be unavailable or
+ nullptr when shadow stack is supported by HW and the Linux kernel but
+ not enabled for the current thread. In case of nullptr, GDB tries to
+ restore the shadow stack pointer after an inferior call. The ptrace
+ call with PTRACE_SETREGSET will fail here with errno ENODEV. We
+ don't want to throw an error in this case but silently continue. */
+ errno = 0;
+ if ((ptrace (PTRACE_SETREGSET, tid, NT_X86_SHSTK, &iov) != 0)
+ && (errno != ENODEV))
+ perror_with_name (_("Failed to write pl3_ssp register"));
+}
+
+INIT_GDB_FILE (x86_linux_nat)
{
/* Initialize the debug register function vectors. */
x86_dr_low.set_control = x86_linux_dr_set_control;
diff --git a/gdb/x86-linux-nat.h b/gdb/x86-linux-nat.h
index a62cc4d..c455653 100644
--- a/gdb/x86-linux-nat.h
+++ b/gdb/x86-linux-nat.h
@@ -92,4 +92,15 @@ private:
extern ps_err_e x86_linux_get_thread_area (pid_t pid, void *addr,
unsigned int *base_addr);
+/* Fetch the value of the shadow stack pointer register from process/thread
+ TID and store it to GDB's register cache. */
+
+extern void x86_linux_fetch_ssp (regcache *regcache, const int tid);
+
+/* Read the value of the shadow stack pointer from GDB's register cache
+ and store it in the shadow stack pointer register of process/thread TID.
+ Throw an error in case of failure. */
+
+extern void x86_linux_store_ssp (const regcache *regcache, const int tid);
+
#endif /* GDB_X86_LINUX_NAT_H */
diff --git a/gdb/x86-tdep.c b/gdb/x86-tdep.c
index 6646b11..ea5226f 100644
--- a/gdb/x86-tdep.c
+++ b/gdb/x86-tdep.c
@@ -17,10 +17,31 @@
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 "i386-tdep.h"
#include "x86-tdep.h"
#include "symtab.h"
+/* See x86-tdep.h. */
+
+void
+x86_supply_ssp (regcache *regcache, const uint64_t ssp)
+{
+ i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (regcache->arch ());
+ gdb_assert (tdep != nullptr && tdep->ssp_regnum != -1);
+ regcache->raw_supply (tdep->ssp_regnum, &ssp);
+}
+
+/* See x86-tdep.h. */
+
+void
+x86_collect_ssp (const regcache *regcache, uint64_t &ssp)
+{
+ i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (regcache->arch ());
+ gdb_assert (tdep != nullptr && tdep->ssp_regnum != -1);
+ regcache->raw_collect (tdep->ssp_regnum, &ssp);
+}
+
/* Check whether NAME is included in NAMES[LO] (inclusive) to NAMES[HI]
(exclusive). */
diff --git a/gdb/x86-tdep.h b/gdb/x86-tdep.h
index 35e3905..855d04b 100644
--- a/gdb/x86-tdep.h
+++ b/gdb/x86-tdep.h
@@ -20,6 +20,15 @@
#ifndef GDB_X86_TDEP_H
#define GDB_X86_TDEP_H
+/* Fill SSP to the shadow stack pointer in GDB's REGCACHE. */
+
+extern void x86_supply_ssp (regcache *regcache, const uint64_t ssp);
+
+/* Collect the value of the shadow stack pointer in GDB's REGCACHE and
+ write it to SSP. */
+
+extern void x86_collect_ssp (const regcache *regcache, uint64_t &ssp);
+
/* Checks whether PC lies in an indirect branch thunk using registers
REGISTER_NAMES[LO] (inclusive) to REGISTER_NAMES[HI] (exclusive). */
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index e91c64c..d8b99a0 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -23,7 +23,6 @@
#include <sys/types.h>
#include <fcntl.h>
-#include <ctype.h>
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
@@ -1491,7 +1490,7 @@ process_xcoff_symbol (struct xcoff_symbol *cs, struct objfile *objfile)
sym->set_type (builtin_type (objfile)->nodebug_text_symbol);
sym->set_domain (FUNCTION_DOMAIN);
- sym->set_aclass_index (LOC_BLOCK);
+ sym->set_loc_class_index (LOC_BLOCK);
sym2 = new (&objfile->objfile_obstack) symbol (*sym);
if (cs->c_sclass == C_EXT || C_WEAKEXT)
@@ -2999,9 +2998,7 @@ xcoff_get_n_import_files (bfd *abfd)
return l_nimpid - 1;
}
-void _initialize_xcoffread ();
-void
-_initialize_xcoffread ()
+INIT_GDB_FILE (xcoffread)
{
add_symtab_fns (bfd_target_xcoff_flavour, &xcoff_sym_fns);
}
diff --git a/gdb/xml-support.c b/gdb/xml-support.c
index fb8b612..ebf6ea6 100644
--- a/gdb/xml-support.c
+++ b/gdb/xml-support.c
@@ -21,7 +21,6 @@
#include "xml-builtin.h"
#include "xml-support.h"
#include "gdbsupport/filestuff.h"
-#include "gdbsupport/gdb-safe-ctype.h"
#include <vector>
#include <string>
@@ -430,10 +429,10 @@ gdb_xml_parser::end_element (const XML_Char *name)
body = scope->body.c_str ();
/* Strip leading and trailing whitespace. */
- while (length > 0 && ISSPACE (body[length - 1]))
+ while (length > 0 && c_isspace (body[length - 1]))
length--;
scope->body.erase (length);
- while (*body && ISSPACE (*body))
+ while (*body && c_isspace (*body))
body++;
}
@@ -999,10 +998,7 @@ xml_fetch_content_from_file (const char *filename, const char *dirname)
return text;
}
-void _initialize_xml_support ();
-void _initialize_xml_support ();
-void
-_initialize_xml_support ()
+INIT_GDB_FILE (xml_support)
{
add_setshow_boolean_cmd ("xml", class_maintenance, &debug_xml,
_("Set XML parser debugging."),
diff --git a/gdb/xml-syscall.c b/gdb/xml-syscall.c
index fe0ea2b..b58fe5d0 100644
--- a/gdb/xml-syscall.c
+++ b/gdb/xml-syscall.c
@@ -319,7 +319,7 @@ xml_init_syscalls_info (const char *filename)
if (!full_file)
return NULL;
- const std::string dirname = ldirname (filename);
+ const std::string dirname = gdb_ldirname (filename);
auto fetch_another = [&dirname] (const char *name)
{
return xml_fetch_content_from_file (name, dirname.c_str ());
diff --git a/gdb/xml-tdesc.c b/gdb/xml-tdesc.c
index 6c095af..2f213dc 100644
--- a/gdb/xml-tdesc.c
+++ b/gdb/xml-tdesc.c
@@ -670,7 +670,7 @@ file_read_description_xml (const char *filename)
return NULL;
}
- const std::string dirname = ldirname (filename);
+ const std::string dirname = gdb_ldirname (filename);
auto fetch_another = [&dirname] (const char *name)
{
return xml_fetch_content_from_file (name, dirname.c_str ());
diff --git a/gdb/xstormy16-tdep.c b/gdb/xstormy16-tdep.c
index 8482461..b63dfa0 100644
--- a/gdb/xstormy16-tdep.c
+++ b/gdb/xstormy16-tdep.c
@@ -546,14 +546,14 @@ xstormy16_find_jmp_table_entry (struct gdbarch *gdbarch, CORE_ADDR faddr)
if (!strcmp (faddr_sect->the_bfd_section->name, ".plt"))
return faddr;
- for (obj_section *osect : faddr_sect->objfile->sections ())
+ for (obj_section &osect : faddr_sect->objfile->sections ())
{
- if (!strcmp (osect->the_bfd_section->name, ".plt"))
+ if (!strcmp (osect.the_bfd_section->name, ".plt"))
{
CORE_ADDR addr, endaddr;
- addr = osect->addr ();
- endaddr = osect->endaddr ();
+ addr = osect.addr ();
+ endaddr = osect.endaddr ();
for (; addr < endaddr; addr += 2 * xstormy16_inst_size)
{
@@ -828,9 +828,7 @@ xstormy16_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
Initializer function for the Sanyo Xstormy16a module.
Called by gdb at start-up. */
-void _initialize_xstormy16_tdep ();
-void
-_initialize_xstormy16_tdep ()
+INIT_GDB_FILE (xstormy16_tdep)
{
gdbarch_register (bfd_arch_xstormy16, xstormy16_gdbarch_init);
}
diff --git a/gdb/xtensa-linux-nat.c b/gdb/xtensa-linux-nat.c
index 11fbf55..4a50f38 100644
--- a/gdb/xtensa-linux-nat.c
+++ b/gdb/xtensa-linux-nat.c
@@ -327,9 +327,7 @@ ps_get_thread_area (struct ps_prochandle *ph,
return PS_OK;
}
-void _initialize_xtensa_linux_nat ();
-void
-_initialize_xtensa_linux_nat ()
+INIT_GDB_FILE (xtensa_linux_nat)
{
const xtensa_regtable_t *ptr;
diff --git a/gdb/xtensa-linux-tdep.c b/gdb/xtensa-linux-tdep.c
index b72d683..7792408 100644
--- a/gdb/xtensa-linux-tdep.c
+++ b/gdb/xtensa-linux-tdep.c
@@ -20,6 +20,7 @@
#include "xtensa-tdep.h"
#include "osabi.h"
#include "linux-tdep.h"
+#include "solib-svr4-linux.h"
#include "solib-svr4.h"
#include "symtab.h"
#include "gdbarch.h"
@@ -111,8 +112,7 @@ xtensa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
linux_init_abi (info, gdbarch, 0);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, linux_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_ilp32_svr4_solib_ops);
set_gdbarch_gdb_signal_from_target (gdbarch,
xtensa_linux_gdb_signal_from_target);
@@ -124,9 +124,7 @@ xtensa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
svr4_fetch_objfile_link_map);
}
-void _initialize_xtensa_linux_tdep ();
-void
-_initialize_xtensa_linux_tdep ()
+INIT_GDB_FILE (xtensa_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_xtensa, bfd_mach_xtensa, GDB_OSABI_LINUX,
xtensa_linux_init_abi);
diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
index a4bbffb..8a2f129 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -3238,8 +3238,7 @@ xtensa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_iterate_over_regset_sections
(gdbarch, xtensa_iterate_over_regset_sections);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_svr4_ilp32_solib_ops);
/* Hook in the ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);
@@ -3253,9 +3252,7 @@ xtensa_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
error (_("xtensa_dump_tdep(): not implemented"));
}
-void _initialize_xtensa_tdep ();
-void
-_initialize_xtensa_tdep ()
+INIT_GDB_FILE (xtensa_tdep)
{
gdbarch_register (bfd_arch_xtensa, xtensa_gdbarch_init, xtensa_dump_tdep);
xtensa_init_reggroups ();
diff --git a/gdb/z80-tdep.c b/gdb/z80-tdep.c
index bfa52dd..c8f0038 100644
--- a/gdb/z80-tdep.c
+++ b/gdb/z80-tdep.c
@@ -962,11 +962,11 @@ z80_overlay_update_1 (struct obj_section *osect)
/* we have interest for sections with same VMA */
for (objfile *objfile : current_program_space->objfiles ())
- for (obj_section *sect : objfile->sections ())
- if (section_is_overlay (sect))
+ for (obj_section &sect : objfile->sections ())
+ if (section_is_overlay (&sect))
{
- sect->ovly_mapped = (lma == bfd_section_lma (sect->the_bfd_section));
- i |= sect->ovly_mapped; /* true, if at least one section is mapped */
+ sect.ovly_mapped = (lma == bfd_section_lma (sect.the_bfd_section));
+ i |= sect.ovly_mapped; /* true, if at least one section is mapped */
}
return i;
}
@@ -985,18 +985,18 @@ z80_overlay_update (struct obj_section *osect)
/* Update all sections, even if only one was requested. */
for (objfile *objfile : current_program_space->objfiles ())
- for (obj_section *sect : objfile->sections ())
+ for (obj_section &sect : objfile->sections ())
{
- if (!section_is_overlay (sect))
+ if (!section_is_overlay (&sect))
continue;
- asection *bsect = sect->the_bfd_section;
+ asection *bsect = sect.the_bfd_section;
bfd_vma lma = bfd_section_lma (bsect);
bfd_vma vma = bfd_section_vma (bsect);
for (int i = 0; i < cache_novly_regions; ++i)
if (cache_ovly_region_table[i][Z80_VMA] == vma)
- sect->ovly_mapped =
+ sect.ovly_mapped =
(cache_ovly_region_table[i][Z80_MAPPED_TO_LMA] == lma);
}
}
@@ -1173,7 +1173,7 @@ z80_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_skip_prologue (gdbarch, z80_skip_prologue);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan); // falling stack
- set_gdbarch_software_single_step (gdbarch, z80_software_single_step);
+ set_gdbarch_get_next_pcs (gdbarch, z80_software_single_step);
set_gdbarch_breakpoint_kind_from_pc (gdbarch, z80_breakpoint_kind_from_pc);
set_gdbarch_sw_breakpoint_from_kind (gdbarch, z80_sw_breakpoint_from_kind);
set_gdbarch_insn_is_call (gdbarch, z80_insn_is_call);
@@ -1331,14 +1331,14 @@ ez80_ddfd_insn_table[] =
{ 0007, 0307, 2, insn_default }, //"ld rr,(ii+d)"
{ 0061, 0377, 2, insn_default }, //"ld ii,(ii+d)"
/* common instructions */
- { 0011, 0367, 2, insn_default }, //"add ii,rr"
+ { 0011, 0317, 1, insn_default }, //"add ii,rr"
{ 0041, 0377, 3, insn_default }, //"ld ii,nn"
{ 0042, 0367, 3, insn_default }, //"ld (nn),ii", "ld ii,(nn)"
{ 0043, 0367, 1, insn_default }, //"inc ii", "dec ii"
{ 0044, 0366, 1, insn_default }, //"inc/dec iih/iil"
{ 0046, 0367, 2, insn_default }, //"ld iih,n", "ld iil,n"
{ 0064, 0376, 2, insn_default }, //"inc (ii+d)", "dec (ii+d)"
- { 0066, 0377, 2, insn_default }, //"ld (ii+d),n"
+ { 0066, 0377, 3, insn_default }, //"ld (ii+d),n"
{ 0166, 0377, 0, insn_default }, //not an instruction
{ 0160, 0370, 2, insn_default }, //"ld (ii+d),r"
{ 0104, 0306, 1, insn_default }, //"ld r,iih", "ld r,iil"
@@ -1360,7 +1360,7 @@ ez80_adl_ddfd_insn_table[] =
{
{ 0007, 0307, 2, insn_default }, //"ld rr,(ii+d)"
{ 0061, 0377, 2, insn_default }, //"ld ii,(ii+d)"
- { 0011, 0367, 1, insn_default }, //"add ii,rr"
+ { 0011, 0317, 1, insn_default }, //"add ii,rr"
{ 0041, 0377, 4, insn_default }, //"ld ii,nn"
{ 0042, 0367, 4, insn_default }, //"ld (nn),ii", "ld ii,(nn)"
{ 0043, 0367, 1, insn_default }, //"inc ii", "dec ii"
@@ -1455,10 +1455,7 @@ z80_get_insn_info (struct gdbarch *gdbarch, const gdb_byte *buf, int *size)
while (1);
}
-extern initialize_file_ftype _initialize_z80_tdep;
-
-void
-_initialize_z80_tdep ()
+INIT_GDB_FILE (z80_tdep)
{
gdbarch_register (bfd_arch_z80, z80_gdbarch_init);
initialize_tdesc_z80 ();