aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/MAINTAINERS14
-rw-r--r--gdb/Makefile.in11
-rw-r--r--gdb/NEWS117
-rw-r--r--gdb/aarch64-linux-nat.c14
-rw-r--r--gdb/aarch64-linux-tdep.c171
-rw-r--r--gdb/aarch64-tdep.c199
-rw-r--r--gdb/aarch64-tdep.h2
-rw-r--r--gdb/ada-exp.y10
-rw-r--r--gdb/ada-lang.c126
-rw-r--r--gdb/ada-lang.h7
-rw-r--r--gdb/ada-lex.l2
-rw-r--r--gdb/ada-tasks.c16
-rw-r--r--gdb/addrmap.c18
-rw-r--r--gdb/addrmap.h12
-rw-r--r--gdb/aix-thread.c8
-rw-r--r--gdb/alpha-tdep.h2
-rw-r--r--gdb/amd-dbgapi-target.c81
-rw-r--r--gdb/amd64-linux-nat.c23
-rw-r--r--gdb/amd64-linux-tdep.c5
-rw-r--r--gdb/amd64-tdep.c22
-rw-r--r--gdb/amd64-tdep.h2
-rw-r--r--gdb/amd64-windows-tdep.c5
-rw-r--r--gdb/amdgpu-tdep.c2
-rw-r--r--gdb/annotate.c2
-rw-r--r--gdb/arc-linux-tdep.c6
-rw-r--r--gdb/arc-tdep.c6
-rw-r--r--gdb/arch-utils.c42
-rw-r--r--gdb/arch/aarch64-mte-linux.c56
-rw-r--r--gdb/arch/aarch64-mte-linux.h27
-rw-r--r--gdb/arch/aarch64-mte.c77
-rw-r--r--gdb/arch/aarch64-mte.h51
-rw-r--r--gdb/arch/amd64.c11
-rw-r--r--gdb/arch/i386.c7
-rw-r--r--gdb/arch/tic6x.c3
-rw-r--r--gdb/arch/x86-linux-tdesc-features.c7
-rw-r--r--gdb/arm-linux-nat.c98
-rw-r--r--gdb/arm-tdep.c28
-rw-r--r--gdb/arm-wince-tdep.c5
-rw-r--r--gdb/auto-load.c8
-rw-r--r--gdb/auxv.c6
-rw-r--r--gdb/avr-tdep.c4
-rw-r--r--gdb/ax-gdb.c6
-rw-r--r--gdb/bfin-tdep.c2
-rw-r--r--gdb/block.c202
-rw-r--r--gdb/block.h48
-rw-r--r--gdb/blockframe.c5
-rw-r--r--gdb/break-catch-throw.c6
-rw-r--r--gdb/break-cond-parse.c699
-rw-r--r--gdb/break-cond-parse.h52
-rw-r--r--gdb/breakpoint.c945
-rw-r--r--gdb/breakpoint.h68
-rw-r--r--gdb/bsd-uthread.c5
-rw-r--r--gdb/btrace.c449
-rw-r--r--gdb/btrace.h49
-rw-r--r--gdb/build-id.c216
-rw-r--r--gdb/build-id.h22
-rw-r--r--gdb/buildsym.c6
-rw-r--r--gdb/c-exp.y13
-rw-r--r--gdb/c-valprint.c3
-rw-r--r--gdb/cli-out.c5
-rw-r--r--gdb/cli-out.h3
-rw-r--r--gdb/cli/cli-cmds.c103
-rw-r--r--gdb/cli/cli-decode.c8
-rw-r--r--gdb/cli/cli-dump.c6
-rw-r--r--gdb/cli/cli-interp.c2
-rw-r--r--gdb/cli/cli-style.c12
-rw-r--r--gdb/cli/cli-style.h3
-rw-r--r--gdb/coff-pe-read.c12
-rw-r--r--gdb/coffread.c102
-rw-r--r--gdb/command.h2
-rw-r--r--gdb/compile/compile-c-symbols.c13
-rw-r--r--gdb/compile/compile-cplus-symbols.c7
-rw-r--r--gdb/compile/compile-object-load.c4
-rw-r--r--gdb/compile/compile.c15
-rw-r--r--gdb/completer.c665
-rw-r--r--gdb/completer.h90
-rw-r--r--gdb/config.in6
-rwxr-xr-xgdb/configure43
-rw-r--r--gdb/configure.ac9
-rw-r--r--gdb/configure.host1
-rw-r--r--gdb/configure.nat9
-rw-r--r--gdb/configure.tgt9
-rwxr-xr-xgdb/contrib/ari/gdb_ari.sh2
-rw-r--r--gdb/contrib/common-misspellings.txt18
-rwxr-xr-xgdb/contrib/gdb-add-index.sh39
-rwxr-xr-xgdb/contrib/spellcheck.sh353
-rw-r--r--gdb/corefile.c3
-rw-r--r--gdb/corelow.c836
-rw-r--r--gdb/cris-tdep.c12
-rw-r--r--gdb/csky-tdep.c2
-rw-r--r--gdb/ctfread.c7
-rw-r--r--gdb/d-exp.y8
-rw-r--r--gdb/d-lang.c5
-rw-r--r--gdb/data-directory/Makefile.in4
-rw-r--r--gdb/dbxread.c2895
-rw-r--r--gdb/dictionary.h2
-rw-r--r--gdb/disasm-flags.h1
-rw-r--r--gdb/disasm-selftests.c2
-rw-r--r--gdb/disasm.c12
-rw-r--r--gdb/doc/gdb.texinfo474
-rw-r--r--gdb/doc/python.texi171
-rw-r--r--gdb/dtrace-probe.c2
-rw-r--r--gdb/dwarf2/abbrev-cache.c1
-rw-r--r--gdb/dwarf2/abbrev.c5
-rw-r--r--gdb/dwarf2/abbrev.h4
-rw-r--r--gdb/dwarf2/ada-imported.c4
-rw-r--r--gdb/dwarf2/attribute.h1
-rw-r--r--gdb/dwarf2/comp-unit-head.c37
-rw-r--r--gdb/dwarf2/cooked-index.c26
-rw-r--r--gdb/dwarf2/cooked-index.h25
-rw-r--r--gdb/dwarf2/dwz.h1
-rw-r--r--gdb/dwarf2/error.h (renamed from gdb/config/nm-nto.h)20
-rw-r--r--gdb/dwarf2/expr.c3
-rw-r--r--gdb/dwarf2/frame-tailcall.c2
-rw-r--r--gdb/dwarf2/frame.c6
-rw-r--r--gdb/dwarf2/index-cache.c2
-rw-r--r--gdb/dwarf2/index-cache.h2
-rw-r--r--gdb/dwarf2/index-write.c11
-rw-r--r--gdb/dwarf2/line-header.h4
-rw-r--r--gdb/dwarf2/loc.c49
-rw-r--r--gdb/dwarf2/macro.c31
-rw-r--r--gdb/dwarf2/macro.h2
-rw-r--r--gdb/dwarf2/mapped-index.h2
-rw-r--r--gdb/dwarf2/parent-map.h41
-rw-r--r--gdb/dwarf2/read-gdb-index.c20
-rw-r--r--gdb/dwarf2/read.c644
-rw-r--r--gdb/dwarf2/read.h34
-rw-r--r--gdb/dwarf2/section.c16
-rw-r--r--gdb/dwarf2/tag.h1
-rw-r--r--gdb/elfread.c145
-rw-r--r--gdb/eval.c25
-rw-r--r--gdb/event-top.c2
-rw-r--r--gdb/event-top.h25
-rw-r--r--gdb/exec.c14
-rw-r--r--gdb/exec.h2
-rw-r--r--gdb/expop.h20
-rw-r--r--gdb/expression.h10
-rw-r--r--gdb/extension-priv.h5
-rw-r--r--gdb/extension.c15
-rw-r--r--gdb/extension.h3
-rw-r--r--gdb/f-exp.y39
-rw-r--r--gdb/fbsd-tdep.c21
-rw-r--r--gdb/features/Makefile2
-rw-r--r--gdb/features/btrace-conf.dtd2
-rw-r--r--gdb/features/i386/32bit-mpx.c51
-rw-r--r--gdb/features/i386/32bit-mpx.xml45
-rw-r--r--gdb/features/i386/64bit-mpx.c51
-rw-r--r--gdb/features/i386/64bit-mpx.xml44
-rw-r--r--gdb/features/mips-dsp-linux.c2
-rw-r--r--gdb/features/mips-linux.c2
-rw-r--r--gdb/features/or1k-linux.c2
-rw-r--r--gdb/features/sparc/sparc32-solaris.c2
-rw-r--r--gdb/features/sparc/sparc64-solaris.c2
-rw-r--r--gdb/findvar.c4
-rw-r--r--gdb/frame-unwind.c12
-rw-r--r--gdb/frame.c6
-rw-r--r--gdb/frv-tdep.c7
-rw-r--r--gdb/ft32-tdep.c5
-rw-r--r--gdb/gcore.c5
-rw-r--r--gdb/gcore.in12
-rw-r--r--gdb/gdb-gdb.py.in2
-rw-r--r--gdb/gdb-stabs.h98
-rw-r--r--gdb/gdb_bfd.c23
-rw-r--r--gdb/gdbarch-gen.c (renamed from gdb/gdbarch.c)376
-rw-r--r--gdb/gdbarch.h5
-rwxr-xr-xgdb/gdbarch.py6
-rw-r--r--gdb/gdbcore.h66
-rw-r--r--gdb/gdbtypes.c10
-rw-r--r--gdb/glibc-tdep.c14
-rw-r--r--gdb/gnu-nat.c2
-rw-r--r--gdb/gnu-v2-abi.c3
-rw-r--r--gdb/gnu-v3-abi.c11
-rw-r--r--gdb/go-exp.y9
-rw-r--r--gdb/go-lang.c5
-rw-r--r--gdb/guile/guile-internal.h28
-rw-r--r--gdb/guile/guile.c1
-rw-r--r--gdb/guile/scm-cmd.c2
-rw-r--r--gdb/guile/scm-objfile.c2
-rw-r--r--gdb/hppa-tdep.c5
-rw-r--r--gdb/i386-darwin-nat.c2
-rw-r--r--gdb/i386-fbsd-nat.c2
-rw-r--r--gdb/i386-linux-nat.c20
-rw-r--r--gdb/i386-linux-tdep.c67
-rw-r--r--gdb/i386-linux-tdep.h9
-rw-r--r--gdb/i386-nto-tdep.c379
-rw-r--r--gdb/i386-tdep.c514
-rw-r--r--gdb/i386-tdep.h24
-rw-r--r--gdb/i387-tdep.c219
-rw-r--r--gdb/i387-tdep.h12
-rw-r--r--gdb/ia64-tdep.c6
-rw-r--r--gdb/ia64-tdep.h2
-rw-r--r--gdb/inf-child.c15
-rw-r--r--gdb/inf-child.h2
-rw-r--r--gdb/inf-ptrace.c2
-rw-r--r--gdb/infcall.c4
-rw-r--r--gdb/infcmd.c33
-rw-r--r--gdb/inferior.c6
-rw-r--r--gdb/infrun.c32
-rw-r--r--gdb/inline-frame.c268
-rw-r--r--gdb/inline-frame.h2
-rw-r--r--gdb/jit.c11
-rw-r--r--gdb/language.c7
-rw-r--r--gdb/language.h4
-rw-r--r--gdb/linespec.c141
-rw-r--r--gdb/linux-fork.c15
-rw-r--r--gdb/linux-tdep.c124
-rw-r--r--gdb/linux-thread-db.c9
-rw-r--r--gdb/loongarch-linux-nat.c16
-rw-r--r--gdb/loongarch-tdep.c24
-rw-r--r--gdb/m2-exp.y10
-rw-r--r--gdb/m2-typeprint.c1
-rw-r--r--gdb/m32c-tdep.c22
-rw-r--r--gdb/m32r-tdep.c4
-rw-r--r--gdb/m68hc11-tdep.c9
-rw-r--r--gdb/m68k-linux-nat.c2
-rw-r--r--gdb/m68k-tdep.c12
-rw-r--r--gdb/machoread.c5
-rw-r--r--gdb/macrocmd.c93
-rw-r--r--gdb/macroscope.c6
-rw-r--r--gdb/macrotab.c89
-rw-r--r--gdb/macrotab.h21
-rw-r--r--gdb/maint.c2
-rwxr-xr-xgdb/make-target-delegates.py2
-rw-r--r--gdb/mdebugread.c28
-rw-r--r--gdb/memattr.c2
-rw-r--r--gdb/mep-tdep.c2
-rw-r--r--gdb/mi/mi-cmd-disas.c3
-rw-r--r--gdb/mi/mi-cmd-file.c4
-rw-r--r--gdb/mi/mi-main.c5
-rw-r--r--gdb/mi/mi-out.c13
-rw-r--r--gdb/mi/mi-out.h3
-rw-r--r--gdb/mi/mi-symbol-cmds.c5
-rw-r--r--gdb/microblaze-tdep.c2
-rw-r--r--gdb/minsyms.c71
-rw-r--r--gdb/minsyms.h36
-rw-r--r--gdb/mips-fbsd-tdep.c4
-rw-r--r--gdb/mips-linux-tdep.c12
-rw-r--r--gdb/mips-tdep.c74
-rw-r--r--gdb/msp430-tdep.c3
-rw-r--r--gdb/nat/aarch64-mte-linux-ptrace.c9
-rw-r--r--gdb/nat/aarch64-scalable-linux-ptrace.c11
-rw-r--r--gdb/nat/fork-inferior.h7
-rw-r--r--gdb/nat/linux-btrace.c70
-rw-r--r--gdb/nat/linux-namespaces.c2
-rw-r--r--gdb/nat/x86-linux-tdesc.c6
-rw-r--r--gdb/nat/x86-xstate.c2
-rw-r--r--gdb/netbsd-tdep.c5
-rw-r--r--gdb/nto-procfs.c1583
-rw-r--r--gdb/nto-tdep.c521
-rw-r--r--gdb/nto-tdep.h194
-rw-r--r--gdb/objc-lang.c42
-rw-r--r--gdb/objfiles.c135
-rw-r--r--gdb/objfiles.h72
-rw-r--r--gdb/obsd-tdep.c5
-rw-r--r--gdb/osabi.c124
-rw-r--r--gdb/osabi.h46
-rw-r--r--gdb/p-exp.y13
-rw-r--r--gdb/p-lang.c11
-rw-r--r--gdb/p-valprint.c4
-rw-r--r--gdb/parse.c22
-rw-r--r--gdb/ppc-linux-tdep.c9
-rw-r--r--gdb/ppc-netbsd-tdep.c1
-rw-r--r--gdb/ppc-sysv-tdep.c10
-rw-r--r--gdb/printcmd.c18
-rw-r--r--gdb/proc-service.c3
-rw-r--r--gdb/procfs.c2
-rw-r--r--gdb/progspace.c4
-rw-r--r--gdb/progspace.h4
-rw-r--r--gdb/psymtab.c23
-rw-r--r--gdb/psymtab.h19
-rw-r--r--gdb/python/lib/gdb/dap/__init__.py3
-rw-r--r--gdb/python/lib/gdb/dap/breakpoint.py31
-rw-r--r--gdb/python/lib/gdb/dap/globalvars.py3
-rw-r--r--gdb/python/lib/gdb/dap/launch.py20
-rw-r--r--gdb/python/lib/gdb/dap/locations.py5
-rw-r--r--gdb/python/lib/gdb/dap/scopes.py23
-rw-r--r--gdb/python/lib/gdb/dap/sources.py6
-rw-r--r--gdb/python/lib/gdb/dap/startup.py7
-rw-r--r--gdb/python/lib/gdb/dap/varref.py1
-rw-r--r--gdb/python/lib/gdb/disassembler.py2
-rw-r--r--gdb/python/lib/gdb/missing_debug.py30
-rw-r--r--gdb/python/lib/gdb/printer/bound_registers.py39
-rw-r--r--gdb/python/lib/gdb/ptwrite.py77
-rw-r--r--gdb/python/py-arch.c9
-rw-r--r--gdb/python/py-block.c11
-rw-r--r--gdb/python/py-breakpoint.c39
-rw-r--r--gdb/python/py-cmd.c11
-rw-r--r--gdb/python/py-connection.c15
-rw-r--r--gdb/python/py-disasm.c40
-rw-r--r--gdb/python/py-event.c18
-rw-r--r--gdb/python/py-event.h2
-rw-r--r--gdb/python/py-evtregistry.c6
-rw-r--r--gdb/python/py-finishbreakpoint.c11
-rw-r--r--gdb/python/py-frame.c49
-rw-r--r--gdb/python/py-framefilter.c6
-rw-r--r--gdb/python/py-function.c6
-rw-r--r--gdb/python/py-gdb-readline.c3
-rw-r--r--gdb/python/py-inferior.c20
-rw-r--r--gdb/python/py-infthread.c14
-rw-r--r--gdb/python/py-instruction.c2
-rw-r--r--gdb/python/py-lazy-string.c10
-rw-r--r--gdb/python/py-linetable.c24
-rw-r--r--gdb/python/py-membuf.c6
-rw-r--r--gdb/python/py-mi.c6
-rw-r--r--gdb/python/py-micmd.c7
-rw-r--r--gdb/python/py-objfile.c16
-rw-r--r--gdb/python/py-param.c8
-rw-r--r--gdb/python/py-prettyprint.c5
-rw-r--r--gdb/python/py-progspace.c9
-rw-r--r--gdb/python/py-record-btrace.c211
-rw-r--r--gdb/python/py-record-btrace.h6
-rw-r--r--gdb/python/py-record.c93
-rw-r--r--gdb/python/py-record.h7
-rw-r--r--gdb/python/py-registers.c25
-rw-r--r--gdb/python/py-stopevent.c3
-rw-r--r--gdb/python/py-symbol.c19
-rw-r--r--gdb/python/py-symtab.c11
-rw-r--r--gdb/python/py-tui.c19
-rw-r--r--gdb/python/py-type.c61
-rw-r--r--gdb/python/py-uiout.h3
-rw-r--r--gdb/python/py-unwind.c34
-rw-r--r--gdb/python/py-utils.c31
-rw-r--r--gdb/python/py-value.c81
-rw-r--r--gdb/python/python-internal.h66
-rw-r--r--gdb/python/python.c17
-rw-r--r--gdb/quick-symbol.h17
-rw-r--r--gdb/ravenscar-thread.c30
-rw-r--r--gdb/record-btrace.c164
-rw-r--r--gdb/record-full.c5
-rw-r--r--gdb/record.c12
-rw-r--r--gdb/record.h5
-rw-r--r--gdb/regcache-dump.c19
-rw-r--r--gdb/remote-sim.c3
-rw-r--r--gdb/remote.c249
-rw-r--r--gdb/remote.h5
-rw-r--r--gdb/riscv-tdep.c2
-rw-r--r--gdb/rs6000-aix-nat.c2
-rw-r--r--gdb/rs6000-aix-tdep.c2
-rw-r--r--gdb/rs6000-lynx178-tdep.c2
-rw-r--r--gdb/rs6000-tdep.c13
-rw-r--r--gdb/run-on-main-thread.c15
-rw-r--r--gdb/rust-lang.h2
-rw-r--r--gdb/s390-tdep.c2
-rw-r--r--gdb/ser-base.c4
-rw-r--r--gdb/sh-tdep.c6
-rw-r--r--gdb/skip.c2
-rw-r--r--gdb/sol-thread.c9
-rw-r--r--gdb/sol2-tdep.c5
-rw-r--r--gdb/solib-aix.c19
-rw-r--r--gdb/solib-darwin.c32
-rw-r--r--gdb/solib-dsbt.c24
-rw-r--r--gdb/solib-frv.c33
-rw-r--r--gdb/solib-rocm.c20
-rw-r--r--gdb/solib-svr4.c83
-rw-r--r--gdb/solib-target.c20
-rw-r--r--gdb/solib.c192
-rw-r--r--gdb/solib.h11
-rw-r--r--gdb/solist.h34
-rw-r--r--gdb/source-cache.c8
-rw-r--r--gdb/source.c61
-rw-r--r--gdb/source.h7
-rw-r--r--gdb/sparc-tdep.c2
-rw-r--r--gdb/stabsread.c2489
-rw-r--r--gdb/stabsread.h101
-rw-r--r--gdb/stack.c10
-rw-r--r--gdb/stubs/ia64vms-stub.c4
-rw-r--r--gdb/stubs/m32r-stub.c6
-rw-r--r--gdb/symfile-debug.c8
-rw-r--r--gdb/symfile.c225
-rw-r--r--gdb/symfile.h4
-rw-r--r--gdb/symmisc.c35
-rw-r--r--gdb/symtab.c111
-rw-r--r--gdb/symtab.h36
-rw-r--r--gdb/target-debug.h8
-rw-r--r--gdb/target-delegates-gen.c (renamed from gdb/target-delegates.c)0
-rw-r--r--gdb/target-descriptions.c56
-rw-r--r--gdb/target-descriptions.h8
-rw-r--r--gdb/target.c63
-rw-r--r--gdb/target.h28
-rw-r--r--gdb/testsuite/gdb.ada/O2_float_param.exp6
-rw-r--r--gdb/testsuite/gdb.ada/access_to_unbounded_array.exp4
-rw-r--r--gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp4
-rw-r--r--gdb/testsuite/gdb.ada/arr_enum_idx_w_gap.exp4
-rw-r--r--gdb/testsuite/gdb.ada/array_of_symbolic_length.exp4
-rw-r--r--gdb/testsuite/gdb.ada/array_of_variable_length.exp4
-rw-r--r--gdb/testsuite/gdb.ada/array_of_variant.exp6
-rw-r--r--gdb/testsuite/gdb.ada/array_ptr_renaming.exp4
-rw-r--r--gdb/testsuite/gdb.ada/arrayidx.exp3
-rw-r--r--gdb/testsuite/gdb.ada/arrayparam.exp4
-rw-r--r--gdb/testsuite/gdb.ada/arrayptr.exp6
-rw-r--r--gdb/testsuite/gdb.ada/big_packed_array.exp6
-rw-r--r--gdb/testsuite/gdb.ada/bp_c_mixed_case.exp4
-rw-r--r--gdb/testsuite/gdb.ada/bp_inlined_func.exp2
-rw-r--r--gdb/testsuite/gdb.ada/call_pn.exp19
-rw-r--r--gdb/testsuite/gdb.ada/catch_assert_if.exp4
-rw-r--r--gdb/testsuite/gdb.ada/catch_ex.exp16
-rw-r--r--gdb/testsuite/gdb.ada/catch_ex_std.exp2
-rw-r--r--gdb/testsuite/gdb.ada/complete.exp4
-rw-r--r--gdb/testsuite/gdb.ada/enum_idx_packed.exp9
-rw-r--r--gdb/testsuite/gdb.ada/excep_handle.exp14
-rw-r--r--gdb/testsuite/gdb.ada/exception-lto.c40
-rw-r--r--gdb/testsuite/gdb.ada/exception-lto.exp35
-rw-r--r--gdb/testsuite/gdb.ada/exec_changed.exp2
-rw-r--r--gdb/testsuite/gdb.ada/fixed_cmp.exp4
-rw-r--r--gdb/testsuite/gdb.ada/fixed_points.exp8
-rw-r--r--gdb/testsuite/gdb.ada/frame_arg_lang.exp9
-rw-r--r--gdb/testsuite/gdb.ada/fun_overload_menu.exp12
-rw-r--r--gdb/testsuite/gdb.ada/fun_renaming.exp22
-rw-r--r--gdb/testsuite/gdb.ada/funcall_ref.exp4
-rw-r--r--gdb/testsuite/gdb.ada/homonym.exp2
-rw-r--r--gdb/testsuite/gdb.ada/mi_string_access.exp4
-rw-r--r--gdb/testsuite/gdb.ada/mi_task_arg.exp7
-rw-r--r--gdb/testsuite/gdb.ada/mi_var_access.exp5
-rw-r--r--gdb/testsuite/gdb.ada/mi_var_array.exp7
-rw-r--r--gdb/testsuite/gdb.ada/mi_var_union.exp7
-rw-r--r--gdb/testsuite/gdb.ada/mi_variant.exp7
-rw-r--r--gdb/testsuite/gdb.ada/mod_from_name.exp9
-rw-r--r--gdb/testsuite/gdb.ada/multiarray.exp7
-rw-r--r--gdb/testsuite/gdb.ada/null_array.exp3
-rw-r--r--gdb/testsuite/gdb.ada/operator_bp.exp6
-rw-r--r--gdb/testsuite/gdb.ada/out_of_line_in_inlined.exp6
-rw-r--r--gdb/testsuite/gdb.ada/packed_array.exp4
-rw-r--r--gdb/testsuite/gdb.ada/packed_array_assign.exp2
-rw-r--r--gdb/testsuite/gdb.ada/packed_record.exp6
-rw-r--r--gdb/testsuite/gdb.ada/packed_tagged.exp7
-rw-r--r--gdb/testsuite/gdb.ada/pckd_arr_ren.exp9
-rw-r--r--gdb/testsuite/gdb.ada/ptype-o.exp4
-rw-r--r--gdb/testsuite/gdb.ada/rec_comp.exp2
-rw-r--r--gdb/testsuite/gdb.ada/rec_ptype.exp4
-rw-r--r--gdb/testsuite/gdb.ada/same_component_name.exp4
-rw-r--r--gdb/testsuite/gdb.ada/set_pckd_arr_elt.exp4
-rw-r--r--gdb/testsuite/gdb.ada/tagged-lookup.exp8
-rw-r--r--gdb/testsuite/gdb.ada/tagged_access.exp25
-rw-r--r--gdb/testsuite/gdb.ada/task_bp.exp2
-rw-r--r--gdb/testsuite/gdb.ada/task_switch_in_core.exp2
-rw-r--r--gdb/testsuite/gdb.ada/tasks.exp6
-rw-r--r--gdb/testsuite/gdb.ada/unc_arr_ptr_in_var_rec.exp4
-rw-r--r--gdb/testsuite/gdb.ada/unchecked_union.exp7
-rw-r--r--gdb/testsuite/gdb.ada/var_rec_arr.exp4
-rw-r--r--gdb/testsuite/gdb.ada/variant.exp7
-rw-r--r--gdb/testsuite/gdb.ada/variant_record_packed_array.exp8
-rw-r--r--gdb/testsuite/gdb.arch/amd64-disp-step-self-call.exp2
-rw-r--r--gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c9
-rw-r--r--gdb/testsuite/gdb.arch/arm-pseudo-unwind.c9
-rw-r--r--gdb/testsuite/gdb.arch/arm-single-step-kernel-helper.c5
-rw-r--r--gdb/testsuite/gdb.arch/arm-single-step-kernel-helper.exp5
-rw-r--r--gdb/testsuite/gdb.arch/e500-prologue.exp2
-rw-r--r--gdb/testsuite/gdb.arch/ftrace-insn-reloc.exp1
-rw-r--r--gdb/testsuite/gdb.arch/i386-disp-step-self-call.exp2
-rw-r--r--gdb/testsuite/gdb.arch/i386-mpx-call.c105
-rw-r--r--gdb/testsuite/gdb.arch/i386-mpx-call.exp398
-rw-r--r--gdb/testsuite/gdb.arch/i386-mpx-map.c61
-rw-r--r--gdb/testsuite/gdb.arch/i386-mpx-map.exp56
-rw-r--r--gdb/testsuite/gdb.arch/i386-mpx-sigsegv.c92
-rw-r--r--gdb/testsuite/gdb.arch/i386-mpx-sigsegv.exp64
-rw-r--r--gdb/testsuite/gdb.arch/i386-mpx-simple_segv.exp124
-rw-r--r--gdb/testsuite/gdb.arch/i386-mpx.c59
-rw-r--r--gdb/testsuite/gdb.arch/i386-mpx.exp123
-rw-r--r--gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp2
-rw-r--r--gdb/testsuite/gdb.arch/ppc64-break-on-_exit.exp2
-rw-r--r--gdb/testsuite/gdb.arch/riscv-tdesc-loading.exp2
-rw-r--r--gdb/testsuite/gdb.arch/riscv-tdesc-regs.exp14
-rw-r--r--gdb/testsuite/gdb.arch/skip-prologue.c54
-rw-r--r--gdb/testsuite/gdb.arch/skip-prologue.exp76
-rw-r--r--gdb/testsuite/gdb.arch/sparc64-adi.c1
-rw-r--r--gdb/testsuite/gdb.base/assign.exp34
-rw-r--r--gdb/testsuite/gdb.base/attach-deleted-exec.exp24
-rw-r--r--gdb/testsuite/gdb.base/batch-exit-status.exp4
-rw-r--r--gdb/testsuite/gdb.base/bitfields.exp18
-rw-r--r--gdb/testsuite/gdb.base/bp-cond-failure.c14
-rw-r--r--gdb/testsuite/gdb.base/bp-cond-failure.exp46
-rw-r--r--gdb/testsuite/gdb.base/break-interp.exp22
-rw-r--r--gdb/testsuite/gdb.base/break-on-linker-gcd-function.exp11
-rw-r--r--gdb/testsuite/gdb.base/break.exp7
-rw-r--r--gdb/testsuite/gdb.base/build-id-seqno.c22
-rw-r--r--gdb/testsuite/gdb.base/build-id-seqno.exp134
-rw-r--r--gdb/testsuite/gdb.base/call-sc.exp2
-rw-r--r--gdb/testsuite/gdb.base/catch-syscall.exp27
-rw-r--r--gdb/testsuite/gdb.base/checkpoint.exp50
-rw-r--r--gdb/testsuite/gdb.base/completion.exp10
-rw-r--r--gdb/testsuite/gdb.base/complex-parts.exp93
-rw-r--r--gdb/testsuite/gdb.base/cond-expr.exp8
-rw-r--r--gdb/testsuite/gdb.base/condbreak.exp57
-rw-r--r--gdb/testsuite/gdb.base/coredump-filter-build-id.exp2
-rw-r--r--gdb/testsuite/gdb.base/corefile-buildid.exp7
-rw-r--r--gdb/testsuite/gdb.base/corefile.exp41
-rw-r--r--gdb/testsuite/gdb.base/cursal.c2
-rw-r--r--gdb/testsuite/gdb.base/cursal.exp4
-rw-r--r--gdb/testsuite/gdb.base/cvexpr.exp264
-rw-r--r--gdb/testsuite/gdb.base/empty-host-env-vars.exp32
-rw-r--r--gdb/testsuite/gdb.base/ending-run.exp38
-rw-r--r--gdb/testsuite/gdb.base/eval-skip.exp85
-rw-r--r--gdb/testsuite/gdb.base/examine-backward.exp56
-rw-r--r--gdb/testsuite/gdb.base/exprs.exp4
-rw-r--r--gdb/testsuite/gdb.base/fileio.exp10
-rw-r--r--gdb/testsuite/gdb.base/filename-completion.exp454
-rw-r--r--gdb/testsuite/gdb.base/foll-exec-mode.exp2
-rw-r--r--gdb/testsuite/gdb.base/foll-exec.exp30
-rw-r--r--gdb/testsuite/gdb.base/gcorebg.c76
-rw-r--r--gdb/testsuite/gdb.base/gcorebg.exp82
-rw-r--r--gdb/testsuite/gdb.base/gnu-ifunc.exp2
-rw-r--r--gdb/testsuite/gdb.base/hbreak-unmapped.exp3
-rw-r--r--gdb/testsuite/gdb.base/hbreak2.exp12
-rw-r--r--gdb/testsuite/gdb.base/history-duplicates.exp10
-rw-r--r--gdb/testsuite/gdb.base/index-cache.exp2
-rw-r--r--gdb/testsuite/gdb.base/info_sources_2.exp2
-rw-r--r--gdb/testsuite/gdb.base/inline-frame-cycle-unwind.exp2
-rw-r--r--gdb/testsuite/gdb.base/interact.exp6
-rw-r--r--gdb/testsuite/gdb.base/killed-outside.exp2
-rw-r--r--gdb/testsuite/gdb.base/limited-length.c2
-rw-r--r--gdb/testsuite/gdb.base/limited-length.exp10
-rw-r--r--gdb/testsuite/gdb.base/lineinc.exp2
-rw-r--r--gdb/testsuite/gdb.base/list-ambiguous0.c2
-rw-r--r--gdb/testsuite/gdb.base/list-before-start.exp36
-rw-r--r--gdb/testsuite/gdb.base/list-dot-nodebug.exp37
-rw-r--r--gdb/testsuite/gdb.base/maint-info-inline-frames-and-blocks.c57
-rw-r--r--gdb/testsuite/gdb.base/maint-info-inline-frames-and-blocks.exp214
-rw-r--r--gdb/testsuite/gdb.base/new-ui.exp8
-rw-r--r--gdb/testsuite/gdb.base/opaque.exp22
-rw-r--r--gdb/testsuite/gdb.base/overlays.exp2
-rw-r--r--gdb/testsuite/gdb.base/pending.exp34
-rw-r--r--gdb/testsuite/gdb.base/printcmds.exp2
-rw-r--r--gdb/testsuite/gdb.base/recurse.exp18
-rw-r--r--gdb/testsuite/gdb.base/reggroups.exp28
-rw-r--r--gdb/testsuite/gdb.base/remote.exp2
-rw-r--r--gdb/testsuite/gdb.base/reset-catchpoint-cond-lib.c75
-rw-r--r--gdb/testsuite/gdb.base/reset-catchpoint-cond.c50
-rw-r--r--gdb/testsuite/gdb.base/reset-catchpoint-cond.exp169
-rw-r--r--gdb/testsuite/gdb.base/reset-catchpoint-cond.py23
-rw-r--r--gdb/testsuite/gdb.base/return.exp4
-rw-r--r--gdb/testsuite/gdb.base/savedregs.exp2
-rw-r--r--gdb/testsuite/gdb.base/scope-hw-watch-disable.exp18
-rw-r--r--gdb/testsuite/gdb.base/sepdebug.exp2
-rw-r--r--gdb/testsuite/gdb.base/setshow.exp36
-rw-r--r--gdb/testsuite/gdb.base/setvar.exp8
-rw-r--r--gdb/testsuite/gdb.base/sigbpt.exp2
-rw-r--r--gdb/testsuite/gdb.base/signals.exp2
-rw-r--r--gdb/testsuite/gdb.base/sigrepeat.c2
-rw-r--r--gdb/testsuite/gdb.base/skip.exp8
-rw-r--r--gdb/testsuite/gdb.base/solib-display.exp2
-rw-r--r--gdb/testsuite/gdb.base/solib-search.exp12
-rw-r--r--gdb/testsuite/gdb.base/step-break.exp12
-rw-r--r--gdb/testsuite/gdb.base/step-into-other-file.c31
-rw-r--r--gdb/testsuite/gdb.base/step-into-other-file.exp36
-rw-r--r--gdb/testsuite/gdb.base/step-into-other-file.h18
-rw-r--r--gdb/testsuite/gdb.base/step-over-syscall.exp6
-rw-r--r--gdb/testsuite/gdb.base/store.exp2
-rw-r--r--gdb/testsuite/gdb.base/structs.exp2
-rw-r--r--gdb/testsuite/gdb.base/style-logging.exp3
-rw-r--r--gdb/testsuite/gdb.base/style.exp13
-rw-r--r--gdb/testsuite/gdb.base/sym-file.exp258
-rw-r--r--gdb/testsuite/gdb.base/sysroot-debug-lookup.exp28
-rw-r--r--gdb/testsuite/gdb.base/testenv.exp2
-rw-r--r--gdb/testsuite/gdb.base/vla-optimized-out.exp6
-rw-r--r--gdb/testsuite/gdb.base/vla-ptr.exp8
-rw-r--r--gdb/testsuite/gdb.base/vla-sideeffect.exp12
-rw-r--r--gdb/testsuite/gdb.base/watch-vfork.exp4
-rw-r--r--gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.exp2
-rw-r--r--gdb/testsuite/gdb.base/wchar.exp6
-rw-r--r--gdb/testsuite/gdb.base/whatis-ptype-typedefs.exp16
-rw-r--r--gdb/testsuite/gdb.base/wrap-line.exp28
-rw-r--r--gdb/testsuite/gdb.btrace/event-tracing-gap.c (renamed from gdb/testsuite/gdb.arch/i386-mpx-simple_segv.c)24
-rw-r--r--gdb/testsuite/gdb.btrace/event-tracing-gap.exp75
-rw-r--r--gdb/testsuite/gdb.btrace/event-tracing.exp52
-rw-r--r--gdb/testsuite/gdb.btrace/i386-ptwrite.S550
-rw-r--r--gdb/testsuite/gdb.btrace/multi-thread-step.exp6
-rw-r--r--gdb/testsuite/gdb.btrace/nohist.exp2
-rw-r--r--gdb/testsuite/gdb.btrace/non-stop.exp44
-rw-r--r--gdb/testsuite/gdb.btrace/null-deref.c26
-rw-r--r--gdb/testsuite/gdb.btrace/ptwrite.c39
-rw-r--r--gdb/testsuite/gdb.btrace/ptwrite.exp201
-rw-r--r--gdb/testsuite/gdb.btrace/stepi.exp14
-rw-r--r--gdb/testsuite/gdb.btrace/x86_64-ptwrite.S544
-rw-r--r--gdb/testsuite/gdb.compile/compile.exp2
-rw-r--r--gdb/testsuite/gdb.cp/anon-ns.exp10
-rw-r--r--gdb/testsuite/gdb.cp/breakpoint-shlib-func.exp13
-rw-r--r--gdb/testsuite/gdb.cp/classes.exp2
-rw-r--r--gdb/testsuite/gdb.cp/exception.exp2
-rw-r--r--gdb/testsuite/gdb.cp/m-static.exp19
-rw-r--r--gdb/testsuite/gdb.cp/member-ptr.exp22
-rw-r--r--gdb/testsuite/gdb.cp/meth-typedefs.exp10
-rw-r--r--gdb/testsuite/gdb.cp/method2.exp4
-rw-r--r--gdb/testsuite/gdb.cp/misc.exp4
-rw-r--r--gdb/testsuite/gdb.cp/nested-types.exp4
-rw-r--r--gdb/testsuite/gdb.cp/ovldbreak.exp8
-rw-r--r--gdb/testsuite/gdb.cp/pass-by-ref-2.exp8
-rw-r--r--gdb/testsuite/gdb.cp/pass-by-ref.exp4
-rw-r--r--gdb/testsuite/gdb.cp/rtti.exp2
-rw-r--r--gdb/testsuite/gdb.cp/step-and-next-inline.exp2
-rw-r--r--gdb/testsuite/gdb.cp/templates.exp15
-rw-r--r--gdb/testsuite/gdb.cp/virtfunc.exp2
-rw-r--r--gdb/testsuite/gdb.dap/catch-exception.exp6
-rw-r--r--gdb/testsuite/gdb.dap/cxx-exception.exp10
-rw-r--r--gdb/testsuite/gdb.dap/global.c31
-rw-r--r--gdb/testsuite/gdb.dap/global.exp72
-rw-r--r--gdb/testsuite/gdb.dap/insn-bp.exp100
-rw-r--r--gdb/testsuite/gdb.dap/memory.exp3
-rw-r--r--gdb/testsuite/gdb.dap/rust-slices.exp6
-rw-r--r--gdb/testsuite/gdb.dap/step-out.exp14
-rw-r--r--gdb/testsuite/gdb.debuginfod/corefile-mapped-file-1.c24
-rw-r--r--gdb/testsuite/gdb.debuginfod/corefile-mapped-file-2.c22
-rw-r--r--gdb/testsuite/gdb.debuginfod/corefile-mapped-file-3.c44
-rw-r--r--gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp380
-rw-r--r--gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp19
-rw-r--r--gdb/testsuite/gdb.debuginfod/solib-with-soname-1.c39
-rw-r--r--gdb/testsuite/gdb.debuginfod/solib-with-soname-2.c41
-rw-r--r--gdb/testsuite/gdb.debuginfod/solib-with-soname.exp290
-rw-r--r--gdb/testsuite/gdb.dwarf2/backward-spec-inter-cu.exp3
-rw-r--r--gdb/testsuite/gdb.dwarf2/count.exp18
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-anon-mptr.exp16
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-bad-parameter-type.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-error.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c6
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-inter-cu-error-2.exp51
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-inter-cu-error.exp51
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-inter-cu-forth-and-back.exp60
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp8
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-lines.c2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-lines.exp10
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.exp4
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-opt-structptr.exp17
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-step-out-of-function-no-stmt.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-using-debug-str.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dwz-unused-pu.exp75
-rw-r--r--gdb/testsuite/gdb.dwarf2/enum-type-c++.cc35
-rw-r--r--gdb/testsuite/gdb.dwarf2/enum-type-c++.exp67
-rw-r--r--gdb/testsuite/gdb.dwarf2/enum-type.exp50
-rw-r--r--gdb/testsuite/gdb.dwarf2/fission-reread.S2
-rw-r--r--gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp3
-rw-r--r--gdb/testsuite/gdb.dwarf2/forward-spec.exp40
-rw-r--r--gdb/testsuite/gdb.dwarf2/gdb-index.exp8
-rw-r--r--gdb/testsuite/gdb.dwarf2/implptrconst.exp9
-rw-r--r--gdb/testsuite/gdb.dwarf2/implptrpiece.exp9
-rw-r--r--gdb/testsuite/gdb.dwarf2/macro-complaints.exp198
-rw-r--r--gdb/testsuite/gdb.dwarf2/member-ptr-forwardref.exp16
-rw-r--r--gdb/testsuite/gdb.dwarf2/multidictionary.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/per-bfd-sharing.exp2
-rw-r--r--gdb/testsuite/gdb.dwarf2/pr13961.S4
-rw-r--r--gdb/testsuite/gdb.dwarf2/pr13961.exp3
-rw-r--r--gdb/testsuite/gdb.dwarf2/self-spec.exp4
-rw-r--r--gdb/testsuite/gdb.dwarf2/struct-with-sig-2.exp2
-rw-r--r--gdb/testsuite/gdb.fortran/entry-point.exp4
-rw-r--r--gdb/testsuite/gdb.fortran/info-types.exp6
-rw-r--r--gdb/testsuite/gdb.fortran/intrinsics.exp8
-rw-r--r--gdb/testsuite/gdb.fortran/multi-dim.exp8
-rw-r--r--gdb/testsuite/gdb.fortran/size.exp4
-rw-r--r--gdb/testsuite/gdb.fortran/type-kinds.exp22
-rw-r--r--gdb/testsuite/gdb.fortran/types.exp21
-rw-r--r--gdb/testsuite/gdb.fortran/vla-alloc-assoc.exp12
-rw-r--r--gdb/testsuite/gdb.fortran/vla-datatypes.exp10
-rw-r--r--gdb/testsuite/gdb.fortran/vla-ptype-sub.exp30
-rw-r--r--gdb/testsuite/gdb.fortran/vla-value-sub-arbitrary.exp10
-rw-r--r--gdb/testsuite/gdb.fortran/vla-value-sub.exp38
-rw-r--r--gdb/testsuite/gdb.fortran/vla-value.exp18
-rw-r--r--gdb/testsuite/gdb.gdb/index-file.exp20
-rw-r--r--gdb/testsuite/gdb.gdb/python-helper.exp15
-rw-r--r--gdb/testsuite/gdb.go/integers.exp2
-rw-r--r--gdb/testsuite/gdb.guile/scm-frame.exp4
-rw-r--r--gdb/testsuite/gdb.guile/scm-parameter.exp24
-rw-r--r--gdb/testsuite/gdb.guile/scm-symbol.exp4
-rw-r--r--gdb/testsuite/gdb.guile/scm-type.exp28
-rw-r--r--gdb/testsuite/gdb.linespec/cp-replace-typedefs-ns-template.exp2
-rw-r--r--gdb/testsuite/gdb.linespec/cpcompletion.exp2
-rw-r--r--gdb/testsuite/gdb.linespec/cpexplicit.exp2
-rw-r--r--gdb/testsuite/gdb.linespec/explicit.exp16
-rw-r--r--gdb/testsuite/gdb.linespec/keywords.exp8
-rw-r--r--gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.c51
-rw-r--r--gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.exp55
-rw-r--r--gdb/testsuite/gdb.linespec/ls-errs.c10
-rw-r--r--gdb/testsuite/gdb.linespec/ls-errs.exp14
-rw-r--r--gdb/testsuite/gdb.mi/dw2-ref-missing-frame.exp10
-rw-r--r--gdb/testsuite/gdb.mi/mi-break-qualified.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-break.exp4
-rw-r--r--gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp31
-rw-r--r--gdb/testsuite/gdb.mi/mi-catch-cpp-exceptions.cc6
-rw-r--r--gdb/testsuite/gdb.mi/mi-complete.exp3
-rw-r--r--gdb/testsuite/gdb.mi/mi-dprintf-pending.exp3
-rw-r--r--gdb/testsuite/gdb.mi/mi-file.exp10
-rw-r--r--gdb/testsuite/gdb.mi/mi-multi-commands.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.exp4
-rw-r--r--gdb/testsuite/gdb.mi/mi-stepi.exp12
-rw-r--r--gdb/testsuite/gdb.mi/mi-sym-info.exp3
-rw-r--r--gdb/testsuite/gdb.mi/mi-thread-bp-deleted.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-cmd.exp22
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-cp.cc9
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-display.exp12
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-invalidate.exp4
-rw-r--r--gdb/testsuite/gdb.mi/mi-vla-c99.exp2
-rw-r--r--gdb/testsuite/gdb.mi/mi-vla-fortran.exp16
-rw-r--r--gdb/testsuite/gdb.mi/new-ui-bp-deleted.exp8
-rw-r--r--gdb/testsuite/gdb.mi/user-selected-context-sync.exp14
-rw-r--r--gdb/testsuite/gdb.mi/var-cmd.c12
-rw-r--r--gdb/testsuite/gdb.modula2/builtin-procedure-adr.exp32
-rw-r--r--gdb/testsuite/gdb.multi/base.exp4
-rw-r--r--gdb/testsuite/gdb.multi/bp-thread-specific.exp31
-rw-r--r--gdb/testsuite/gdb.multi/dummy-frame-restore.exp8
-rw-r--r--gdb/testsuite/gdb.multi/inferior-specific-bp-1.c2
-rw-r--r--gdb/testsuite/gdb.multi/inferior-specific-bp-2.c5
-rw-r--r--gdb/testsuite/gdb.multi/inferior-specific-bp.exp83
-rw-r--r--gdb/testsuite/gdb.multi/multi-target-continue.exp2
-rw-r--r--gdb/testsuite/gdb.multi/multi-target-ping-pong-next.exp4
-rw-r--r--gdb/testsuite/gdb.multi/multi-term-settings.c1
-rw-r--r--gdb/testsuite/gdb.multi/multi-term-settings.exp2
-rw-r--r--gdb/testsuite/gdb.multi/pending-bp-del-inferior.c28
-rw-r--r--gdb/testsuite/gdb.multi/pending-bp-del-inferior.exp214
-rw-r--r--gdb/testsuite/gdb.multi/pending-bp-lib.c22
-rw-r--r--gdb/testsuite/gdb.multi/pending-bp.c66
-rw-r--r--gdb/testsuite/gdb.multi/pending-bp.exp332
-rw-r--r--gdb/testsuite/gdb.multi/tids.exp6
-rw-r--r--gdb/testsuite/gdb.opt/break-on-_exit.exp2
-rw-r--r--gdb/testsuite/gdb.opt/inline-bt.exp26
-rw-r--r--gdb/testsuite/gdb.opt/inline-cmds.exp18
-rw-r--r--gdb/testsuite/gdb.pascal/floats.exp2
-rw-r--r--gdb/testsuite/gdb.pascal/integers.exp2
-rw-r--r--gdb/testsuite/gdb.pascal/types.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-arch.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-breakpoint.exp4
-rw-r--r--gdb/testsuite/gdb.python/py-cmd.exp8
-rw-r--r--gdb/testsuite/gdb.python/py-disasm-exec.exp21
-rw-r--r--gdb/testsuite/gdb.python/py-disasm-obj.exp21
-rw-r--r--gdb/testsuite/gdb.python/py-disasm.exp.tcl (renamed from gdb/testsuite/gdb.python/py-disasm.exp)56
-rw-r--r--gdb/testsuite/gdb.python/py-disasm.py8
-rw-r--r--gdb/testsuite/gdb.python/py-format-string.exp10
-rw-r--r--gdb/testsuite/gdb.python/py-frame.exp8
-rw-r--r--gdb/testsuite/gdb.python/py-framefilter-invalidarg.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-inferior.exp3
-rw-r--r--gdb/testsuite/gdb.python/py-mi-cmd.exp48
-rw-r--r--gdb/testsuite/gdb.python/py-missing-debug.exp3
-rw-r--r--gdb/testsuite/gdb.python/py-pp-cast.py2
-rw-r--r--gdb/testsuite/gdb.python/py-pp-maint.exp8
-rw-r--r--gdb/testsuite/gdb.python/py-pp-re-notag.py1
-rw-r--r--gdb/testsuite/gdb.python/py-prettyprint-stub.py2
-rw-r--r--gdb/testsuite/gdb.python/py-progspace-events.exp31
-rw-r--r--gdb/testsuite/gdb.python/py-progspace.exp2
-rw-r--r--gdb/testsuite/gdb.python/py-read-memory-leak.c27
-rw-r--r--gdb/testsuite/gdb.python/py-read-memory-leak.exp44
-rw-r--r--gdb/testsuite/gdb.python/py-read-memory-leak.py93
-rw-r--r--gdb/testsuite/gdb.python/py-record-btrace.exp11
-rw-r--r--gdb/testsuite/gdb.python/py-type.exp34
-rw-r--r--gdb/testsuite/gdb.python/py-xmethods.exp4
-rw-r--r--gdb/testsuite/gdb.python/python.exp9
-rw-r--r--gdb/testsuite/gdb.python/sys-exit.exp69
-rw-r--r--gdb/testsuite/gdb.reverse/break-precsave.exp6
-rw-r--r--gdb/testsuite/gdb.reverse/break-reverse.exp4
-rw-r--r--gdb/testsuite/gdb.reverse/func-map-to-same-line.exp4
-rw-r--r--gdb/testsuite/gdb.reverse/machinestate-precsave.exp2
-rw-r--r--gdb/testsuite/gdb.reverse/ppc_record_test_isa_3_1.c2
-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/singlejmp-reverse.exp6
-rw-r--r--gdb/testsuite/gdb.reverse/step-precsave.exp8
-rw-r--r--gdb/testsuite/gdb.reverse/step-reverse.exp6
-rw-r--r--gdb/testsuite/gdb.server/build-id-seqno.c22
-rw-r--r--gdb/testsuite/gdb.server/build-id-seqno.exp200
-rw-r--r--gdb/testsuite/gdb.server/exit-multiple-threads.c1
-rw-r--r--gdb/testsuite/gdb.server/remote-read-msgs.exp3
-rw-r--r--gdb/testsuite/gdb.server/server-pipe.exp13
-rw-r--r--gdb/testsuite/gdb.server/server-run.exp33
-rw-r--r--gdb/testsuite/gdb.server/solib-list.exp2
-rw-r--r--gdb/testsuite/gdb.testsuite/parse_options_args.exp2
-rw-r--r--gdb/testsuite/gdb.threads/create-fail.c2
-rw-r--r--gdb/testsuite/gdb.threads/del-pending-thread-bp-lib.c22
-rw-r--r--gdb/testsuite/gdb.threads/del-pending-thread-bp.c85
-rw-r--r--gdb/testsuite/gdb.threads/del-pending-thread-bp.exp98
-rw-r--r--gdb/testsuite/gdb.threads/fork-thread-pending.c1
-rw-r--r--gdb/testsuite/gdb.threads/interrupt-while-step-over.exp2
-rw-r--r--gdb/testsuite/gdb.threads/leader-exit-attach.exp14
-rw-r--r--gdb/testsuite/gdb.threads/print-threads.exp6
-rw-r--r--gdb/testsuite/gdb.threads/schedlock.exp6
-rw-r--r--gdb/testsuite/gdb.threads/signal-command-handle-nopass.c19
-rw-r--r--gdb/testsuite/gdb.threads/signal-sigtrap.c17
-rw-r--r--gdb/testsuite/gdb.threads/stepi-over-clone.exp2
-rw-r--r--gdb/testsuite/gdb.threads/thread-bp-deleted.exp2
-rw-r--r--gdb/testsuite/gdb.threads/thread_check.exp2
-rw-r--r--gdb/testsuite/gdb.threads/tls-sepdebug.exp13
-rw-r--r--gdb/testsuite/gdb.threads/watchpoint-fork-mt.c1
-rw-r--r--gdb/testsuite/gdb.trace/basic-libipa.exp6
-rw-r--r--gdb/testsuite/gdb.trace/change-loc.exp1
-rw-r--r--gdb/testsuite/gdb.trace/collection.exp4
-rw-r--r--gdb/testsuite/gdb.trace/entry-values.exp6
-rw-r--r--gdb/testsuite/gdb.trace/ftrace-lock.exp1
-rw-r--r--gdb/testsuite/gdb.trace/ftrace.exp1
-rw-r--r--gdb/testsuite/gdb.trace/mi-tracepoint-changed.exp2
-rw-r--r--gdb/testsuite/gdb.trace/pending.exp1
-rw-r--r--gdb/testsuite/gdb.trace/range-stepping.exp1
-rw-r--r--gdb/testsuite/gdb.trace/strace.exp1
-rw-r--r--gdb/testsuite/gdb.trace/tfind.exp4
-rw-r--r--gdb/testsuite/gdb.trace/trace-break.exp1
-rw-r--r--gdb/testsuite/gdb.trace/trace-condition.exp1
-rw-r--r--gdb/testsuite/gdb.trace/trace-enable-disable.exp1
-rw-r--r--gdb/testsuite/gdb.trace/trace-mt.exp1
-rw-r--r--gdb/testsuite/gdb.trace/tracecmd.exp3
-rw-r--r--gdb/testsuite/gdb.trace/tspeed.exp1
-rw-r--r--gdb/testsuite/gdb.tui/info-win.exp2
-rw-r--r--gdb/testsuite/gdb.tui/wrap-line.exp31
-rw-r--r--gdb/testsuite/gdb.xml/tdesc-arch.exp8
-rw-r--r--gdb/testsuite/gdb.xml/tdesc-regs.exp35
-rw-r--r--gdb/testsuite/lib/ada.exp31
-rw-r--r--gdb/testsuite/lib/cache.exp202
-rw-r--r--gdb/testsuite/lib/check-test-names.exp10
-rw-r--r--gdb/testsuite/lib/dwarf.exp2
-rw-r--r--gdb/testsuite/lib/gdb-utils.exp32
-rw-r--r--gdb/testsuite/lib/gdb.exp550
-rw-r--r--gdb/testsuite/lib/mi-support.exp39
-rw-r--r--gdb/testsuite/lib/prelink-support.exp2
-rw-r--r--gdb/testsuite/lib/selftest-support.exp2
-rw-r--r--gdb/testsuite/lib/trace-support.exp14
-rw-r--r--gdb/tid-parse.c84
-rw-r--r--gdb/tid-parse.h10
-rw-r--r--gdb/tilegx-linux-nat.c2
-rw-r--r--gdb/top.c19
-rw-r--r--gdb/top.h2
-rw-r--r--gdb/tracectf.c12
-rw-r--r--gdb/tracefile-tfile.c17
-rw-r--r--gdb/tracepoint.c42
-rw-r--r--gdb/trad-frame.c8
-rw-r--r--gdb/tui/tui-command.c10
-rw-r--r--gdb/tui/tui-command.h6
-rw-r--r--gdb/tui/tui-data.h16
-rw-r--r--gdb/tui/tui-disasm.c20
-rw-r--r--gdb/tui/tui-file.c6
-rw-r--r--gdb/tui/tui-hooks.c3
-rw-r--r--gdb/tui/tui-layout.c2
-rw-r--r--gdb/tui/tui-regs.c45
-rw-r--r--gdb/tui/tui-regs.h2
-rw-r--r--gdb/tui/tui-source.c21
-rw-r--r--gdb/tui/tui-source.h6
-rw-r--r--gdb/tui/tui-win.c6
-rw-r--r--gdb/tui/tui-wingeneral.c27
-rw-r--r--gdb/tui/tui-wingeneral.h20
-rw-r--r--gdb/tui/tui-winsource.c12
-rw-r--r--gdb/tui/tui-winsource.h8
-rw-r--r--gdb/tui/tui.c2
-rw-r--r--gdb/typeprint.c2
-rw-r--r--gdb/ui-out.c8
-rw-r--r--gdb/ui-out.h6
-rw-r--r--gdb/ui.c2
-rw-r--r--gdb/unittests/enum-flags-selftests.c306
-rw-r--r--gdb/unittests/intrusive_list-selftests.c938
-rw-r--r--gdb/unittests/scoped_mmap-selftests.c2
-rw-r--r--gdb/user-regs.c14
-rw-r--r--gdb/utils.c72
-rw-r--r--gdb/utils.h14
-rw-r--r--gdb/v850-tdep.c4
-rw-r--r--gdb/valops.c7
-rw-r--r--gdb/value.c117
-rw-r--r--gdb/value.h35
-rw-r--r--gdb/varobj.c5
-rw-r--r--gdb/x86-tdep.c2
-rw-r--r--gdb/xml-support.c4
-rw-r--r--gdb/xml-support.h5
-rw-r--r--gdb/yy-remap.h2
-rw-r--r--gdb/z80-tdep.c20
856 files changed, 22967 insertions, 14618 deletions
diff --git a/gdb/MAINTAINERS b/gdb/MAINTAINERS
index 24bffa9..b821901 100644
--- a/gdb/MAINTAINERS
+++ b/gdb/MAINTAINERS
@@ -328,7 +328,7 @@ the native maintainer when resolving ABI issues.
Lancelot Six lancelot.six@amd.com
arc --target=arc-elf
- Shahab Vahedi shahab@synopsys.com
+ Shahab Vahedi list@vahedi.org
arm --target=arm-elf
Alan Hayward alan.hayward@arm.com
@@ -346,7 +346,6 @@ the native maintainer when resolving ABI issues.
h8300 --target=h8300-elf
i386 --target=i386-elf
- Felix Willgerodt felix.willgerodt@intel.com
ia64 --target=ia64-linux-gnu
(--target=ia64-elf broken)
@@ -422,7 +421,6 @@ the native maintainer when resolving ABI issues.
vax --target=vax-netbsd
x86-64 --target=x86_64-linux-gnu
- Felix Willgerodt felix.willgerodt@intel.com
xstormy16 --target=xstormy16-elf
xtensa --target=xtensa-elf
@@ -473,7 +471,7 @@ SystemTap Sergio Durigan Junior sergiodj@sergiodj.net
Reverse debugging / Record and Replay / Tracing:
record
- full Guinevere Larsen blarsen@redhat.com
+ full Guinevere Larsen guinevere@redhat.com
btrace Markus T. Metzger markus.t.metzger@intel.com
@@ -606,6 +604,7 @@ Mike Frysinger vapier@gentoo.org
Gary Funck gary@intrepid.com
Martin Galvan martingalvan@sourceware.org
Chen Gang gang.chen.5i5j@gmail.com
+Klaus Gerlicher klaus.gerlicher@intel.com
Mircea Gherzan mircea.gherzan@intel.com
Paul Gilliam pgilliam@us.ibm.com
Tristan Gingold tgingold@free.fr
@@ -656,7 +655,7 @@ Jan Kratochvil jan.kratochvil@redhat.com
Maxim Kuvyrkov maxim@kugelworks.com
Pierre Langlois pierre.langlois@arm.com
Jonathan Larmour jifl@ecoscentric.com
-Guinevere Larsen blarsen@redhat.com
+Guinevere Larsen guinevere@redhat.com
Jeff Law law@redhat.com
Justin Lebar justin.lebar@gmail.com
David Lecomber david@streamline-computing.com
@@ -690,7 +689,7 @@ Chris Moller cmoller@redhat.com
Patrick Monnerat patrick@monnerat.net
Phil Muldoon pmuldoon@redhat.com
Pierre Muller muller@sourceware.org
-Gaius Mulley gaius@glam.ac.uk
+Gaius Mulley gaiusmod2@gmail.com
Masaki Muranaka monaka@monami-software.com
Joseph Myers josmyers@redhat.com
Fernando Nasser fnasser@redhat.com
@@ -790,7 +789,7 @@ Ulrich Weigand uweigand@de.ibm.com
Ken Werner ken.werner@de.ibm.com
Tim Wiederhake tim.wiederhake@intel.com
Mark Wielaard mark@klomp.org
-Felix Willgerodt felix.willgerodt@intel.com
+Felix Willgerodt felix.willgerodt@gmail.com
Nathan Williams nathanw@wasabisystems.com
Bob Wilson bob.wilson@acm.org
Jim Wilson wilson@tuliptree.org
@@ -866,6 +865,7 @@ Stan Shebs (Global) stanshebs@google.com
Joel Brobecker (Global, Ada) brobecker@adacore.com
Doug Evans (Global) dje@google.com
Yao Qi (Global) qiyao@sourceware.org
+Felix Willgerodt (amd64, i386) felix.willgerodt@gmail.com
Folks that have been caught up in a paper trail:
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 1c697bf..ecb323d 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -746,6 +746,7 @@ ALL_64_TARGET_OBS = \
amd64-windows-tdep.o \
arch/aarch64.o \
arch/aarch64-insn.o \
+ arch/aarch64-mte.o \
arch/aarch64-mte-linux.o \
arch/aarch64-scalable-linux.o \
arch/amd64-linux-tdesc.o \
@@ -831,7 +832,6 @@ ALL_TARGET_OBS = \
i386-go32-tdep.o \
i386-linux-tdep.o \
i386-netbsd-tdep.o \
- i386-nto-tdep.o \
i386-obsd-tdep.o \
i386-sol2-tdep.o \
i386-tdep.o \
@@ -859,7 +859,6 @@ ALL_TARGET_OBS = \
nds32-tdep.o \
nios2-linux-tdep.o \
nios2-tdep.o \
- nto-tdep.o \
obsd-tdep.o \
or1k-linux-tdep.o \
or1k-tdep.o \
@@ -1052,6 +1051,7 @@ COMMON_SFILES = \
break-catch-sig.c \
break-catch-syscall.c \
break-catch-throw.c \
+ break-cond-parse.c \
breakpoint.c \
bt-utils.c \
btrace.c \
@@ -1321,6 +1321,7 @@ HFILES_NO_SRCDIR = \
bfd-target.h \
bfin-tdep.h \
block.h \
+ break-cond-parse.h \
breakpoint.h \
bsd-kvm.h \
bsd-uthread.h \
@@ -1443,7 +1444,6 @@ HFILES_NO_SRCDIR = \
nds32-tdep.h \
nios2-tdep.h \
elf-none-tdep.h \
- nto-tdep.h \
objc-lang.h \
objfiles.h \
obsd-nat.h \
@@ -1551,6 +1551,7 @@ HFILES_NO_SRCDIR = \
arch/aarch32.h \
arch/aarch64.h \
arch/aarch64-insn.h \
+ arch/aarch64-mte.h \
arch/aarch64-mte-linux.h \
arch/aarch64-scalable-linux.h \
arch/amd64-linux-tdesc.h \
@@ -1579,7 +1580,6 @@ HFILES_NO_SRCDIR = \
compile/gcc-c-plugin.h \
compile/gcc-cp-plugin.h \
config/nm-linux.h \
- config/nm-nto.h \
config/djgpp/langinfo.h \
config/djgpp/nl_types.h \
config/i386/nm-i386gnu.h \
@@ -1664,6 +1664,7 @@ ALLDEPFILES = \
arch/aarch32.c \
arch/aarch64.c \
arch/aarch64-insn.c \
+ arch/aarch64-mte.c \
arch/aarch64-mte-linux.c \
arch/aarch64-scalable-linux.c \
arch/amd64.c \
@@ -2527,7 +2528,7 @@ clean-po:
# rule has no dependencies and always regenerates gdb.pot. This is
# relatively harmless since the .po files do not directly depend on
# it. The .pot file is left in the build directory. Since GDB's
-# Makefile lacks a cannonical list of sources (missing xm, tm and nm
+# Makefile lacks a canonical list of sources (missing xm, tm and nm
# files) force this rule.
$(PACKAGE).pot: po/$(PACKAGE).pot
po/$(PACKAGE).pot: force
diff --git a/gdb/NEWS b/gdb/NEWS
index 47677cb..42668cb 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,16 +3,117 @@
*** Changes since GDB 15
-* Debugger Adapter Protocol changes
-
- ** The "scopes" request will now return a scope holding global
- variables from the stack frame's compilation unit.
+* Debugging support for Intel MPX has been removed. This includes the
+ removal of
+ ** MPX register support
+ ** the commands "show/set mpx bound" (deprecated since GDB 15)
+ ** i386 and amd64 implementation of the hooks report_signal_info and
+ get_siginfo_type.
+
+* GDB now supports printing of asynchronous events from the Intel Processor
+ Trace during 'record instruction-history', 'record function-call-history'
+ and all stepping commands. This can be controlled with the new
+ "set record btrace pt event-tracing" command.
+
+* GDB now supports printing of ptwrite payloads from the Intel Processor
+ Trace during 'record instruction-history', 'record function-call-history'
+ and all stepping commands. The payload is also accessible in Python as a
+ RecordAuxiliary object. Printing is customizable via a ptwrite filter
+ function in Python. By default, the raw ptwrite payload is printed for
+ each ptwrite that is encountered.
+
+* For breakpoints that are created in the 'pending' state, any
+ 'thread' or 'task' keywords are parsed at the time the breakpoint is
+ created, rather than at the time the breakpoint becomes non-pending.
+
+* Thread-specific breakpoints are only inserted into the program space
+ in which the thread of interest is running. In most cases program
+ spaces are unique for each inferior, so this means that
+ thread-specific breakpoints will usually only be inserted for the
+ inferior containing the thread of interest. The breakpoint will
+ be hit no less than before.
* For ARM targets, the offset of the pc in the jmp_buf has been fixed to match
glibc 2.20 and later. This should only matter when not using libc probes.
This may cause breakage when using an incompatible libc, like uclibc or
newlib, or an older glibc.
+* MTE (Memory Tagging Extension) debugging is now supported on AArch64 baremetal
+ targets.
+
+* Remove support (native and remote) for QNX Neutrino (triplet
+ `i[3456]86-*-nto*`).
+
+* In a record session, when a forward emulation reaches the end of the reverse
+ history, the warning message has been changed to indicate that the end of the
+ history has been reached. It also specifies that the forward execution can
+ continue, and the recording will also continue.
+
+* Python API
+
+ ** Added gdb.record.clear. Clears the trace data of the current recording.
+ This forces re-decoding of the trace for successive commands.
+
+* Debugger Adapter Protocol changes
+
+ ** The "scopes" request will now return a scope holding global
+ variables from the stack frame's compilation unit.
+
+ ** The "scopes" request will return a "returnValue" scope holding
+ the return value from the latest "stepOut" command, when
+ appropriate.
+
+* New commands
+
+set style line-number foreground COLOR
+set style line-number background COLOR
+set style line-number intensity VALUE
+ Control the styling of line numbers printed by GDB.
+
+maintenance info inline-frames [ADDRESS]
+ New command which displays GDB's inline-frame information for the
+ current address, or for ADDRESS if specified. The output identifies
+ inlined frames which start at the specified address.
+
+maintenance info blocks [ADDRESS]
+ New command which displays information about all of the blocks at
+ ADDRESS, or at the current address if ADDRESS is not given. Blocks
+ are listed starting at the inner global block out to the most inner
+ block.
+
+* Changed commands
+
+remove-symbol-file
+ This command now supports file-name completion.
+
+remove-symbol-file -a ADDRESS
+ The ADDRESS expression can now be a full expression consisting of
+ multiple terms, e.g. 'function + 0x1000' (without quotes),
+ previously only a single term could be given.
+
+target core
+target exec
+target tfile
+target ctf
+compile file
+maint print c-tdesc
+save gdb-index
+ These commands now require their filename argument to be quoted if
+ it contains white space or quote characters. If the argument
+ contains no such special characters then quoting is not required.
+
+maintenance print remote-registers
+ Add an "Expedited" column to the output of the command. It indicates
+ which registers were included in the last stop reply packet received by
+ GDB.
+
+* New remote packets
+
+vFile:stat
+ Return information about files on the remote system. Like
+ vFile:fstat but takes a filename rather than an open file
+ descriptor.
+
*** Changes in GDB 15
* The MPX commands "show/set mpx bound" have been deprecated, as Intel
@@ -308,7 +409,7 @@ qIsAddressTagged
* The printf command now accepts a '%V' output format which will
format an expression just as the 'print' command would. Print
- options can be placed withing '[...]' after the '%V' to modify how
+ options can be placed within '[...]' after the '%V' to modify how
the value is printed. E.g:
printf "%V", some_array
printf "%V[-array-indexes on]", some_array
@@ -6585,7 +6686,7 @@ qSupported:
target.
qXfer:auxv:read:
- Fetch an OS auxilliary vector from the remote stub. This packet is a
+ Fetch an OS auxiliary vector from the remote stub. This packet is a
more efficient replacement for qPart:auxv:read.
qXfer:memory-map:read:
@@ -7793,7 +7894,7 @@ with that. The sub-program to run is specified using the syntax
* MIPS 64 remote protocol
A long standing bug in the mips64 remote protocol where by GDB
-expected certain 32 bit registers (ex SR) to be transfered as 32
+expected certain 32 bit registers (ex SR) to be transferred as 32
instead of 64 bits has been fixed.
The command ``set remote-mips64-transfers-32bit-regs on'' has been
@@ -8549,7 +8650,7 @@ MIPS remote debugging protocol.
This version includes preliminary support for Chill, a Pascal like language
used by telecommunications companies. Chill support is also being integrated
-into the GNU compiler, but we don't know when it will be publically available.
+into the GNU compiler, but we don't know when it will be publicly available.
*** Changes in GDB-4.8:
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 2e6541f..0fa5bee 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -496,12 +496,11 @@ fetch_tlsregs_from_thread (struct regcache *regcache)
gdb_assert (regno != -1);
gdb_assert (tdep->tls_register_count > 0);
- uint64_t tpidrs[tdep->tls_register_count];
- memset(tpidrs, 0, sizeof(tpidrs));
+ std::vector<uint64_t> tpidrs (tdep->tls_register_count);
struct iovec iovec;
- iovec.iov_base = tpidrs;
- iovec.iov_len = sizeof (tpidrs);
+ iovec.iov_base = tpidrs.data ();
+ iovec.iov_len = tpidrs.size () * sizeof (tpidrs[0]);
int tid = get_ptrace_pid (regcache->ptid ());
if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_TLS, &iovec) != 0)
@@ -524,8 +523,7 @@ store_tlsregs_to_thread (struct regcache *regcache)
gdb_assert (regno != -1);
gdb_assert (tdep->tls_register_count > 0);
- uint64_t tpidrs[tdep->tls_register_count];
- memset(tpidrs, 0, sizeof(tpidrs));
+ std::vector<uint64_t> tpidrs (tdep->tls_register_count);
for (int i = 0; i < tdep->tls_register_count; i++)
{
@@ -536,8 +534,8 @@ store_tlsregs_to_thread (struct regcache *regcache)
}
struct iovec iovec;
- iovec.iov_base = &tpidrs;
- iovec.iov_len = sizeof (tpidrs);
+ iovec.iov_base = tpidrs.data ();
+ iovec.iov_len = tpidrs.size () * sizeof (tpidrs[0]);
int tid = get_ptrace_pid (regcache->ptid ());
if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_TLS, &iovec) != 0)
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index a1296a8..c608a84 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -48,6 +48,7 @@
#include "record-full.h"
#include "linux-record.h"
+#include "arch/aarch64-mte.h"
#include "arch/aarch64-mte-linux.h"
#include "arch/aarch64-scalable-linux.h"
@@ -1297,8 +1298,7 @@ aarch64_linux_supply_za_regset (const struct regset *regset,
}
else
{
- gdb_byte za_zeroed[za_bytes];
- memset (za_zeroed, 0, za_bytes);
+ gdb::byte_vector za_zeroed (za_bytes, 0);
regcache->raw_supply (tdep->sme_za_regnum, za_zeroed);
}
}
@@ -2427,29 +2427,6 @@ aarch64_linux_gcc_target_options (struct gdbarch *gdbarch)
return {};
}
-/* Helper to get the allocation tag from a 64-bit ADDRESS.
-
- Return the allocation tag if successful and nullopt otherwise. */
-
-static std::optional<CORE_ADDR>
-aarch64_mte_get_atag (CORE_ADDR address)
-{
- gdb::byte_vector tags;
-
- /* Attempt to fetch the allocation tag. */
- if (!target_fetch_memtags (address, 1, tags,
- static_cast<int> (memtag_type::allocation)))
- return {};
-
- /* Only one tag should've been returned. Make sure we got exactly that. */
- if (tags.size () != 1)
- error (_("Target returned an unexpected number of tags."));
-
- /* Although our tags are 4 bits in size, they are stored in a
- byte. */
- return tags[0];
-}
-
/* Implement the tagged_address_p gdbarch method. */
static bool
@@ -2466,132 +2443,6 @@ aarch64_linux_tagged_address_p (struct gdbarch *gdbarch, CORE_ADDR address)
return true;
}
-/* Implement the memtag_matches_p gdbarch method. */
-
-static bool
-aarch64_linux_memtag_matches_p (struct gdbarch *gdbarch,
- struct value *address)
-{
- gdb_assert (address != nullptr);
-
- CORE_ADDR addr = value_as_address (address);
-
- /* Fetch the allocation tag for ADDRESS. */
- std::optional<CORE_ADDR> atag
- = aarch64_mte_get_atag (gdbarch_remove_non_address_bits (gdbarch, addr));
-
- if (!atag.has_value ())
- return true;
-
- /* Fetch the logical tag for ADDRESS. */
- gdb_byte ltag = aarch64_mte_get_ltag (addr);
-
- /* Are the tags the same? */
- return ltag == *atag;
-}
-
-/* Implement the set_memtags gdbarch method. */
-
-static bool
-aarch64_linux_set_memtags (struct gdbarch *gdbarch, struct value *address,
- size_t length, const gdb::byte_vector &tags,
- memtag_type tag_type)
-{
- gdb_assert (!tags.empty ());
- gdb_assert (address != nullptr);
-
- CORE_ADDR addr = value_as_address (address);
-
- /* Set the logical tag or the allocation tag. */
- if (tag_type == memtag_type::logical)
- {
- /* When setting logical tags, we don't care about the length, since
- we are only setting a single logical tag. */
- addr = aarch64_mte_set_ltag (addr, tags[0]);
-
- /* Update the value's content with the tag. */
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- gdb_byte *srcbuf = address->contents_raw ().data ();
- store_unsigned_integer (srcbuf, sizeof (addr), byte_order, addr);
- }
- else
- {
- /* Remove the top byte. */
- addr = gdbarch_remove_non_address_bits (gdbarch, addr);
-
- /* With G being the number of tag granules and N the number of tags
- passed in, we can have the following cases:
-
- 1 - G == N: Store all the N tags to memory.
-
- 2 - G < N : Warn about having more tags than granules, but write G
- tags.
-
- 3 - G > N : This is a "fill tags" operation. We should use the tags
- as a pattern to fill the granules repeatedly until we have
- written G tags to memory.
- */
-
- size_t g = aarch64_mte_get_tag_granules (addr, length,
- AARCH64_MTE_GRANULE_SIZE);
- size_t n = tags.size ();
-
- if (g < n)
- warning (_("Got more tags than memory granules. Tags will be "
- "truncated."));
- else if (g > n)
- warning (_("Using tag pattern to fill memory range."));
-
- if (!target_store_memtags (addr, length, tags,
- static_cast<int> (memtag_type::allocation)))
- return false;
- }
- return true;
-}
-
-/* Implement the get_memtag gdbarch method. */
-
-static struct value *
-aarch64_linux_get_memtag (struct gdbarch *gdbarch, struct value *address,
- memtag_type tag_type)
-{
- gdb_assert (address != nullptr);
-
- CORE_ADDR addr = value_as_address (address);
- CORE_ADDR tag = 0;
-
- /* Get the logical tag or the allocation tag. */
- if (tag_type == memtag_type::logical)
- tag = aarch64_mte_get_ltag (addr);
- else
- {
- /* Remove the top byte. */
- addr = gdbarch_remove_non_address_bits (gdbarch, addr);
- std::optional<CORE_ADDR> atag = aarch64_mte_get_atag (addr);
-
- if (!atag.has_value ())
- return nullptr;
-
- tag = *atag;
- }
-
- /* Convert the tag to a value. */
- return value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_int,
- tag);
-}
-
-/* Implement the memtag_to_string gdbarch method. */
-
-static std::string
-aarch64_linux_memtag_to_string (struct gdbarch *gdbarch, struct value *tag_value)
-{
- if (tag_value == nullptr)
- return "";
-
- CORE_ADDR tag = value_as_address (tag_value);
-
- return string_printf ("0x%s", phex_nz (tag, sizeof (tag)));
-}
/* AArch64 Linux implementation of the report_signal_info gdbarch
hook. Displays information about possible memory tag violations. */
@@ -2900,24 +2751,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);
- /* Register a hook for checking if there is a memory tag match. */
- set_gdbarch_memtag_matches_p (gdbarch,
- aarch64_linux_memtag_matches_p);
-
- /* Register a hook for setting the logical/allocation tags for
- a range of addresses. */
- set_gdbarch_set_memtags (gdbarch, aarch64_linux_set_memtags);
-
- /* Register a hook for extracting the logical/allocation tag from an
- address. */
- set_gdbarch_get_memtag (gdbarch, aarch64_linux_get_memtag);
-
- /* Set the allocation tag granule size to 16 bytes. */
- set_gdbarch_memtag_granule_size (gdbarch, AARCH64_MTE_GRANULE_SIZE);
-
- /* Register a hook for converting a memory tag to a string. */
- set_gdbarch_memtag_to_string (gdbarch, aarch64_linux_memtag_to_string);
-
set_gdbarch_report_signal_info (gdbarch,
aarch64_linux_report_signal_info);
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index e4bca6c..8a2a9b1 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -45,6 +45,7 @@
#include "aarch64-tdep.h"
#include "aarch64-ravenscar-thread.h"
+#include "arch/aarch64-mte.h"
#include "record.h"
#include "record-full.h"
@@ -1727,16 +1728,15 @@ pass_in_v (struct gdbarch *gdbarch,
{
int regnum = AARCH64_V0_REGNUM + info->nsrn;
/* Enough space for a full vector register. */
- gdb_byte reg[register_size (gdbarch, regnum)];
- gdb_assert (len <= sizeof (reg));
+ gdb::byte_vector reg (register_size (gdbarch, regnum), 0);
+ gdb_assert (len <= reg.size ());
info->argnum++;
info->nsrn++;
- memset (reg, 0, sizeof (reg));
/* PCS C.1, the argument is allocated to the least significant
bits of V register. */
- memcpy (reg, buf, len);
+ memcpy (reg.data (), buf, len);
regcache->cooked_write (regnum, reg);
aarch64_debug_printf ("arg %d in %s", info->argnum,
@@ -2543,8 +2543,8 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
{
int regno = AARCH64_V0_REGNUM + i;
/* Enough space for a full vector register. */
- gdb_byte buf[register_size (gdbarch, regno)];
- gdb_assert (len <= sizeof (buf));
+ gdb::byte_vector buf (register_size (gdbarch, regno));
+ gdb_assert (len <= buf.size ());
aarch64_debug_printf
("read HFA or HVA return value element %d from %s",
@@ -2552,7 +2552,7 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
regs->cooked_read (regno, buf);
- memcpy (valbuf, buf, len);
+ memcpy (valbuf, buf.data (), len);
valbuf += len;
}
}
@@ -2657,8 +2657,8 @@ aarch64_store_return_value (struct type *type, struct regcache *regs,
{
int regno = AARCH64_V0_REGNUM + i;
/* Enough space for a full vector register. */
- gdb_byte tmpbuf[register_size (gdbarch, regno)];
- gdb_assert (len <= sizeof (tmpbuf));
+ gdb::byte_vector tmpbuf (register_size (gdbarch, regno));
+ gdb_assert (len <= tmpbuf.size ());
aarch64_debug_printf
("write HFA or HVA return value element %d to %s",
@@ -2669,7 +2669,7 @@ aarch64_store_return_value (struct type *type, struct regcache *regs,
original contents of the register before overriding it with a new
value that has a potential size <= 16 bytes. */
regs->cooked_read (regno, tmpbuf);
- memcpy (tmpbuf, valbuf,
+ memcpy (tmpbuf.data (), valbuf,
len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len);
regs->cooked_write (regno, tmpbuf);
valbuf += len;
@@ -3302,18 +3302,16 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, const frame_info_ptr &next_frame,
{
unsigned raw_regnum = AARCH64_V0_REGNUM + regnum_offset;
- /* Enough space for a full vector register. */
- int raw_reg_size = register_size (gdbarch, raw_regnum);
- gdb_byte raw_buf[raw_reg_size];
- static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);
+ /* Enough space for a full vector register.
- /* Ensure the register buffer is zero, we want gdb writes of the
+ Ensure the register buffer is zero, we want gdb writes of the
various 'scalar' pseudo registers to behavior like architectural
writes, register width bytes are written the remainder are set to
zero. */
- memset (raw_buf, 0, register_size (gdbarch, AARCH64_V0_REGNUM));
+ gdb::byte_vector raw_buf (register_size (gdbarch, raw_regnum), 0);
+ static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);
- gdb::array_view<gdb_byte> raw_view (raw_buf, raw_reg_size);
+ gdb::array_view<gdb_byte> raw_view (raw_buf);
copy (buf, raw_view.slice (0, buf.size ()));
put_frame_register (next_frame, raw_regnum, raw_view);
}
@@ -4088,6 +4086,156 @@ aarch64_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
return streq (inst.opcode->name, "ret");
}
+/* Helper to get the allocation tag from a 64-bit ADDRESS.
+
+ Return the allocation tag if successful and nullopt otherwise. */
+
+std::optional<CORE_ADDR>
+aarch64_mte_get_atag (CORE_ADDR address)
+{
+ gdb::byte_vector tags;
+
+ /* Attempt to fetch the allocation tag. */
+ if (!target_fetch_memtags (address, 1, tags,
+ static_cast<int> (memtag_type::allocation)))
+ return {};
+
+ /* Only one tag should've been returned. Make sure we got exactly that. */
+ if (tags.size () != 1)
+ error (_("Target returned an unexpected number of tags."));
+
+ /* Although our tags are 4 bits in size, they are stored in a
+ byte. */
+ return tags[0];
+}
+
+/* Implement the memtag_matches_p gdbarch method. */
+
+static bool
+aarch64_memtag_matches_p (struct gdbarch *gdbarch,
+ struct value *address)
+{
+ gdb_assert (address != nullptr);
+
+ CORE_ADDR addr = value_as_address (address);
+
+ /* Fetch the allocation tag for ADDRESS. */
+ std::optional<CORE_ADDR> atag
+ = aarch64_mte_get_atag (gdbarch_remove_non_address_bits (gdbarch, addr));
+
+ if (!atag.has_value ())
+ return true;
+
+ /* Fetch the logical tag for ADDRESS. */
+ gdb_byte ltag = aarch64_mte_get_ltag (addr);
+
+ /* Are the tags the same? */
+ return ltag == *atag;
+}
+
+/* Implement the set_memtags gdbarch method. */
+
+static bool
+aarch64_set_memtags (struct gdbarch *gdbarch, struct value *address,
+ size_t length, const gdb::byte_vector &tags,
+ memtag_type tag_type)
+{
+ gdb_assert (!tags.empty ());
+ gdb_assert (address != nullptr);
+
+ CORE_ADDR addr = value_as_address (address);
+
+ /* Set the logical tag or the allocation tag. */
+ if (tag_type == memtag_type::logical)
+ {
+ /* When setting logical tags, we don't care about the length, since
+ we are only setting a single logical tag. */
+ addr = aarch64_mte_set_ltag (addr, tags[0]);
+
+ /* Update the value's content with the tag. */
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte *srcbuf = address->contents_raw ().data ();
+ store_unsigned_integer (srcbuf, sizeof (addr), byte_order, addr);
+ }
+ else
+ {
+ /* Remove the top byte. */
+ addr = gdbarch_remove_non_address_bits (gdbarch, addr);
+
+ /* With G being the number of tag granules and N the number of tags
+ passed in, we can have the following cases:
+
+ 1 - G == N: Store all the N tags to memory.
+
+ 2 - G < N : Warn about having more tags than granules, but write G
+ tags.
+
+ 3 - G > N : This is a "fill tags" operation. We should use the tags
+ as a pattern to fill the granules repeatedly until we have
+ written G tags to memory.
+ */
+
+ size_t g = aarch64_mte_get_tag_granules (addr, length,
+ AARCH64_MTE_GRANULE_SIZE);
+ size_t n = tags.size ();
+
+ if (g < n)
+ warning (_("Got more tags than memory granules. Tags will be "
+ "truncated."));
+ else if (g > n)
+ warning (_("Using tag pattern to fill memory range."));
+
+ if (!target_store_memtags (addr, length, tags,
+ static_cast<int> (memtag_type::allocation)))
+ return false;
+ }
+ return true;
+}
+
+/* Implement the get_memtag gdbarch method. */
+
+static struct value *
+aarch64_get_memtag (struct gdbarch *gdbarch, struct value *address,
+ memtag_type tag_type)
+{
+ gdb_assert (address != nullptr);
+
+ CORE_ADDR addr = value_as_address (address);
+ CORE_ADDR tag = 0;
+
+ /* Get the logical tag or the allocation tag. */
+ if (tag_type == memtag_type::logical)
+ tag = aarch64_mte_get_ltag (addr);
+ else
+ {
+ /* Remove the top byte. */
+ addr = gdbarch_remove_non_address_bits (gdbarch, addr);
+ std::optional<CORE_ADDR> atag = aarch64_mte_get_atag (addr);
+
+ if (!atag.has_value ())
+ return nullptr;
+
+ tag = *atag;
+ }
+
+ /* Convert the tag to a value. */
+ return value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_int,
+ tag);
+}
+
+/* Implement the memtag_to_string gdbarch method. */
+
+static std::string
+aarch64_memtag_to_string (struct gdbarch *gdbarch, struct value *tag_value)
+{
+ if (tag_value == nullptr)
+ return "";
+
+ CORE_ADDR tag = value_as_address (tag_value);
+
+ return string_printf ("0x%s", phex_nz (tag, sizeof (tag)));
+}
+
/* AArch64 implementation of the remove_non_address_bits gdbarch hook. Remove
non address bits from a pointer value. */
@@ -4504,6 +4652,23 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
aarch64_pseudo_register_reggroup_p);
set_gdbarch_cannot_store_register (gdbarch, aarch64_cannot_store_register);
+ /* Set the allocation tag granule size to 16 bytes. */
+ set_gdbarch_memtag_granule_size (gdbarch, AARCH64_MTE_GRANULE_SIZE);
+
+ /* Register a hook for checking if there is a memory tag match. */
+ set_gdbarch_memtag_matches_p (gdbarch, aarch64_memtag_matches_p);
+
+ /* Register a hook for setting the logical/allocation tags for
+ a range of addresses. */
+ set_gdbarch_set_memtags (gdbarch, aarch64_set_memtags);
+
+ /* Register a hook for extracting the logical/allocation tag from an
+ address. */
+ set_gdbarch_get_memtag (gdbarch, aarch64_get_memtag);
+
+ /* Register a hook for converting a memory tag to a string. */
+ set_gdbarch_memtag_to_string (gdbarch, aarch64_memtag_to_string);
+
/* ABI */
set_gdbarch_short_bit (gdbarch, 16);
set_gdbarch_int_bit (gdbarch, 32);
diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
index 0e6024b..50166fb 100644
--- a/gdb/aarch64-tdep.h
+++ b/gdb/aarch64-tdep.h
@@ -203,4 +203,6 @@ void aarch64_displaced_step_fixup (struct gdbarch *gdbarch,
bool aarch64_displaced_step_hw_singlestep (struct gdbarch *gdbarch);
+std::optional<CORE_ADDR> aarch64_mte_get_atag (CORE_ADDR address);
+
#endif /* aarch64-tdep.h */
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 0126db5..ed8ed44 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -1232,7 +1232,7 @@ primary : '*' primary %prec '.'
/* yylex defined in ada-lex.c: Reads one token, getting characters */
/* through lexptr. */
-/* Remap normal flex interface names (yylex) as well as gratuitiously */
+/* Remap normal flex interface names (yylex) as well as gratuitously */
/* global symbol names, so we can have multiple flex-generated parsers */
/* in gdb. */
@@ -1477,7 +1477,7 @@ block_lookup (const struct block *context, const char *raw_name)
if (context == NULL
&& (syms.empty () || syms[0].symbol->aclass () != LOC_BLOCK))
- symtab = lookup_symtab (name);
+ symtab = lookup_symtab (current_program_space, name);
else
symtab = NULL;
@@ -1831,7 +1831,7 @@ write_var_or_type (struct parser_state *par_state,
if (block != nullptr)
objfile = block->objfile ();
- struct bound_minimal_symbol msym
+ bound_minimal_symbol msym
= ada_lookup_simple_minsym (decoded_name.c_str (), objfile);
if (msym.minsym != NULL)
{
@@ -1857,7 +1857,9 @@ write_var_or_type (struct parser_state *par_state,
}
}
- if (!have_full_symbols () && !have_partial_symbols () && block == NULL)
+ if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space)
+ && block == NULL)
error (_("No symbol table is loaded. Use the \"file\" command."));
if (block == par_state->expression_context_block)
error (_("No definition of \"%s\" in current context."), name0.ptr);
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 46c2057..d14a556 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -201,7 +201,8 @@ static symbol_name_matcher_ftype *ada_get_symbol_name_matcher
static int symbols_are_identical_enums
(const std::vector<struct block_symbol> &syms);
-static int ada_identical_enum_types_p (struct type *type1, struct type *type2);
+static bool ada_identical_enum_types_p (struct type *type1,
+ struct type *type2);
/* The character set used for source files. */
@@ -798,7 +799,6 @@ ada_get_decoded_type (struct type *type)
const char *
ada_main_name ()
{
- struct bound_minimal_symbol msym;
static gdb::unique_xmalloc_ptr<char> main_program_name;
/* For Ada, the name of the main procedure is stored in a specific
@@ -806,7 +806,9 @@ ada_main_name ()
extract its address, and then read that string. If we didn't find
that string, then most probably the main procedure is not written
in Ada. */
- msym = lookup_minimal_symbol (ADA_MAIN_PROGRAM_SYMBOL_NAME, NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space,
+ ADA_MAIN_PROGRAM_SYMBOL_NAME);
if (msym.minsym != NULL)
{
@@ -1486,7 +1488,7 @@ ada_decode (const char *encoded, bool wrap, bool operators, bool wide)
if (i < len0 + 3
&& encoded[i] == 'N' && encoded[i+1] == '_' && encoded[i+2] == '_')
{
- /* Backtrack a bit up until we reach either the begining of
+ /* Backtrack a bit up until we reach either the beginning of
the encoded name, or "__". Make sure that we only find
digits or lowercase characters. */
const char *ptr = encoded + i - 1;
@@ -3696,9 +3698,11 @@ See set/show multiple-symbol."));
gdb_printf ("[%d] ", i + first_choice);
ada_print_symbol_signature (gdb_stdout, syms[i].symbol,
&type_print_raw_options);
- gdb_printf (_(" at %s:%d\n"),
- symtab_to_filename_for_display (symtab),
- syms[i].symbol->line ());
+ gdb_printf (_(" at %ps:%ps\n"),
+ styled_string (file_name_style.style (),
+ symtab_to_filename_for_display (symtab)),
+ styled_string (line_number_style.style (),
+ pulongest (syms[i].symbol->line ())));
}
else if (is_enumeral
&& syms[i].symbol->type ()->name () != NULL)
@@ -3717,9 +3721,10 @@ See set/show multiple-symbol."));
if (symtab != NULL)
gdb_printf (is_enumeral
- ? _(" in %s (enumeral)\n")
- : _(" at %s:?\n"),
- symtab_to_filename_for_display (symtab));
+ ? _(" in %ps (enumeral)\n")
+ : _(" at %ps:?\n"),
+ styled_string (file_name_style.style (),
+ symtab_to_filename_for_display (symtab)));
else
gdb_printf (is_enumeral
? _(" (enumeral)\n")
@@ -3812,8 +3817,6 @@ ada_resolve_enum (std::vector<struct block_symbol> &syms,
for (int i = 0; i < syms.size (); ++i)
{
struct type *type2 = ada_check_typedef (syms[i].symbol->type ());
- if (type1->num_fields () != type2->num_fields ())
- continue;
if (strcmp (type1->name (), type2->name ()) != 0)
continue;
if (ada_identical_enum_types_p (type1, type2))
@@ -4689,9 +4692,9 @@ make_array_descriptor (struct type *type, struct value *arr)
even in this case, some expensive name-based symbol searches are still
sometimes necessary - to find an XVZ variable, mostly. */
-/* Clear all entries from the symbol cache. */
+/* See ada-lang.h. */
-static void
+void
ada_clear_symbol_cache (program_space *pspace)
{
ada_pspace_data_handle.clear (pspace);
@@ -4921,10 +4924,10 @@ add_defn_to_vec (std::vector<struct block_symbol> &result,
specially: "standard__" is first stripped off, and only static and
global symbols are searched. */
-struct bound_minimal_symbol
+bound_minimal_symbol
ada_lookup_simple_minsym (const char *name, struct objfile *objfile)
{
- struct bound_minimal_symbol result;
+ bound_minimal_symbol result;
symbol_name_match_type match_type = name_match_type_from_name (name);
lookup_name_info lookup_name (name, match_type);
@@ -4964,47 +4967,44 @@ is_nondebugging_type (struct type *type)
return (name != NULL && strcmp (name, "<variable, no debug info>") == 0);
}
-/* Return nonzero if TYPE1 and TYPE2 are two enumeration types
+/* Return true if TYPE1 and TYPE2 are two enumeration types
that are deemed "identical" for practical purposes.
This function assumes that TYPE1 and TYPE2 are both TYPE_CODE_ENUM
- types and that their number of enumerals is identical (in other
- words, type1->num_fields () == type2->num_fields ()). */
+ types. */
-static int
+static bool
ada_identical_enum_types_p (struct type *type1, struct type *type2)
{
- int i;
-
/* The heuristic we use here is fairly conservative. We consider
that 2 enumerate types are identical if they have the same
number of enumerals and that all enumerals have the same
underlying value and name. */
+ if (type1->num_fields () != type2->num_fields ())
+ return false;
+
/* All enums in the type should have an identical underlying value. */
- for (i = 0; i < type1->num_fields (); i++)
+ for (int i = 0; i < type1->num_fields (); i++)
if (type1->field (i).loc_enumval () != type2->field (i).loc_enumval ())
- return 0;
+ return false;
/* All enumerals should also have the same name (modulo any numerical
suffix). */
- for (i = 0; i < type1->num_fields (); i++)
+ for (int i = 0; i < type1->num_fields (); i++)
{
const char *name_1 = type1->field (i).name ();
const char *name_2 = type2->field (i).name ();
int len_1 = strlen (name_1);
int len_2 = strlen (name_2);
- ada_remove_trailing_digits (type1->field (i).name (), &len_1);
- ada_remove_trailing_digits (type2->field (i).name (), &len_2);
- if (len_1 != len_2
- || strncmp (type1->field (i).name (),
- type2->field (i).name (),
- len_1) != 0)
- return 0;
+ ada_remove_trailing_digits (name_1, &len_1);
+ ada_remove_trailing_digits (name_2, &len_2);
+ if (len_1 != len_2 || strncmp (name_1, name_2, len_1) != 0)
+ return false;
}
- return 1;
+ return true;
}
/* Return nonzero if all the symbols in SYMS are all enumeral symbols
@@ -5049,12 +5049,6 @@ symbols_are_identical_enums (const std::vector<struct block_symbol> &syms)
if (syms[i].symbol->value_longest () != syms[0].symbol->value_longest ())
return 0;
- /* Quick check: They should all have the same number of enumerals. */
- for (i = 1; i < syms.size (); i++)
- if (syms[i].symbol->type ()->num_fields ()
- != syms[0].symbol->type ()->num_fields ())
- return 0;
-
/* All the sanity checks passed, so we might have a set of
identical enumeration types. Perform a more complete
comparison of the type of each symbol. */
@@ -5827,8 +5821,8 @@ is_name_suffix (const char *str)
/* ??? We should not modify STR directly, as we are doing below. This
is fine in this case, but may become problematic later if we find
that this alternative did not work, and want to try matching
- another one from the begining of STR. Since we modified it, we
- won't be able to find the begining of the string anymore! */
+ another one from the beginning of STR. Since we modified it, we
+ won't be able to find the beginning of the string anymore! */
if (str[0] == 'X')
{
str += 1;
@@ -10781,7 +10775,7 @@ ada_unop_atr_operation::evaluate (struct type *expect_type,
struct type *type_arg = nullptr;
value *val = nullptr;
- if (std::get<0> (m_storage)->opcode () == OP_TYPE)
+ if (std::get<0> (m_storage)->type_p ())
{
value *tem = std::get<0> (m_storage)->evaluate (nullptr, exp,
EVAL_AVOID_SIDE_EFFECTS);
@@ -11195,16 +11189,9 @@ ada_funcall_operation::evaluate (struct type *expect_type,
}
return call_function_by_hand (callee, expect_type, argvec);
case TYPE_CODE_INTERNAL_FUNCTION:
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- /* We don't know anything about what the internal
- function might return, but we have to return
- something. */
- return value::zero (builtin_type (exp->gdbarch)->builtin_int,
- not_lval);
- else
return call_internal_function (exp->gdbarch, exp->language_defn,
callee, nargs,
- argvec.data ());
+ argvec.data (), noside);
case TYPE_CODE_STRUCT:
{
@@ -11685,7 +11672,8 @@ ada_has_this_exception_support (const struct exception_support_info *einfo)
that should be compiled with debugging information. As a result, we
expect to find that symbol in the symtabs. */
- sym = standard_lookup (einfo->catch_exception_sym, NULL, SEARCH_VFT);
+ sym = standard_lookup (einfo->catch_exception_sym, NULL,
+ SEARCH_FUNCTION_DOMAIN);
if (sym == NULL)
{
/* Perhaps we did not find our symbol because the Ada runtime was
@@ -11702,8 +11690,9 @@ ada_has_this_exception_support (const struct exception_support_info *einfo)
the name of the exception being raised (this name is printed in
the catchpoint message, and is also used when trying to catch
a specific exception). We do not handle this case for now. */
- struct bound_minimal_symbol msym
- = lookup_minimal_symbol (einfo->catch_exception_sym, NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space,
+ einfo->catch_exception_sym);
if (msym.minsym && msym.minsym->type () != mst_solib_trampoline)
error (_("Your Ada runtime appears to be missing some debugging "
@@ -11719,11 +11708,13 @@ ada_has_this_exception_support (const struct exception_support_info *einfo)
error (_("Symbol \"%s\" is not a function (class = %d)"),
sym->linkage_name (), sym->aclass ());
- sym = standard_lookup (einfo->catch_handlers_sym, NULL, SEARCH_VFT);
+ sym = standard_lookup (einfo->catch_handlers_sym, NULL,
+ SEARCH_FUNCTION_DOMAIN);
if (sym == NULL)
{
- struct bound_minimal_symbol msym
- = lookup_minimal_symbol (einfo->catch_handlers_sym, NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space,
+ einfo->catch_handlers_sym);
if (msym.minsym && msym.minsym->type () != mst_solib_trampoline)
error (_("Your Ada runtime appears to be missing some debugging "
@@ -12078,11 +12069,11 @@ struct ada_catchpoint : public code_breakpoint
enable_state = enabled ? bp_enabled : bp_disabled;
language = language_ada;
- re_set ();
+ re_set (pspace);
}
struct bp_location *allocate_location () override;
- void re_set () override;
+ void re_set (program_space *pspace) override;
void check_status (struct bpstat *bs) override;
enum print_stop_action print_it (const bpstat *bs) const override;
bool print_one (const bp_location **) const override;
@@ -12127,7 +12118,7 @@ static struct symtab_and_line ada_exception_sal
catchpoint kinds. */
void
-ada_catchpoint::re_set ()
+ada_catchpoint::re_set (program_space *pspace)
{
std::vector<symtab_and_line> sals;
try
@@ -12642,7 +12633,7 @@ ada_exception_catchpoint_cond_string (const char *excep_string,
may then be set only on user-defined exceptions which have the
same not-fully-qualified name (e.g. my_package.constraint_error).
- To avoid this unexcepted behavior, these standard exceptions are
+ To avoid this unexpected behavior, these standard exceptions are
systematically prefixed by "standard". This means that "catch
exception constraint_error" is rewritten into "catch exception
standard.constraint_error".
@@ -12722,6 +12713,10 @@ create_ada_exception_catchpoint (struct gdbarch *gdbarch,
int enabled,
int from_tty)
{
+ /* This works around an obscure issue when an Ada program is
+ compiled with LTO. */
+ scoped_restore_current_language save_language (language_ada);
+
std::unique_ptr<ada_catchpoint> c
(new ada_catchpoint (gdbarch, ex_kind,
cond_string.empty () ? nullptr : cond_string.c_str (),
@@ -13056,7 +13051,12 @@ ada_add_global_exceptions (compiled_regex *preg,
},
NULL,
SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
- SEARCH_VAR_DOMAIN);
+ 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. */
@@ -13884,7 +13884,7 @@ static struct cmd_list_element *show_ada_list;
static void
ada_new_objfile_observer (struct objfile *objfile)
{
- ada_clear_symbol_cache (objfile->pspace);
+ ada_clear_symbol_cache (objfile->pspace ());
}
/* This module's 'free_objfile' observer. */
@@ -13892,7 +13892,7 @@ ada_new_objfile_observer (struct objfile *objfile)
static void
ada_free_objfile_observer (struct objfile *objfile)
{
- ada_clear_symbol_cache (objfile->pspace);
+ ada_clear_symbol_cache (objfile->pspace ());
}
/* Charsets known to GNAT. */
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index d14bfd4..050d298 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -239,8 +239,7 @@ extern struct block_symbol ada_lookup_symbol (const char *,
extern block_symbol ada_lookup_encoded_symbol
(const char *name, const struct block *block, domain_search_flags domain);
-extern struct bound_minimal_symbol ada_lookup_simple_minsym (const char *,
- objfile *);
+extern bound_minimal_symbol ada_lookup_simple_minsym (const char *, objfile *);
extern int ada_scan_number (const char *, int, LONGEST *, int *);
@@ -434,4 +433,8 @@ extern block_symbol ada_resolve_variable (struct symbol *sym,
extern struct type *ada_index_type (struct type *type, int n,
const char *name);
+/* Clear the Ada symbol cache. */
+
+extern void ada_clear_symbol_cache (program_space *pspace);
+
#endif
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index 136e6dd..3fe0c2e 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -510,7 +510,7 @@ processReal (struct parser_state *par_state, const char *num0)
encoded and the resulting name is equal to it. Similarly, if the name
starts with '<', it is copied verbatim. Otherwise, it differs
from NAME0 in that:
- + Characters between '...' are transfered verbatim to yylval.ssym.
+ + Characters between '...' are transferred verbatim to yylval.ssym.
+ Trailing "'" characters in quoted sequences are removed (a leading quote is
preserved to indicate that the name is not to be GNAT-encoded).
+ Unquoted whitespace is removed.
diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c
index 83059d7..d050b26 100644
--- a/gdb/ada-tasks.c
+++ b/gdb/ada-tasks.c
@@ -266,7 +266,7 @@ struct ada_tasks_inferior_data
reference it - this number is printed beside each task in the tasks
info listing displayed by "info tasks". This number is equal to
its index in the vector + 1. Reciprocally, to compute the index
- of a task in the vector, we need to substract 1 from its number. */
+ of a task in the vector, we need to subtract 1 from its number. */
std::vector<ada_task_info> task_list;
};
@@ -600,7 +600,7 @@ ada_get_tcb_types_info (void)
/* Check for the CPU offset. */
bound_minimal_symbol first_id_sym
- = lookup_bound_minimal_symbol ("__gnat_gdb_cpu_first_id");
+ = lookup_minimal_symbol (current_program_space, "__gnat_gdb_cpu_first_id");
unsigned int first_id = 0;
if (first_id_sym.minsym != nullptr)
{
@@ -712,9 +712,7 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info)
sizeof (task_info->name) - 1);
else
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol_by_pc (task_id);
+ bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (task_id);
if (msym.minsym)
{
const char *full_name = msym.minsym->linkage_name ();
@@ -914,7 +912,6 @@ read_known_tasks_list (struct ada_tasks_inferior_data *data)
static void
ada_tasks_inferior_data_sniffer (struct ada_tasks_inferior_data *data)
{
- struct bound_minimal_symbol msym;
struct symbol *sym;
/* Return now if already set. */
@@ -923,7 +920,8 @@ ada_tasks_inferior_data_sniffer (struct ada_tasks_inferior_data *data)
/* Try array. */
- msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, KNOWN_TASKS_NAME);
if (msym.minsym != NULL)
{
data->known_tasks_kind = ADA_TASKS_ARRAY;
@@ -970,7 +968,7 @@ ada_tasks_inferior_data_sniffer (struct ada_tasks_inferior_data *data)
/* Try list. */
- msym = lookup_minimal_symbol (KNOWN_TASKS_LIST, NULL, NULL);
+ msym = lookup_minimal_symbol (current_program_space, KNOWN_TASKS_LIST);
if (msym.minsym != NULL)
{
data->known_tasks_kind = ADA_TASKS_LIST;
@@ -1495,7 +1493,7 @@ ada_tasks_clear_pspace_data (program_space *pspace)
static void
ada_tasks_new_objfile_observer (objfile *objfile)
{
- ada_tasks_clear_pspace_data (objfile->pspace);
+ ada_tasks_clear_pspace_data (objfile->pspace ());
}
/* The qcs command line flags for the "task apply" commands. Keep
diff --git a/gdb/addrmap.c b/gdb/addrmap.c
index b9a0f77..696a7dc 100644
--- a/gdb/addrmap.c
+++ b/gdb/addrmap.c
@@ -354,7 +354,9 @@ addrmap_mutable::~addrmap_mutable ()
/* See addrmap.h. */
void
-addrmap_dump (struct addrmap *map, struct ui_file *outfile, void *payload)
+addrmap_dump (struct addrmap *map, struct ui_file *outfile, void *payload,
+ gdb::function_view<void (struct ui_file *outfile,
+ const void *value)> annotate_value)
{
/* True if the previously printed addrmap entry was for PAYLOAD.
If so, we want to print the next one as well (since the next
@@ -373,10 +375,16 @@ addrmap_dump (struct addrmap *map, struct ui_file *outfile, void *payload)
addr_str = "<ends here>";
if (matches || previous_matched)
- gdb_printf (outfile, " %s%s %s\n",
- payload != nullptr ? " " : "",
- core_addr_to_string (start_addr),
- addr_str);
+ {
+ gdb_printf (outfile, " %s%s %s",
+ payload != nullptr ? " " : "",
+ core_addr_to_string (start_addr),
+ addr_str);
+ if (annotate_value != nullptr)
+ annotate_value (outfile, obj);
+
+ gdb_printf (outfile, "\n");
+ }
previous_matched = matches;
diff --git a/gdb/addrmap.h b/gdb/addrmap.h
index 5378b75..85d4645 100644
--- a/gdb/addrmap.h
+++ b/gdb/addrmap.h
@@ -20,8 +20,9 @@
#ifndef ADDRMAP_H
#define ADDRMAP_H
-#include "splay-tree.h"
#include "gdbsupport/function-view.h"
+#include "gdbsupport/gdb_obstack.h"
+#include "splay-tree.h"
/* An address map is essentially a table mapping CORE_ADDRs onto GDB
data structures, like blocks, symtabs, partial symtabs, and so on.
@@ -218,8 +219,13 @@ private:
/* Dump the addrmap to OUTFILE. If PAYLOAD is non-NULL, only dump any
components that map to PAYLOAD. (If PAYLOAD is NULL, the entire
- map is dumped.) */
+ map is dumped.) If ANNOTATE_VALUE is non-nullptr, call it for each
+ value. */
+
void addrmap_dump (struct addrmap *map, struct ui_file *outfile,
- void *payload);
+ void *payload,
+ gdb::function_view<void (struct ui_file *outfile,
+ const void *value)>
+ annotate_value = nullptr);
#endif /* ADDRMAP_H */
diff --git a/gdb/aix-thread.c b/gdb/aix-thread.c
index f2c5605..9e6952b 100644
--- a/gdb/aix-thread.c
+++ b/gdb/aix-thread.c
@@ -376,7 +376,6 @@ pid_to_prc (ptid_t *ptidp)
static int
pdc_symbol_addrs (pthdb_user_t user_current_pid, pthdb_symbol_t *symbols, int count)
{
- struct bound_minimal_symbol ms;
int i;
char *name;
@@ -396,7 +395,8 @@ pdc_symbol_addrs (pthdb_user_t user_current_pid, pthdb_symbol_t *symbols, int co
symbols[i].addr = 0;
else
{
- ms = lookup_minimal_symbol (name, NULL, NULL);
+ bound_minimal_symbol ms
+ = lookup_minimal_symbol (current_program_space, name);
if (ms.minsym == NULL)
{
if (debug_aix_thread)
@@ -956,7 +956,6 @@ pd_enable (inferior *inf)
{
int status;
char *stub_name;
- struct bound_minimal_symbol ms;
struct aix_thread_variables *data;
if (inf == NULL)
@@ -980,7 +979,8 @@ pd_enable (inferior *inf)
return;
/* Set a breakpoint on the returned stub function. */
- ms = lookup_minimal_symbol (stub_name, NULL, NULL);
+ bound_minimal_symbol ms
+ = lookup_minimal_symbol (current_program_space, stub_name);
if (ms.minsym == NULL)
return;
data->pd_brk_addr = ms.value_address ();
diff --git a/gdb/alpha-tdep.h b/gdb/alpha-tdep.h
index 0423abb..4554ac0 100644
--- a/gdb/alpha-tdep.h
+++ b/gdb/alpha-tdep.h
@@ -99,7 +99,7 @@ struct alpha_gdbarch_tdep : gdbarch_tdep_base
int sc_fpregs_offset = 0;
int jb_pc = 0; /* Offset to PC value in jump buffer.
- If htis is negative, longjmp support
+ If this is negative, longjmp support
will be disabled. */
size_t jb_elt_size = 0; /* And the size of each entry in the buf. */
};
diff --git a/gdb/amd-dbgapi-target.c b/gdb/amd-dbgapi-target.c
index 073270f..2bb79ac 100644
--- a/gdb/amd-dbgapi-target.c
+++ b/gdb/amd-dbgapi-target.c
@@ -483,12 +483,12 @@ struct amd_dbgapi_target_breakpoint : public code_breakpoint
disposition = disp_donttouch;
}
- void re_set () override;
+ void re_set (program_space *) override;
void check_status (struct bpstat *bs) override;
};
void
-amd_dbgapi_target_breakpoint::re_set ()
+amd_dbgapi_target_breakpoint::re_set (program_space *)
{
/* Nothing. */
}
@@ -684,7 +684,7 @@ amd_dbgapi_target::resume (ptid_t scope_ptid, int step, enum gdb_signal signo)
switch (signo)
{
case GDB_SIGNAL_BUS:
- exception = AMD_DBGAPI_EXCEPTION_WAVE_APERTURE_VIOLATION;
+ exception = AMD_DBGAPI_EXCEPTION_WAVE_ADDRESS_ERROR;
break;
case GDB_SIGNAL_SEGV:
exception = AMD_DBGAPI_EXCEPTION_WAVE_MEMORY_VIOLATION;
@@ -1167,7 +1167,7 @@ process_one_event (amd_dbgapi_event_id_t event_id,
ws.set_thread_exited (0);
else if (status == AMD_DBGAPI_STATUS_SUCCESS)
{
- if (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_APERTURE_VIOLATION)
+ if (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_ADDRESS_ERROR)
ws.set_stopped (GDB_SIGNAL_BUS);
else if (stop_reason
& AMD_DBGAPI_WAVE_STOP_REASON_MEMORY_VIOLATION)
@@ -1992,19 +1992,35 @@ amd_dbgapi_inferior_pre_detach (inferior *inf)
detach_amd_dbgapi (inf);
}
-/* get_os_pid callback. */
+/* client_process_get_info callback. */
static amd_dbgapi_status_t
-amd_dbgapi_get_os_pid_callback
- (amd_dbgapi_client_process_id_t client_process_id, pid_t *pid)
+amd_dbgapi_client_process_get_info_callback
+ (amd_dbgapi_client_process_id_t client_process_id,
+ amd_dbgapi_client_process_info_t query, size_t value_size, void *value)
{
inferior *inf = reinterpret_cast<inferior *> (client_process_id);
if (inf->pid == 0)
return AMD_DBGAPI_STATUS_ERROR_PROCESS_EXITED;
- *pid = inf->pid;
- return AMD_DBGAPI_STATUS_SUCCESS;
+ if (value == nullptr)
+ return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT;
+
+ switch (query)
+ {
+ case AMD_DBGAPI_CLIENT_PROCESS_INFO_OS_PID:
+ if (value_size != sizeof (amd_dbgapi_os_process_id_t))
+ return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT_COMPATIBILITY;
+
+ *static_cast<amd_dbgapi_os_process_id_t *> (value) = inf->pid;
+ return AMD_DBGAPI_STATUS_SUCCESS;
+
+ case AMD_DBGAPI_CLIENT_PROCESS_INFO_CORE_STATE:
+ return AMD_DBGAPI_STATUS_ERROR_NOT_AVAILABLE;
+ }
+
+ return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT;
}
/* insert_breakpoint callback. */
@@ -2060,6 +2076,50 @@ amd_dbgapi_remove_breakpoint_callback
return AMD_DBGAPI_STATUS_SUCCESS;
}
+/* xfer_global_memory callback. */
+
+static amd_dbgapi_status_t
+amd_dbgapi_xfer_global_memory_callback
+ (amd_dbgapi_client_process_id_t client_process_id,
+ amd_dbgapi_global_address_t global_address,
+ amd_dbgapi_size_t *value_size, void *read_buffer,
+ const void *write_buffer)
+{
+ if ((read_buffer != nullptr) == (write_buffer != nullptr))
+ return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT_COMPATIBILITY;
+
+ inferior *inf = reinterpret_cast<inferior *> (client_process_id);
+
+ /* We need to set inferior_ptid / current_inferior as those are
+ used by the target which will process the xfer_partial request.
+
+ Note that we end up here when amd-dbgapi tries to access device memory or
+ register content which are at this point mapped/saved in the host process
+ memory. As a consequence, unwinding GPU frames will most likely call into
+ here. If we used switch_to_thread to select a host thread, this would
+ implicitly call reinit_frame_cache. We do not want to clear the frame
+ cache while trying to build it. */
+ scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
+ scoped_restore_current_inferior restore_current_inferior;
+ scoped_restore_current_program_space restore_program_space;
+ inferior_ptid = ptid_t (inf->pid);
+ set_current_inferior (inf);
+ set_current_program_space (inf->pspace);
+
+ target_xfer_status status
+ = target_xfer_partial (inf->top_target (), TARGET_OBJECT_RAW_MEMORY,
+ nullptr, static_cast<gdb_byte *> (read_buffer),
+ static_cast<const gdb_byte *> (write_buffer),
+ global_address, *value_size, value_size);
+
+ if (status == TARGET_XFER_EOF)
+ return AMD_DBGAPI_STATUS_ERROR_PROCESS_EXITED;
+ else if (status != TARGET_XFER_OK)
+ return AMD_DBGAPI_STATUS_ERROR_MEMORY_ACCESS;
+
+ return AMD_DBGAPI_STATUS_SUCCESS;
+}
+
/* signal_received observer. */
static void
@@ -2138,9 +2198,10 @@ amd_dbgapi_log_message_callback (amd_dbgapi_log_level_t level,
static amd_dbgapi_callbacks_t dbgapi_callbacks = {
.allocate_memory = malloc,
.deallocate_memory = free,
- .get_os_pid = amd_dbgapi_get_os_pid_callback,
+ .client_process_get_info = amd_dbgapi_client_process_get_info_callback,
.insert_breakpoint = amd_dbgapi_insert_breakpoint_callback,
.remove_breakpoint = amd_dbgapi_remove_breakpoint_callback,
+ .xfer_global_memory = amd_dbgapi_xfer_global_memory_callback,
.log_message = amd_dbgapi_log_message_callback,
};
diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
index aa9295d..742fc81 100644
--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -79,6 +79,8 @@ static int amd64_linux_gregset32_reg_offset[] =
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ /* MPX is deprecated. Yet we keep this to not give the registers below
+ a new number. That could break older gdbservers. */
-1, -1, -1, -1, /* MPX registers BND0 ... BND3. */
-1, -1, /* MPX registers BNDCFGU, BNDSTATUS. */
-1, -1, -1, -1, -1, -1, -1, -1, /* k0 ... k7 (AVX512) */
@@ -235,22 +237,21 @@ amd64_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
if (have_ptrace_getregset == TRIBOOL_TRUE)
{
- char xstateregs[tdep->xsave_layout.sizeof_xsave];
- struct iovec iov;
-
/* 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
xstateregs not to be copied by PTRACE_GETREGSET. Make sure that
the location is at least initialized with a defined value. */
- memset (xstateregs, 0, sizeof (xstateregs));
- iov.iov_base = xstateregs;
- iov.iov_len = sizeof (xstateregs);
+ gdb::byte_vector xstateregs (tdep->xsave_layout.sizeof_xsave, 0);
+ struct iovec iov;
+
+ iov.iov_base = xstateregs.data ();
+ iov.iov_len = xstateregs.size ();
if (ptrace (PTRACE_GETREGSET, tid,
(unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
perror_with_name (_("Couldn't get extended state status"));
- amd64_supply_xsave (regcache, -1, xstateregs);
+ amd64_supply_xsave (regcache, -1, xstateregs.data ());
}
else
{
@@ -300,16 +301,16 @@ amd64_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
if (have_ptrace_getregset == TRIBOOL_TRUE)
{
- char xstateregs[tdep->xsave_layout.sizeof_xsave];
+ gdb::byte_vector xstateregs (tdep->xsave_layout.sizeof_xsave);
struct iovec iov;
- iov.iov_base = xstateregs;
- iov.iov_len = sizeof (xstateregs);
+ iov.iov_base = xstateregs.data ();
+ iov.iov_len = xstateregs.size ();
if (ptrace (PTRACE_GETREGSET, tid,
(unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
perror_with_name (_("Couldn't get extended state status"));
- amd64_collect_xsave (regcache, regnum, xstateregs, 0);
+ amd64_collect_xsave (regcache, regnum, xstateregs.data (), 0);
if (ptrace (PTRACE_SETREGSET, tid,
(unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index d7662ca..77de821 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -86,6 +86,8 @@ int amd64_linux_gregset_reg_offset[] =
-1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ /* MPX is deprecated. Yet we keep this to not give the registers below
+ a new number. That could break older gdbservers. */
-1, -1, -1, -1, /* MPX registers BND0 ... BND3. */
-1, -1, /* MPX registers BNDCFGU and BNDSTATUS. */
-1, -1, -1, -1, -1, -1, -1, -1, /* xmm16 ... xmm31 (AVX512) */
@@ -1816,9 +1818,6 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch,
set_gdbarch_process_record (gdbarch, i386_process_record);
set_gdbarch_process_record_signal (gdbarch, amd64_linux_record_signal);
-
- set_gdbarch_get_siginfo_type (gdbarch, x86_linux_get_siginfo_type);
- set_gdbarch_report_signal_info (gdbarch, i386_linux_report_signal_info);
}
static void
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index df6b882..b63e35d 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -110,11 +110,6 @@ static const char * const amd64_ymmh_avx512_names[] =
"ymm28h", "ymm29h", "ymm30h", "ymm31h"
};
-static const char * const amd64_mpx_names[] =
-{
- "bnd0raw", "bnd1raw", "bnd2raw", "bnd3raw", "bndcfgu", "bndstatus"
-};
-
static const char * const amd64_k_names[] =
{
"k0", "k1", "k2", "k3",
@@ -1039,13 +1034,6 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[8];
- /* BND registers can be in arbitrary values at the moment of the
- inferior call. This can cause boundary violations that are not
- due to a real bug or even desired by the user. The best to be done
- is set the BND registers to allow access to the whole memory, INIT
- state, before pushing the inferior call. */
- i387_reset_bnd_regs (gdbarch, regcache);
-
/* Pass arguments. */
sp = amd64_push_arguments (regcache, nargs, args, sp, return_method);
@@ -3196,13 +3184,6 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch,
tdep->ymm0h_regnum = AMD64_YMM0H_REGNUM;
}
- if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx") != NULL)
- {
- tdep->mpx_register_names = amd64_mpx_names;
- tdep->bndcfgu_regnum = AMD64_BNDCFGU_REGNUM;
- tdep->bnd0r_regnum = AMD64_BND0R_REGNUM;
- }
-
if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments") != NULL)
{
tdep->fsbase_regnum = AMD64_FSBASE_REGNUM;
@@ -3377,11 +3358,10 @@ const struct target_desc *
amd64_target_description (uint64_t xcr0, bool segments)
{
static target_desc *amd64_tdescs \
- [2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
+ [2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
target_desc **tdesc;
tdesc = &amd64_tdescs[(xcr0 & X86_XSTATE_AVX) ? 1 : 0]
- [(xcr0 & X86_XSTATE_MPX) ? 1 : 0]
[(xcr0 & X86_XSTATE_AVX512) ? 1 : 0]
[(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]
[segments ? 1 : 0];
diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h
index 696c65b..544ed91 100644
--- a/gdb/amd64-tdep.h
+++ b/gdb/amd64-tdep.h
@@ -66,6 +66,8 @@ enum amd64_regnum
AMD64_MXCSR_REGNUM = AMD64_XMM0_REGNUM + 16,
AMD64_YMM0H_REGNUM, /* %ymm0h */
AMD64_YMM15H_REGNUM = AMD64_YMM0H_REGNUM + 15,
+ /* MPX is deprecated. Yet we keep this to not give the registers below
+ a new number. That could break older gdbservers. */
AMD64_BND0R_REGNUM = AMD64_YMM15H_REGNUM + 1,
AMD64_BND3R_REGNUM = AMD64_BND0R_REGNUM + 3,
AMD64_BNDCFGU_REGNUM,
diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index 9636201..29a1f60 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -324,7 +324,7 @@ amd64_windows_push_dummy_call
/* Pass "hidden" argument". */
if (return_method == return_method_struct)
{
- /* The "hidden" argument is passed throught the first argument
+ /* The "hidden" argument is passed through the first argument
register. */
const int arg_regnum = amd64_windows_dummy_call_integer_regs[0];
@@ -435,11 +435,10 @@ amd64_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
if (target_read_memory (pc + 1, buf, sizeof buf) == 0)
{
- struct bound_minimal_symbol s;
CORE_ADDR call_dest;
call_dest = pc + 5 + extract_signed_integer (buf, 4, byte_order);
- s = lookup_minimal_symbol_by_pc (call_dest);
+ bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest);
if (s.minsym != NULL
&& s.minsym->linkage_name () != NULL
&& strcmp (s.minsym->linkage_name (), "__main") == 0)
diff --git a/gdb/amdgpu-tdep.c b/gdb/amdgpu-tdep.c
index 49996ae..6fe7973 100644
--- a/gdb/amdgpu-tdep.c
+++ b/gdb/amdgpu-tdep.c
@@ -28,8 +28,6 @@
#include "gdbsupport/selftest.h"
#include "gdbtypes.h"
#include "inferior.h"
-#include "objfiles.h"
-#include "observable.h"
#include "producer.h"
#include "reggroups.h"
diff --git a/gdb/annotate.c b/gdb/annotate.c
index 8818029..c1d4229 100644
--- a/gdb/annotate.c
+++ b/gdb/annotate.c
@@ -457,7 +457,7 @@ annotate_source_line (struct symtab *s, int line, int mid_statement,
/* Update the current symtab and line. */
symtab_and_line sal;
- sal.pspace = s->compunit ()->objfile ()->pspace;
+ sal.pspace = s->compunit ()->objfile ()->pspace ();
sal.symtab = s;
sal.line = line;
set_current_source_symtab_and_line (sal);
diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
index 30bd40c..69980f9 100644
--- a/gdb/arc-linux-tdep.c
+++ b/gdb/arc-linux-tdep.c
@@ -428,7 +428,7 @@ arc_linux_software_single_step (struct regcache *regcache)
CORE_ADDR next_pc = arc_insn_get_linear_next_pc (curr_insn);
std::vector<CORE_ADDR> next_pcs;
- /* For instructions with delay slots, the fall thru is not the
+ /* For instructions with delay slots, the fall through is not the
instruction immediately after the current instruction, but the one
after that. */
if (curr_insn.has_delay_slot)
@@ -506,8 +506,8 @@ arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
So we look for the symbol `_dl_linux_resolver', and if we are there,
gdb sets a breakpoint at the return address, and continues. */
- struct bound_minimal_symbol resolver
- = lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);
+ bound_minimal_symbol resolver
+ = lookup_minimal_symbol (current_program_space, "_dl_linux_resolver");
if (arc_debug)
{
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 9491107..9adf295 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -861,7 +861,7 @@ arc_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, CORE_ADDR funaddr,
struct regcache *regcache)
{
*real_pc = funaddr;
- *bp_addr = entry_point_address ();
+ *bp_addr = entry_point_address (current_program_space);
return sp;
}
@@ -1438,7 +1438,7 @@ arc_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR entrypoint,
1) Store instruction for each callee-saved register (R25 - R13 + 1)
2) Two instructions for FP
3) One for BLINK
- 4) Three substract instructions for SP (for variadic args, for
+ 4) Three subtract instructions for SP (for variadic args, for
callee saved regs and for local vars) and assuming that those SUB use
long-immediate (hence double length).
5) Stores of arguments registers are considered part of prologue too
@@ -2117,7 +2117,7 @@ arc_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
return true;
}
-/* Check for the existance of "lp_start" and "lp_end" in target description.
+/* Check for the existence of "lp_start" and "lp_end" in target description.
If both are present, assume there is hardware loop support in the target.
This can be improved by looking into "lpc_size" field of "isa_config"
auxiliary register. */
diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index 83e2947..6ffa410 100644
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -37,6 +37,7 @@
#include "auxv.h"
#include "observable.h"
#include "solib-target.h"
+#include "event-top.h"
#include "gdbsupport/version.h"
@@ -56,7 +57,7 @@ displaced_step_at_entry_point (struct gdbarch *gdbarch)
CORE_ADDR addr;
int bp_len;
- addr = entry_point_address ();
+ addr = entry_point_address (current_program_space);
/* Inferior calls also use the entry point as a breakpoint location.
We don't want displaced stepping to interfere with those
@@ -404,13 +405,13 @@ set_endian (const char *ignore_args, int from_tty, struct cmd_list_element *c)
if (set_endian_string == endian_auto)
{
target_byte_order_user = BFD_ENDIAN_UNKNOWN;
- if (! gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("set_endian: architecture update failed"));
}
else if (set_endian_string == endian_little)
{
info.byte_order = BFD_ENDIAN_LITTLE;
- if (! gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
gdb_printf (gdb_stderr,
_("Little endian target not supported by GDB\n"));
else
@@ -419,7 +420,7 @@ set_endian (const char *ignore_args, int from_tty, struct cmd_list_element *c)
else if (set_endian_string == endian_big)
{
info.byte_order = BFD_ENDIAN_BIG;
- if (! gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
gdb_printf (gdb_stderr,
_("Big endian target not supported by GDB\n"));
else
@@ -561,7 +562,7 @@ set_architecture (const char *ignore_args,
if (strcmp (set_architecture_string, "auto") == 0)
{
target_architecture_user = NULL;
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("could not select an architecture automatically"));
}
else
@@ -569,7 +570,7 @@ set_architecture (const char *ignore_args,
info.bfd_arch_info = bfd_scan_arch (set_architecture_string);
if (info.bfd_arch_info == NULL)
internal_error (_("set_architecture: bfd_scan_arch failed"));
- if (gdbarch_update_p (info))
+ if (gdbarch_update_p (current_inferior (), info))
target_architecture_user = info.bfd_arch_info;
else
gdb_printf (gdb_stderr,
@@ -579,22 +580,23 @@ set_architecture (const char *ignore_args,
show_architecture (gdb_stdout, from_tty, NULL, NULL);
}
-/* Try to select a global architecture that matches "info". Return
- non-zero if the attempt succeeds. */
+/* See arch-utils.h. */
+
int
-gdbarch_update_p (struct gdbarch_info info)
+gdbarch_update_p (inferior *inf, struct gdbarch_info info)
{
struct gdbarch *new_gdbarch;
/* Check for the current file. */
if (info.abfd == NULL)
- info.abfd = current_program_space->exec_bfd ();
+ info.abfd = inf->pspace->exec_bfd ();
+
if (info.abfd == NULL)
- info.abfd = current_program_space->core_bfd ();
+ info.abfd = inf->pspace->core_bfd ();
/* Check for the current target description. */
if (info.target_desc == NULL)
- info.target_desc = target_current_description ();
+ info.target_desc = target_current_description (inf);
new_gdbarch = gdbarch_find_by_info (info);
@@ -609,7 +611,7 @@ gdbarch_update_p (struct gdbarch_info info)
/* If it is the same old architecture, accept the request (but don't
swap anything). */
- if (new_gdbarch == current_inferior ()->arch ())
+ if (new_gdbarch == inf->arch ())
{
if (gdbarch_debug)
gdb_printf (gdb_stdlog, "gdbarch_update_p: "
@@ -626,7 +628,7 @@ gdbarch_update_p (struct gdbarch_info info)
host_address_to_string (new_gdbarch),
gdbarch_bfd_arch_info (new_gdbarch)->printable_name);
- current_inferior ()->set_arch (new_gdbarch);
+ inf->set_arch (new_gdbarch);
return 1;
}
@@ -653,7 +655,7 @@ set_gdbarch_from_file (bfd *abfd)
struct gdbarch *gdbarch;
info.abfd = abfd;
- info.target_desc = target_current_description ();
+ info.target_desc = target_current_description (current_inferior ());
gdbarch = gdbarch_find_by_info (info);
if (gdbarch == NULL)
@@ -751,7 +753,7 @@ initialize_current_architecture (void)
info.byte_order = default_byte_order;
info.byte_order_for_code = info.byte_order;
- if (! gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("initialize_current_architecture: Selection of "
"initial architecture failed"));
@@ -1040,7 +1042,11 @@ default_print_insn (bfd_vma memaddr, disassemble_info *info)
info->mach, current_program_space->exec_bfd ());
gdb_assert (disassemble_fn != NULL);
- return (*disassemble_fn) (memaddr, info);
+ int res = (*disassemble_fn) (memaddr, info);
+
+ QUIT;
+
+ return res;
}
/* See arch-utils.h. */
@@ -1192,7 +1198,7 @@ pstring_list (const char *const *list)
return ret;
}
-#include "gdbarch.c"
+#include "gdbarch-gen.c"
enum return_value_convention
default_gdbarch_return_value
diff --git a/gdb/arch/aarch64-mte-linux.c b/gdb/arch/aarch64-mte-linux.c
index e0b441e..49426d7 100644
--- a/gdb/arch/aarch64-mte-linux.c
+++ b/gdb/arch/aarch64-mte-linux.c
@@ -75,59 +75,3 @@ aarch64_mte_unpack_tags (gdb::byte_vector &tags, bool skip_first)
tags = std::move (unpacked_tags);
}
-/* See arch/aarch64-mte-linux.h */
-
-size_t
-aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len, size_t granule_size)
-{
- /* An empty range has 0 tag granules. */
- if (len == 0)
- return 0;
-
- /* Start address */
- CORE_ADDR s_addr = align_down (addr, granule_size);
- /* End address */
- CORE_ADDR e_addr = align_down (addr + len - 1, granule_size);
-
- /* We always have at least 1 granule because len is non-zero at this
- point. */
- return 1 + (e_addr - s_addr) / granule_size;
-}
-
-/* See arch/aarch64-mte-linux.h */
-
-CORE_ADDR
-aarch64_mte_make_ltag_bits (CORE_ADDR value)
-{
- return value & AARCH64_MTE_LOGICAL_MAX_VALUE;
-}
-
-/* See arch/aarch64-mte-linux.h */
-
-CORE_ADDR
-aarch64_mte_make_ltag (CORE_ADDR value)
-{
- return (aarch64_mte_make_ltag_bits (value)
- << AARCH64_MTE_LOGICAL_TAG_START_BIT);
-}
-
-/* See arch/aarch64-mte-linux.h */
-
-CORE_ADDR
-aarch64_mte_set_ltag (CORE_ADDR address, CORE_ADDR tag)
-{
- /* Remove the existing tag. */
- address &= ~aarch64_mte_make_ltag (AARCH64_MTE_LOGICAL_MAX_VALUE);
-
- /* Return the new tagged address. */
- return address | aarch64_mte_make_ltag (tag);
-}
-
-/* See arch/aarch64-mte-linux.h */
-
-CORE_ADDR
-aarch64_mte_get_ltag (CORE_ADDR address)
-{
- CORE_ADDR ltag_addr = address >> AARCH64_MTE_LOGICAL_TAG_START_BIT;
- return aarch64_mte_make_ltag_bits (ltag_addr);
-}
diff --git a/gdb/arch/aarch64-mte-linux.h b/gdb/arch/aarch64-mte-linux.h
index 460b10e..686749f 100644
--- a/gdb/arch/aarch64-mte-linux.h
+++ b/gdb/arch/aarch64-mte-linux.h
@@ -29,12 +29,6 @@
/* The MTE regset consists of a single 64-bit register. */
#define AARCH64_LINUX_SIZEOF_MTE 8
-/* We have one tag per 16 bytes of memory. */
-#define AARCH64_MTE_GRANULE_SIZE 16
-#define AARCH64_MTE_TAG_BIT_SIZE 4
-#define AARCH64_MTE_LOGICAL_TAG_START_BIT 56
-#define AARCH64_MTE_LOGICAL_MAX_VALUE 0xf
-
/* Memory tagging definitions. */
#ifndef SEGV_MTEAERR
# define SEGV_MTEAERR 8
@@ -50,27 +44,6 @@ enum class aarch64_memtag_type
mte_allocation
};
-/* Return the number of tag granules in the memory range
- [ADDR, ADDR + LEN) given GRANULE_SIZE. */
-extern size_t aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len,
- size_t granule_size);
-
-/* Return the 4-bit tag made from VALUE. */
-extern CORE_ADDR aarch64_mte_make_ltag_bits (CORE_ADDR value);
-
-/* Return the 4-bit tag that can be OR-ed to an address. */
-extern CORE_ADDR aarch64_mte_make_ltag (CORE_ADDR value);
-
-/* Helper to set the logical TAG for a 64-bit ADDRESS.
-
- It is always possible to set the logical tag. */
-extern CORE_ADDR aarch64_mte_set_ltag (CORE_ADDR address, CORE_ADDR tag);
-
-/* Helper to get the logical tag from a 64-bit ADDRESS.
-
- It is always possible to get the logical tag. */
-extern CORE_ADDR aarch64_mte_get_ltag (CORE_ADDR address);
-
/* Given a TAGS vector containing 1 MTE tag per byte, pack the data as
2 tags per byte and resize the vector. */
extern void aarch64_mte_pack_tags (gdb::byte_vector &tags);
diff --git a/gdb/arch/aarch64-mte.c b/gdb/arch/aarch64-mte.c
new file mode 100644
index 0000000..908e12c
--- /dev/null
+++ b/gdb/arch/aarch64-mte.c
@@ -0,0 +1,77 @@
+/* Common AArch64 functionality for MTE
+
+ Copyright (C) 2021-2024 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 "arch/aarch64-mte.h"
+
+/* See arch/aarch64-mte.h */
+
+size_t
+aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len, size_t granule_size)
+{
+ /* An empty range has 0 tag granules. */
+ if (len == 0)
+ return 0;
+
+ /* Start address */
+ CORE_ADDR s_addr = align_down (addr, granule_size);
+ /* End address */
+ CORE_ADDR e_addr = align_down (addr + len - 1, granule_size);
+
+ /* We always have at least 1 granule because len is non-zero at this
+ point. */
+ return 1 + (e_addr - s_addr) / granule_size;
+}
+
+/* See arch/aarch64-mte.h */
+
+CORE_ADDR
+aarch64_mte_make_ltag_bits (CORE_ADDR value)
+{
+ return value & AARCH64_MTE_LOGICAL_MAX_VALUE;
+}
+
+/* See arch/aarch64-mte.h */
+
+CORE_ADDR
+aarch64_mte_make_ltag (CORE_ADDR value)
+{
+ return (aarch64_mte_make_ltag_bits (value)
+ << AARCH64_MTE_LOGICAL_TAG_START_BIT);
+}
+
+/* See arch/aarch64-mte.h */
+
+CORE_ADDR
+aarch64_mte_set_ltag (CORE_ADDR address, CORE_ADDR tag)
+{
+ /* Remove the existing tag. */
+ address &= ~aarch64_mte_make_ltag (AARCH64_MTE_LOGICAL_MAX_VALUE);
+
+ /* Return the new tagged address. */
+ return address | aarch64_mte_make_ltag (tag);
+}
+
+/* See arch/aarch64-mte.h */
+
+CORE_ADDR
+aarch64_mte_get_ltag (CORE_ADDR address)
+{
+ CORE_ADDR ltag_addr = address >> AARCH64_MTE_LOGICAL_TAG_START_BIT;
+ return aarch64_mte_make_ltag_bits (ltag_addr);
+}
diff --git a/gdb/arch/aarch64-mte.h b/gdb/arch/aarch64-mte.h
new file mode 100644
index 0000000..7d8445e
--- /dev/null
+++ b/gdb/arch/aarch64-mte.h
@@ -0,0 +1,51 @@
+/* Common AArch64 definitions for MTE
+
+ Copyright (C) 2021-2024 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 ARCH_AARCH64_MTE_H
+#define ARCH_AARCH64_MTE_H
+
+
+/* We have one tag per 16 bytes of memory. */
+#define AARCH64_MTE_GRANULE_SIZE 16
+#define AARCH64_MTE_TAG_BIT_SIZE 4
+#define AARCH64_MTE_LOGICAL_TAG_START_BIT 56
+#define AARCH64_MTE_LOGICAL_MAX_VALUE 0xf
+
+/* Return the number of tag granules in the memory range
+ [ADDR, ADDR + LEN) given GRANULE_SIZE. */
+extern size_t aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len,
+ size_t granule_size);
+
+/* Return the 4-bit tag made from VALUE. */
+extern CORE_ADDR aarch64_mte_make_ltag_bits (CORE_ADDR value);
+
+/* Return the 4-bit tag that can be OR-ed to an address. */
+extern CORE_ADDR aarch64_mte_make_ltag (CORE_ADDR value);
+
+/* Helper to set the logical TAG for a 64-bit ADDRESS.
+
+ It is always possible to set the logical tag. */
+extern CORE_ADDR aarch64_mte_set_ltag (CORE_ADDR address, CORE_ADDR tag);
+
+/* Helper to get the logical tag from a 64-bit ADDRESS.
+
+ It is always possible to get the logical tag. */
+extern CORE_ADDR aarch64_mte_get_ltag (CORE_ADDR address);
+
+#endif /* ARCH_AARCH64_MTE_H */
diff --git a/gdb/arch/amd64.c b/gdb/arch/amd64.c
index 94d55d7..5fc9947 100644
--- a/gdb/arch/amd64.c
+++ b/gdb/arch/amd64.c
@@ -17,13 +17,13 @@
#include "amd64.h"
#include "gdbsupport/x86-xstate.h"
+#include "gdbsupport/osabi.h"
#include <stdlib.h>
#include "../features/i386/64bit-avx.c"
#include "../features/i386/64bit-avx512.c"
#include "../features/i386/64bit-core.c"
#include "../features/i386/64bit-linux.c"
-#include "../features/i386/64bit-mpx.c"
#include "../features/i386/64bit-segments.c"
#include "../features/i386/64bit-sse.c"
#include "../features/i386/pkeys.c"
@@ -46,7 +46,7 @@ amd64_create_target_description (uint64_t xcr0, bool is_x32, bool is_linux,
is_x32 ? "i386:x64-32" : "i386:x86-64");
if (is_linux)
- set_tdesc_osabi (tdesc.get (), "GNU/Linux");
+ set_tdesc_osabi (tdesc.get (), GDB_OSABI_LINUX);
#endif
long regnum = 0;
@@ -65,13 +65,6 @@ amd64_create_target_description (uint64_t xcr0, bool is_x32, bool is_linux,
if (xcr0 & X86_XSTATE_AVX)
regnum = create_feature_i386_64bit_avx (tdesc.get (), regnum);
- if (xcr0 & X86_XSTATE_MPX)
- {
- /* MPX is not available on x32. */
- gdb_assert (!is_x32);
- regnum = create_feature_i386_64bit_mpx (tdesc.get (), regnum);
- }
-
if (xcr0 & X86_XSTATE_AVX512)
regnum = create_feature_i386_64bit_avx512 (tdesc.get (), regnum);
diff --git a/gdb/arch/i386.c b/gdb/arch/i386.c
index f3165c5..2072eae 100644
--- a/gdb/arch/i386.c
+++ b/gdb/arch/i386.c
@@ -18,6 +18,7 @@
#include "i386.h"
#include "gdbsupport/tdesc.h"
#include "gdbsupport/x86-xstate.h"
+#include "gdbsupport/osabi.h"
#include <stdlib.h>
#include "../features/i386/32bit-core.c"
@@ -25,7 +26,6 @@
#include "../features/i386/32bit-sse.c"
#include "../features/i386/32bit-avx.c"
#include "../features/i386/32bit-avx512.c"
-#include "../features/i386/32bit-mpx.c"
#include "../features/i386/32bit-segments.c"
#include "../features/i386/pkeys.c"
@@ -39,7 +39,7 @@ i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
#ifndef IN_PROCESS_AGENT
set_tdesc_architecture (tdesc.get (), "i386");
if (is_linux)
- set_tdesc_osabi (tdesc.get (), "GNU/Linux");
+ set_tdesc_osabi (tdesc.get (), GDB_OSABI_LINUX);
#endif
long regnum = 0;
@@ -59,9 +59,6 @@ i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
if (xcr0 & X86_XSTATE_AVX)
regnum = create_feature_i386_32bit_avx (tdesc.get (), regnum);
- if (xcr0 & X86_XSTATE_MPX)
- regnum = create_feature_i386_32bit_mpx (tdesc.get (), regnum);
-
if (xcr0 & X86_XSTATE_AVX512)
regnum = create_feature_i386_32bit_avx512 (tdesc.get (), regnum);
diff --git a/gdb/arch/tic6x.c b/gdb/arch/tic6x.c
index 680a794..b8a722b 100644
--- a/gdb/arch/tic6x.c
+++ b/gdb/arch/tic6x.c
@@ -16,6 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "gdbsupport/tdesc.h"
+#include "gdbsupport/osabi.h"
#include "tic6x.h"
#include "../features/tic6x-core.c"
@@ -30,7 +31,7 @@ tic6x_create_target_description (enum c6x_feature feature)
target_desc_up tdesc = allocate_target_description ();
set_tdesc_architecture (tdesc.get (), "tic6x");
- set_tdesc_osabi (tdesc.get (), "GNU/Linux");
+ set_tdesc_osabi (tdesc.get (), GDB_OSABI_LINUX);
long regnum = 0;
diff --git a/gdb/arch/x86-linux-tdesc-features.c b/gdb/arch/x86-linux-tdesc-features.c
index ad1d919..f6eb112 100644
--- a/gdb/arch/x86-linux-tdesc-features.c
+++ b/gdb/arch/x86-linux-tdesc-features.c
@@ -65,7 +65,6 @@ static constexpr x86_xstate_feature x86_linux_all_xstate_features[] = {
{ X86_XSTATE_PKRU, true, true, true },
{ X86_XSTATE_AVX512, true, true, true },
{ X86_XSTATE_AVX, true, true, true },
- { X86_XSTATE_MPX, true, true, false },
{ X86_XSTATE_SSE, true, false, false },
{ X86_XSTATE_X87, true, false, false }
};
@@ -150,9 +149,9 @@ x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0)
the target descriptions (see nat/x86-linux-tdesc.c), the feature order
represents the bit order within the generated index number.
- i386 | x87 sse mpx avx avx512 pkru
- amd64 | mpx avx avx512 pkru
- i32 | avx avx512 pkru
+ i386 | x87 sse avx avx512 pkru
+ amd64 | avx avx512 pkru
+ i32 | avx avx512 pkru
The features are ordered so that for each mode (i386, amd64, i32) the
generated index will form a continuous range. */
diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
index ac53bed..7b4faac 100644
--- a/gdb/arm-linux-nat.c
+++ b/gdb/arm-linux-nat.c
@@ -876,6 +876,14 @@ arm_hwbp_control_is_enabled (arm_hwbp_control_t control)
return control & 0x1;
}
+/* Is the breakpoint control value CONTROL initialized? */
+
+static int
+arm_hwbp_control_is_initialized (arm_hwbp_control_t control)
+{
+ return control != 0;
+}
+
/* Change a breakpoint control word so that it is in the disabled state. */
static arm_hwbp_control_t
arm_hwbp_control_disable (arm_hwbp_control_t control)
@@ -1234,6 +1242,34 @@ arm_linux_nat_target::low_delete_thread (struct arch_lwp_info *arch_lwp)
xfree (arch_lwp);
}
+/* For PID, set the address register of hardware breakpoint pair I to
+ ADDRESS. */
+
+static void
+sethbpregs_hwbp_address (int pid, int i, unsigned int address)
+{
+ PTRACE_TYPE_ARG3 address_reg = (PTRACE_TYPE_ARG3) ((i << 1) + 1);
+
+ errno = 0;
+
+ if (ptrace (PTRACE_SETHBPREGS, pid, address_reg, &address) < 0)
+ perror_with_name (_("Unexpected error updating breakpoint address"));
+}
+
+/* For PID, set the control register of hardware breakpoint pair I to
+ CONTROL. */
+
+static void
+sethbpregs_hwbp_control (int pid, int i, arm_hwbp_control_t control)
+{
+ PTRACE_TYPE_ARG3 control_reg = (PTRACE_TYPE_ARG3) ((i << 1) + 2);
+
+ errno = 0;
+
+ if (ptrace (PTRACE_SETHBPREGS, pid, control_reg, &control) < 0)
+ perror_with_name (_("Unexpected error setting breakpoint control"));
+}
+
/* Called when resuming a thread.
The hardware debug registers are updated when there is any change. */
@@ -1257,16 +1293,58 @@ arm_linux_nat_target::low_prepare_to_resume (struct lwp_info *lwp)
for (i = 0; i < arm_linux_get_hw_breakpoint_count (); i++)
if (arm_lwp_info->bpts_changed[i])
{
- errno = 0;
- if (arm_hwbp_control_is_enabled (bpts[i].control))
- if (ptrace (PTRACE_SETHBPREGS, pid,
- (PTRACE_TYPE_ARG3) ((i << 1) + 1), &bpts[i].address) < 0)
- perror_with_name (_("Unexpected error setting breakpoint"));
-
- if (bpts[i].control != 0)
- if (ptrace (PTRACE_SETHBPREGS, pid,
- (PTRACE_TYPE_ARG3) ((i << 1) + 2), &bpts[i].control) < 0)
- perror_with_name (_("Unexpected error setting breakpoint"));
+ unsigned int address = bpts[i].address;
+ arm_hwbp_control_t control = bpts[i].control;
+
+ if (!arm_hwbp_control_is_initialized (control))
+ {
+ /* Nothing to do. */
+ }
+ else if (!arm_hwbp_control_is_enabled (control))
+ {
+ /* Disable hardware breakpoint, just write the control
+ register. */
+ sethbpregs_hwbp_control (pid, i, control);
+ }
+ else
+ {
+ /* We used to do here simply:
+ 1. address_reg = address
+ 2. control_reg = control
+ but the write to address_reg can fail for thumb2 instructions if
+ the address is not 4-byte aligned.
+
+ It's not clear whether this is a kernel bug or not, partly
+ because PTRACE_SETHBPREGS is undocumented.
+
+ The context is that we're using two ptrace calls to set the two
+ halves of a register pair. For each ptrace call, the kernel must
+ check the arguments, and return -1 and set errno appropriately if
+ something is wrong. One of the aspects that needs validation is
+ whether, in terms of hw_breakpoint_arch_parse, the breakpoint
+ address matches the breakpoint length. This aspect can only be
+ checked by looking in both registers, which only makes sense
+ once a pair is written in full.
+
+ The problem is that the kernel checks this aspect after each
+ ptrace call, and consequently for the first call it may be
+ checking this aspect using a default or previous value for the
+ part of the pair not written by the call. A possible fix for
+ this would be to only check this aspect when writing the
+ control reg.
+
+ Work around this by first using an inoffensive address, which is
+ guaranteed to hit the offset == 0 case in
+ hw_breakpoint_arch_parse. */
+ unsigned int aligned_address = address & ~0x7U;
+ if (aligned_address != address)
+ {
+ sethbpregs_hwbp_address (pid, i, aligned_address);
+ sethbpregs_hwbp_control (pid, i, control);
+ }
+ sethbpregs_hwbp_address (pid, i, address);
+ sethbpregs_hwbp_control (pid, i, control);
+ }
arm_lwp_info->bpts_changed[i] = 0;
}
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index f36ce63..9c996b8 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -712,7 +712,6 @@ arm_find_mapping_symbol (CORE_ADDR memaddr, CORE_ADDR *start)
int
arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
{
- struct bound_minimal_symbol sym;
char type;
arm_displaced_step_copy_insn_closure *dsc = nullptr;
arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
@@ -752,7 +751,7 @@ arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
return type == 't';
/* Thumb functions have a "special" bit set in minimal symbols. */
- sym = lookup_minimal_symbol_by_pc (memaddr);
+ bound_minimal_symbol sym = lookup_minimal_symbol_by_pc (memaddr);
if (sym.minsym)
return (MSYMBOL_IS_SPECIAL (sym.minsym));
@@ -913,9 +912,8 @@ static int
skip_prologue_function (struct gdbarch *gdbarch, CORE_ADDR pc, int is_thumb)
{
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
- struct bound_minimal_symbol msym;
- msym = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (pc);
if (msym.minsym != NULL
&& msym.value_address () == pc
&& msym.minsym->linkage_name () != NULL)
@@ -1684,7 +1682,6 @@ arm_skip_stack_protector(CORE_ADDR pc, struct gdbarch *gdbarch)
{
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
unsigned int basereg;
- struct bound_minimal_symbol stack_chk_guard;
int offset;
int is_thumb = arm_pc_is_thumb (gdbarch, pc);
CORE_ADDR addr;
@@ -1695,7 +1692,7 @@ arm_skip_stack_protector(CORE_ADDR pc, struct gdbarch *gdbarch)
if (!addr)
return pc;
- stack_chk_guard = lookup_minimal_symbol_by_pc (addr);
+ bound_minimal_symbol stack_chk_guard = lookup_minimal_symbol_by_pc (addr);
/* ADDR must correspond to a symbol whose name is __stack_chk_guard.
Otherwise, this sequence cannot be for stack protector. */
if (stack_chk_guard.minsym == NULL
@@ -4860,7 +4857,7 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
si = pop_stack_item (si);
}
- /* Finally, update teh SP register. */
+ /* Finally, update the SP register. */
regcache_cooked_write_unsigned (regcache, ARM_SP_REGNUM, sp);
return sp;
@@ -9391,9 +9388,8 @@ arm_skip_cmse_entry (CORE_ADDR pc, const char *name, struct objfile *objfile)
char *target_name = (char *) alloca (target_len);
xsnprintf (target_name, target_len, "%s%s", "__acle_se_", name);
- struct bound_minimal_symbol minsym
- = lookup_minimal_symbol (target_name, NULL, objfile);
-
+ bound_minimal_symbol minsym
+ = lookup_minimal_symbol (current_program_space, target_name, objfile);
if (minsym.minsym != nullptr)
return minsym.value_address ();
@@ -9467,7 +9463,6 @@ arm_skip_stub (const frame_info_ptr &frame, CORE_ADDR pc)
{
char *target_name;
int target_len = namelen - 2;
- struct bound_minimal_symbol minsym;
struct objfile *objfile;
struct obj_section *sec;
@@ -9482,7 +9477,8 @@ arm_skip_stub (const frame_info_ptr &frame, CORE_ADDR pc)
sec = find_pc_section (pc);
objfile = (sec == NULL) ? NULL : sec->objfile;
- minsym = lookup_minimal_symbol (target_name, NULL, objfile);
+ bound_minimal_symbol minsym
+ = lookup_minimal_symbol (current_program_space, target_name, objfile);
if (minsym.minsym != NULL)
return minsym.value_address ();
else
@@ -9508,7 +9504,7 @@ arm_update_current_architecture (void)
/* Update the architecture. */
gdbarch_info info;
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("could not update architecture"));
}
@@ -12143,7 +12139,7 @@ arm_record_ld_st_imm_offset (arm_insn_decode_record *arm_insn_r)
record_buf[arm_insn_r->reg_rec_count++] = reg_dest;
/* The LDR instruction is capable of doing branching. If MOV LR, PC
- preceeds a LDR instruction having R15 as reg_base, it
+ precedes a LDR instruction having R15 as reg_base, it
emulates a branch and link instruction, and hence we need to save
CPSR and PC as well. */
if (ARM_PC_REGNUM == reg_dest)
@@ -12267,7 +12263,7 @@ arm_record_ld_st_reg_offset (arm_insn_decode_record *arm_insn_r)
if (15 == reg_src2)
{
/* If R15 was used as Rn, hence current PC+8. */
- /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ /* Pre-indexed mode doesn't reach here ; illegal insn. */
u_regval[0] = u_regval[0] + 8;
}
/* Calculate target store address, Rn +/- Rm, register offset. */
@@ -12580,7 +12576,7 @@ arm_record_b_bl (arm_insn_decode_record *arm_insn_r)
/* Handle B, BL, BLX(1) insns. */
/* B simply branches so we do nothing here. */
- /* Note: BLX(1) doesnt fall here but instead it falls into
+ /* Note: BLX(1) doesn't fall here but instead it falls into
extension space. */
if (bit (arm_insn_r->arm_insn, 24))
{
diff --git a/gdb/arm-wince-tdep.c b/gdb/arm-wince-tdep.c
index eab496c..403795f 100644
--- a/gdb/arm-wince-tdep.c
+++ b/gdb/arm-wince-tdep.c
@@ -40,7 +40,6 @@ arm_pe_skip_trampoline_code (const frame_info_ptr &frame, CORE_ADDR pc)
struct gdbarch *gdbarch = get_frame_arch (frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
ULONGEST indirect;
- struct bound_minimal_symbol indsym;
const char *symname;
CORE_ADDR next_pc;
@@ -61,7 +60,7 @@ arm_pe_skip_trampoline_code (const frame_info_ptr &frame, CORE_ADDR pc)
if (indirect == 0)
return 0;
- indsym = lookup_minimal_symbol_by_pc (indirect);
+ bound_minimal_symbol indsym = lookup_minimal_symbol_by_pc (indirect);
if (indsym.minsym == NULL)
return 0;
@@ -100,7 +99,7 @@ arm_wince_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
long offset = sign_extend (this_instr & 0x000fffff, 23) << 2;
CORE_ADDR call_dest = (pc + 8 + offset) & 0xffffffffU;
- struct bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest);
+ bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest);
if (s.minsym != NULL
&& s.minsym->linkage_name () != NULL
diff --git a/gdb/auto-load.c b/gdb/auto-load.c
index afc98eb..e753333 100644
--- a/gdb/auto-load.c
+++ b/gdb/auto-load.c
@@ -783,7 +783,7 @@ auto_load_objfile_script_1 (struct objfile *objfile, const char *realname,
/* Add this script to the hash table too so
"info auto-load ${lang}-scripts" can print it. */
pspace_info
- = get_auto_load_pspace_data_for_loading (objfile->pspace);
+ = get_auto_load_pspace_data_for_loading (objfile->pspace ());
maybe_add_script_file (pspace_info, is_safe, debugfile, debugfile,
language);
@@ -1048,7 +1048,7 @@ source_section_scripts (struct objfile *objfile, const char *section_name,
const char *start, const char *end)
{
auto_load_pspace_info *pspace_info
- = get_auto_load_pspace_data_for_loading (objfile->pspace);
+ = get_auto_load_pspace_data_for_loading (objfile->pspace ());
for (const char *p = start; p < end; ++p)
{
@@ -1629,7 +1629,7 @@ This option has security implications for untrusted inferiors."),
See the commands 'set auto-load safe-path' and 'show auto-load safe-path' to\n\
access the current full list setting."),
&cmdlist);
- set_cmd_completer (cmd, filename_completer);
+ set_cmd_completer (cmd, deprecated_filename_completer);
cmd = add_cmd ("add-auto-load-scripts-directory", class_support,
add_auto_load_dir,
@@ -1638,7 +1638,7 @@ access the current full list setting."),
See the commands 'set auto-load scripts-directory' and\n\
'show auto-load scripts-directory' to access the current full list setting."),
&cmdlist);
- set_cmd_completer (cmd, filename_completer);
+ set_cmd_completer (cmd, deprecated_filename_completer);
add_setshow_boolean_cmd ("auto-load", class_maintenance,
&debug_auto_load, _("\
diff --git a/gdb/auxv.c b/gdb/auxv.c
index 616564c..c831b2b 100644
--- a/gdb/auxv.c
+++ b/gdb/auxv.c
@@ -81,7 +81,6 @@ ld_so_xfer_auxv (gdb_byte *readbuf,
ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
{
- struct bound_minimal_symbol msym;
CORE_ADDR data_address, pointer_address;
gdbarch *arch = current_inferior ()->arch ();
type *ptr_type = builtin_type (arch)->builtin_data_ptr;
@@ -91,7 +90,8 @@ ld_so_xfer_auxv (gdb_byte *readbuf,
LONGEST retval;
size_t block;
- msym = lookup_minimal_symbol ("_dl_auxv", NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, "_dl_auxv");
if (msym.minsym == NULL)
return TARGET_XFER_E_IO;
@@ -328,7 +328,7 @@ parse_auxv (target_ops *ops, gdbarch *gdbarch, const gdb_byte **readptr,
/* Auxiliary Vector information structure. This is used by GDB
for caching purposes for each inferior. This helps reduce the
- overhead of transfering data from a remote target to the local host. */
+ overhead of transferring data from a remote target to the local host. */
struct auxv_info
{
std::optional<gdb::byte_vector> data;
diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c
index 1e39f85..9c97d3c 100644
--- a/gdb/avr-tdep.c
+++ b/gdb/avr-tdep.c
@@ -530,7 +530,6 @@ avr_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR pc_beg, CORE_ADDR pc_end,
int i;
unsigned short insn;
int scan_stage = 0;
- struct bound_minimal_symbol msymbol;
unsigned char prologue[AVR_MAX_PROLOGUE_SIZE];
int vpc = 0;
int len;
@@ -623,7 +622,8 @@ avr_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR pc_beg, CORE_ADDR pc_end,
body_addr |= ((insn & 0xf) | ((insn & 0x0f00) >> 4)) << 8;
pc_offset += 2;
- msymbol = lookup_minimal_symbol ("__prologue_saves__", NULL, NULL);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space, "__prologue_saves__");
if (!msymbol.minsym)
break;
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index ab5e800..3d61901 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -598,9 +598,9 @@ gen_var_ref (struct agent_expr *ax, struct axs_value *value, struct symbol *var)
case LOC_UNRESOLVED:
{
- struct bound_minimal_symbol msym
- = lookup_minimal_symbol (var->linkage_name (), NULL, NULL);
-
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space,
+ var->linkage_name ());
if (!msym.minsym)
error (_("Couldn't resolve symbol `%s'."), var->print_name ());
diff --git a/gdb/bfin-tdep.c b/gdb/bfin-tdep.c
index b89b7df..1fa7a66 100644
--- a/gdb/bfin-tdep.c
+++ b/gdb/bfin-tdep.c
@@ -465,7 +465,7 @@ bfin_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
/* TODO:
Dwarf2 uses entry point value AFTER some register initializations.
- We should perhaps skip such asssignments as well (R6 = R1, ...). */
+ We should perhaps skip such assignments as well (R6 = R1, ...). */
return pc;
}
diff --git a/gdb/block.c b/gdb/block.c
index 511689c..6f60877 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -25,6 +25,8 @@
#include "addrmap.h"
#include "gdbtypes.h"
#include "objfiles.h"
+#include "cli/cli-cmds.h"
+#include "inferior.h"
/* This is used by struct block to store namespace-related info for
C++ files, namely using declarations and the current namespace in
@@ -41,13 +43,10 @@ struct block_namespace_info : public allocate_on_obstack<block_namespace_info>
struct objfile *
block::objfile () const
{
- const struct global_block *global_block;
-
if (function () != nullptr)
return function ()->objfile ();
- global_block = (struct global_block *) this->global_block ();
- return global_block->compunit_symtab->objfile ();
+ return this->global_block ()->compunit ()->objfile ();
}
/* See block. */
@@ -227,7 +226,7 @@ call_site_for_pc (struct gdbarch *gdbarch, CORE_ADDR pc)
if (cs == nullptr)
{
- struct bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (pc);
/* DW_TAG_gnu_call_site will be missing just if GCC could not determine
the call target. */
@@ -364,7 +363,7 @@ block::static_block () const
/* See block.h. */
-const struct block *
+const struct global_block *
block::global_block () const
{
const block *block = this;
@@ -372,33 +371,40 @@ block::global_block () const
while (block->superblock () != NULL)
block = block->superblock ();
- return block;
+ return block->as_global_block ();
}
/* See block.h. */
-const struct block *
-block::function_block () const
+struct global_block *
+block::as_global_block ()
{
- const block *block = this;
+ gdb_assert (this->is_global_block ());
- while (block != nullptr && block->function () == nullptr)
- block = block->superblock ();
+ return static_cast<struct global_block *>(this);
+}
- return block;
+/* See block.h. */
+
+const struct global_block *
+block::as_global_block () const
+{
+ gdb_assert (this->is_global_block ());
+
+ return static_cast<const struct global_block *>(this);
}
/* See block.h. */
-void
-block::set_compunit_symtab (struct compunit_symtab *cu)
+const struct block *
+block::function_block () const
{
- struct global_block *gb;
+ const block *block = this;
+
+ while (block != nullptr && block->function () == nullptr)
+ block = block->superblock ();
- gdb_assert (superblock () == NULL);
- gb = (struct global_block *) this;
- gdb_assert (gb->compunit_symtab == NULL);
- gb->compunit_symtab = cu;
+ return block;
}
/* See block.h. */
@@ -416,21 +422,6 @@ block::static_link () const
return (struct dynamic_prop *) objfile_lookup_static_link (objfile, this);
}
-/* Return the compunit of the global block. */
-
-static struct compunit_symtab *
-get_block_compunit_symtab (const struct block *block)
-{
- struct global_block *gb;
-
- gdb_assert (block->superblock () == NULL);
- gb = (struct global_block *) block;
- gdb_assert (gb->compunit_symtab != NULL);
- return gb->compunit_symtab;
-}
-
-
-
/* Initialize a block iterator, either to iterate over a single block,
or, for static and global blocks, all the included symtabs as
well. */
@@ -438,33 +429,29 @@ get_block_compunit_symtab (const struct block *block)
static void
initialize_block_iterator (const struct block *block,
struct block_iterator *iter,
- const lookup_name_info *name = nullptr)
+ const lookup_name_info *name)
{
enum block_enum which;
- struct compunit_symtab *cu;
iter->idx = -1;
iter->name = name;
- if (block->superblock () == NULL)
- {
- which = GLOBAL_BLOCK;
- cu = get_block_compunit_symtab (block);
- }
- else if (block->superblock ()->superblock () == NULL)
- {
- which = STATIC_BLOCK;
- cu = get_block_compunit_symtab (block->superblock ());
- }
+ if (block->is_global_block ())
+ which = GLOBAL_BLOCK;
+ else if (block->is_static_block ())
+ which = STATIC_BLOCK;
else
{
iter->d.block = block;
+
/* A signal value meaning that we're iterating over a single
block. */
iter->which = FIRST_LOCAL_BLOCK;
return;
}
+ compunit_symtab *cu = block->global_block ()->compunit ();
+
/* If this is an included symtab, find the canonical includer and
use it instead. */
while (cu->user != NULL)
@@ -834,3 +821,124 @@ make_blockranges (struct objfile *objfile,
return blr;
}
+/* Implement 'maint info blocks' command. If passed an argument then
+ print a list of all blocks at the given address. With no arguments
+ then list all blocks at the current address of the current inferior. */
+
+static void
+maintenance_info_blocks (const char *arg, int from_tty)
+{
+ CORE_ADDR address;
+
+ /* With no argument use the program counter of the current thread. If
+ there is an argument then use this as the address to examine. */
+ if (arg == nullptr)
+ {
+ if (inferior_ptid == null_ptid)
+ error (_("no inferior thread"));
+
+ struct regcache *regcache = get_thread_regcache (inferior_thread ());
+ address = regcache_read_pc (regcache);
+ }
+ else
+ address = parse_and_eval_address (arg);
+
+ /* Find the inner most block for ADDRESS. */
+ const struct block *cur_block = block_for_pc (address);
+ if (cur_block == nullptr)
+ {
+ gdb_printf (_("No blocks at %s\n"), core_addr_to_string_nz (address));
+ return;
+ }
+
+ gdb_printf (_("Blocks at %s:\n"), core_addr_to_string_nz (address));
+
+ const struct objfile *toplevel_objfile = cur_block->objfile ();
+ if (toplevel_objfile != nullptr)
+ gdb_printf (_(" from objfile: [(objfile *) %s] %s\n"),
+ host_address_to_string (toplevel_objfile),
+ objfile_name (toplevel_objfile));
+
+ gdb_printf ("\n");
+
+ /* List the blocks backwards; global block (widest scope) first, down to
+ the smallest scoped block last. To do this we need to build the list
+ of blocks starting from the inner block, then print that list
+ backwards. */
+ std::vector<const struct block *> blocks;
+ while (cur_block != nullptr)
+ {
+ blocks.emplace_back (cur_block);
+ cur_block = cur_block->superblock ();
+ }
+
+ for (auto it = blocks.rbegin (); it != blocks.rend (); ++it)
+ {
+ cur_block = *it;
+
+ gdb_assert (cur_block->objfile () == toplevel_objfile);
+
+ gdb_printf (_("[(block *) %s] %s..%s\n"),
+ host_address_to_string (cur_block),
+ core_addr_to_string_nz (cur_block->start ()),
+ core_addr_to_string_nz (cur_block->end ()));
+ gdb_printf (_(" entry pc: %s\n"),
+ core_addr_to_string_nz (cur_block->entry_pc ()));
+
+ if (cur_block->is_static_block ())
+ gdb_printf (_(" is static block\n"));
+
+ if (cur_block->is_global_block ())
+ gdb_printf (_(" is global block\n"));
+
+ if (cur_block->function () != nullptr)
+ {
+ if (cur_block->inlined_p ())
+ gdb_printf (_(" inline function: %s\n"),
+ cur_block->function ()->print_name ());
+ else
+ gdb_printf (_(" function: %s\n"),
+ cur_block->function ()->print_name ());
+ }
+
+ if (cur_block->scope () != nullptr
+ && *cur_block->scope () != '\0')
+ gdb_printf (_(" scope: %s\n"), cur_block->scope ());
+
+ if (int symbol_count = mdict_size (cur_block->multidict ());
+ symbol_count > 0)
+ gdb_printf (_(" symbol count: %d\n"), symbol_count);
+
+ if (cur_block->is_contiguous ())
+ gdb_printf (_(" is contiguous\n"));
+ else
+ {
+ gdb_printf (_(" address ranges:\n"));
+ for (const blockrange &rng : cur_block->ranges ())
+ gdb_printf (_(" %s..%s\n"),
+ core_addr_to_string_nz (rng.start ()),
+ core_addr_to_string_nz (rng.end ()));
+ }
+ }
+}
+
+
+
+void _initialize_block ();
+void
+_initialize_block ()
+{
+ add_cmd ("blocks", class_maintenance, maintenance_info_blocks,
+ _("\
+Display block information for current thread.\n\
+\n\
+Usage:\n\
+\n\
+ maintenance info blocks [ADDRESS]\n\
+\n\
+With no ADDRESS show all blocks at the current address, starting with the\n\
+global block and working down to the inner most block.\n\
+\n\
+When ADDRESS is given, list the blocks at ADDRESS."),
+ &maintenanceinfolist);
+}
diff --git a/gdb/block.h b/gdb/block.h
index ae676c4..c3babad 100644
--- a/gdb/block.h
+++ b/gdb/block.h
@@ -264,25 +264,26 @@ struct block : public allocate_on_obstack<block>
return sup->is_global_block ();
}
- /* Return the static block associated with block. */
+ /* Return the global block associated with block. */
- const struct block *global_block () const;
+ const struct global_block *global_block () const;
/* Return true if this block is a global block. */
bool is_global_block () const
{ return superblock () == nullptr; }
+ /* Return this block as a global_block. This block must be a global
+ block. */
+ struct global_block *as_global_block ();
+ const struct global_block *as_global_block () const;
+
/* Return the function block for this block. Returns nullptr if
there is no enclosing function, i.e., if this block is a static
or global block. */
const struct block *function_block () const;
- /* Set the compunit of this block, which must be a global block. */
-
- void set_compunit_symtab (struct compunit_symtab *);
-
/* Return a property to evaluate the static link associated to this
block.
@@ -346,13 +347,31 @@ private:
};
/* The global block is singled out so that we can provide a back-link
- to the compunit symtab. */
+ to the compunit. */
struct global_block : public block
{
- /* This holds a pointer to the compunit symtab holding this block. */
+ /* Set the compunit of this global block.
+
+ The compunit must not have been set previously. */
+ void set_compunit (compunit_symtab *cu)
+ {
+ gdb_assert (m_compunit == nullptr);
+ m_compunit = cu;
+ }
+
+ /* Return the compunit of this global block.
- struct compunit_symtab *compunit_symtab = nullptr;
+ The compunit must have been set previously. */
+ compunit_symtab *compunit () const
+ {
+ gdb_assert (m_compunit != nullptr);
+ return m_compunit;
+ }
+
+private:
+ /* This holds a pointer to the compunit holding this block. */
+ compunit_symtab *m_compunit = nullptr;
};
struct blockvector
@@ -394,12 +413,15 @@ struct blockvector
{ return m_num_blocks; }
/* Return the global block of this blockvector. */
- struct block *global_block ()
- { return this->block (GLOBAL_BLOCK); }
+ struct global_block *global_block ()
+ { return static_cast<struct global_block *> (this->block (GLOBAL_BLOCK)); }
/* Const version of the above. */
- const struct block *global_block () const
- { return this->block (GLOBAL_BLOCK); }
+ const struct global_block *global_block () const
+ {
+ return static_cast<const struct global_block *>
+ (this->block (GLOBAL_BLOCK));
+ }
/* Return the static block of this blockvector. */
struct block *static_block ()
diff --git a/gdb/blockframe.c b/gdb/blockframe.c
index 55e82fb..7275eb1 100644
--- a/gdb/blockframe.c
+++ b/gdb/blockframe.c
@@ -85,7 +85,6 @@ CORE_ADDR
get_pc_function_start (CORE_ADDR pc)
{
const struct block *bl;
- struct bound_minimal_symbol msymbol;
bl = block_for_pc (pc);
if (bl)
@@ -99,7 +98,7 @@ get_pc_function_start (CORE_ADDR pc)
}
}
- msymbol = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (pc);
if (msymbol.minsym)
{
CORE_ADDR fstart = msymbol.value_address ();
@@ -216,9 +215,9 @@ find_pc_partial_function_sym (CORE_ADDR pc,
{
struct obj_section *section;
struct symbol *f;
- struct bound_minimal_symbol msymbol;
struct compunit_symtab *compunit_symtab = NULL;
CORE_ADDR mapped_pc;
+ bound_minimal_symbol msymbol;
/* To ensure that the symbol returned belongs to the correct section
(and that the last [random] symbol from the previous section
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index b7e29a7..c1c88d9 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -81,10 +81,10 @@ struct exception_catchpoint : public code_breakpoint
_("invalid type-matching regexp")))
{
pspace = current_program_space;
- re_set ();
+ re_set (pspace);
}
- void re_set () override;
+ void re_set (program_space *pspace) override;
enum print_stop_action print_it (const bpstat *bs) const override;
bool print_one (const bp_location **) const override;
void print_mention () const override;
@@ -197,7 +197,7 @@ exception_catchpoint::check_status (struct bpstat *bs)
/* Implement the 're_set' method. */
void
-exception_catchpoint::re_set ()
+exception_catchpoint::re_set (program_space *pspace)
{
std::vector<symtab_and_line> sals;
struct program_space *filter_pspace = current_program_space;
diff --git a/gdb/break-cond-parse.c b/gdb/break-cond-parse.c
new file mode 100644
index 0000000..b2b1324
--- /dev/null
+++ b/gdb/break-cond-parse.c
@@ -0,0 +1,699 @@
+/* Copyright (C) 2023 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 "defs.h"
+#include "gdbsupport/gdb_assert.h"
+#include "gdbsupport/selftest.h"
+#include "test-target.h"
+#include "scoped-mock-context.h"
+#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?
+
+ Given the following string and pointer 'ptr':
+
+ ABC DEF GHI JKL
+ ^
+ ptr
+
+ Parsing 'forward' will return the token 'GHI' and update 'ptr' to point
+ between GHI and JKL. Parsing 'backward' will return the token 'DEF' and
+ update 'ptr' to point between ABC and DEF.
+*/
+
+enum class parse_direction
+{
+ /* Parse the next token forwards. */
+ forward,
+
+ /* Parse the previous token backwards. */
+ backward
+};
+
+/* Find the next token in DIRECTION from *CURR. */
+
+static std::string_view
+find_next_token (const char **curr, parse_direction direction)
+{
+ const char *tok_start, *tok_end;
+
+ gdb_assert (**curr != '\0');
+
+ if (direction == parse_direction::forward)
+ {
+ *curr = skip_spaces (*curr);
+ tok_start = *curr;
+ *curr = skip_to_space (*curr);
+ tok_end = *curr - 1;
+ }
+ else
+ {
+ gdb_assert (direction == parse_direction::backward);
+
+ while (isspace (**curr))
+ --(*curr);
+
+ tok_end = *curr;
+
+ while (!isspace (**curr))
+ --(*curr);
+
+ tok_start = (*curr) + 1;
+ }
+
+ return std::string_view (tok_start, tok_end - tok_start + 1);
+}
+
+/* A class that represents a complete parsed token. Each token has a type
+ and a std::string_view into the original breakpoint condition string. */
+
+struct token
+{
+ /* The types a token might take. */
+ enum class type
+ {
+ /* These are the token types for the 'if', 'thread', 'inferior', and
+ 'task' keywords. The m_content for these token types is the value
+ passed to the keyword, not the keyword itself. */
+ CONDITION,
+ THREAD,
+ INFERIOR,
+ TASK,
+
+ /* This is the token used when we find unknown content, the m_content
+ for this token is the rest of the input string. */
+ REST,
+
+ /* This is the token for the -force-condition token, the m_content for
+ this token contains the keyword itself. */
+ FORCE
+ };
+
+ token (enum type type, std::string_view content)
+ : m_type (type),
+ m_content (std::move (content))
+ {
+ /* Nothing. */
+ }
+
+ /* Return a string representing this token. Only used for debug. */
+ std::string to_string () const
+ {
+ switch (m_type)
+ {
+ case type::CONDITION:
+ return string_printf ("{ CONDITION: \"%s\" }",
+ std::string (m_content).c_str ());
+ case type::THREAD:
+ return string_printf ("{ THREAD: \"%s\" }",
+ std::string (m_content).c_str ());
+ case type::INFERIOR:
+ return string_printf ("{ INFERIOR: \"%s\" }",
+ std::string (m_content).c_str ());
+ case type::TASK:
+ return string_printf ("{ TASK: \"%s\" }",
+ std::string (m_content).c_str ());
+ case type::REST:
+ return string_printf ("{ REST: \"%s\" }",
+ std::string (m_content).c_str ());
+ case type::FORCE:
+ return string_printf ("{ FORCE }");
+ default:
+ return "** unknown **";
+ }
+ }
+
+ /* The type of this token. */
+ const type &get_type () const
+ {
+ return m_type;
+ }
+
+ /* Return the value of this token. */
+ const std::string_view &get_value () const
+ {
+ gdb_assert (m_content.size () > 0);
+ return m_content;
+ }
+
+ /* Extend this token with the contents of OTHER. This only makes sense
+ if OTHER is the next token after this one in the original string,
+ however, enforcing that restriction is left to the caller of this
+ function.
+
+ When OTHER is a keyword/value token, e.g. 'thread 1', the m_content
+ for OTHER will only point to the '1'. However, as the m_content is a
+ std::string_view, then when we merge the m_content of OTHER into this
+ token we automatically merge in the 'thread' part too, as it
+ naturally sits between this token and OTHER. */
+
+ void
+ extend (const token &other)
+ {
+ m_content = std::string_view (this->m_content.data (),
+ (other.m_content.data ()
+ - this->m_content.data ()
+ + other.m_content.size ()));
+ }
+
+private:
+ /* The type of this token. */
+ type m_type;
+
+ /* The important content part of this token. The extend member function
+ depends on this being a std::string_view. */
+ std::string_view m_content;
+};
+
+/* Split STR, a breakpoint condition string, into a vector of tokens where
+ each token represents a component of the condition. Tokens are first
+ parsed from the front of STR until we encounter an 'if' token. At this
+ point tokens are parsed from the end of STR until we encounter an
+ unknown token, which we assume is the other end of the 'if' condition.
+ If when scanning forward we encounter an unknown token then the
+ remainder of STR is placed into a 'rest' token (the rest of the
+ string), and no backward scan is performed. */
+
+static std::vector<token>
+parse_all_tokens (const char *str)
+{
+ gdb_assert (str != nullptr);
+
+ std::vector<token> forward_results;
+ std::vector<token> backward_results;
+
+ const char *cond_start = nullptr;
+ const char *cond_end = nullptr;
+ parse_direction direction = parse_direction::forward;
+ std::vector<token> *curr_results = &forward_results;
+ while (*str != '\0')
+ {
+ /* Find the next token. If moving backward and this token starts at
+ the same location as the condition then we must have found the
+ other end of the condition string -- we're done. */
+ std::string_view t = find_next_token (&str, direction);
+ if (direction == parse_direction::backward && t.data () <= cond_start)
+ {
+ cond_end = &t.back ();
+ break;
+ }
+
+ /* We only have a single flag option to check for. All the other
+ options take a value so require an additional token to be found.
+ Additionally, we require that this flag be at least '-f', we
+ don't allow it to be abbreviated to '-'. */
+ if (t.length () > 1 && startswith ("-force-condition", t))
+ {
+ curr_results->emplace_back (token::type::FORCE, t);
+ continue;
+ }
+
+ /* Maybe the first token was the last token in the string. If this
+ is the case then we definitely can't try to extract a value
+ token. This also means that the token T is meaningless. Reset
+ TOK to point at the start of the unknown content and break out of
+ the loop. We'll record the unknown part of the string outside of
+ the scanning loop (below). */
+ if (direction == parse_direction::forward && *str == '\0')
+ {
+ str = t.data ();
+ break;
+ }
+
+ /* As before, find the next token and, if we are scanning backwards,
+ check that we have not reached the start of the condition string. */
+ std::string_view v = find_next_token (&str, direction);
+ if (direction == parse_direction::backward && v.data () <= cond_start)
+ {
+ /* Use token T here as that must also be part of the condition
+ string. */
+ cond_end = &t.back ();
+ break;
+ }
+
+ /* When moving backward we will first parse the value token then the
+ keyword token, so swap them now. */
+ if (direction == parse_direction::backward)
+ std::swap (t, v);
+
+ /* Check for valid option in token T. If we find a valid option then
+ parse the value from the token V. Except for 'if', that's handled
+ differently.
+
+ For the 'if' token we need to capture the entire condition
+ string, so record the start of the condition string and then
+ start scanning backwards looking for the end of the condition
+ string.
+
+ The order of these checks is important, at least the check for
+ 'thread' must occur before the check for 'task'. We accept
+ abbreviations of these token names, and 't' should resolve to
+ 'thread', which will only happen if we check 'thread' first. */
+ if (direction == parse_direction::forward && startswith ("if", t))
+ {
+ cond_start = v.data ();
+ str = str + strlen (str);
+ gdb_assert (*str == '\0');
+ --str;
+ direction = parse_direction::backward;
+ curr_results = &backward_results;
+ continue;
+ }
+ else if (startswith ("thread", t))
+ curr_results->emplace_back (token::type::THREAD, v);
+ else if (startswith ("inferior", t))
+ curr_results->emplace_back (token::type::INFERIOR, v);
+ else if (startswith ("task", t))
+ curr_results->emplace_back (token::type::TASK, v);
+ else
+ {
+ /* An unknown token. If we are scanning forward then reset TOK
+ to point at the start of the unknown content, we record this
+ outside of the scanning loop (below).
+
+ If we are scanning backward then unknown content is assumed to
+ be the other end of the condition string, obviously, this is
+ just a heuristic, we could be looking at a mistyped command
+ line, but this will be spotted when the condition is
+ eventually evaluated.
+
+ Either way, no more scanning is required after this. */
+ if (direction == parse_direction::forward)
+ str = t.data ();
+ else
+ {
+ gdb_assert (direction == parse_direction::backward);
+ cond_end = &v.back ();
+ }
+ break;
+ }
+ }
+
+ if (cond_start != nullptr)
+ {
+ /* If we found the start of a condition string then we should have
+ switched to backward scan mode, and found the end of the condition
+ string. Capture the whole condition string into COND_STRING
+ now. */
+ gdb_assert (direction == parse_direction::backward);
+ gdb_assert (cond_end != nullptr);
+
+ std::string_view v (cond_start, cond_end - cond_start + 1);
+
+ forward_results.emplace_back (token::type::CONDITION, v);
+ }
+ else if (*str != '\0')
+ {
+ /* If we didn't have a condition start pointer then we should still
+ be in forward scanning mode. If we didn't reach the end of the
+ input string (TOK is not at the null character) then the rest of
+ the input string is garbage that we didn't understand.
+
+ Record the unknown content into REST. The caller of this function
+ will report this as an error later on. We could report the error
+ here, but we prefer to allow the caller to run other checks, and
+ prioritise other errors before reporting this problem. */
+ gdb_assert (direction == parse_direction::forward);
+ gdb_assert (cond_end == nullptr);
+
+ std::string_view v (str, strlen (str));
+
+ forward_results.emplace_back (token::type::REST, v);
+ }
+
+ /* If we have tokens in the BACKWARD_RESULTS vector then this means that
+ we found an 'if' condition (which will be the last thing in the
+ FORWARD_RESULTS vector), and then we started a backward scan.
+
+ The last tokens from the input string (those after the 'if' condition)
+ will be the first tokens added to the BACKWARD_RESULTS vector, so the
+ last items in the BACKWARD_RESULTS vector are those next to the 'if'
+ condition.
+
+ Check the tokens in the BACKWARD_RESULTS vector from back to front.
+ If the tokens look invalid then we assume that they are actually part
+ of the 'if' condition, and merge the token with the 'if' condition.
+ If it turns out that this was incorrect and that instead the user just
+ messed up entering the token value, then this will show as an error
+ when parsing the 'if' condition.
+
+ Doing this allows us to handle things like:
+
+ break function if ( variable == thread )
+
+ Where 'thread' is a local variable within 'function'. When parsing
+ this we will initially see 'thread )' as a thread token with ')' as
+ the value. However, the following code will spot that ')' is not a
+ valid thread-id, and so we merge 'thread )' into the 'if' condition
+ string.
+
+ This code also handles the special treatment for '-force-condition',
+ which exists for backwards compatibility reasons. Traditionally this
+ flag, if it occurred immediately after the 'if' condition, would be
+ treated as part of the 'if' condition. When the breakpoint condition
+ parsing code was rewritten, this behaviour was retained. */
+ gdb_assert (backward_results.empty ()
+ || (forward_results.back ().get_type ()
+ == token::type::CONDITION));
+ while (!backward_results.empty ())
+ {
+ token &t = backward_results.back ();
+
+ if (t.get_type () == token::type::FORCE)
+ forward_results.back ().extend (std::move (t));
+ else if (t.get_type () == token::type::THREAD)
+ {
+ const char *end;
+ std::string v (t.get_value ());
+ if (is_thread_id (v.c_str (), &end) && *end == '\0')
+ break;
+ forward_results.back ().extend (std::move (t));
+ }
+ else if (t.get_type () == token::type::INFERIOR
+ || t.get_type () == token::type::TASK)
+ {
+ /* Place the token's value into a null-terminated string, parse
+ the string as a number and check that the entire string was
+ parsed. If this is true then this looks like a valid inferior
+ or task number, otherwise, assume an invalid id, and merge
+ this token with the 'if' token. */
+ char *end;
+ std::string v (t.get_value ());
+ (void) strtol (v.c_str (), &end, 0);
+ if (end > v.c_str () && *end == '\0')
+ break;
+ forward_results.back ().extend (std::move (t));
+ }
+ else
+ gdb_assert_not_reached ("unexpected token type");
+
+ /* If we found an actual valid token above then we will have broken
+ out of the loop. We only get here if the token was merged with
+ the 'if' condition, in which case we can discard the last token
+ and then check the token before that. */
+ backward_results.pop_back ();
+ }
+
+ /* If after the above checks we still have some tokens in the
+ BACKWARD_RESULTS vector, then these need to be appended to the
+ FORWARD_RESULTS vector. However, we first reverse the order so that
+ FORWARD_RESULTS retains the tokens in the order they appeared in the
+ input string. */
+ if (!backward_results.empty ())
+ forward_results.insert (forward_results.end (),
+ backward_results.rbegin (),
+ backward_results.rend ());
+
+ return forward_results;
+}
+
+/* Called when the global debug_breakpoint is true. Prints VEC to the
+ debug output stream. */
+
+static void
+dump_condition_tokens (const std::vector<token> &vec)
+{
+ gdb_assert (debug_breakpoint);
+
+ bool first = true;
+ std::string str = "Tokens: ";
+ for (const token &t : vec)
+ {
+ if (!first)
+ str += " ";
+ first = false;
+ str += t.to_string ();
+ }
+ breakpoint_debug_printf ("%s", str.c_str ());
+}
+
+/* See break-cond-parse.h. */
+
+void
+create_breakpoint_parse_arg_string
+ (const char *str, gdb::unique_xmalloc_ptr<char> *cond_string_ptr,
+ int *thread_ptr, int *inferior_ptr, int *task_ptr,
+ gdb::unique_xmalloc_ptr<char> *rest_ptr, bool *force_ptr)
+{
+ /* Set up the defaults. */
+ cond_string_ptr->reset ();
+ rest_ptr->reset ();
+ *thread_ptr = -1;
+ *inferior_ptr = -1;
+ *task_ptr = -1;
+ *force_ptr = false;
+
+ if (str == nullptr)
+ return;
+
+ /* Split STR into a series of tokens. */
+ std::vector<token> tokens = parse_all_tokens (str);
+ if (debug_breakpoint)
+ dump_condition_tokens (tokens);
+
+ /* Temporary variables. Initialised to the default state, then updated
+ as we parse TOKENS. If all of TOKENS is parsed successfully then the
+ state from these variables is copied into the output arguments before
+ the function returns. */
+ int thread = -1, inferior = -1, task = -1;
+ bool force = false;
+ gdb::unique_xmalloc_ptr<char> cond_string, rest;
+
+ for (const token &t : tokens)
+ {
+ std::string tok_value (t.get_value ());
+ switch (t.get_type ())
+ {
+ case token::type::FORCE:
+ force = true;
+ break;
+ case token::type::THREAD:
+ {
+ if (thread != -1)
+ error ("You can specify only one thread.");
+ if (task != -1 || inferior != -1)
+ error ("You can specify only one of thread, inferior, or task.");
+ const char *tmptok;
+ thread_info *thr = parse_thread_id (tok_value.c_str (), &tmptok);
+ gdb_assert (*tmptok == '\0');
+ thread = thr->global_num;
+ }
+ break;
+ case token::type::INFERIOR:
+ {
+ if (inferior != -1)
+ error ("You can specify only one inferior.");
+ if (task != -1 || thread != -1)
+ error ("You can specify only one of thread, inferior, or task.");
+ char *tmptok;
+ long inferior_id = strtol (tok_value.c_str (), &tmptok, 0);
+ if (*tmptok != '\0')
+ error (_("Junk '%s' after inferior keyword."), tmptok);
+ if (inferior_id > INT_MAX)
+ error (_("No inferior number '%ld'"), inferior_id);
+ inferior = static_cast<int> (inferior_id);
+ struct inferior *inf = find_inferior_id (inferior);
+ if (inf == nullptr)
+ error (_("No inferior number '%d'"), inferior);
+ }
+ break;
+ case token::type::TASK:
+ {
+ if (task != -1)
+ error ("You can specify only one task.");
+ if (inferior != -1 || thread != -1)
+ error ("You can specify only one of thread, inferior, or task.");
+ char *tmptok;
+ long task_id = strtol (tok_value.c_str (), &tmptok, 0);
+ if (*tmptok != '\0')
+ error (_("Junk '%s' after task keyword."), tmptok);
+ if (task_id > INT_MAX)
+ error (_("Unknown task %ld"), task_id);
+ task = static_cast<int> (task_id);
+ if (!valid_task_id (task))
+ error (_("Unknown task %d."), task);
+ }
+ break;
+ case token::type::CONDITION:
+ cond_string.reset (savestring (t.get_value ().data (),
+ t.get_value ().size ()));
+ break;
+ case token::type::REST:
+ rest.reset (savestring (t.get_value ().data (),
+ t.get_value ().size ()));
+ break;
+ }
+ }
+
+ /* Move results into the output locations. */
+ *force_ptr = force;
+ *thread_ptr = thread;
+ *inferior_ptr = inferior;
+ *task_ptr = task;
+ rest_ptr->reset (rest.release ());
+ cond_string_ptr->reset (cond_string.release ());
+}
+
+#if GDB_SELF_TEST
+
+namespace selftests {
+
+/* Run a single test of the create_breakpoint_parse_arg_string function.
+ INPUT is passed to create_breakpoint_parse_arg_string while all other
+ arguments are the expected output from
+ create_breakpoint_parse_arg_string. */
+
+static void
+test (const char *input, const char *condition, int thread = -1,
+ int inferior = -1, int task = -1, bool force = false,
+ const char *rest = nullptr, const char *error_msg = nullptr)
+{
+ gdb::unique_xmalloc_ptr<char> extracted_condition;
+ gdb::unique_xmalloc_ptr<char> extracted_rest;
+ int extracted_thread, extracted_inferior, extracted_task;
+ bool extracted_force_condition;
+ std::string exception_msg, error_str;
+
+ if (error_msg != nullptr)
+ error_str = std::string (error_msg) + "\n";
+
+ try
+ {
+ create_breakpoint_parse_arg_string (input, &extracted_condition,
+ &extracted_thread,
+ &extracted_inferior,
+ &extracted_task, &extracted_rest,
+ &extracted_force_condition);
+ }
+ catch (const gdb_exception_error &ex)
+ {
+ string_file buf;
+
+ exception_print (&buf, ex);
+ exception_msg = buf.release ();
+ }
+
+ if ((condition == nullptr) != (extracted_condition.get () == nullptr)
+ || (condition != nullptr
+ && strcmp (condition, extracted_condition.get ()) != 0)
+ || (rest == nullptr) != (extracted_rest.get () == nullptr)
+ || (rest != nullptr && strcmp (rest, extracted_rest.get ()) != 0)
+ || thread != extracted_thread
+ || inferior != extracted_inferior
+ || task != extracted_task
+ || force != extracted_force_condition
+ || exception_msg != error_str)
+ {
+ if (run_verbose ())
+ {
+ debug_printf ("input: '%s'\n", input);
+ debug_printf ("condition: '%s'\n", extracted_condition.get ());
+ debug_printf ("rest: '%s'\n", extracted_rest.get ());
+ debug_printf ("thread: %d\n", extracted_thread);
+ debug_printf ("inferior: %d\n", extracted_inferior);
+ debug_printf ("task: %d\n", extracted_task);
+ debug_printf ("forced: %s\n",
+ extracted_force_condition ? "true" : "false");
+ debug_printf ("exception: '%s'\n", exception_msg.c_str ());
+ }
+
+ /* Report the failure. */
+ SELF_CHECK (false);
+ }
+}
+
+/* Wrapper for test function. Pass through the default values for all
+ parameters, except the last parameter, which indicates that we expect
+ INPUT to trigger an error. */
+
+static void
+test_error (const char *input, const char *error_msg)
+{
+ test (input, nullptr, -1, -1, -1, false, nullptr, error_msg);
+}
+
+/* Test the create_breakpoint_parse_arg_string function. Just wraps
+ multiple calls to the test function above. */
+
+static void
+create_breakpoint_parse_arg_string_tests ()
+{
+ gdbarch *arch = current_inferior ()->arch ();
+ scoped_restore_current_pspace_and_thread restore;
+ scoped_mock_context<test_target_ops> mock_target (arch);
+
+ int global_thread_num = mock_target.mock_thread.global_num;
+
+ /* Test parsing valid breakpoint condition strings. */
+ test (" if blah ", "blah");
+ test (" if blah thread 1", "blah", global_thread_num);
+ test (" if blah inferior 1", "blah", -1, 1);
+ test (" if blah thread 1 ", "blah", global_thread_num);
+ test ("thread 1 woof", nullptr, global_thread_num, -1, -1, false, "woof");
+ test ("thread 1 X", nullptr, global_thread_num, -1, -1, false, "X");
+ test (" if blah thread 1 -force-condition", "blah", global_thread_num,
+ -1, -1, true);
+ test (" -force-condition if blah thread 1", "blah", global_thread_num,
+ -1, -1, true);
+ test (" -force-condition if blah thread 1 ", "blah", global_thread_num,
+ -1, -1, true);
+ test ("thread 1 -force-condition if blah", "blah", global_thread_num,
+ -1, -1, true);
+ test ("if (A::outer::func ())", "(A::outer::func ())");
+ test ("if ( foo == thread )", "( foo == thread )");
+ test ("if ( foo == thread ) inferior 1", "( foo == thread )", -1, 1);
+ test ("if ( foo == thread ) thread 1", "( foo == thread )",
+ global_thread_num);
+ test ("if foo == thread", "foo == thread");
+ test ("if foo == thread 1", "foo ==", global_thread_num);
+
+ /* Test parsing some invalid breakpoint condition strings. */
+ test_error ("thread 1 if foo == 123 thread 1",
+ "You can specify only one thread.");
+ test_error ("thread 1 if foo == 123 inferior 1",
+ "You can specify only one of thread, inferior, or task.");
+ test_error ("thread 1 if foo == 123 task 1",
+ "You can specify only one of thread, inferior, or task.");
+ test_error ("inferior 1 if foo == 123 inferior 1",
+ "You can specify only one inferior.");
+ test_error ("inferior 1 if foo == 123 thread 1",
+ "You can specify only one of thread, inferior, or task.");
+ test_error ("inferior 1 if foo == 123 task 1",
+ "You can specify only one of thread, inferior, or task.");
+ test_error ("thread 1.2.3", "Invalid thread ID: 1.2.3");
+ test_error ("thread 1/2", "Invalid thread ID: 1/2");
+ test_error ("thread 1xxx", "Invalid thread ID: 1xxx");
+ test_error ("inferior 1xxx", "Junk 'xxx' after inferior keyword.");
+ test_error ("task 1xxx", "Junk 'xxx' after task keyword.");
+}
+
+} // namespace selftests
+#endif /* GDB_SELF_TEST */
+
+void _initialize_break_cond_parse ();
+void
+_initialize_break_cond_parse ()
+{
+#if GDB_SELF_TEST
+ selftests::register_test
+ ("create_breakpoint_parse_arg_string",
+ selftests::create_breakpoint_parse_arg_string_tests);
+#endif
+}
diff --git a/gdb/break-cond-parse.h b/gdb/break-cond-parse.h
new file mode 100644
index 0000000..cbee70f
--- /dev/null
+++ b/gdb/break-cond-parse.h
@@ -0,0 +1,52 @@
+/* Copyright (C) 2023 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/>. */
+
+#if !defined (BREAK_COND_PARSE_H)
+#define BREAK_COND_PARSE_H 1
+
+/* Given TOK, a string possibly containing a condition, thread, inferior,
+ task and force-condition flag, as accepted by the 'break' command,
+ extract the condition string, thread, inferior, task number, and the
+ force_condition flag, then set *COND_STRING, *THREAD, *INFERIOR, *TASK,
+ and *FORCE.
+
+ As TOK is parsed, if an unknown keyword is encountered before the 'if'
+ keyword then everything starting from the unknown keyword is placed into
+ *REST.
+
+ Both *COND and *REST are initialized to nullptr. If no 'if' keyword is
+ found then *COND will be returned as nullptr. If no unknown content is
+ found then *REST is returned as nullptr.
+
+ If no thread is found, *THREAD is set to -1. If no inferior is found,
+ *INFERIOR is set to -1. If no task is found, *TASK is set to -1. If
+ the -force-condition flag is not found then *FORCE is set to false.
+
+ Due to the free-form nature that the string TOK might take (a 'thread'
+ keyword can appear before or after an 'if' condition) then we end up
+ having to check for keywords from both the start of TOK and the end of
+ TOK.
+
+ If TOK is nullptr, or TOK is the empty string, then the output variables
+ are all given their default values. */
+
+extern void create_breakpoint_parse_arg_string
+ (const char *tok, gdb::unique_xmalloc_ptr<char> *cond_string,
+ int *thread, int *inferior, int *task,
+ gdb::unique_xmalloc_ptr<char> *rest, bool *force);
+
+#endif
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index a973518..4cf6857 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -70,6 +70,7 @@
#include "cli/cli-style.h"
#include "cli/cli-decode.h"
#include <unordered_set>
+#include "break-cond-parse.h"
/* readline include files */
#include "readline/tilde.h"
@@ -90,9 +91,12 @@
static void map_breakpoint_numbers (const char *,
gdb::function_view<void (breakpoint *)>);
-static void
- create_sals_from_location_spec_default (location_spec *locspec,
- linespec_result *canonical);
+static void parse_breakpoint_sals (location_spec *locspec,
+ linespec_result *canonical,
+ program_space *search_pspace);
+
+static void breakpoint_re_set_one (breakpoint *b,
+ program_space *filter_pspace);
static void create_breakpoints_sal (struct gdbarch *,
struct linespec_result *,
@@ -282,14 +286,12 @@ static bool strace_marker_p (struct breakpoint *b);
static void bkpt_probe_create_sals_from_location_spec
(location_spec *locspec,
- struct linespec_result *canonical);
-static void tracepoint_probe_create_sals_from_location_spec
- (location_spec *locspec,
- struct linespec_result *canonical);
+ struct linespec_result *canonical,
+ struct program_space *search_pspace);
const struct breakpoint_ops code_breakpoint_ops =
{
- create_sals_from_location_spec_default,
+ parse_breakpoint_sals,
create_breakpoints_sal,
};
@@ -300,10 +302,11 @@ static const struct breakpoint_ops bkpt_probe_breakpoint_ops =
create_breakpoints_sal,
};
-/* Tracepoints set on probes. */
+/* Tracepoints set on probes. We use the same methods as for breakpoints
+ on probes. */
static const struct breakpoint_ops tracepoint_probe_breakpoint_ops =
{
- tracepoint_probe_create_sals_from_location_spec,
+ bkpt_probe_create_sals_from_location_spec,
create_breakpoints_sal,
};
@@ -353,7 +356,7 @@ struct internal_breakpoint : public code_breakpoint
disposition = disp_donttouch;
}
- void re_set () override;
+ void re_set (program_space *pspace) override;
void check_status (struct bpstat *bs) override;
enum print_stop_action print_it (const bpstat *bs) const override;
void print_mention () const override;
@@ -390,7 +393,7 @@ struct momentary_breakpoint : public code_breakpoint
gdb_assert (inferior == -1);
}
- void re_set () override;
+ void re_set (program_space *pspace) override;
void check_status (struct bpstat *bs) override;
enum print_stop_action print_it (const bpstat *bs) const override;
void print_mention () const override;
@@ -401,7 +404,7 @@ struct dprintf_breakpoint : public ordinary_breakpoint
{
using ordinary_breakpoint::ordinary_breakpoint;
- void re_set () override;
+ void re_set (program_space *pspace) override;
int breakpoint_hit (const struct bp_location *bl,
const address_space *aspace,
CORE_ADDR bp_addr,
@@ -576,13 +579,8 @@ show_always_inserted_mode (struct ui_file *file, int from_tty,
value);
}
-/* True if breakpoint debug output is enabled. */
-static bool debug_breakpoint = false;
-
-/* Print a "breakpoint" debug statement. */
-#define breakpoint_debug_printf(fmt, ...) \
- debug_prefixed_printf_cond (debug_breakpoint, "breakpoint", fmt, \
- ##__VA_ARGS__)
+/* See breakpoint.h. */
+bool debug_breakpoint = false;
/* "show debug breakpoint" implementation. */
static void
@@ -1555,7 +1553,46 @@ breakpoint_set_thread (struct breakpoint *b, int thread)
int old_thread = b->thread;
b->thread = thread;
if (old_thread != thread)
- notify_breakpoint_modified (b);
+ {
+ /* If THREAD is in a different program_space than OLD_THREAD, or the
+ breakpoint has switched to or from being thread-specific, then we
+ need to re-set the locations of this breakpoint. First, figure
+ out the program_space for the old and new threads, use a value of
+ nullptr to indicate the breakpoint is in all program spaces. */
+ program_space *old_pspace = nullptr;
+ if (old_thread != -1)
+ {
+ struct thread_info *thr = find_thread_global_id (old_thread);
+ gdb_assert (thr != nullptr);
+ old_pspace = thr->inf->pspace;
+ }
+
+ program_space *new_pspace = nullptr;
+ if (thread != -1)
+ {
+ struct thread_info *thr = find_thread_global_id (thread);
+ gdb_assert (thr != nullptr);
+ new_pspace = thr->inf->pspace;
+ }
+
+ /* If the program space has changed for this breakpoint, then
+ re-evaluate it's locations. */
+ if (old_pspace != new_pspace)
+ {
+ /* The breakpoint is now associated with a completely different
+ program space. Discard all of the current locations and then
+ re-set the breakpoint in the new program space, this will
+ create the new locations. */
+ b->clear_locations ();
+ breakpoint_re_set_one (b, new_pspace);
+ }
+
+ /* If the program space didn't change, or the breakpoint didn't
+ acquire any new locations after the clear_locations call, then we
+ need to notify of the breakpoint modification now. */
+ if (old_pspace == new_pspace || !b->has_locations ())
+ notify_breakpoint_modified (b);
+ }
}
/* See breakpoint.h. */
@@ -1574,7 +1611,45 @@ breakpoint_set_inferior (struct breakpoint *b, int inferior)
int old_inferior = b->inferior;
b->inferior = inferior;
if (old_inferior != inferior)
- notify_breakpoint_modified (b);
+ {
+ /* If INFERIOR is in a different program_space than OLD_INFERIOR, or
+ the breakpoint has switch to or from inferior-specific, then we
+ need to re-set the locations of this breakpoint. First, figure
+ out the program_space for the old and new inferiors, use a value
+ of nullptr to indicate the breakpoint is in all program
+ spaces. */
+ program_space *old_pspace = nullptr;
+ if (old_inferior != -1)
+ {
+ struct inferior *inf = find_inferior_id (old_inferior);
+ gdb_assert (inf != nullptr);
+ old_pspace = inf->pspace;
+ }
+
+ program_space *new_pspace = nullptr;
+ if (inferior != -1)
+ {
+ struct inferior *inf = find_inferior_id (inferior);
+ gdb_assert (inf != nullptr);
+ new_pspace = inf->pspace;
+ }
+
+ if (old_pspace != new_pspace)
+ {
+ /* The breakpoint is now associated with a completely different
+ program space. Discard all of the current locations and then
+ re-set the breakpoint in the new program space, this will
+ create the new locations. */
+ b->clear_locations ();
+ breakpoint_re_set_one (b, new_pspace);
+ }
+
+ /* If the program space didn't change, or the breakpoint didn't
+ acquire any new locations after the clear_locations call, then we
+ need to notify of the breakpoint modification now. */
+ if (old_pspace == new_pspace || !b->has_locations ())
+ notify_breakpoint_modified (b);
+ }
}
/* See breakpoint.h. */
@@ -3468,7 +3543,7 @@ create_internal_breakpoint (struct gdbarch *gdbarch,
static struct breakpoint *
create_internal_breakpoint (struct gdbarch *gdbarch,
- struct bound_minimal_symbol &msym, enum bptype type)
+ bound_minimal_symbol &msym, enum bptype type)
{
CORE_ADDR address;
@@ -3500,10 +3575,10 @@ static const char *const longjmp_names[] =
struct breakpoint_objfile_data
{
/* Minimal symbol for "_ovly_debug_event" (if any). */
- struct bound_minimal_symbol overlay_msym;
+ bound_minimal_symbol overlay_msym;
/* Minimal symbol(s) for "longjmp", "siglongjmp", etc. (if any). */
- struct bound_minimal_symbol longjmp_msym[NUM_LONGJMP_NAMES];
+ bound_minimal_symbol longjmp_msym[NUM_LONGJMP_NAMES];
/* True if we have looked for longjmp probes. */
int longjmp_searched = 0;
@@ -3513,10 +3588,10 @@ struct breakpoint_objfile_data
std::vector<probe *> longjmp_probes;
/* Minimal symbol for "std::terminate()" (if any). */
- struct bound_minimal_symbol terminate_msym;
+ bound_minimal_symbol terminate_msym;
/* Minimal symbol for "_Unwind_DebugHook" (if any). */
- struct bound_minimal_symbol exception_msym;
+ bound_minimal_symbol exception_msym;
/* True if we have looked for exception probes. */
int exception_searched = 0;
@@ -3572,9 +3647,9 @@ create_overlay_event_breakpoint (void)
if (bp_objfile_data->overlay_msym.minsym == NULL)
{
- struct bound_minimal_symbol m;
-
- m = lookup_minimal_symbol_text (func_name, objfile);
+ bound_minimal_symbol m
+ = lookup_minimal_symbol_text (current_program_space, func_name,
+ objfile);
if (m.minsym == NULL)
{
/* Avoid future lookups in this objfile. */
@@ -3677,9 +3752,9 @@ create_longjmp_master_breakpoint_names (objfile *objfile)
func_name = longjmp_names[i];
if (bp_objfile_data->longjmp_msym[i].minsym == NULL)
{
- struct bound_minimal_symbol m;
-
- m = lookup_minimal_symbol_text (func_name, objfile);
+ bound_minimal_symbol m
+ = lookup_minimal_symbol_text (objfile->pspace (), func_name,
+ objfile);
if (m.minsym == NULL)
{
/* Prevent future lookups in this objfile. */
@@ -3710,7 +3785,7 @@ create_longjmp_master_breakpoint (void)
{
set_current_program_space (pspace);
- for (objfile *obj : current_program_space->objfiles ())
+ for (objfile *obj : pspace->objfiles ())
{
/* Skip separate debug object, it's handled in the loop below. */
if (obj->separate_debug_objfile_backlink != nullptr)
@@ -3736,14 +3811,13 @@ create_std_terminate_master_breakpoint (void)
const char *const func_name = "std::terminate()";
scoped_restore_current_program_space restore_pspace;
- scoped_restore_current_language save_language;
- set_language (language_cplus);
+ scoped_restore_current_language save_language (language_cplus);
for (struct program_space *pspace : program_spaces)
{
set_current_program_space (pspace);
- for (objfile *objfile : current_program_space->objfiles ())
+ for (objfile *objfile : pspace->objfiles ())
{
struct breakpoint *b;
struct breakpoint_objfile_data *bp_objfile_data;
@@ -3755,9 +3829,9 @@ create_std_terminate_master_breakpoint (void)
if (bp_objfile_data->terminate_msym.minsym == NULL)
{
- struct bound_minimal_symbol m;
-
- m = lookup_minimal_symbol (func_name, NULL, objfile);
+ bound_minimal_symbol m
+ = lookup_minimal_symbol (current_program_space, func_name,
+ objfile);
if (m.minsym == NULL || (m.minsym->type () != mst_text
&& m.minsym->type () != mst_file_text))
{
@@ -3848,9 +3922,8 @@ create_exception_master_breakpoint_hook (objfile *objfile)
if (bp_objfile_data->exception_msym.minsym == NULL)
{
- struct bound_minimal_symbol debug_hook;
-
- debug_hook = lookup_minimal_symbol_text (func_name, objfile);
+ bound_minimal_symbol debug_hook
+ = lookup_minimal_symbol_text (objfile->pspace (), func_name, objfile);
if (debug_hook.minsym == NULL)
{
bp_objfile_data->exception_msym.minsym = &msym_not_found;
@@ -6319,7 +6392,8 @@ print_breakpoint_location (const breakpoint *b, const bp_location *loc)
if (uiout->is_mi_like_p ())
uiout->field_string ("fullname", symtab_to_fullname (loc->symtab));
- uiout->field_signed ("line", loc->line_number);
+ uiout->field_signed ("line", loc->line_number,
+ line_number_style.style ());
}
else if (loc)
{
@@ -6330,20 +6404,7 @@ print_breakpoint_location (const breakpoint *b, const bp_location *loc)
uiout->field_stream ("at", stb);
}
else
- {
- uiout->field_string ("pending", b->locspec->to_string ());
- /* If extra_string is available, it could be holding a condition
- or dprintf arguments. In either case, make sure it is printed,
- too, but only for non-MI streams. */
- if (!uiout->is_mi_like_p () && b->extra_string != NULL)
- {
- if (b->type == bp_dprintf)
- uiout->text (",");
- else
- uiout->text (" ");
- uiout->text (b->extra_string.get ());
- }
- }
+ uiout->field_string ("pending", b->locspec->to_string ());
if (loc && is_breakpoint (b)
&& breakpoint_condition_evaluation_mode () == condition_evaluation_target
@@ -6592,7 +6653,7 @@ print_one_breakpoint_location (struct breakpoint *b,
}
}
- if (loc != NULL && !header_of_multiple)
+ if (loc != nullptr && !header_of_multiple && !loc->shlib_disabled)
{
std::vector<int> inf_nums;
int mi_only = 1;
@@ -8092,11 +8153,7 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile)
if (loc.shlib_disabled != 0)
continue;
- if (objfile->pspace != loc.pspace)
- continue;
-
- if (loc.loc_type != bp_loc_hardware_breakpoint
- && loc.loc_type != bp_loc_software_breakpoint)
+ if (objfile->pspace () != loc.pspace)
continue;
if (is_addr_in_objfile (loc_addr, objfile))
@@ -8146,6 +8203,65 @@ catchpoint::catchpoint (struct gdbarch *gdbarch, bool temp,
pspace = current_program_space;
}
+/* See breakpoint.h. */
+
+void
+catchpoint::re_set (program_space *filter_pspace)
+{
+ /* All catchpoints are associated with a specific program_space. */
+ gdb_assert (pspace != nullptr);
+
+ /* If only a single program space changed, and it's not the program space
+ for which this catchpoint applies, then there's nothing to do. */
+ if (filter_pspace != nullptr && filter_pspace != pspace)
+ return;
+
+ /* Catchpoints have a single dummy location. */
+ gdb_assert (locations ().size () == 1);
+ bp_location &bl = m_locations.front ();
+
+ if (cond_string == nullptr)
+ {
+ /* It shouldn't be possible to have a parsed condition expression
+ cached on this location if the catchpoint doesn't have a condition
+ string set. */
+ gdb_assert (bl.cond == nullptr);
+
+ /* Nothing to re-compute, and the catchpoint cannot change. */
+ return;
+ }
+
+ bool previous_disabled_by_cond = bl.disabled_by_cond;
+
+ /* Start by marking the location disabled and discarding the previously
+ computed condition expression. Now if we get an exception, even if
+ it's a quit exception, we'll leave the location disabled and there
+ will be no (possibly invalid) expression cached. */
+ bl.disabled_by_cond = true;
+ bl.cond = nullptr;
+
+ const char *s = cond_string.get ();
+ try
+ {
+ switch_to_program_space_and_thread (pspace);
+
+ bl.cond = parse_exp_1 (&s, bl.address, block_for_pc (bl.address),
+ nullptr);
+ bl.disabled_by_cond = false;
+ }
+ catch (const gdb_exception_error &e)
+ {
+ /* Any exception thrown must be from either the parse_exp_1 or
+ earlier in the try block. As such the following two asserts
+ should be true. */
+ gdb_assert (bl.disabled_by_cond);
+ gdb_assert (bl.cond == nullptr);
+ }
+
+ if (previous_disabled_by_cond != bl.disabled_by_cond)
+ notify_breakpoint_modified (this);
+}
+
/* Notify interpreters and observers that breakpoint B was created. */
static void
@@ -8708,8 +8824,8 @@ code_breakpoint::code_breakpoint (struct gdbarch *gdbarch_,
command line, otherwise it's an error. */
if (type == bp_dprintf)
update_dprintf_command_list (this);
- else if (extra_string != nullptr)
- error (_("Garbage '%s' at end of command"), extra_string.get ());
+ else
+ gdb_assert (extra_string == nullptr);
/* The order of the locations is now stable. Set the location
condition using the location's number. */
@@ -8823,10 +8939,9 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
static void
parse_breakpoint_sals (location_spec *locspec,
- struct linespec_result *canonical)
+ struct linespec_result *canonical,
+ struct program_space *search_pspace)
{
- struct symtab_and_line cursal;
-
if (locspec->type () == LINESPEC_LOCATION_SPEC)
{
const char *spec
@@ -8875,7 +8990,8 @@ parse_breakpoint_sals (location_spec *locspec,
ObjC: However, don't match an Objective-C method name which
may have a '+' or '-' succeeded by a '['. */
- cursal = get_current_source_symtab_and_line ();
+ symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
if (last_displayed_sal_is_valid ())
{
const char *spec = NULL;
@@ -8888,7 +9004,7 @@ parse_breakpoint_sals (location_spec *locspec,
&& strchr ("+-", spec[0]) != NULL
&& spec[1] != '['))
{
- decode_line_full (locspec, DECODE_LINE_FUNFIRSTLINE, NULL,
+ decode_line_full (locspec, DECODE_LINE_FUNFIRSTLINE, search_pspace,
get_last_displayed_symtab (),
get_last_displayed_line (),
canonical, NULL, NULL);
@@ -8896,7 +9012,7 @@ parse_breakpoint_sals (location_spec *locspec,
}
}
- decode_line_full (locspec, DECODE_LINE_FUNFIRSTLINE, NULL,
+ decode_line_full (locspec, DECODE_LINE_FUNFIRSTLINE, search_pspace,
cursal.symtab, cursal.line, canonical, NULL, NULL);
}
@@ -8938,197 +9054,6 @@ check_fast_tracepoint_sals (struct gdbarch *gdbarch,
}
}
-/* Given TOK, a string specification of condition and thread, as accepted
- by the 'break' command, extract the condition string into *COND_STRING.
- If no condition string is found then *COND_STRING is set to nullptr.
-
- If the breakpoint specification has an associated thread, task, or
- inferior, these are extracted into *THREAD, *TASK, and *INFERIOR
- respectively, otherwise these arguments are set to -1 (for THREAD and
- INFERIOR) or 0 (for TASK).
-
- PC identifies the context at which the condition should be parsed. */
-
-static void
-find_condition_and_thread (const char *tok, CORE_ADDR pc,
- gdb::unique_xmalloc_ptr<char> *cond_string,
- int *thread, int *inferior, int *task,
- gdb::unique_xmalloc_ptr<char> *rest)
-{
- cond_string->reset ();
- *thread = -1;
- *inferior = -1;
- *task = -1;
- rest->reset ();
- bool force = false;
-
- while (tok && *tok)
- {
- const char *end_tok;
- int toklen;
- const char *cond_start = NULL;
- const char *cond_end = NULL;
-
- tok = skip_spaces (tok);
-
- if ((*tok == '"' || *tok == ',') && rest)
- {
- rest->reset (savestring (tok, strlen (tok)));
- break;
- }
-
- end_tok = skip_to_space (tok);
-
- toklen = end_tok - tok;
-
- if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
- {
- tok = cond_start = end_tok + 1;
- try
- {
- parse_exp_1 (&tok, pc, block_for_pc (pc), 0);
- }
- catch (const gdb_exception_error &)
- {
- if (!force)
- throw;
- else
- tok = tok + strlen (tok);
- }
- cond_end = tok;
- cond_string->reset (savestring (cond_start, cond_end - cond_start));
- }
- else if (toklen >= 1 && strncmp (tok, "-force-condition", toklen) == 0)
- {
- tok = tok + toklen;
- force = true;
- }
- else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
- {
- const char *tmptok;
- struct thread_info *thr;
-
- if (*thread != -1)
- error(_("You can specify only one thread."));
-
- if (*task != -1)
- error (_("You can specify only one of thread or task."));
-
- if (*inferior != -1)
- error (_("You can specify only one of inferior or thread."));
-
- tok = end_tok + 1;
- thr = parse_thread_id (tok, &tmptok);
- if (tok == tmptok)
- error (_("Junk after thread keyword."));
- *thread = thr->global_num;
- tok = tmptok;
- }
- else if (toklen >= 1 && strncmp (tok, "inferior", toklen) == 0)
- {
- if (*inferior != -1)
- error(_("You can specify only one inferior."));
-
- if (*task != -1)
- error (_("You can specify only one of inferior or task."));
-
- if (*thread != -1)
- error (_("You can specify only one of inferior or thread."));
-
- char *tmptok;
- tok = end_tok + 1;
- *inferior = strtol (tok, &tmptok, 0);
- if (tok == tmptok)
- error (_("Junk after inferior keyword."));
- if (!valid_global_inferior_id (*inferior))
- error (_("Unknown inferior number %d."), *inferior);
- tok = tmptok;
- }
- else if (toklen >= 1 && strncmp (tok, "task", toklen) == 0)
- {
- char *tmptok;
-
- if (*task != -1)
- error(_("You can specify only one task."));
-
- if (*thread != -1)
- error (_("You can specify only one of thread or task."));
-
- if (*inferior != -1)
- error (_("You can specify only one of inferior or task."));
-
- tok = end_tok + 1;
- *task = strtol (tok, &tmptok, 0);
- if (tok == tmptok)
- error (_("Junk after task keyword."));
- if (!valid_task_id (*task))
- error (_("Unknown task %d."), *task);
- tok = tmptok;
- }
- else if (rest)
- {
- rest->reset (savestring (tok, strlen (tok)));
- break;
- }
- else
- error (_("Junk at end of arguments."));
- }
-}
-
-/* Call 'find_condition_and_thread' for each sal in SALS until a parse
- succeeds. The parsed values are written to COND_STRING, THREAD,
- TASK, and REST. See the comment of 'find_condition_and_thread'
- for the description of these parameters and INPUT. */
-
-static void
-find_condition_and_thread_for_sals (const std::vector<symtab_and_line> &sals,
- const char *input,
- gdb::unique_xmalloc_ptr<char> *cond_string,
- int *thread, int *inferior, int *task,
- gdb::unique_xmalloc_ptr<char> *rest)
-{
- int num_failures = 0;
- for (auto &sal : sals)
- {
- gdb::unique_xmalloc_ptr<char> cond;
- int thread_id = -1;
- int inferior_id = -1;
- int task_id = -1;
- gdb::unique_xmalloc_ptr<char> remaining;
-
- /* Here we want to parse 'arg' to separate condition from thread
- number. But because parsing happens in a context and the
- contexts of sals might be different, try each until there is
- success. Finding one successful parse is sufficient for our
- goal. When setting the breakpoint we'll re-parse the
- condition in the context of each sal. */
- try
- {
- find_condition_and_thread (input, sal.pc, &cond, &thread_id,
- &inferior_id, &task_id, &remaining);
- *cond_string = std::move (cond);
- /* A value of -1 indicates that these fields are unset. At most
- one of these fields should be set (to a value other than -1)
- at this point. */
- gdb_assert (((thread_id == -1 ? 1 : 0)
- + (task_id == -1 ? 1 : 0)
- + (inferior_id == -1 ? 1 : 0)) >= 2);
- *thread = thread_id;
- *inferior = inferior_id;
- *task = task_id;
- *rest = std::move (remaining);
- break;
- }
- catch (const gdb_exception_error &e)
- {
- num_failures++;
- /* If no sal remains, do not continue. */
- if (num_failures == sals.size ())
- throw;
- }
- }
-}
-
/* Decode a static tracepoint marker spec. */
static std::vector<symtab_and_line>
@@ -9186,6 +9111,39 @@ breakpoint_ops_for_location_spec_type (enum location_spec_type locspec_type,
}
}
+/* Return the program space to use as a filter when searching for locations
+ of a breakpoint specific to THREAD or INFERIOR. If THREAD and INFERIOR
+ are both -1, meaning all threads/inferiors, then this function returns
+ nullptr, indicating no program space filtering should be performed.
+ Otherwise, this function returns the program space for the inferior that
+ contains THREAD (when THREAD is not -1), or the program space for
+ INFERIOR (when INFERIOR is not -1). */
+
+static struct program_space *
+find_program_space_for_breakpoint (int thread, int inferior)
+{
+ if (thread != -1)
+ {
+ gdb_assert (inferior == -1);
+
+ struct thread_info *thr = find_thread_global_id (thread);
+ gdb_assert (thr != nullptr);
+ gdb_assert (thr->inf != nullptr);
+ return thr->inf->pspace;
+ }
+ else if (inferior != -1)
+ {
+ gdb_assert (thread == -1);
+
+ struct inferior *inf = find_inferior_id (inferior);
+ gdb_assert (inf != nullptr);
+
+ return inf->pspace;
+ }
+
+ return nullptr;
+}
+
/* See breakpoint.h. */
const struct breakpoint_ops *
@@ -9245,9 +9203,52 @@ create_breakpoint (struct gdbarch *gdbarch,
? (extra_string != nullptr && !parse_extra)
: (extra_string == nullptr || parse_extra));
+ /* Will hold either copies of the similarly named function argument, or
+ will hold a modified version of the function argument, depending on
+ the value of PARSE_EXTRA. */
+ gdb::unique_xmalloc_ptr<char> cond_string_copy;
+ gdb::unique_xmalloc_ptr<char> extra_string_copy;
+
+ if (parse_extra)
+ {
+ /* Parse EXTRA_STRING splitting the parts out. */
+ create_breakpoint_parse_arg_string (extra_string, &cond_string_copy,
+ &thread, &inferior, &task,
+ &extra_string_copy,
+ &force_condition);
+
+ /* We could check that EXTRA_STRING_COPY is empty at this point -- it
+ should be, as we only get here for things that are not bp_dprintf,
+ however, we prefer to give the location spec parser a chance to
+ run first, this means the user will get errors about invalid
+ location spec instead of an error about garbage at the end of the
+ command line.
+
+ We still do the EXTRA_STRING_COPY is empty check, just later in
+ this function. */
+
+ gdb_assert (thread == -1 || thread > 0);
+ gdb_assert (task == -1 || task > 0);
+ gdb_assert (inferior == -1 || inferior > 0);
+ }
+ else
+ {
+ if (cond_string != nullptr)
+ cond_string_copy.reset (xstrdup (cond_string));
+ if (extra_string != nullptr)
+ extra_string_copy.reset (xstrdup (extra_string));
+ }
+
+ /* Clear these. Updated values are now held in the *_copy locals. */
+ cond_string = nullptr;
+ extra_string = nullptr;
+
try
{
- ops->create_sals_from_location_spec (locspec, &canonical);
+ struct program_space *search_pspace
+ = find_program_space_for_breakpoint (thread, inferior);
+ ops->create_sals_from_location_spec (locspec, &canonical,
+ search_pspace);
}
catch (const gdb_exception_error &e)
{
@@ -9280,6 +9281,13 @@ create_breakpoint (struct gdbarch *gdbarch,
throw;
}
+ /* Only bp_dprintf breakpoints should have anything in EXTRA_STRING_COPY
+ by this point. For all other breakpoints this indicates an error. We
+ could place this check earlier in the function, but we prefer to see
+ errors from the location spec parser before we see this error message. */
+ if (type_wanted != bp_dprintf && extra_string_copy.get () != nullptr)
+ error (_("Garbage '%s' at end of command"), extra_string_copy.get ());
+
if (!pending && canonical.lsals.empty ())
return 0;
@@ -9303,63 +9311,31 @@ create_breakpoint (struct gdbarch *gdbarch,
breakpoint. */
if (!pending)
{
- gdb::unique_xmalloc_ptr<char> cond_string_copy;
- gdb::unique_xmalloc_ptr<char> extra_string_copy;
-
- if (parse_extra)
+ /* Check the validity of the condition. We should error out if the
+ condition is invalid at all of the locations and if it is not
+ forced. In the PARSE_EXTRA case above, this check is done when
+ parsing the EXTRA_STRING. */
+ if (cond_string_copy.get () != nullptr && !force_condition)
{
- gdb_assert (type_wanted != bp_dprintf);
-
- gdb::unique_xmalloc_ptr<char> rest;
- gdb::unique_xmalloc_ptr<char> cond;
-
+ int num_failures = 0;
const linespec_sals &lsal = canonical.lsals[0];
-
- find_condition_and_thread_for_sals (lsal.sals, extra_string,
- &cond, &thread, &inferior,
- &task, &rest);
-
- if (rest.get () != nullptr && *(rest.get ()) != '\0')
- error (_("Garbage '%s' at end of command"), rest.get ());
-
- cond_string_copy = std::move (cond);
- extra_string_copy = std::move (rest);
- }
- else
- {
- /* Check the validity of the condition. We should error out
- if the condition is invalid at all of the locations and
- if it is not forced. In the PARSE_EXTRA case above, this
- check is done when parsing the EXTRA_STRING. */
- if (cond_string != nullptr && !force_condition)
+ for (const auto &sal : lsal.sals)
{
- int num_failures = 0;
- const linespec_sals &lsal = canonical.lsals[0];
- for (const auto &sal : lsal.sals)
+ const char *cond = cond_string_copy.get ();
+ try
{
- const char *cond = cond_string;
- try
- {
- parse_exp_1 (&cond, sal.pc, block_for_pc (sal.pc), 0);
- /* One success is sufficient to keep going. */
- break;
- }
- catch (const gdb_exception_error &)
- {
- num_failures++;
- /* If this is the last sal, error out. */
- if (num_failures == lsal.sals.size ())
- throw;
- }
+ parse_exp_1 (&cond, sal.pc, block_for_pc (sal.pc), 0);
+ /* One success is sufficient to keep going. */
+ break;
+ }
+ catch (const gdb_exception_error &)
+ {
+ num_failures++;
+ /* If this is the last sal, error out. */
+ if (num_failures == lsal.sals.size ())
+ throw;
}
}
-
- /* Create a private copy of condition string. */
- if (cond_string)
- cond_string_copy.reset (xstrdup (cond_string));
- /* Create a private copy of any extra string. */
- if (extra_string)
- extra_string_copy.reset (xstrdup (extra_string));
}
ops->create_breakpoints_sal (gdbarch, &canonical,
@@ -9376,32 +9352,27 @@ create_breakpoint (struct gdbarch *gdbarch,
type_wanted);
b->locspec = locspec->clone ();
- if (parse_extra)
- b->cond_string = NULL;
- else
- {
- /* Create a private copy of condition string. */
- b->cond_string.reset (cond_string != NULL
- ? xstrdup (cond_string)
- : NULL);
- b->thread = thread;
- }
+ /* Create a private copy of the condition string. */
+ b->cond_string = std::move (cond_string_copy);
+
+ b->thread = thread;
+ b->task = task;
+ b->inferior = inferior;
/* Create a private copy of any extra string. */
- b->extra_string.reset (extra_string != NULL
- ? xstrdup (extra_string)
- : NULL);
+ b->extra_string = std::move (extra_string_copy);
+
b->ignore_count = ignore_count;
b->disposition = tempflag ? disp_del : disp_donttouch;
b->condition_not_parsed = 1;
b->enable_state = enabled ? bp_enabled : bp_disabled;
- if ((type_wanted != bp_breakpoint
- && type_wanted != bp_hardware_breakpoint) || thread != -1)
- b->pspace = current_program_space;
+
+ if (b->type == bp_dprintf)
+ update_dprintf_command_list (b.get ());
install_breakpoint (internal, std::move (b), 0);
}
-
+
if (canonical.lsals.size () > 1)
{
warning (_("Multiple breakpoints were set.\nUse the "
@@ -9750,7 +9721,7 @@ break_range_command (const char *arg, int from_tty)
arg_start = arg;
location_spec_up start_locspec
= string_to_location_spec (&arg, current_language);
- parse_breakpoint_sals (start_locspec.get (), &canonical_start);
+ parse_breakpoint_sals (start_locspec.get (), &canonical_start, nullptr);
if (arg[0] != ',')
error (_("Too few arguments."));
@@ -9851,7 +9822,7 @@ watchpoint_exp_is_const (const struct expression *exp)
/* Implement the "re_set" method for watchpoints. */
void
-watchpoint::re_set ()
+watchpoint::re_set (struct program_space *pspace)
{
/* Watchpoint can be either on expression using entirely global
variables, or it can be on local variables.
@@ -10509,45 +10480,6 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
'wp_frame'. */
frame_id watchpoint_frame = get_frame_id (wp_frame);
- /* If the expression is "local", then set up a "watchpoint scope"
- breakpoint at the point where we've left the scope of the watchpoint
- expression. Create the scope breakpoint before the watchpoint, so
- that we will encounter it first in bpstat_stop_status. */
- if (exp_valid_block != NULL && wp_frame != NULL)
- {
- frame_id caller_frame_id = frame_unwind_caller_id (wp_frame);
-
- if (frame_id_p (caller_frame_id))
- {
- gdbarch *caller_arch = frame_unwind_caller_arch (wp_frame);
- CORE_ADDR caller_pc = frame_unwind_caller_pc (wp_frame);
-
- scope_breakpoint
- = create_internal_breakpoint (caller_arch, caller_pc,
- bp_watchpoint_scope);
-
- /* create_internal_breakpoint could invalidate WP_FRAME. */
- wp_frame = NULL;
-
- scope_breakpoint->enable_state = bp_enabled;
-
- /* Automatically delete the breakpoint when it hits. */
- scope_breakpoint->disposition = disp_del;
-
- /* Only break in the proper frame (help with recursion). */
- scope_breakpoint->frame_id = caller_frame_id;
-
- /* Set the address at which we will stop. */
- bp_location &loc = scope_breakpoint->first_loc ();
- loc.gdbarch = caller_arch;
- loc.requested_address = caller_pc;
- loc.address
- = adjust_breakpoint_address (loc.gdbarch, loc.requested_address,
- scope_breakpoint->type,
- current_program_space);
- }
- }
-
/* Now set up the breakpoint. We create all watchpoints as hardware
watchpoints here even if hardware watchpoints are turned off, a call
to update_watchpoint later in this function will cause the type to
@@ -10618,14 +10550,6 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
w->watchpoint_thread = null_ptid;
}
- if (scope_breakpoint != NULL)
- {
- /* The scope breakpoint is related to the watchpoint. We will
- need to act on them together. */
- w->related_breakpoint = scope_breakpoint;
- scope_breakpoint->related_breakpoint = w.get ();
- }
-
if (!just_location)
value_free_to_mark (mark);
@@ -10633,7 +10557,60 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
that should be inserted. */
update_watchpoint (w.get (), true /* reparse */);
+ /* If the expression is "local", then set up a "watchpoint scope"
+ breakpoint at the point where we've left the scope of the watchpoint
+ expression. Create the scope breakpoint before the watchpoint, so
+ that we will encounter it first in bpstat_stop_status. */
+ if (exp_valid_block != nullptr && wp_frame != nullptr)
+ {
+ frame_id caller_frame_id = frame_unwind_caller_id (wp_frame);
+
+ if (frame_id_p (caller_frame_id))
+ {
+ gdbarch *caller_arch = frame_unwind_caller_arch (wp_frame);
+ CORE_ADDR caller_pc = frame_unwind_caller_pc (wp_frame);
+
+ scope_breakpoint
+ = create_internal_breakpoint (caller_arch, caller_pc,
+ bp_watchpoint_scope);
+
+ /* create_internal_breakpoint could invalidate WP_FRAME. */
+ wp_frame = nullptr;
+
+ scope_breakpoint->enable_state = bp_enabled;
+
+ /* Automatically delete the breakpoint when it hits. */
+ scope_breakpoint->disposition = disp_del;
+
+ /* Only break in the proper frame (help with recursion). */
+ scope_breakpoint->frame_id = caller_frame_id;
+
+ /* Set the address at which we will stop. */
+ bp_location &loc = scope_breakpoint->first_loc ();
+ loc.gdbarch = caller_arch;
+ loc.requested_address = caller_pc;
+ loc.address
+ = adjust_breakpoint_address (loc.gdbarch, loc.requested_address,
+ scope_breakpoint->type,
+ current_program_space);
+ }
+ }
+
+ if (scope_breakpoint != nullptr)
+ {
+ /* The scope breakpoint is related to the watchpoint. We will
+ need to act on them together. */
+ w->related_breakpoint = scope_breakpoint;
+ scope_breakpoint->related_breakpoint = w.get ();
+ }
+
+ /* Verify that the scope breakpoint comes before the watchpoint in the
+ breakpoint chain. */
+ gdb_assert (scope_breakpoint == nullptr
+ || &breakpoint_chain.back () == scope_breakpoint);
+ watchpoint *watchpoint_ptr = w.get ();
install_breakpoint (internal, std::move (w), 1);
+ gdb_assert (&breakpoint_chain.back () == watchpoint_ptr);
}
/* Return count of debug registers needed to watch the given expression.
@@ -10754,7 +10731,7 @@ static const gdb::option::option_def watch_option_defs[] = {
"location",
[] (watch_options *opt) { return &opt->location; },
N_("\
-This evaluates EXPRESSION and watches the memory to which is refers.\n\
+This evaluates EXPRESSION and watches the memory to which it refers.\n\
-l can be used as a short form of -location."),
},
};
@@ -11127,7 +11104,7 @@ clear_command (const char *arg, int from_tty)
}
}
- /* Now go thru the 'found' chain and delete them. */
+ /* Now go through the 'found' chain and delete them. */
if (found.empty ())
{
if (arg)
@@ -11850,10 +11827,11 @@ code_breakpoint::say_where () const
{
const char *filename
= symtab_to_filename_for_display (bl.symtab);
- gdb_printf (": file %ps, line %d.",
+ gdb_printf (": file %ps, line %ps.",
styled_string (file_name_style.style (),
filename),
- bl.line_number);
+ styled_string (line_number_style.style (),
+ pulongest (bl.line_number)));
}
else
/* This is not ideal, but each location may have a
@@ -11872,7 +11850,8 @@ code_breakpoint::say_where () const
/* See breakpoint.h. */
-bp_location_range breakpoint::locations () const
+bp_location_range
+breakpoint::locations () const
{
return bp_location_range (m_locations.begin (), m_locations.end ());
}
@@ -11962,7 +11941,7 @@ breakpoint::print_recreate (struct ui_file *fp) const
/* Default breakpoint_ops methods. */
void
-code_breakpoint::re_set ()
+code_breakpoint::re_set (struct program_space *pspace)
{
/* FIXME: is this still reachable? */
if (breakpoint_location_spec_empty_p (this))
@@ -11972,7 +11951,7 @@ code_breakpoint::re_set ()
return;
}
- re_set_default ();
+ re_set_default (pspace);
}
int
@@ -12178,7 +12157,7 @@ code_breakpoint::decode_location_spec (location_spec *locspec,
/* Virtual table for internal breakpoints. */
void
-internal_breakpoint::re_set ()
+internal_breakpoint::re_set (struct program_space *pspace)
{
switch (type)
{
@@ -12271,7 +12250,7 @@ internal_breakpoint::print_mention () const
/* Virtual table for momentary breakpoints */
void
-momentary_breakpoint::re_set ()
+momentary_breakpoint::re_set (struct program_space *pspace)
{
/* Keep temporary breakpoints, which can be encountered when we step
over a dlopen call and solib_add is resetting the breakpoints.
@@ -12312,12 +12291,13 @@ longjmp_breakpoint::~longjmp_breakpoint ()
static void
bkpt_probe_create_sals_from_location_spec (location_spec *locspec,
- struct linespec_result *canonical)
+ struct linespec_result *canonical,
+ struct program_space *search_pspace)
{
struct linespec_sals lsal;
- lsal.sals = parse_probes (locspec, NULL, canonical);
+ lsal.sals = parse_probes (locspec, search_pspace, canonical);
lsal.canonical = xstrdup (canonical->locspec->to_string ());
canonical->lsals.push_back (std::move (lsal));
}
@@ -12406,21 +12386,10 @@ tracepoint::print_recreate (struct ui_file *fp) const
gdb_printf (fp, " passcount %d\n", pass_count);
}
-/* Virtual table for tracepoints on static probes. */
-
-static void
-tracepoint_probe_create_sals_from_location_spec
- (location_spec *locspec,
- struct linespec_result *canonical)
-{
- /* We use the same method for breakpoint on probes. */
- bkpt_probe_create_sals_from_location_spec (locspec, canonical);
-}
-
void
-dprintf_breakpoint::re_set ()
+dprintf_breakpoint::re_set (struct program_space *pspace)
{
- re_set_default ();
+ re_set_default (pspace);
/* 1 - connect to target 1, that can run breakpoint commands.
2 - create a dprintf, which resolves fine.
@@ -12474,8 +12443,10 @@ dprintf_breakpoint::after_condition_true (struct bpstat *bs)
markers (`-m'). */
static void
-strace_marker_create_sals_from_location_spec (location_spec *locspec,
- struct linespec_result *canonical)
+strace_marker_create_sals_from_location_spec
+ (location_spec *locspec,
+ struct linespec_result *canonical,
+ struct program_space *search_pspace)
{
struct linespec_sals lsal;
const char *arg_start, *arg;
@@ -12890,7 +12861,7 @@ update_static_tracepoint (tracepoint *tp, struct symtab_and_line sal)
uiout->field_string ("fullname", fullname);
}
- uiout->field_signed ("line", sal2.line);
+ uiout->field_signed ("line", sal2.line, line_number_style.style ());
uiout->text ("\n");
tp->first_loc ().line_number = sal2.line;
@@ -12933,6 +12904,13 @@ locations_are_equal (const bp_location_list &a, const bp_location_range &b)
if (a_iter->disabled_by_cond != b_iter->disabled_by_cond)
return false;
+
+ /* When a breakpoint is set by address, it is not created as
+ pending; but then during an solib event or the like it may
+ acquire a symbol. So, check this here. */
+ if (a_iter->symbol != b_iter->symbol
+ || a_iter->msymbol != b_iter->msymbol)
+ return false;
}
return (a_iter == a.end ()) == (b_iter == b.end ());
@@ -13143,24 +13121,6 @@ code_breakpoint::location_spec_to_sals (location_spec *locspec,
{
for (auto &sal : sals)
resolve_sal_pc (&sal);
- if (condition_not_parsed && extra_string != NULL)
- {
- gdb::unique_xmalloc_ptr<char> local_cond, local_extra;
- int local_thread, local_task, local_inferior;
-
- find_condition_and_thread_for_sals (sals, extra_string.get (),
- &local_cond, &local_thread,
- &local_inferior,
- &local_task, &local_extra);
- gdb_assert (cond_string == nullptr);
- if (local_cond != nullptr)
- cond_string = std::move (local_cond);
- thread = local_thread;
- task = local_task;
- if (local_extra != nullptr)
- extra_string = std::move (local_extra);
- condition_not_parsed = 0;
- }
if (type == bp_static_tracepoint)
{
@@ -13181,51 +13141,46 @@ code_breakpoint::location_spec_to_sals (location_spec *locspec,
locations. */
void
-code_breakpoint::re_set_default ()
+code_breakpoint::re_set_default (struct program_space *filter_pspace)
{
- struct program_space *filter_pspace = current_program_space;
std::vector<symtab_and_line> expanded, expanded_end;
- int found;
- std::vector<symtab_and_line> sals = location_spec_to_sals (locspec.get (),
- filter_pspace,
- &found);
- if (found)
- expanded = std::move (sals);
-
- if (locspec_range_end != nullptr)
- {
- std::vector<symtab_and_line> sals_end
- = location_spec_to_sals (locspec_range_end.get (),
- filter_pspace, &found);
+ /* If this breakpoint is thread- or inferior-specific, then find the
+ program space in which this breakpoint exists. Otherwise, for
+ breakpoints that are not thread- or inferior-specific, BP_PSPACE will
+ be nullptr. */
+ program_space *bp_pspace
+ = find_program_space_for_breakpoint (this->thread, this->inferior);
+
+ /* If this is not a thread or inferior specific breakpoint, or it is a
+ thread or inferior specific breakpoint but we are looking for new
+ locations in the program space that the specific thread or inferior is
+ running, then look for new locations for this breakpoint. */
+ if (bp_pspace == nullptr || filter_pspace == bp_pspace)
+ {
+ int found;
+ std::vector<symtab_and_line> sals
+ = location_spec_to_sals (locspec.get (), filter_pspace, &found);
if (found)
- expanded_end = std::move (sals_end);
+ expanded = std::move (sals);
+
+ if (locspec_range_end != nullptr)
+ {
+ std::vector<symtab_and_line> sals_end
+ = location_spec_to_sals (locspec_range_end.get (),
+ filter_pspace, &found);
+ if (found)
+ expanded_end = std::move (sals_end);
+ }
}
+ /* Update the locations for this breakpoint. For thread-specific
+ breakpoints this will remove any old locations that are for the wrong
+ program space -- this can happen if the user changes the thread of a
+ thread-specific breakpoint. */
update_breakpoint_locations (this, filter_pspace, expanded, expanded_end);
}
-/* Default method for creating SALs from an address string. It basically
- calls parse_breakpoint_sals. Return 1 for success, zero for failure. */
-
-static void
-create_sals_from_location_spec_default (location_spec *locspec,
- struct linespec_result *canonical)
-{
- parse_breakpoint_sals (locspec, canonical);
-}
-
-/* Reset a breakpoint. */
-
-static void
-breakpoint_re_set_one (breakpoint *b)
-{
- input_radix = b->input_radix;
- set_language (b->language);
-
- b->re_set ();
-}
-
/* Re-set breakpoint locations for the current program space.
Locations bound to other program spaces are left untouched. */
@@ -13237,12 +13192,11 @@ breakpoint_re_set (void)
scoped_restore save_input_radix = make_scoped_restore (&input_radix);
scoped_restore_current_pspace_and_thread restore_pspace_thread;
- /* breakpoint_re_set_one sets the current_language to the language
- of the breakpoint it is resetting (see prepare_re_set_context)
- before re-evaluating the breakpoint's location. This change can
- unfortunately get undone by accident if the language_mode is set
- to auto, and we either switch frames, or more likely in this context,
- we select the current frame.
+ /* To ::re_set each breakpoint we set the current_language to the
+ language of the breakpoint before re-evaluating the breakpoint's
+ location. This change can unfortunately get undone by accident if
+ the language_mode is set to auto, and we either switch frames, or
+ more likely in this context, we select the current frame.
We prevent this by temporarily turning the language_mode to
language_mode_manual. We restore it once all breakpoints
@@ -13259,7 +13213,9 @@ breakpoint_re_set (void)
{
try
{
- breakpoint_re_set_one (&b);
+ input_radix = b.input_radix;
+ set_language (b.language);
+ b.re_set (current_program_space);
}
catch (const gdb_exception &ex)
{
@@ -13280,6 +13236,53 @@ breakpoint_re_set (void)
/* Now we can insert. */
update_global_location_list (UGLL_MAY_INSERT);
}
+
+/* Re-set locations for breakpoint B in FILTER_PSPACE. If FILTER_PSPACE is
+ nullptr then re-set locations for B in all program spaces. Locations
+ bound to program spaces other than FILTER_PSPACE are left untouched. */
+
+static void
+breakpoint_re_set_one (breakpoint *b, program_space *filter_pspace)
+{
+ {
+ scoped_restore_current_language save_language;
+ scoped_restore save_input_radix = make_scoped_restore (&input_radix);
+ scoped_restore_current_pspace_and_thread restore_pspace_thread;
+
+ /* To ::re_set each breakpoint we set the current_language to the
+ language of the breakpoint before re-evaluating the breakpoint's
+ location. This change can unfortunately get undone by accident if
+ the language_mode is set to auto, and we either switch frames, or
+ more likely in this context, we select the current frame.
+
+ We prevent this by temporarily turning the language_mode to
+ language_mode_manual. We restore it once all breakpoints
+ have been reset. */
+ scoped_restore save_language_mode = make_scoped_restore (&language_mode);
+ language_mode = language_mode_manual;
+
+ /* Note: we must not try to insert locations until after all
+ breakpoints have been re-set. Otherwise, e.g., when re-setting
+ breakpoint 1, we'd insert the locations of breakpoint 2, which
+ hadn't been re-set yet, and thus may have stale locations. */
+
+ try
+ {
+ input_radix = b->input_radix;
+ set_language (b->language);
+ b->re_set (filter_pspace);
+ }
+ catch (const gdb_exception &ex)
+ {
+ exception_fprintf (gdb_stderr, ex,
+ "Error in re-setting breakpoint %d: ",
+ b->number);
+ }
+ }
+
+ /* Now we can insert. */
+ update_global_location_list (UGLL_MAY_INSERT);
+}
/* Reset the thread number of this breakpoint:
@@ -15094,14 +15097,14 @@ This includes all types of breakpoints (breakpoints, watchpoints,\n\
catchpoints, tracepoints). Use the 'source' command in another debug\n\
session to restore them."),
&save_cmdlist);
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, deprecated_filename_completer);
cmd_list_element *save_tracepoints_cmd
= add_cmd ("tracepoints", class_trace, save_tracepoints_command, _("\
Save current tracepoint definitions as a script.\n\
Use the 'source' command in another debug session to restore them."),
&save_cmdlist);
- set_cmd_completer (save_tracepoints_cmd, filename_completer);
+ set_cmd_completer (save_tracepoints_cmd, deprecated_filename_completer);
c = add_com_alias ("save-tracepoints", save_tracepoints_cmd, class_trace, 0);
deprecate_cmd (c, "save tracepoints");
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index ddc3719..cef1d72 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -46,6 +46,14 @@ struct linespec_result;
struct linespec_sals;
struct inferior;
+/* True if breakpoint debug output is enabled. */
+extern bool debug_breakpoint;
+
+/* Print a "breakpoint" debug statement. */
+#define breakpoint_debug_printf(fmt, ...) \
+ debug_prefixed_printf_cond (debug_breakpoint, "breakpoint", fmt, \
+ ##__VA_ARGS__)
+
/* Enum for exception-handling support in 'catch throw', 'catch rethrow',
'catch catch' and the MI equivalent. */
@@ -452,7 +460,7 @@ public:
as ``address'' (above) except for cases in which
ADJUST_BREAKPOINT_ADDRESS has computed a different address at
which to place the breakpoint in order to comply with a
- processor's architectual constraints. */
+ processor's architectural constraints. */
CORE_ADDR requested_address = 0;
/* An additional address assigned with this location. This is currently
@@ -560,15 +568,15 @@ enum print_stop_action
struct breakpoint_ops
{
- /* Create SALs from location spec, storing the result in
- linespec_result.
-
- For an explanation about the arguments, see the function
- `create_sals_from_location_spec_default'.
+ /* Create SALs from LOCSPEC, storing the result in linespec_result
+ CANONICAL. If SEARCH_PSPACE is not nullptr then only results in the
+ corresponding program space are returned. If SEARCH_PSPACE is nullptr
+ then results for all program spaces are returned.
This function is called inside `create_breakpoint'. */
void (*create_sals_from_location_spec) (location_spec *locspec,
- struct linespec_result *canonical);
+ linespec_result *canonical,
+ program_space *search_pspace);
/* This method will be responsible for creating a breakpoint given its SALs.
Usually, it just calls `create_breakpoints_sal' (for ordinary
@@ -700,11 +708,19 @@ struct breakpoint : public intrusive_list_node<breakpoint>
/* Reevaluate a breakpoint. This is necessary after symbols change
(e.g., an executable or DSO was loaded, or the inferior just
- started). */
- virtual void re_set ()
- {
- /* Nothing to re-set. */
- }
+ started).
+
+ If not nullptr, then FILTER_PSPACE is the program space in which
+ symbols may have changed, we only need to add new locations in
+ FILTER_PSPACE.
+
+ If FILTER_PSPACE is nullptr then all program spaces may have changed,
+ new locations need to be searched for in every program space.
+
+ This is pure virtual as, at a minimum, each sub-class must recompute
+ any cached condition expressions based off of the cond_string member
+ variable. */
+ virtual void re_set (program_space *filter_pspace) = 0;
/* Insert the breakpoint or watchpoint or activate the catchpoint.
Return 0 for success, 1 if the breakpoint, watchpoint or
@@ -821,9 +837,21 @@ struct breakpoint : public intrusive_list_node<breakpoint>
equals this. */
struct frame_id frame_id = null_frame_id;
- /* The program space used to set the breakpoint. This is only set
- for breakpoints which are specific to a program space; for
- non-thread-specific ordinary breakpoints this is NULL. */
+ /* The program space used to set the breakpoint. This is only set for
+ breakpoints that are not type bp_breakpoint or bp_hardware_breakpoint.
+ For thread or inferior specific breakpoints, the breakpoints are
+ managed via the thread and inferior member variables. */
+
+ /* If not nullptr then this is the program space for which this
+ breakpoint was created. All watchpoint and catchpoint sub-types set
+ this field, but not all of the code_breakpoint sub-types do;
+ generally, user created breakpoint types don't set this field, though
+ things might be more consistent if they did.
+
+ When this variable is nullptr then a breakpoint might be associated
+ with multiple program spaces, though you need to check the thread,
+ inferior and task variables to see if a breakpoint was created for a
+ specific thread, inferior, or Ada task respectively. */
program_space *pspace = NULL;
/* The location specification we used to set the breakpoint. */
@@ -933,7 +961,7 @@ struct code_breakpoint : public breakpoint
/* Add a location for SAL to this breakpoint. */
bp_location *add_location (const symtab_and_line &sal);
- void re_set () override;
+ void re_set (program_space *pspace) override;
int insert_location (struct bp_location *) override;
int remove_location (struct bp_location *,
enum remove_bp_reason reason) override;
@@ -955,7 +983,7 @@ protected:
struct program_space *search_pspace);
/* Helper method that does the basic work of re_set. */
- void re_set_default ();
+ void re_set_default (program_space *pspace);
/* Find the SaL locations corresponding to the given LOCATION.
On return, FOUND will be 1 if any SaL was found, zero otherwise. */
@@ -977,7 +1005,7 @@ struct watchpoint : public breakpoint
{
using breakpoint::breakpoint;
- void re_set () override;
+ void re_set (program_space *pspace) override;
int insert_location (struct bp_location *) override;
int remove_location (struct bp_location *,
enum remove_bp_reason reason) override;
@@ -1118,6 +1146,10 @@ struct catchpoint : public breakpoint
catchpoint (struct gdbarch *gdbarch, bool temp, const char *cond_string);
~catchpoint () override = 0;
+
+ /* If the catchpoint has a condition set then recompute the cached
+ expression within the single dummy location. */
+ void re_set (program_space *filter_pspace) override;
};
diff --git a/gdb/bsd-uthread.c b/gdb/bsd-uthread.c
index a686f17..eb1ed42 100644
--- a/gdb/bsd-uthread.c
+++ b/gdb/bsd-uthread.c
@@ -157,9 +157,8 @@ static int bsd_uthread_active;
static CORE_ADDR
bsd_uthread_lookup_address (const char *name, struct objfile *objfile)
{
- struct bound_minimal_symbol sym;
-
- sym = lookup_minimal_symbol (name, NULL, objfile);
+ bound_minimal_symbol sym
+ = lookup_minimal_symbol (current_program_space, name, objfile);
if (sym.minsym)
return sym.value_address ();
diff --git a/gdb/btrace.c b/gdb/btrace.c
index 66f20ee..152f6f2 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -32,6 +32,7 @@
#include "gdbsupport/rsp-low.h"
#include "cli/cli-cmds.h"
#include "cli/cli-utils.h"
+#include "extension.h"
#include "gdbarch.h"
/* For maintenance commands. */
@@ -40,6 +41,7 @@
#include <inttypes.h>
#include <ctype.h>
#include <algorithm>
+#include <string>
/* Command lists for btrace maintenance commands. */
static struct cmd_list_element *maint_btrace_cmdlist;
@@ -545,32 +547,39 @@ ftrace_new_gap (struct btrace_thread_info *btinfo, int errcode,
Return the chronologically latest function segment, never NULL. */
static struct btrace_function *
-ftrace_update_function (struct btrace_thread_info *btinfo, CORE_ADDR pc)
+ftrace_update_function (struct btrace_thread_info *btinfo,
+ std::optional<CORE_ADDR> pc)
{
- struct bound_minimal_symbol bmfun;
- struct minimal_symbol *mfun;
- struct symbol *fun;
- struct btrace_function *bfun;
+ struct minimal_symbol *mfun = nullptr;
+ struct symbol *fun = nullptr;
/* Try to determine the function we're in. We use both types of symbols
to avoid surprises when we sometimes get a full symbol and sometimes
only a minimal symbol. */
- fun = find_pc_function (pc);
- bmfun = lookup_minimal_symbol_by_pc (pc);
- mfun = bmfun.minsym;
+ if (pc.has_value ())
+ {
+ fun = find_pc_function (*pc);
+ bound_minimal_symbol bmfun = lookup_minimal_symbol_by_pc (*pc);
+ mfun = bmfun.minsym;
- if (fun == NULL && mfun == NULL)
- DEBUG_FTRACE ("no symbol at %s", core_addr_to_string_nz (pc));
+ if (fun == nullptr && mfun == nullptr)
+ DEBUG_FTRACE ("no symbol at %s", core_addr_to_string_nz (*pc));
+ }
/* If we didn't have a function, we create one. */
if (btinfo->functions.empty ())
return ftrace_new_function (btinfo, mfun, fun);
/* If we had a gap before, we create a function. */
- bfun = &btinfo->functions.back ();
+ btrace_function *bfun = &btinfo->functions.back ();
if (bfun->errcode != 0)
return ftrace_new_function (btinfo, mfun, fun);
+ /* If there is no valid PC, which can happen for events with a
+ suppressed IP, we can't do more than return the last bfun. */
+ if (!pc.has_value ())
+ return bfun;
+
/* Check the last instruction, if we have one.
We do this check first, since it allows us to fill in the call stack
links in addition to the normal flow links. */
@@ -604,7 +613,7 @@ ftrace_update_function (struct btrace_thread_info *btinfo, CORE_ADDR pc)
case BTRACE_INSN_CALL:
/* Ignore calls to the next instruction. They are used for PIC. */
- if (last->pc + last->size == pc)
+ if (last->pc + last->size == *pc)
break;
return ftrace_new_call (btinfo, mfun, fun);
@@ -613,10 +622,10 @@ ftrace_update_function (struct btrace_thread_info *btinfo, CORE_ADDR pc)
{
CORE_ADDR start;
- start = get_pc_function_start (pc);
+ start = get_pc_function_start (*pc);
/* A jump to the start of a function is (typically) a tail call. */
- if (start == pc)
+ if (start == *pc)
return ftrace_new_tailcall (btinfo, mfun, fun);
/* Some versions of _Unwind_RaiseException use an indirect
@@ -641,6 +650,18 @@ ftrace_update_function (struct btrace_thread_info *btinfo, CORE_ADDR pc)
break;
}
+
+ case BTRACE_INSN_AUX:
+ /* An aux insn couldn't have switched the function. But the
+ segment might not have had a symbol name resolved yet, as events
+ might not have an IP. Use the current IP in that case and update
+ the name. */
+ if (bfun->sym == nullptr && bfun->msym == nullptr)
+ {
+ bfun->sym = fun;
+ bfun->msym = mfun;
+ }
+ break;
}
}
@@ -665,6 +686,11 @@ ftrace_update_insns (struct btrace_function *bfun, const btrace_insn &insn)
{
bfun->insn.push_back (insn);
+ if (insn.iclass == BTRACE_INSN_AUX)
+ bfun->flags |= BFUN_CONTAINS_AUX;
+ else
+ bfun->flags |= BFUN_CONTAINS_NON_AUX;
+
if (record_debug > 1)
ftrace_debug (bfun, "update insn");
}
@@ -1097,7 +1123,8 @@ btrace_compute_ftrace_bts (struct thread_info *tp,
break;
}
- bfun = ftrace_update_function (btinfo, pc);
+ bfun = ftrace_update_function (btinfo,
+ std::make_optional<CORE_ADDR> (pc));
/* Maintain the function level offset.
For all but the last block, we do it here. */
@@ -1196,11 +1223,69 @@ pt_btrace_insn_flags (const struct pt_insn &insn)
static btrace_insn
pt_btrace_insn (const struct pt_insn &insn)
{
- return {(CORE_ADDR) insn.ip, (gdb_byte) insn.size,
+ return {{static_cast<CORE_ADDR> (insn.ip)},
+ static_cast<gdb_byte> (insn.size),
pt_reclassify_insn (insn.iclass),
pt_btrace_insn_flags (insn)};
}
+#if defined (HAVE_PT_INSN_EVENT)
+/* Helper for events that will result in an aux_insn. */
+
+static void
+handle_pt_aux_insn (btrace_thread_info *btinfo, std::string &aux_str,
+ std::optional<CORE_ADDR> pc)
+{
+ btinfo->aux_data.emplace_back (std::move (aux_str));
+ struct btrace_function *bfun = ftrace_update_function (btinfo, pc);
+
+ btrace_insn insn {{btinfo->aux_data.size () - 1}, 0,
+ BTRACE_INSN_AUX, 0};
+
+ ftrace_update_insns (bfun, insn);
+}
+
+/* Check if the recording contains real instructions and not only auxiliary
+ instructions since the last gap (or since the beginning). */
+
+static bool
+ftrace_contains_non_aux_since_last_gap (const btrace_thread_info *btinfo)
+{
+ const std::vector<btrace_function> &functions = btinfo->functions;
+
+ std::vector<btrace_function>::const_reverse_iterator rit;
+ for (rit = functions.crbegin (); rit != functions.crend (); ++rit)
+ {
+ if (rit->errcode != 0)
+ return false;
+
+ if ((rit->flags & BFUN_CONTAINS_NON_AUX) != 0)
+ return true;
+ }
+
+ return false;
+}
+#endif /* defined (HAVE_PT_INSN_EVENT) */
+
+#if (LIBIPT_VERSION >= 0x201)
+/* Translate an interrupt vector to a mnemonic string as defined for x86.
+ Returns nullptr if there is none. */
+
+static const char *
+decode_interrupt_vector (const uint8_t vector)
+{
+ static const char *mnemonic[]
+ = { "#de", "#db", nullptr, "#bp", "#of", "#br", "#ud", "#nm",
+ "#df", "#mf", "#ts", "#np", "#ss", "#gp", "#pf", nullptr,
+ "#mf", "#ac", "#mc", "#xm", "#ve", "#cp" };
+
+ if (vector < (sizeof (mnemonic) / sizeof (mnemonic[0])))
+ return mnemonic[vector];
+
+ return nullptr;
+}
+#endif /* defined (LIBIPT_VERSION >= 0x201) */
+
/* Handle instruction decode events (libipt-v2). */
static int
@@ -1211,9 +1296,9 @@ handle_pt_insn_events (struct btrace_thread_info *btinfo,
#if defined (HAVE_PT_INSN_EVENT)
while (status & pts_event_pending)
{
- struct btrace_function *bfun;
struct pt_event event;
uint64_t offset;
+ std::optional<CORE_ADDR> pc;
status = pt_insn_event (decoder, &event, sizeof (event));
if (status < 0)
@@ -1225,30 +1310,294 @@ handle_pt_insn_events (struct btrace_thread_info *btinfo,
break;
case ptev_enabled:
- if (event.status_update != 0)
- break;
+ {
+ if (event.status_update != 0)
+ break;
- if (event.variant.enabled.resumed == 0 && !btinfo->functions.empty ())
- {
- bfun = ftrace_new_gap (btinfo, BDE_PT_DISABLED, gaps);
+ /* Only create a new gap if there are non-aux instructions in
+ the trace since the last gap. We could be at the beginning
+ of the recording and could already have handled one or more
+ events, like ptev_iret, that created aux insns. In that
+ case we don't want to create a gap or print a warning. */
+ if (event.variant.enabled.resumed == 0
+ && ftrace_contains_non_aux_since_last_gap (btinfo))
+ {
+ struct btrace_function *bfun
+ = ftrace_new_gap (btinfo, BDE_PT_NON_CONTIGUOUS, gaps);
- pt_insn_get_offset (decoder, &offset);
+ pt_insn_get_offset (decoder, &offset);
- warning (_("Non-contiguous trace at instruction %u (offset = 0x%"
- PRIx64 ")."), bfun->insn_offset - 1, offset);
- }
+ warning
+ (_("Non-contiguous trace at instruction %u (offset = 0x%"
+ PRIx64 ")."), bfun->insn_offset - 1, offset);
+ }
- break;
+ break;
+ }
case ptev_overflow:
- bfun = ftrace_new_gap (btinfo, BDE_PT_OVERFLOW, gaps);
+ {
+ struct btrace_function *bfun
+ = ftrace_new_gap (btinfo, BDE_PT_OVERFLOW, gaps);
- pt_insn_get_offset (decoder, &offset);
+ pt_insn_get_offset (decoder, &offset);
- warning (_("Overflow at instruction %u (offset = 0x%" PRIx64 ")."),
- bfun->insn_offset - 1, offset);
+ warning (_("Overflow at instruction %u (offset = 0x%" PRIx64 ")."),
+ bfun->insn_offset - 1, offset);
- break;
+ break;
+ }
+#if defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE)
+ case ptev_ptwrite:
+ {
+ std::optional<std::string> ptw_string;
+
+ /* Lookup the PC if available. The event often doesn't provide
+ one, so we look into the last function segment as well.
+ Looking further back makes limited sense for ptwrite. */
+ if (event.ip_suppressed == 0)
+ pc = event.variant.ptwrite.ip;
+ else if (!btinfo->functions.empty ())
+ {
+ std::vector<btrace_insn> &insns
+ = btinfo->functions.back ().insn;
+ for (auto insn = insns.rbegin (); insn != insns.rend ();
+ ++insn)
+ {
+ switch (insn->iclass)
+ {
+ case BTRACE_INSN_AUX:
+ continue;
+
+ case BTRACE_INSN_OTHER:
+ case BTRACE_INSN_CALL:
+ case BTRACE_INSN_RETURN:
+ case BTRACE_INSN_JUMP:
+ pc = insn->pc;
+ break;
+ /* No default to rely on compiler warnings. */
+ }
+ break;
+ }
+ }
+
+ if (!pc.has_value ())
+ warning (_("Failed to determine the PC for ptwrite."));
+
+
+ if (btinfo->ptw_callback_fun != nullptr)
+ ptw_string
+ = btinfo->ptw_callback_fun (event.variant.ptwrite.payload,
+ pc, btinfo->ptw_context);
+
+ if (ptw_string.has_value () && (*ptw_string).empty ())
+ continue;
+
+ if (!ptw_string.has_value ())
+ *ptw_string = hex_string (event.variant.ptwrite.payload);
+
+ handle_pt_aux_insn (btinfo, *ptw_string, pc);
+
+ break;
+ }
+#endif /* defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) */
+
+#if (LIBIPT_VERSION >= 0x201)
+ case ptev_interrupt:
+ {
+ std::string aux_string = std::string (_("interrupt: vector = "))
+ + hex_string (event.variant.interrupt.vector);
+
+ const char *decoded
+ = decode_interrupt_vector (event.variant.interrupt.vector);
+ if (decoded != nullptr)
+ aux_string += std::string (" (") + decoded + ")";
+
+ if (event.variant.interrupt.has_cr2 != 0)
+ {
+ aux_string += std::string (", cr2 = ")
+ + hex_string (event.variant.interrupt.cr2);
+ }
+
+ if (event.ip_suppressed == 0)
+ {
+ pc = event.variant.interrupt.ip;
+ aux_string += std::string (", ip = ") + hex_string (*pc);
+ }
+
+ handle_pt_aux_insn (btinfo, aux_string, pc);
+ break;
+ }
+
+ case ptev_iret:
+ {
+ std::string aux_string = std::string (_("iret"));
+
+ if (event.ip_suppressed == 0)
+ {
+ pc = event.variant.iret.ip;
+ aux_string += std::string (": ip = ") + hex_string (*pc);
+ }
+
+ handle_pt_aux_insn (btinfo, aux_string, pc);
+ break;
+ }
+
+ case ptev_smi:
+ {
+ std::string aux_string = std::string (_("smi"));
+
+ if (event.ip_suppressed == 0)
+ {
+ pc = event.variant.smi.ip;
+ aux_string += std::string (": ip = ") + hex_string (*pc);
+ }
+
+ handle_pt_aux_insn (btinfo, aux_string, pc);
+ break;
+ }
+
+ case ptev_rsm:
+ {
+ std::string aux_string = std::string (_("rsm"));
+
+ if (event.ip_suppressed == 0)
+ {
+ pc = event.variant.rsm.ip;
+ aux_string += std::string (": ip = ") + hex_string (*pc);
+ }
+
+ handle_pt_aux_insn (btinfo, aux_string, pc);
+ break;
+ }
+
+ case ptev_sipi:
+ {
+ std::string aux_string = std::string (_("sipi: vector = "))
+ + hex_string (event.variant.sipi.vector);
+
+ handle_pt_aux_insn (btinfo, aux_string, pc);
+ break;
+ }
+
+ case ptev_init:
+ {
+ std::string aux_string = std::string (_("init"));
+
+ if (event.ip_suppressed == 0)
+ {
+ pc = event.variant.init.ip;
+ aux_string += std::string (": ip = ") + hex_string (*pc);
+ }
+
+ handle_pt_aux_insn (btinfo, aux_string, pc);
+ break;
+ }
+
+ case ptev_vmentry:
+ {
+ std::string aux_string = std::string (_("vmentry"));
+
+ if (event.ip_suppressed == 0)
+ {
+ pc = event.variant.vmentry.ip;
+ aux_string += std::string (": ip = ") + hex_string (*pc);
+ }
+
+ handle_pt_aux_insn (btinfo, aux_string, pc);
+ break;
+ }
+
+ case ptev_vmexit:
+ {
+ std::string aux_string = std::string (_("vmexit"));
+
+ if (event.variant.vmexit.has_vector != 0
+ || event.variant.vmexit.has_vmxr != 0
+ || event.variant.vmexit.has_vmxq != 0
+ || event.ip_suppressed != 0)
+ aux_string += std::string (":");
+
+ if (event.variant.vmexit.has_vector != 0)
+ {
+ aux_string += std::string (_(" vector = "))
+ + hex_string (event.variant.vmexit.vector);
+
+ const char* decoded = decode_interrupt_vector
+ (event.variant.vmexit.vector);
+ if (decoded != nullptr)
+ aux_string += std::string (" (") + decoded + ")";
+ }
+
+ if (event.variant.vmexit.has_vmxr != 0)
+ {
+ std::string seperator = aux_string.back () == ':' ? "" : ",";
+ aux_string += seperator + std::string (" vmxr = ")
+ + hex_string (event.variant.vmexit.vmxr);
+ }
+
+ if (event.variant.vmexit.has_vmxq != 0)
+ {
+ std::string seperator = aux_string.back () == ':' ? "" : ",";
+ aux_string += seperator + std::string (" vmxq = ")
+ + hex_string (event.variant.vmexit.vmxq);
+ }
+
+ if (event.ip_suppressed == 0)
+ {
+ pc = event.variant.vmexit.ip;
+ std::string seperator = aux_string.back () == ':' ? "" : ",";
+ aux_string += seperator + std::string (" ip = ")
+ + hex_string (*pc);
+ }
+
+ handle_pt_aux_insn (btinfo, aux_string, pc);
+ break;
+ }
+
+ case ptev_shutdown:
+ {
+ std::string aux_string = std::string (_("shutdown"));
+
+ if (event.ip_suppressed == 0)
+ {
+ pc = event.variant.shutdown.ip;
+ aux_string += std::string (": ip = ") + hex_string (*pc);
+ }
+
+ handle_pt_aux_insn (btinfo, aux_string, pc);
+ break;
+ }
+
+ case ptev_uintr:
+ {
+ std::string aux_string = std::string (_("uintr: vector = "))
+ + hex_string (event.variant.uintr.vector);
+
+ if (event.ip_suppressed == 0)
+ {
+ pc = event.variant.uintr.ip;
+ aux_string += std::string (", ip = ") + hex_string (*pc);
+ }
+
+ handle_pt_aux_insn (btinfo, aux_string, pc);
+ break;
+ }
+
+ case ptev_uiret:
+ {
+ std::string aux_string = std::string (_("uiret"));
+
+ if (event.ip_suppressed == 0)
+ {
+ pc = event.variant.uiret.ip;
+ aux_string += std::string (": ip = ") + hex_string (*pc);
+ }
+
+ handle_pt_aux_insn (btinfo, aux_string, pc);
+ break;
+ }
+#endif /* defined (LIBIPT_VERSION >= 0x201) */
}
}
#endif /* defined (HAVE_PT_INSN_EVENT) */
@@ -1275,7 +1624,7 @@ handle_pt_insn_event_flags (struct btrace_thread_info *btinfo,
struct btrace_function *bfun;
uint64_t offset;
- bfun = ftrace_new_gap (btinfo, BDE_PT_DISABLED, gaps);
+ bfun = ftrace_new_gap (btinfo, BDE_PT_NON_CONTIGUOUS, gaps);
pt_insn_get_offset (decoder, &offset);
@@ -1314,6 +1663,9 @@ ftrace_add_pt (struct btrace_thread_info *btinfo,
uint64_t offset;
int status;
+ /* Register the ptwrite filter. */
+ apply_ext_lang_ptwrite_filter (btinfo);
+
for (;;)
{
struct pt_insn insn;
@@ -1341,7 +1693,9 @@ ftrace_add_pt (struct btrace_thread_info *btinfo,
/* Handle events indicated by flags in INSN. */
handle_pt_insn_event_flags (btinfo, decoder, insn, gaps);
- bfun = ftrace_update_function (btinfo, insn.ip);
+ bfun
+ = ftrace_update_function (btinfo,
+ std::make_optional<CORE_ADDR> (insn.ip));
/* Maintain the function level offset. */
*plevel = std::min (*plevel, bfun->level);
@@ -1820,6 +2174,8 @@ btrace_clear_history (struct btrace_thread_info *btinfo)
btinfo->insn_history = NULL;
btinfo->call_history = NULL;
btinfo->replay = NULL;
+
+ btinfo->aux_data.clear ();
}
/* Clear the branch trace maintenance histories in BTINFO. */
@@ -1877,8 +2233,8 @@ btrace_decode_error (enum btrace_format format, int errcode)
case BDE_PT_USER_QUIT:
return _("trace decode cancelled");
- case BDE_PT_DISABLED:
- return _("disabled");
+ case BDE_PT_NON_CONTIGUOUS:
+ return _("non-contiguous");
case BDE_PT_OVERFLOW:
return _("overflow");
@@ -2649,6 +3005,27 @@ pt_print_packet (const struct pt_packet *packet)
case ppt_mnt:
gdb_printf (("mnt %" PRIx64 ""), packet->payload.mnt.payload);
break;
+
+#if (LIBIPT_VERSION >= 0x200)
+ case ppt_ptw:
+ gdb_printf (("ptw %u: 0x%" PRIx64 "%s"), packet->payload.ptw.plc,
+ packet->payload.ptw.payload,
+ packet->payload.ptw.ip ? (" ip") : (""));
+ break;
+#endif /* defined (LIBIPT_VERSION >= 0x200) */
+
+#if (LIBIPT_VERSION >= 0x201)
+ case ppt_cfe:
+ gdb_printf (("cfe %u: 0x%x%s"), packet->payload.cfe.type,
+ packet->payload.cfe.vector,
+ packet->payload.cfe.ip ? (" ip") : (""));
+ break;
+
+ case ppt_evd:
+ gdb_printf (("evd %u: 0x%" PRIx64 ""), packet->payload.evd.type,
+ packet->payload.evd.payload);
+ break;
+#endif /* defined (LIBIPT_VERSION >= 0x201) */
}
}
diff --git a/gdb/btrace.h b/gdb/btrace.h
index f05ec2b..a4960f3 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -35,6 +35,7 @@
#endif
#include <vector>
+#include <string>
struct thread_info;
struct btrace_function;
@@ -52,7 +53,10 @@ enum btrace_insn_class
BTRACE_INSN_RETURN,
/* The instruction is an unconditional jump. */
- BTRACE_INSN_JUMP
+ BTRACE_INSN_JUMP,
+
+ /* The instruction is a pseudo instruction containing auxiliary data. */
+ BTRACE_INSN_AUX
};
/* Instruction flags. */
@@ -68,8 +72,19 @@ DEF_ENUM_FLAGS_TYPE (enum btrace_insn_flag, btrace_insn_flags);
This represents a single instruction in a branch trace. */
struct btrace_insn
{
- /* The address of this instruction. */
- CORE_ADDR pc;
+ union
+ {
+ /* The address of this instruction. Applies to btrace_insn with
+ iclass == BTRACE_INSN_OTHER or
+ iclass == BTRACE_INSN_CALL or
+ iclass == BTRACE_INSN_RETURN or
+ iclass == BTRACE_INSN_JUMP. */
+ CORE_ADDR pc;
+
+ /* Index into btrace_info::aux_data. Applies to btrace_insn with
+ iclass == BTRACE_INSN_AUX. */
+ uint64_t aux_data_index;
+ };
/* The size of this instruction in bytes. */
gdb_byte size;
@@ -91,7 +106,15 @@ enum btrace_function_flag
/* The 'up' link points to a tail call. This obviously only makes sense
if bfun_up_links_to_ret is clear. */
- BFUN_UP_LINKS_TO_TAILCALL = (1 << 1)
+ BFUN_UP_LINKS_TO_TAILCALL = (1 << 1),
+
+ /* Indicates that at least one auxiliary instruction is in the current
+ function segment. */
+ BFUN_CONTAINS_AUX = (1 << 2),
+
+ /* Indicates that at least one instruction not of type BTRACE_INSN_AUX
+ is in the current function segment. */
+ BFUN_CONTAINS_NON_AUX = (1 << 3)
};
DEF_ENUM_FLAGS_TYPE (enum btrace_function_flag, btrace_function_flags);
@@ -112,7 +135,7 @@ enum btrace_pt_error
BDE_PT_USER_QUIT = 1,
/* Tracing was temporarily disabled. */
- BDE_PT_DISABLED,
+ BDE_PT_NON_CONTIGUOUS,
/* Trace recording overflowed. */
BDE_PT_OVERFLOW
@@ -165,7 +188,7 @@ struct btrace_function
/* The instruction number offset for the first instruction in this
function segment.
- If INSN is empty this is the insn_offset of the succeding function
+ If INSN is empty this is the insn_offset of the succeeding function
segment in control-flow order. */
unsigned int insn_offset;
@@ -330,6 +353,20 @@ struct btrace_thread_info
function segment i will be at index (i - 1). */
std::vector<btrace_function> functions;
+ /* Optional auxiliary information that is printed in all commands
+ displaying or stepping through the execution history. */
+ std::vector<std::string> aux_data;
+
+ /* Function pointer to the ptwrite callback. Returns the string returned
+ by the ptwrite filter function. */
+ std::optional<std::string> (*ptw_callback_fun) (const uint64_t payload,
+ std::optional<uint64_t> ip,
+ const void *ptw_context)
+ = nullptr;
+
+ /* Context for the ptw_callback_fun. */
+ void *ptw_context = nullptr;
+
/* The function level offset. When added to each function's LEVEL,
this normalizes the function levels such that the smallest level
becomes zero. */
diff --git a/gdb/build-id.c b/gdb/build-id.c
index 8ce94f1..6266be1 100644
--- a/gdb/build-id.c
+++ b/gdb/build-id.c
@@ -26,6 +26,8 @@
#include "filenames.h"
#include "gdbcore.h"
#include "cli/cli-style.h"
+#include "gdbsupport/scoped_fd.h"
+#include "debuginfod-support.h"
/* See build-id.h. */
@@ -73,50 +75,149 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
return retval;
}
-/* Helper for build_id_to_debug_bfd. LINK is a path to a potential
- build-id-based separate debug file, potentially a symlink to the real file.
- If the file exists and matches BUILD_ID, return a BFD reference to it. */
+/* Helper for build_id_to_debug_bfd. ORIGINAL_LINK with SUFFIX appended is
+ a path to a potential build-id-based separate debug file, potentially a
+ symlink to the real file. If the file exists and matches BUILD_ID,
+ return a BFD reference to it. */
static gdb_bfd_ref_ptr
-build_id_to_debug_bfd_1 (const std::string &link, size_t build_id_len,
- const bfd_byte *build_id)
+build_id_to_debug_bfd_1 (const std::string &original_link,
+ size_t build_id_len, const bfd_byte *build_id,
+ const char *suffix)
{
- separate_debug_file_debug_printf ("Trying %s...", link.c_str ());
-
- /* lrealpath() is expensive even for the usually non-existent files. */
- gdb::unique_xmalloc_ptr<char> filename_holder;
- const char *filename = nullptr;
- if (is_target_filename (link))
- filename = link.c_str ();
- else if (access (link.c_str (), F_OK) == 0)
+ tribool supports_target_stat = TRIBOOL_UNKNOWN;
+
+ /* Drop the 'target:' prefix if the target filesystem is local. */
+ std::string_view original_link_view (original_link);
+ if (is_target_filename (original_link) && target_filesystem_is_local ())
+ original_link_view
+ = original_link_view.substr (strlen (TARGET_SYSROOT_PREFIX));
+
+ /* The upper bound of '10' here is completely arbitrary. The loop should
+ terminate via 'break' when either (a) a readable symlink is found, or
+ (b) a non-existing entry is found.
+
+ However, for remote targets, we rely on the remote returning sane
+ error codes. If a remote sends back the wrong error code then it
+ might trick GDB into thinking that the symlink exists, but points to a
+ missing file, in which case GDB will try the next seqno. We don't
+ want a broken remote to cause GDB to spin here forever, hence a fixed
+ upper bound. */
+
+ for (unsigned seqno = 0; seqno < 10; seqno++)
{
- filename_holder.reset (lrealpath (link.c_str ()));
- filename = filename_holder.get ();
- }
+ std::string link (original_link_view);
- if (filename == NULL)
- {
- separate_debug_file_debug_printf ("unable to compute real path");
- return {};
- }
+ if (seqno > 0)
+ string_appendf (link, ".%u", seqno);
- /* We expect to be silent on the non-existing files. */
- gdb_bfd_ref_ptr debug_bfd = gdb_bfd_open (filename, gnutarget);
+ link += suffix;
- if (debug_bfd == NULL)
- {
- separate_debug_file_debug_printf ("unable to open.");
- return {};
- }
+ separate_debug_file_debug_printf ("Trying %s...", link.c_str ());
- if (!build_id_verify (debug_bfd.get(), build_id_len, build_id))
- {
- separate_debug_file_debug_printf ("build-id does not match.");
- return {};
+ gdb::unique_xmalloc_ptr<char> filename_holder;
+ const char *filename = nullptr;
+ if (is_target_filename (link))
+ {
+ gdb_assert (link.length () >= strlen (TARGET_SYSROOT_PREFIX));
+ const char *link_on_target
+ = link.c_str () + strlen (TARGET_SYSROOT_PREFIX);
+
+ fileio_error target_errno;
+ if (supports_target_stat != TRIBOOL_FALSE)
+ {
+ struct stat sb;
+ int res = target_fileio_stat (nullptr, link_on_target, &sb,
+ &target_errno);
+
+ if (res != 0 && target_errno != FILEIO_ENOSYS)
+ {
+ separate_debug_file_debug_printf ("path doesn't exist");
+ break;
+ }
+ else if (res != 0 && target_errno == FILEIO_ENOSYS)
+ supports_target_stat = TRIBOOL_FALSE;
+ else
+ {
+ supports_target_stat = TRIBOOL_TRUE;
+ filename = link.c_str ();
+ }
+ }
+
+ if (supports_target_stat == TRIBOOL_FALSE)
+ {
+ gdb_assert (filename == nullptr);
+
+ /* Connecting to a target that doesn't support 'stat'. Try
+ 'readlink' as an alternative. This isn't ideal, but is
+ maybe better than nothing. Returns EINVAL if the path
+ isn't a symbolic link, which hints that the path is
+ available -- there are other errors e.g. ENOENT for when
+ 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_errno);
+ if (link_target.has_value ()
+ || target_errno == FILEIO_EINVAL)
+ filename = link.c_str ();
+ else
+ {
+ separate_debug_file_debug_printf ("path doesn't exist");
+ break;
+ }
+ }
+ }
+ else
+ {
+ struct stat buf;
+
+ /* The `access' call below automatically dereferences LINK, but
+ we want to stop incrementing SEQNO once we find a symlink
+ that doesn't exist. */
+ if (lstat (link.c_str (), &buf) != 0)
+ {
+ separate_debug_file_debug_printf ("path doesn't exist");
+ break;
+ }
+
+ /* Can LINK be accessed, or if LINK is a symlink, can the file
+ pointed too be accessed? Do this as lrealpath() is
+ expensive, even for the usually non-existent files. */
+ if (access (link.c_str (), F_OK) == 0)
+ {
+ filename_holder.reset (lrealpath (link.c_str ()));
+ filename = filename_holder.get ();
+ }
+ }
+
+ if (filename == nullptr)
+ {
+ separate_debug_file_debug_printf ("unable to compute real path");
+ continue;
+ }
+
+ /* We expect to be silent on the non-existing files. */
+ gdb_bfd_ref_ptr debug_bfd = gdb_bfd_open (filename, gnutarget);
+
+ if (debug_bfd == NULL)
+ {
+ separate_debug_file_debug_printf ("unable to open `%s`", filename);
+ continue;
+ }
+
+ if (!build_id_verify (debug_bfd.get(), build_id_len, build_id))
+ {
+ separate_debug_file_debug_printf ("build-id does not match");
+ continue;
+ }
+
+ separate_debug_file_debug_printf ("found a match");
+ return debug_bfd;
}
- separate_debug_file_debug_printf ("found a match");
- return debug_bfd;
+ separate_debug_file_debug_printf ("no suitable file found");
+ return {};
}
/* Common code for finding BFDs of a given build-id. This function
@@ -156,10 +257,8 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
while (size-- > 0)
string_appendf (link, "%02x", (unsigned) *data++);
- link += suffix;
-
gdb_bfd_ref_ptr debug_bfd
- = build_id_to_debug_bfd_1 (link, build_id_len, build_id);
+ = build_id_to_debug_bfd_1 (link, build_id_len, build_id, suffix);
if (debug_bfd != NULL)
return debug_bfd;
@@ -176,7 +275,8 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
|| !target_filesystem_is_local ()))
{
link = gdb_sysroot + link;
- debug_bfd = build_id_to_debug_bfd_1 (link, build_id_len, build_id);
+ debug_bfd = build_id_to_debug_bfd_1 (link, build_id_len, build_id,
+ suffix);
if (debug_bfd != NULL)
return debug_bfd;
}
@@ -193,9 +293,11 @@ build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
return build_id_to_bfd_suffix (build_id_len, build_id, ".debug");
}
-/* See build-id.h. */
+/* Find and open a BFD for an executable file given a build-id. If no BFD
+ can be found, return NULL. The returned reference to the BFD must be
+ released by the caller. */
-gdb_bfd_ref_ptr
+static gdb_bfd_ref_ptr
build_id_to_exec_bfd (size_t build_id_len, const bfd_byte *build_id)
{
return build_id_to_bfd_suffix (build_id_len, build_id, "");
@@ -237,3 +339,37 @@ find_separate_debug_file_by_buildid (struct objfile *objfile,
return std::string ();
}
+
+/* See build-id.h. */
+
+gdb_bfd_ref_ptr
+find_objfile_by_build_id (const bfd_build_id *build_id,
+ const char *expected_filename)
+{
+ /* Try to find the executable (or shared object) by looking for a
+ (sym)link on disk from the build-id to the object file. */
+ gdb_bfd_ref_ptr abfd = build_id_to_exec_bfd (build_id->size,
+ build_id->data);
+
+ if (abfd != nullptr)
+ return abfd;
+
+ /* Attempt to query debuginfod for the executable. */
+ gdb::unique_xmalloc_ptr<char> path;
+ scoped_fd fd = debuginfod_exec_query (build_id->data, build_id->size,
+ expected_filename, &path);
+ if (fd.get () >= 0)
+ {
+ abfd = gdb_bfd_open (path.get (), gnutarget);
+
+ if (abfd == nullptr)
+ warning (_("\"%ps\" from debuginfod cannot be opened as bfd: %s"),
+ styled_string (file_name_style.style (), path.get ()),
+ gdb_bfd_errmsg (bfd_get_error (), nullptr).c_str ());
+ else if (!build_id_verify (abfd.get (), build_id->size,
+ build_id->data))
+ abfd = nullptr;
+ }
+
+ return abfd;
+}
diff --git a/gdb/build-id.h b/gdb/build-id.h
index c5f20f8..1d2e789 100644
--- a/gdb/build-id.h
+++ b/gdb/build-id.h
@@ -40,13 +40,6 @@ extern int build_id_verify (bfd *abfd,
extern gdb_bfd_ref_ptr build_id_to_debug_bfd (size_t build_id_len,
const bfd_byte *build_id);
-/* Find and open a BFD for an executable file given a build-id. If no BFD
- can be found, return NULL. The returned reference to the BFD must be
- released by the caller. */
-
-extern gdb_bfd_ref_ptr build_id_to_exec_bfd (size_t build_id_len,
- const bfd_byte *build_id);
-
/* Find the separate debug file for OBJFILE, by using the build-id
associated with OBJFILE's BFD. If successful, returns the file name for the
separate debug file, otherwise, return an empty string.
@@ -60,6 +53,21 @@ extern gdb_bfd_ref_ptr build_id_to_exec_bfd (size_t build_id_len,
extern std::string find_separate_debug_file_by_buildid
(struct objfile *objfile, deferred_warnings *warnings);
+/* Find an objfile (executable or shared library) that matches BUILD_ID.
+ This is done by first checking in the debug-file-directory for a
+ suitable .build-id/ sub-directory, and looking for a file with the
+ required build-id (usually a symbolic link or hard link to the actual
+ file).
+
+ If that doesn't find us a file then we call to debuginfod to see if it
+ can provide the required file.
+
+ EXPECTED_FILENAME is used in output messages from debuginfod, this
+ should be the file we were looking for but couldn't find. */
+
+extern gdb_bfd_ref_ptr find_objfile_by_build_id
+ (const bfd_build_id *build_id, const char *expected_filename);
+
/* Return an hex-string representation of BUILD_ID. */
static inline std::string
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index 1c762ad..02d6848 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -951,11 +951,7 @@ buildsym_compunit::end_compunit_symtab_with_blockvector
cu->set_producer (m_producer);
cu->set_blockvector (blockvector);
- {
- struct block *b = blockvector->global_block ();
-
- b->set_compunit_symtab (cu);
- }
+ blockvector->global_block ()->set_compunit (cu);
cu->set_macro_table (release_macros ());
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 6022317..645cb59 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -1210,10 +1210,11 @@ variable: name_not_typename
std::string arg = copy_name ($1.stoken);
bound_minimal_symbol msymbol
- = lookup_bound_minimal_symbol (arg.c_str ());
+ = lookup_minimal_symbol (current_program_space, arg.c_str ());
if (msymbol.minsym == NULL)
{
- if (!have_full_symbols () && !have_partial_symbols ())
+ if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space))
error (_("No symbol table is loaded. Use the \"file\" command."));
else
error (_("No symbol \"%s\" in current context."),
@@ -3086,10 +3087,8 @@ classify_name (struct parser_state *par_state, const struct block *block,
|| is_quoted_name)
{
/* See if it's a file name. */
- struct symtab *symtab;
-
- symtab = lookup_symtab (copy.c_str ());
- if (symtab)
+ if (auto symtab = lookup_symtab (current_program_space, copy.c_str ());
+ symtab != nullptr)
{
yylval.bval
= symtab->compunit ()->blockvector ()->static_block ();
@@ -3149,7 +3148,7 @@ classify_name (struct parser_state *par_state, const struct block *block,
if (bsym.symbol == NULL
&& par_state->language ()->la_language == language_cplus
&& is_a_field_of_this.type == NULL
- && lookup_minimal_symbol (copy.c_str (), NULL, NULL).minsym == NULL)
+ && lookup_minimal_symbol (current_program_space, copy.c_str ()).minsym == nullptr)
return UNKNOWN_CPP_NAME;
return NAME;
diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c
index ca24b15..bad9490 100644
--- a/gdb/c-valprint.c
+++ b/gdb/c-valprint.c
@@ -176,8 +176,7 @@ print_unpacked_pointer (struct type *type, struct type *elttype,
{
/* Print vtbl's nicely. */
CORE_ADDR vt_address = unpack_pointer (type, valaddr + embedded_offset);
- struct bound_minimal_symbol msymbol =
- lookup_minimal_symbol_by_pc (vt_address);
+ bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (vt_address);
/* If 'symbol_print' is set, we did the work above. */
if (!options->symbol_print
diff --git a/gdb/cli-out.c b/gdb/cli-out.c
index 1c303f0..d8a542d 100644
--- a/gdb/cli-out.c
+++ b/gdb/cli-out.c
@@ -94,13 +94,14 @@ cli_ui_out::do_end (ui_out_type type)
void
cli_ui_out::do_field_signed (int fldno, int width, ui_align alignment,
- const char *fldname, LONGEST value)
+ const char *fldname, LONGEST value,
+ const ui_file_style &style)
{
if (m_suppress_output)
return;
do_field_string (fldno, width, alignment, fldname, plongest (value),
- ui_file_style ());
+ style);
}
/* output an unsigned field */
diff --git a/gdb/cli-out.h b/gdb/cli-out.h
index f17cb0c..f0654b2 100644
--- a/gdb/cli-out.h
+++ b/gdb/cli-out.h
@@ -52,7 +52,8 @@ protected:
virtual void do_begin (ui_out_type type, const char *id) override;
virtual void do_end (ui_out_type type) override;
virtual void do_field_signed (int fldno, int width, ui_align align,
- const char *fldname, LONGEST value) override;
+ const char *fldname, LONGEST value,
+ const ui_file_style &style) override;
virtual void do_field_unsigned (int fldno, int width, ui_align align,
const char *fldname, ULONGEST value)
override;
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 3af794c..ea2e156 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -51,7 +51,6 @@
#include "cli/cli-cmds.h"
#include "cli/cli-style.h"
#include "cli/cli-utils.h"
-#include "cli/cli-style.h"
#include "extension.h"
#include "gdbsupport/pathstuff.h"
@@ -423,31 +422,7 @@ complete_command (const char *arg, int from_tty)
{
std::string arg_prefix (arg, word - arg);
- if (result.number_matches == 1)
- printf_unfiltered ("%s%s\n", arg_prefix.c_str (), result.match_list[0]);
- else
- {
- result.sort_match_list ();
-
- for (size_t i = 0; i < result.number_matches; i++)
- {
- printf_unfiltered ("%s%s",
- arg_prefix.c_str (),
- result.match_list[i + 1]);
- if (quote_char)
- printf_unfiltered ("%c", quote_char);
- printf_unfiltered ("\n");
- }
- }
-
- if (result.number_matches == max_completions)
- {
- /* ARG_PREFIX and WORD are included in the output so that emacs
- will include the message in the output. */
- printf_unfiltered (_("%s%s %s\n"),
- arg_prefix.c_str (), word,
- get_max_completions_reached_message ());
- }
+ result.print_matches (arg_prefix, word, quote_char);
}
}
@@ -984,7 +959,7 @@ edit_command (const char *arg, int from_tty)
if (arg == 0)
{
set_default_source_symtab_and_line ();
- sal = get_current_source_symtab_and_line ();
+ sal = get_current_source_symtab_and_line (current_program_space);
}
/* Bare "edit" edits file with present line. */
@@ -1041,16 +1016,23 @@ edit_command (const char *arg, int from_tty)
gdbarch = sal.symtab->compunit ()->objfile ()->arch ();
sym = find_pc_function (sal.pc);
if (sym)
- gdb_printf ("%s is in %s (%s:%d).\n",
- paddress (gdbarch, sal.pc),
- sym->print_name (),
- symtab_to_filename_for_display (sal.symtab),
- sal.line);
+ gdb_printf ("%ps is in %ps (%ps:%ps).\n",
+ styled_string (address_style.style (),
+ paddress (gdbarch, sal.pc)),
+ styled_string (function_name_style.style (),
+ sym->print_name ()),
+ styled_string (file_name_style.style (),
+ symtab_to_filename_for_display (sal.symtab)),
+ styled_string (line_number_style.style (),
+ pulongest (sal.line)));
else
- gdb_printf ("%s is at %s:%d.\n",
- paddress (gdbarch, sal.pc),
- symtab_to_filename_for_display (sal.symtab),
- sal.line);
+ gdb_printf ("%ps is at %ps:%ps.\n",
+ styled_string (address_style.style (),
+ paddress (gdbarch, sal.pc)),
+ styled_string (file_name_style.style (),
+ symtab_to_filename_for_display (sal.symtab)),
+ styled_string (line_number_style.style (),
+ pulongest (sal.line)));
}
/* If what was given does not imply a symtab, it must be an
@@ -1142,19 +1124,14 @@ pipe_command (const char *arg, int from_tty)
if (to_shell_command == nullptr)
error (_("Error launching \"%s\""), shell_command);
- try
- {
- stdio_file pipe_file (to_shell_command);
+ int exit_status;
+ {
+ SCOPE_EXIT { exit_status = pclose (to_shell_command); };
- execute_command_to_ui_file (&pipe_file, gdb_cmd.c_str (), from_tty);
- }
- catch (...)
- {
- pclose (to_shell_command);
- throw;
- }
+ stdio_file pipe_file (to_shell_command);
- int exit_status = pclose (to_shell_command);
+ execute_command_to_ui_file (&pipe_file, gdb_cmd.c_str (), from_tty);
+ }
if (exit_status < 0)
error (_("shell command \"%s\" failed: %s"), shell_command,
@@ -1240,7 +1217,8 @@ list_command (const char *arg, int from_tty)
if (get_first_line_listed () == 0 && (arg == nullptr || arg[0] != '.'))
{
set_default_source_symtab_and_line ();
- list_around_line (arg, get_current_source_symtab_and_line ());
+ list_around_line
+ (arg, get_current_source_symtab_and_line (current_program_space));
}
/* "l" and "l +" lists the next few lines, unless we're listing past
@@ -1248,7 +1226,8 @@ list_command (const char *arg, int from_tty)
else if (arg == nullptr || arg[0] == '+')
{
set_default_source_symtab_and_line ();
- const symtab_and_line cursal = get_current_source_symtab_and_line ();
+ const symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
if (last_symtab_line (cursal.symtab) >= cursal.line)
print_source_lines (cursal.symtab,
source_lines_range (cursal.line), 0);
@@ -1262,7 +1241,8 @@ list_command (const char *arg, int from_tty)
else if (arg[0] == '-')
{
set_default_source_symtab_and_line ();
- const symtab_and_line cursal = get_current_source_symtab_and_line ();
+ const symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
if (get_first_line_listed () == 1)
error (_("Already at the start of %s."),
@@ -1295,7 +1275,7 @@ list_command (const char *arg, int from_tty)
{
/* The inferior is not running, so reset the current source
location to the default (usually the main function). */
- clear_current_source_symtab_and_line ();
+ clear_current_source_symtab_and_line (current_program_space);
try
{
set_default_source_symtab_and_line ();
@@ -1305,7 +1285,8 @@ list_command (const char *arg, int from_tty)
error (_("Insufficient debug info for showing source "
"lines at default location"));
}
- cursal = get_current_source_symtab_and_line ();
+ cursal
+ = get_current_source_symtab_and_line (current_program_space);
gdb_assert (cursal.symtab != nullptr);
}
@@ -1327,7 +1308,8 @@ list_command (const char *arg, int from_tty)
and clear NO_END; however, if one of the arguments is blank,
set DUMMY_BEG or DUMMY_END to record that fact. */
- if (!have_full_symbols () && !have_partial_symbols ())
+ if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space))
error (_("No symbol table is loaded. Use the \"file\" command."));
std::vector<symtab_and_line> sals;
@@ -2141,9 +2123,11 @@ print_sal_location (const symtab_and_line &sal)
const char *sym_name = NULL;
if (sal.symbol != NULL)
sym_name = sal.symbol->print_name ();
- gdb_printf (_("file: \"%s\", line number: %d, symbol: \"%s\"\n"),
+ gdb_printf (_("file: \"%s\", line number: %ps, symbol: \"%s\"\n"),
symtab_to_filename_for_display (sal.symtab),
- sal.line, sym_name != NULL ? sym_name : "???");
+ styled_string (line_number_style.style (),
+ pulongest (sal.line)),
+ sym_name != NULL ? sym_name : "???");
}
/* Print a list of files and line numbers which a user may choose from
@@ -2638,7 +2622,7 @@ The debugger's current working directory specifies where scripts and other\n\
files that can be loaded by GDB are located.\n\
In order to change the inferior's current working directory, the recommended\n\
way is to use the \"set cwd\" command."), &cmdlist);
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, deprecated_filename_completer);
add_com ("echo", class_support, echo_command, _("\
Print a constant string. Give string as argument.\n\
@@ -2804,7 +2788,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, filename_completer);
+ set_cmd_completer (shell_cmd, deprecated_filename_completer);
add_com_alias ("!", shell_cmd, class_support, 0);
@@ -2893,7 +2877,8 @@ you must type \"disassemble 'foo.c'::bar\" and not \"disassemble foo.c:bar\"."))
c = add_com ("make", class_support, make_command, _("\
Run the ``make'' program using the rest of the line as arguments."));
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, deprecated_filename_completer);
+
c = add_cmd ("user", no_class, show_user, _("\
Show definitions of non-python/scheme user defined commands.\n\
Argument is the name of the user defined command.\n\
@@ -2977,5 +2962,5 @@ Note that the file \"%s\" is read automatically in this way\n\
when GDB is started."), GDBINIT).release ();
c = add_cmd ("source", class_support, source_command,
source_help_text, &cmdlist);
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, deprecated_filename_completer);
}
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index d9a2ab4..163012a 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -866,7 +866,7 @@ add_setshow_filename_cmd (const char *name, enum command_class theclass,
nullptr, nullptr, set_func,
show_func, set_list, show_list);
- set_cmd_completer (commands.set, filename_completer);
+ set_cmd_completer (commands.set, deprecated_filename_completer);
return commands;
}
@@ -890,7 +890,7 @@ add_setshow_filename_cmd (const char *name, command_class theclass,
nullptr, show_func, set_list,
show_list);
- set_cmd_completer (cmds.set, filename_completer);
+ set_cmd_completer (cmds.set, deprecated_filename_completer);
return cmds;
}
@@ -1015,7 +1015,7 @@ add_setshow_optional_filename_cmd (const char *name, enum command_class theclass
nullptr, nullptr, set_func, show_func,
set_list, show_list);
- set_cmd_completer (commands.set, filename_completer);
+ set_cmd_completer (commands.set, deprecated_filename_completer);
return commands;
}
@@ -1039,7 +1039,7 @@ add_setshow_optional_filename_cmd (const char *name, command_class theclass,
set_func, get_func, nullptr, show_func,
set_list,show_list);
- set_cmd_completer (cmds.set, filename_completer);
+ set_cmd_completer (cmds.set, deprecated_filename_completer);
return cmds;
}
diff --git a/gdb/cli/cli-dump.c b/gdb/cli/cli-dump.c
index 9b44c6e..2b9307e 100644
--- a/gdb/cli/cli-dump.c
+++ b/gdb/cli/cli-dump.c
@@ -348,7 +348,7 @@ add_dump_command (const char *name,
struct dump_context *d;
c = add_cmd (name, all_commands, descr, &dump_cmdlist);
- c->completer = filename_completer;
+ set_cmd_completer (c, deprecated_filename_completer);
d = XNEW (struct dump_context);
d->func = func;
d->mode = FOPEN_WB;
@@ -356,7 +356,7 @@ add_dump_command (const char *name,
c->func = call_dump_func;
c = add_cmd (name, all_commands, descr, &append_cmdlist);
- c->completer = filename_completer;
+ set_cmd_completer (c, deprecated_filename_completer);
d = XNEW (struct dump_context);
d->func = func;
d->mode = FOPEN_AB;
@@ -705,6 +705,6 @@ Arguments are FILE OFFSET START END where all except FILE are optional.\n\
OFFSET will be added to the base address of the file (default zero).\n\
If START and END are given, only the file contents within that range\n\
(file relative) will be restored to target memory."));
- c->completer = filename_completer;
+ set_cmd_completer (c, deprecated_filename_completer);
/* FIXME: completers for other commands. */
}
diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
index fa5d70e..1817573 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -228,7 +228,7 @@ cli_interp::exec (const char *command_str)
interpreter which has a new ui_file for gdb_stdout, use that one
instead of the default.
- It is important that it gets reset everytime, since the user
+ It is important that it gets reset every time, since the user
could set gdb to use a different interpreter. */
ui_file *old_stream = m_cli_uiout->set_stream (gdb_stdout);
SCOPE_EXIT { m_cli_uiout->set_stream (old_stream); };
diff --git a/gdb/cli/cli-style.c b/gdb/cli/cli-style.c
index 5928998..36a8bd9 100644
--- a/gdb/cli/cli-style.c
+++ b/gdb/cli/cli-style.c
@@ -126,6 +126,10 @@ cli_style_option disasm_comment_style ("comment", ui_file_style::WHITE,
/* See cli-style.h. */
+cli_style_option line_number_style ("line-number", ui_file_style::DIM);
+
+/* See cli-style.h. */
+
cli_style_option::cli_style_option (const char *name,
ui_file_style::basic_color fg,
ui_file_style::intensity intensity)
@@ -529,6 +533,14 @@ then this style has no effect."),
&style_disasm_show_list,
false);
+ line_number_style.add_setshow_commands (no_class, _("\
+Line number display styling.\n\
+Configure colors and display intensity for line numbers\n\
+The \"line-number\" style is used when GDB displays line numbers\n\
+coming from your source code."),
+ &style_set_list, &style_show_list,
+ false);
+
/* Setup 'disassembler address' style and 'disassembler symbol' style,
these are aliases for 'address' and 'function' styles respectively. */
add_alias_cmd ("address", address_prefix_cmds.set, no_class, 0,
diff --git a/gdb/cli/cli-style.h b/gdb/cli/cli-style.h
index 1663b4e..5052b86 100644
--- a/gdb/cli/cli-style.h
+++ b/gdb/cli/cli-style.h
@@ -145,6 +145,9 @@ extern cli_style_option tui_active_border_style;
/* The style to use for the GDB version string. */
extern cli_style_option version_style;
+/* The style for a line number. */
+extern cli_style_option line_number_style;
+
/* True if source styling is enabled. */
extern bool source_styling;
diff --git a/gdb/coff-pe-read.c b/gdb/coff-pe-read.c
index 0da4f12..bb85b00 100644
--- a/gdb/coff-pe-read.c
+++ b/gdb/coff-pe-read.c
@@ -174,24 +174,24 @@ add_pe_forwarded_sym (minimal_symbol_reader &reader,
const char *forward_func_name, int ordinal,
const char *dll_name, struct objfile *objfile)
{
- struct bound_minimal_symbol msymbol;
enum minimal_symbol_type msymtype;
int forward_dll_name_len = strlen (forward_dll_name);
- short section;
std::string forward_qualified_name = string_printf ("%s!%s",
forward_dll_name,
forward_func_name);
- msymbol = lookup_bound_minimal_symbol (forward_qualified_name.c_str ());
-
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space,
+ forward_qualified_name.c_str ());
if (!msymbol.minsym)
{
int i;
for (i = 0; i < forward_dll_name_len; i++)
forward_qualified_name[i] = tolower (forward_qualified_name[i]);
- msymbol = lookup_bound_minimal_symbol (forward_qualified_name.c_str ());
+ msymbol = lookup_minimal_symbol (current_program_space,
+ forward_qualified_name.c_str ());
}
if (!msymbol.minsym)
@@ -214,7 +214,7 @@ add_pe_forwarded_sym (minimal_symbol_reader &reader,
unrelocated_addr vma = unrelocated_addr (msymbol.value_address ()
- objfile->text_section_offset ());
msymtype = msymbol.minsym->type ();
- section = msymbol.minsym->section_index ();
+ int section = msymbol.minsym->section_index ();
/* Generate a (hopefully unique) qualified name using the first part
of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
diff --git a/gdb/coffread.c b/gdb/coffread.c
index daae3ff..abe150d 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -37,6 +37,7 @@
#include "block.h"
#include "dictionary.h"
#include "dwarf2/public.h"
+#include "gdb-stabs.h"
#include "coff-pe-read.h"
@@ -121,7 +122,7 @@ static unsigned local_auxesz;
static int pe_file;
/* Chain of typedefs of pointers to empty struct/union types.
- They are chained thru the SYMBOL_VALUE_CHAIN. */
+ They are chained through the SYMBOL_VALUE_CHAIN. */
static struct symbol *opaque_type_chain[HASHSIZE];
@@ -204,6 +205,98 @@ static void read_one_sym (struct coff_symbol *,
static void coff_symtab_read (minimal_symbol_reader &,
file_ptr, unsigned int, struct objfile *);
+/* Scan and build partial symbols for an coff symbol file.
+ The coff file has already been processed to get its minimal symbols.
+
+ This routine is the equivalent of dbx_symfile_init and dbx_symfile_read
+ rolled into one.
+
+ OBJFILE is the object file we are reading symbols from.
+ ADDR is the address relative to which the symbols are (e.g.
+ the base address of the text segment).
+ TEXTADDR is the address of the text section.
+ TEXTSIZE is the size of the text section.
+ STABSECTS is the list of .stab sections in OBJFILE.
+ STABSTROFFSET and STABSTRSIZE define the location in OBJFILE where the
+ .stabstr section exists.
+
+ This routine is mostly copied from dbx_symfile_init and dbx_symfile_read,
+ adjusted for coff details. */
+
+void
+coffstab_build_psymtabs (struct objfile *objfile,
+ CORE_ADDR textaddr, unsigned int textsize,
+ const std::vector<asection *> &stabsects,
+ file_ptr stabstroffset, unsigned int stabstrsize)
+{
+ int val;
+ bfd *sym_bfd = objfile->obfd.get ();
+ const char *name = bfd_get_filename (sym_bfd);
+ unsigned int stabsize;
+
+ /* Allocate struct to keep track of stab reading. */
+ dbx_objfile_data_key.emplace (objfile);
+ dbx_symfile_info *key = dbx_objfile_data_key.get (objfile);
+
+ DBX_TEXT_ADDR (objfile) = textaddr;
+ DBX_TEXT_SIZE (objfile) = textsize;
+
+#define COFF_STABS_SYMBOL_SIZE 12 /* XXX FIXME XXX */
+ DBX_SYMBOL_SIZE (objfile) = COFF_STABS_SYMBOL_SIZE;
+ DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
+
+ if (stabstrsize > bfd_get_size (sym_bfd))
+ error (_("ridiculous string table size: %d bytes"), stabstrsize);
+ DBX_STRINGTAB (objfile) = (char *)
+ obstack_alloc (&objfile->objfile_obstack, stabstrsize + 1);
+ OBJSTAT (objfile, sz_strtab += stabstrsize + 1);
+
+ /* Now read in the string table in one big gulp. */
+
+ val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET);
+ if (val < 0)
+ perror_with_name (name);
+ val = bfd_read (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd);
+ if (val != stabstrsize)
+ perror_with_name (name);
+
+ stabsread_new_init ();
+ free_header_files ();
+ init_header_files ();
+
+ key->ctx.processing_acc_compilation = 1;
+
+ /* In a coff file, we've already installed the minimal symbols that came
+ from the coff (non-stab) symbol table, so always act like an
+ incremental load here. */
+ scoped_restore save_symbuf_sections
+ = make_scoped_restore (&key->ctx.symbuf_sections);
+ if (stabsects.size () == 1)
+ {
+ stabsize = bfd_section_size (stabsects[0]);
+ DBX_SYMCOUNT (objfile) = stabsize / DBX_SYMBOL_SIZE (objfile);
+ DBX_SYMTAB_OFFSET (objfile) = stabsects[0]->filepos;
+ }
+ else
+ {
+ DBX_SYMCOUNT (objfile) = 0;
+ for (asection *section : stabsects)
+ {
+ stabsize = bfd_section_size (section);
+ DBX_SYMCOUNT (objfile) += stabsize / DBX_SYMBOL_SIZE (objfile);
+ }
+
+ DBX_SYMTAB_OFFSET (objfile) = stabsects[0]->filepos;
+
+ key->ctx.sect_idx = 1;
+ key->ctx.symbuf_sections = &stabsects;
+ key->ctx.symbuf_left = bfd_section_size (stabsects[0]);
+ key->ctx.symbuf_read = 0;
+ }
+
+ read_stabs_symtab (objfile, 0);
+}
+
/* We are called once per section from coff_symfile_read. We
need to examine each section we are passed, check to see
if it is something we are interested in processing, and
@@ -574,12 +667,13 @@ coff_read_minsyms (file_ptr symtab_offset, unsigned int nsyms,
{
int lead
= bfd_get_symbol_leading_char (objfile->obfd.get ());
- struct bound_minimal_symbol found;
if (lead != '\0' && *name1 == lead)
name1 += 1;
- found = lookup_minimal_symbol (name1, NULL, objfile);
+ bound_minimal_symbol found
+ = lookup_minimal_symbol (current_program_space, name1,
+ objfile);
/* If found, there are symbols named "_imp_foo" and "foo"
respectively in OBJFILE. Set the type of symbol "foo"
@@ -1643,7 +1737,7 @@ process_coff_symbol (struct coff_symbol *cs,
This is not just a consequence of GDB's type
management; CC and GCC (at least through version
2.4) both output variables of either type char *
- or caddr_t with the type refering to the C_TPDEF
+ or caddr_t with the type referring to the C_TPDEF
symbol for caddr_t. If a future compiler cleans
this up it GDB is not ready for it yet, but if it
becomes ready we somehow need to disable this
diff --git a/gdb/command.h b/gdb/command.h
index 615f4e5..0ceaf3e 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -876,7 +876,7 @@ extern void cmd_show_list (struct cmd_list_element *, int);
/* Used everywhere whenever at least one parameter is required and
none is specified. */
-extern void error_no_arg (const char *) ATTRIBUTE_NORETURN;
+[[noreturn]] extern void error_no_arg (const char *);
/* Command line saving and repetition.
diff --git a/gdb/compile/compile-c-symbols.c b/gdb/compile/compile-c-symbols.c
index 20e8550..7a38d3a 100644
--- a/gdb/compile/compile-c-symbols.c
+++ b/gdb/compile/compile-c-symbols.c
@@ -259,8 +259,7 @@ convert_symbol_sym (compile_c_instance *context, const char *identifier,
to use and BMSYM is the minimal symbol to convert. */
static void
-convert_symbol_bmsym (compile_c_instance *context,
- struct bound_minimal_symbol bmsym)
+convert_symbol_bmsym (compile_c_instance *context, bound_minimal_symbol bmsym)
{
struct minimal_symbol *msym = bmsym.minsym;
struct objfile *objfile = bmsym.objfile;
@@ -356,9 +355,8 @@ gcc_convert_symbol (void *datum,
}
else if (request == GCC_C_ORACLE_SYMBOL)
{
- struct bound_minimal_symbol bmsym;
-
- bmsym = lookup_minimal_symbol (identifier, NULL, NULL);
+ bound_minimal_symbol bmsym
+ = lookup_minimal_symbol (current_program_space, identifier);
if (bmsym.minsym != NULL)
{
convert_symbol_bmsym (context, bmsym);
@@ -413,9 +411,8 @@ gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context,
}
else
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_bound_minimal_symbol (identifier);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, identifier);
if (msym.minsym != NULL)
{
if (compile_debug)
diff --git a/gdb/compile/compile-cplus-symbols.c b/gdb/compile/compile-cplus-symbols.c
index 9b95cdd..6c482e7 100644
--- a/gdb/compile/compile-cplus-symbols.c
+++ b/gdb/compile/compile-cplus-symbols.c
@@ -275,7 +275,7 @@ convert_symbol_sym (compile_cplus_instance *instance,
static void
convert_symbol_bmsym (compile_cplus_instance *instance,
- struct bound_minimal_symbol bmsym)
+ bound_minimal_symbol bmsym)
{
struct minimal_symbol *msym = bmsym.minsym;
struct objfile *objfile = bmsym.objfile;
@@ -453,9 +453,8 @@ gcc_cplus_symbol_address (void *datum, struct gcc_cp_context *gcc_context,
}
else
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_bound_minimal_symbol (identifier);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, identifier);
if (msym.minsym != nullptr)
{
if (compile_debug)
diff --git a/gdb/compile/compile-object-load.c b/gdb/compile/compile-object-load.c
index 08e30be..df48b1c 100644
--- a/gdb/compile/compile-object-load.c
+++ b/gdb/compile/compile-object-load.c
@@ -604,7 +604,6 @@ compile_object_load (const compile_file_names &file_names,
CORE_ADDR regs_addr, out_value_addr = 0;
struct symbol *func_sym;
struct type *func_type;
- struct bound_minimal_symbol bmsym;
long storage_needed;
asymbol **symbol_table, **symp;
long number_of_symbols, missing_symbols;
@@ -765,7 +764,8 @@ compile_object_load (const compile_file_names &file_names,
continue;
}
- bmsym = lookup_minimal_symbol (sym->name, NULL, NULL);
+ bound_minimal_symbol bmsym
+ = lookup_minimal_symbol (current_program_space, sym->name);
switch (bmsym.minsym == NULL
? mst_unknown : bmsym.minsym->type ())
{
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index 88531a2..89f9790 100644
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -17,6 +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 "progspace.h"
#include "ui.h"
#include "ui-out.h"
#include "command.h"
@@ -302,14 +303,13 @@ compile_file_command (const char *args, int from_tty)
enum compile_i_scope_types scope
= options.raw ? COMPILE_I_RAW_SCOPE : COMPILE_I_SIMPLE_SCOPE;
- args = skip_spaces (args);
+ std::string filename = extract_single_filename_arg (args);
/* After processing options, check whether we have a filename. */
- if (args == nullptr || args[0] == '\0')
+ if (filename.empty ())
error (_("You must provide a filename for this command."));
- args = skip_spaces (args);
- std::string abspath = gdb_abspath (args);
+ std::string abspath = gdb_abspath (filename.c_str ());
std::string buffer = string_printf ("#include \"%s\"\n", abspath.c_str ());
eval_compile_command (NULL, buffer.c_str (), scope, NULL);
}
@@ -327,8 +327,8 @@ compile_file_command_completer (struct cmd_list_element *ignore,
(tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group))
return;
- word = advance_to_filename_complete_word_point (tracker, text);
- filename_completer (ignore, tracker, text, word);
+ word = advance_to_filename_maybe_quoted_complete_word_point (tracker, text);
+ filename_maybe_quoted_completer (ignore, tracker, text, word);
}
/* Handle the input from the 'compile code' command. The
@@ -487,7 +487,8 @@ get_expr_block_and_pc (CORE_ADDR *pc)
if (block == NULL)
{
- struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+ symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
if (cursal.symtab)
block = cursal.symtab->compunit ()->blockvector ()->static_block ();
diff --git a/gdb/completer.c b/gdb/completer.c
index 1008ec2..4735aa5 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -31,6 +31,7 @@
#include "linespec.h"
#include "cli/cli-decode.h"
#include "gdbsupport/gdb_tilde_expand.h"
+#include "readline/readline.h"
/* FIXME: This is needed because of lookup_cmd_1 (). We should be
calling a hook instead so we eliminate the CLI dependency. */
@@ -48,10 +49,13 @@
/* Forward declarations. */
static const char *completion_find_completion_word (completion_tracker &tracker,
const char *text,
- int *quote_char);
+ int *quote_char,
+ bool *found_any_quoting);
static void set_rl_completer_word_break_characters (const char *break_chars);
+static bool gdb_path_isdir (const char *filename);
+
/* See completer.h. */
class completion_tracker::completion_hash_entry
@@ -182,6 +186,17 @@ static const char gdb_completer_file_name_break_characters[] =
" \t\n*|\"';:?><";
#endif
+/* When completing on file names, for commands that don't accept quoted
+ file names, the only character that can be used as a word separator is
+ the path separator. Every other character is treated as a literal
+ character within the filename. */
+static const char gdb_completer_path_break_characters[] =
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+ ";";
+#else
+ ":";
+#endif
+
/* Characters that can be used to quote expressions. Note that we can't
include '"' (double quote) because the gdb C parser treats such quoted
sequences as strings. */
@@ -203,14 +218,296 @@ noop_completer (struct cmd_list_element *ignore,
{
}
-/* Complete on filenames. */
+/* Return 1 if the character at EINDEX in STRING is quoted (there is an
+ unclosed quoted string), or if the character at EINDEX is quoted by a
+ backslash. */
-void
-filename_completer (struct cmd_list_element *ignore,
- completion_tracker &tracker,
- const char *text, const char *word)
+static int
+gdb_completer_file_name_char_is_quoted (char *string, int eindex)
{
- rl_completer_quote_characters = gdb_completer_file_name_quote_characters;
+ for (int i = 0; i <= eindex && string[i] != '\0'; )
+ {
+ char c = string[i];
+
+ if (c == '\\')
+ {
+ /* The backslash itself is not quoted. */
+ if (i >= eindex)
+ return 0;
+ ++i;
+ /* But the next character is. */
+ if (i >= eindex)
+ return 1;
+ if (string[i] == '\0')
+ return 0;
+ ++i;
+ continue;
+ }
+ else if (strchr (rl_completer_quote_characters, c) != nullptr)
+ {
+ /* This assumes that extract_string_maybe_quoted can handle a
+ string quoted with character C. Currently this is true as the
+ only characters we put in rl_completer_quote_characters are
+ single and/or double quotes, both of which
+ extract_string_maybe_quoted can handle. */
+ gdb_assert (c == '"' || c == '\'');
+ const char *tmp = &string[i];
+ (void) extract_string_maybe_quoted (&tmp);
+ i = tmp - string;
+
+ /* Consider any character within the string we just skipped over
+ as quoted, though this might not be completely correct; the
+ opening and closing quotes are not themselves quoted. But so
+ far this doesn't seem to have caused any issues. */
+ if (i > eindex)
+ return 1;
+ }
+ else
+ ++i;
+ }
+
+ return 0;
+}
+
+/* Removing character escaping from FILENAME. QUOTE_CHAR is the quote
+ character around FILENAME or the null-character if there is no quoting
+ around FILENAME. */
+
+static char *
+gdb_completer_file_name_dequote (char *filename, int quote_char)
+{
+ std::string tmp;
+
+ if (quote_char == '\'')
+ {
+ /* There is no backslash escaping within a single quoted string. In
+ this case we can just return the input string. */
+ tmp = filename;
+ }
+ else if (quote_char == '"')
+ {
+ /* Remove escaping from a double quoted string. */
+ for (const char *input = filename;
+ *input != '\0';
+ ++input)
+ {
+ if (input[0] == '\\'
+ && input[1] != '\0'
+ && strchr ("\"\\", input[1]) != nullptr)
+ ++input;
+ tmp += *input;
+ }
+ }
+ else
+ {
+ gdb_assert (quote_char == '\0');
+
+ /* Remove escaping from an unquoted string. */
+ for (const char *input = filename;
+ *input != '\0';
+ ++input)
+ {
+ /* We allow anything to be escaped in an unquoted string. */
+ if (*input == '\\')
+ {
+ ++input;
+ if (*input == '\0')
+ break;
+ }
+
+ tmp += *input;
+ }
+ }
+
+ return strdup (tmp.c_str ());
+}
+
+/* Implement readline's rl_directory_rewrite_hook. Remove any quoting from
+ the string *DIRNAME,update *DIRNAME, and return non-zero. If *DIRNAME
+ doesn't need updating then return zero. See readline docs for more
+ information. */
+
+static int
+gdb_completer_directory_rewrite (char **dirname)
+{
+ if (!rl_completion_found_quote)
+ return 0;
+
+ int quote_char = rl_completion_quote_character;
+ char *new_dirname
+ = gdb_completer_file_name_dequote (*dirname, quote_char);
+ free (*dirname);
+ *dirname = new_dirname;
+
+ return 1;
+}
+
+/* Apply character escaping to the filename in TEXT and return a newly
+ allocated buffer containing the possibly updated filename.
+
+ QUOTE_CHAR is the quote character surrounding TEXT, or the
+ null-character if there are no quotes around TEXT. */
+
+static char *
+gdb_completer_file_name_quote_1 (const char *text, char quote_char)
+{
+ std::string str;
+
+ if (quote_char == '\'')
+ {
+ /* There is no backslash escaping permitted within a single quoted
+ string, so in this case we can just return the input sting. */
+ str = text;
+ }
+ else if (quote_char == '"')
+ {
+ /* Add escaping for a double quoted filename. */
+ for (const char *input = text;
+ *input != '\0';
+ ++input)
+ {
+ if (strchr ("\"\\", *input) != nullptr)
+ str += '\\';
+ str += *input;
+ }
+ }
+ else
+ {
+ gdb_assert (quote_char == '\0');
+
+ /* Add escaping for an unquoted filename. */
+ for (const char *input = text;
+ *input != '\0';
+ ++input)
+ {
+ if (strchr (" \t\n\\\"'", *input)
+ != nullptr)
+ str += '\\';
+ str += *input;
+ }
+ }
+
+ return strdup (str.c_str ());
+}
+
+/* Apply character escaping to the filename in TEXT. QUOTE_PTR points to
+ the quote character surrounding TEXT, or points to the null-character if
+ there are no quotes around TEXT. MATCH_TYPE will be one of the readline
+ constants SINGLE_MATCH or MULTI_MATCH depending on if there is one or
+ many completions.
+
+ We also add a trailing character, either a '/' of closing quote, if
+ MATCH_TYPE is 'SINGLE_MATCH'. We do this because readline will only
+ add this trailing character when completing at the end of a line. */
+
+static char *
+gdb_completer_file_name_quote (char *text, int match_type, char *quote_ptr)
+{
+ char *result = gdb_completer_file_name_quote_1 (text, *quote_ptr);
+
+ if (match_type == SINGLE_MATCH)
+ {
+ /* Add trailing '/' if TEXT is a directory, otherwise add a closing
+ quote character matching *QUOTE_PTR. */
+ char c = (gdb_path_isdir (gdb_tilde_expand (text).c_str ())
+ ? '/' : *quote_ptr);
+
+ /* Reallocate RESULT adding C to the end. But only if C is
+ interesting, otherwise we can save the reallocation. */
+ if (c != '\0')
+ {
+ char buf[2] = { c, '\0' };
+ result = reconcat (result, result, buf, nullptr);
+ }
+ }
+
+ return result;
+}
+
+/* The function is used to update the completion word MATCH before
+ displaying it to the user in the 'complete' command output. This
+ function is only used for formatting filename or directory names.
+
+ This function checks to see if the completion word MATCH is a directory,
+ in which case a trailing "/" (forward-slash) is added, otherwise
+ QUOTE_CHAR is added as a trailing quote.
+
+ When ADD_ESCAPES is true any special characters (e.g. whitespace,
+ quotes) will be escaped with a backslash. See
+ gdb_completer_file_name_quote_1 for full details on escaping. When
+ ADD_ESCAPES is false then no escaping will be added and MATCH (with the
+ correct trailing character) will be used unmodified.
+
+ Return the updated completion word as a string. */
+
+static std::string
+filename_match_formatter_1 (const char *match, char quote_char,
+ bool add_escapes)
+{
+ std::string result;
+ if (add_escapes)
+ {
+ gdb::unique_xmalloc_ptr<char> quoted_match
+ (gdb_completer_file_name_quote_1 (match, quote_char));
+ result = quoted_match.get ();
+ }
+ else
+ result = match;
+
+ if (gdb_path_isdir (gdb_tilde_expand (match).c_str ()))
+ result += "/";
+ else
+ result += quote_char;
+
+ return result;
+}
+
+/* The formatting function used to format the results of a 'complete'
+ command when the result is a filename, but the filename should not have
+ any escape characters added. Most commands that accept a filename don't
+ expect the filename to be quoted or to contain escape characters.
+
+ See filename_match_formatter_1 for more argument details. */
+
+static std::string
+filename_unquoted_match_formatter (const char *match, char quote_char)
+{
+ return filename_match_formatter_1 (match, quote_char, false);
+}
+
+/* The formatting function used to format the results of a 'complete'
+ command when the result is a filename, and the filename should have any
+ special character (e.g. whitespace, quotes) within it escaped with a
+ backslash. A limited number of commands accept this style of filename
+ argument.
+
+ See filename_match_formatter_1 for more argument details. */
+
+static std::string
+filename_maybe_quoted_match_formatter (const char *match, char quote_char)
+{
+ return filename_match_formatter_1 (match, quote_char, true);
+}
+
+/* Generate filename completions of WORD, storing the completions into
+ TRACKER. This is used for generating completions for commands that
+ only accept unquoted filenames as well as for commands that accept
+ quoted and escaped filenames.
+
+ When QUOTE_MATCHES is true TRACKER will be given a match formatter
+ function which will add escape characters (if needed) in the results.
+ When QUOTE_MATCHES is false the match formatter provided will not add
+ any escaping to the results. */
+
+static void
+filename_completer_generate_completions (completion_tracker &tracker,
+ const char *word,
+ bool quote_matches)
+{
+ if (quote_matches)
+ tracker.set_match_format_func (filename_maybe_quoted_match_formatter);
+ else
+ tracker.set_match_format_func (filename_unquoted_match_formatter);
int subsequent_name = 0;
while (1)
@@ -230,37 +527,68 @@ filename_completer (struct cmd_list_element *ignore,
if (p[strlen (p) - 1] == '~')
continue;
- /* Readline appends a trailing '/' if the completion is a
- directory. If this completion request originated from outside
- readline (e.g. GDB's 'complete' command), then we append the
- trailing '/' ourselves now. */
- if (!tracker.from_readline ())
- {
- std::string expanded = gdb_tilde_expand (p_rl);
- struct stat finfo;
- const bool isdir = (stat (expanded.c_str (), &finfo) == 0
- && S_ISDIR (finfo.st_mode));
- if (isdir)
- p_rl.reset (concat (p_rl.get (), "/", nullptr));
- }
-
tracker.add_completion
(make_completion_match_str (std::move (p_rl), word, word));
}
}
-/* The corresponding completer_handle_brkchars
- implementation. */
+/* The brkchars callback used when completing filenames that can be
+ quoted. */
static void
-filename_completer_handle_brkchars (struct cmd_list_element *ignore,
- completion_tracker &tracker,
- const char *text, const char *word)
+filename_maybe_quoted_completer_handle_brkchars
+ (struct cmd_list_element *ignore, completion_tracker &tracker,
+ const char *text, const char *word)
{
set_rl_completer_word_break_characters
(gdb_completer_file_name_break_characters);
rl_completer_quote_characters = gdb_completer_file_name_quote_characters;
+ rl_char_is_quoted_p = gdb_completer_file_name_char_is_quoted;
+}
+
+/* Complete on filenames. This is for commands that accepts possibly
+ quoted filenames. */
+
+void
+filename_maybe_quoted_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char *word)
+{
+ filename_maybe_quoted_completer_handle_brkchars (ignore, tracker,
+ text, word);
+ filename_completer_generate_completions (tracker, word, true);
+}
+
+/* The brkchars callback used by commands that don't accept quoted
+ filenames. */
+
+static void
+deprecated_filename_completer_handle_brkchars
+ (struct cmd_list_element *ignore, completion_tracker &tracker,
+ const char *text, const char *word)
+{
+ gdb_assert (word == nullptr);
+
+ set_rl_completer_word_break_characters (gdb_completer_path_break_characters);
+ rl_completer_quote_characters = nullptr;
+ rl_filename_quoting_desired = 0;
+
+ tracker.set_use_custom_word_point (true);
+ word = advance_to_deprecated_filename_complete_word_point (tracker, text);
+ deprecated_filename_completer (ignore, tracker, text, word);
+}
+
+/* See completer.h. */
+
+void
+deprecated_filename_completer
+ (struct cmd_list_element *ignore, completion_tracker &tracker,
+ const char *text, const char *word)
+{
+ gdb_assert (tracker.use_custom_word_point ());
+ gdb_assert (word != nullptr);
+ filename_completer_generate_completions (tracker, word, false);
}
/* Find the bounds of the current word for completion purposes, and
@@ -275,7 +603,9 @@ filename_completer_handle_brkchars (struct cmd_list_element *ignore,
boundaries of the current word. QC, if non-null, is set to the
opening quote character if we found an unclosed quoted substring,
'\0' otherwise. DP, if non-null, is set to the value of the
- delimiter character that caused a word break. */
+ delimiter character that caused a word break. FOUND_ANY_QUOTING, if
+ non-null, is set to true if we found any quote characters (single or
+ double quotes, or a backslash) while finding the completion word. */
struct gdb_rl_completion_word_info
{
@@ -286,7 +616,7 @@ struct gdb_rl_completion_word_info
static const char *
gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
- int *qc, int *dp,
+ int *qc, int *dp, bool *found_any_quoting,
const char *line_buffer)
{
int scan, end, delimiter, pass_next, isbrk;
@@ -298,6 +628,8 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
the empty string. */
if (point == 0)
{
+ if (found_any_quoting != nullptr)
+ *found_any_quoting = false;
if (qc != NULL)
*qc = '\0';
if (dp != NULL)
@@ -308,6 +640,7 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
end = point;
delimiter = 0;
quote_char = '\0';
+ bool found_quote = false;
brkchars = info->word_break_characters;
@@ -333,6 +666,7 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
if (quote_char != '\'' && line_buffer[scan] == '\\')
{
pass_next = 1;
+ found_quote = true;
continue;
}
@@ -353,6 +687,7 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
/* Found start of a quoted substring. */
quote_char = line_buffer[scan];
point = scan + 1;
+ found_quote = true;
}
}
}
@@ -366,8 +701,22 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
{
scan = line_buffer[point];
- if (strchr (brkchars, scan) != 0)
- break;
+ if (strchr (brkchars, scan) == 0)
+ continue;
+
+ /* Call the application-specific function to tell us whether
+ this word break character is quoted and should be skipped.
+ The const_cast is needed here to comply with the readline
+ API. The only function we register for rl_char_is_quoted_p
+ treats the input buffer as 'const', so we're OK. */
+ if (rl_char_is_quoted_p != nullptr && found_quote
+ && (*rl_char_is_quoted_p) (const_cast<char *> (line_buffer),
+ point))
+ continue;
+
+ /* Convoluted code, but it avoids an n^2 algorithm with calls
+ to char_is_quoted. */
+ break;
}
}
@@ -391,6 +740,8 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
}
}
+ if (found_any_quoting != nullptr)
+ *found_any_quoting = found_quote;
if (qc != NULL)
*qc = quote_char;
if (dp != NULL)
@@ -401,13 +752,23 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
/* Find the completion word point for TEXT, emulating the algorithm
readline uses to find the word point, using WORD_BREAK_CHARACTERS
- as word break characters. */
+ as word break characters.
+
+ The output argument *FOUND_ANY_QUOTING is set to true if the completion
+ word found either has an opening quote, or contains backslash escaping
+ within it. Otherwise *FOUND_ANY_QUOTING is set to false.
+
+ The output argument *QC is set to the opening quote character for the
+ completion word that is found, or to the null character if there is no
+ opening quote. */
static const char *
advance_to_completion_word (completion_tracker &tracker,
const char *word_break_characters,
const char *quote_characters,
- const char *text)
+ const char *text,
+ bool *found_any_quoting,
+ int *qc)
{
gdb_rl_completion_word_info info;
@@ -417,7 +778,8 @@ advance_to_completion_word (completion_tracker &tracker,
int delimiter;
const char *start
- = gdb_rl_find_completion_word (&info, NULL, &delimiter, text);
+ = gdb_rl_find_completion_word (&info, qc, &delimiter, found_any_quoting,
+ text);
tracker.advance_custom_word_point_by (start - text);
@@ -438,18 +800,54 @@ advance_to_expression_complete_word_point (completion_tracker &tracker,
{
const char *brk_chars = current_language->word_break_characters ();
const char *quote_chars = gdb_completer_expression_quote_characters;
- return advance_to_completion_word (tracker, brk_chars, quote_chars, text);
+ return advance_to_completion_word (tracker, brk_chars, quote_chars,
+ text, nullptr, nullptr);
}
/* See completer.h. */
const char *
-advance_to_filename_complete_word_point (completion_tracker &tracker,
- const char *text)
+advance_to_filename_maybe_quoted_complete_word_point
+ (completion_tracker &tracker, const char *text)
{
const char *brk_chars = gdb_completer_file_name_break_characters;
const char *quote_chars = gdb_completer_file_name_quote_characters;
- return advance_to_completion_word (tracker, brk_chars, quote_chars, text);
+ rl_char_is_quoted_p = gdb_completer_file_name_char_is_quoted;
+ bool found_any_quoting = false;
+ int qc;
+ const char *result
+ = advance_to_completion_word (tracker, brk_chars, quote_chars,
+ text, &found_any_quoting, &qc);
+ rl_completion_found_quote = found_any_quoting ? 1 : 0;
+ if (qc != '\0')
+ {
+ tracker.set_quote_char (qc);
+ /* If we're completing for readline (not the 'complete' command) then
+ we want readline to correctly detect the opening quote. The set
+ of quote characters will have been set during the brkchars phase,
+ so now we move the word point back by one (so it's pointing at
+ the quote character) and now readline will correctly spot the
+ opening quote. For the 'complete' command setting the quote
+ character in the tracker is enough, so there's no need to move
+ the word point back here. */
+ if (tracker.from_readline ())
+ tracker.advance_custom_word_point_by (-1);
+ }
+ return result;
+}
+
+/* See completer.h. */
+
+const char *
+advance_to_deprecated_filename_complete_word_point (completion_tracker &tracker,
+ const char *text)
+{
+ const char *brk_chars = gdb_completer_path_break_characters;
+ const char *quote_chars = nullptr;
+ rl_filename_quoting_desired = 0;
+
+ return advance_to_completion_word (tracker, brk_chars, quote_chars,
+ text, nullptr, nullptr);
}
/* See completer.h. */
@@ -490,7 +888,8 @@ complete_nested_command_line (completion_tracker &tracker, const char *text)
int quote_char = '\0';
const char *word = completion_find_completion_word (tracker, text,
- &quote_char);
+ &quote_char,
+ nullptr);
if (tracker.use_custom_word_point ())
{
@@ -607,8 +1006,8 @@ complete_files_symbols (completion_tracker &tracker,
symbol_start, word);
/* If text includes characters which cannot appear in a file
name, they cannot be asking for completion on files. */
- if (strcspn (text,
- gdb_completer_file_name_break_characters) == text_len)
+ if (strcspn (text, gdb_completer_file_name_break_characters)
+ == text_len)
fn_list = make_source_files_completion_list (text, text);
}
@@ -658,8 +1057,7 @@ complete_source_filenames (const char *text)
/* If text includes characters which cannot appear in a file name,
the user cannot be asking for completion on files. */
- if (strcspn (text,
- gdb_completer_file_name_break_characters)
+ if (strcspn (text, gdb_completer_file_name_break_characters)
== text_len)
return make_source_files_completion_list (text, text);
@@ -1260,6 +1658,7 @@ complete_line_internal_1 (completion_tracker &tracker,
completing file names then we can switch to the file name quote
character set (i.e., both single- and double-quotes). */
rl_completer_quote_characters = gdb_completer_expression_quote_characters;
+ rl_char_is_quoted_p = nullptr;
/* Decide whether to complete on a list of gdb commands or on
symbols. */
@@ -1479,10 +1878,25 @@ int max_completions = 200;
/* Initial size of the table. It automagically grows from here. */
#define INITIAL_COMPLETION_HTAB_SIZE 200
+/* The function is used to update the completion word MATCH before
+ displaying it to the user in the 'complete' command output. This
+ default function is used in all cases except those where a completion
+ function overrides this function by calling set_match_format_func.
+
+ This function returns MATCH with QUOTE_CHAR appended. If QUOTE_CHAR is
+ the null-character then the returned string will just contain MATCH. */
+
+static std::string
+default_match_formatter (const char *match, char quote_char)
+{
+ return std::string (match) + quote_char;
+}
+
/* See completer.h. */
completion_tracker::completion_tracker (bool from_readline)
- : m_from_readline (from_readline)
+ : m_from_readline (from_readline),
+ m_match_format_func (default_match_formatter)
{
discard_completions ();
}
@@ -1692,8 +2106,11 @@ complete (const char *line, char const **word, int *quote_char)
try
{
+ bool found_any_quoting = false;
+
*word = completion_find_completion_word (tracker_handle_brkchars,
- line, quote_char);
+ line, quote_char,
+ &found_any_quoting);
/* Completers that provide a custom word point in the
handle_brkchars phase also compute their completions then.
@@ -1703,6 +2120,12 @@ complete (const char *line, char const **word, int *quote_char)
tracker = &tracker_handle_brkchars;
else
{
+ /* Setting this global matches what readline does within
+ gen_completion_matches. We need this set correctly in case
+ our completion function calls back into readline to perform
+ completion (e.g. filename_completer does this). */
+ rl_completion_found_quote = found_any_quoting;
+
complete_line (tracker_handle_completions, *word, line, strlen (line));
tracker = &tracker_handle_completions;
}
@@ -1877,8 +2300,11 @@ default_completer_handle_brkchars (struct cmd_list_element *ignore,
completer_handle_brkchars_ftype *
completer_handle_brkchars_func_for_completer (completer_ftype *fn)
{
- if (fn == filename_completer)
- return filename_completer_handle_brkchars;
+ if (fn == deprecated_filename_completer)
+ return deprecated_filename_completer_handle_brkchars;
+
+ if (fn == filename_maybe_quoted_completer)
+ return filename_maybe_quoted_completer_handle_brkchars;
if (fn == location_completer)
return location_completer_handle_brkchars;
@@ -1926,7 +2352,21 @@ gdb_completion_word_break_characters_throw ()
gdb_custom_word_point_brkchars[0] = rl_line_buffer[rl_point];
rl_completer_word_break_characters = gdb_custom_word_point_brkchars;
- rl_completer_quote_characters = NULL;
+
+ /* When performing filename completion we have two options, unquoted
+ filename completion, in which case the quote characters will have
+ already been set to nullptr, or quoted filename completion in
+ which case the quote characters will be set to a string of
+ characters. In this second case we need readline to perform the
+ check for a quoted string so that it sets its internal notion of
+ the quote character correctly, this allows readline to correctly
+ add the trailing quote (if necessary) after completing a
+ filename.
+
+ For non-filename completion we manually add a trailing quote if
+ needed, so we clear the quote characters set here. */
+ if (!rl_filename_completion_desired)
+ rl_completer_quote_characters = NULL;
/* Clear this too, so that if we're completing a quoted string,
readline doesn't consider the quote character a delimiter.
@@ -1973,11 +2413,16 @@ gdb_completion_word_break_characters () noexcept
handle_brkchars phase (using TRACKER) to figure out the right work break
characters for the command in TEXT. QUOTE_CHAR, if non-null, is set to
the opening quote character if we found an unclosed quoted substring,
- '\0' otherwise. */
+ '\0' otherwise.
+
+ The argument *FOUND_ANY_QUOTING is set to true if the completion word is
+ either surrounded by quotes, or contains any backslash escapes, but is
+ only set if TRACKER.use_custom_word_point() is false, otherwise
+ *FOUND_ANY_QUOTING is just set to false. */
static const char *
completion_find_completion_word (completion_tracker &tracker, const char *text,
- int *quote_char)
+ int *quote_char, bool *found_any_quoting)
{
size_t point = strlen (text);
@@ -1987,6 +2432,12 @@ completion_find_completion_word (completion_tracker &tracker, const char *text,
{
gdb_assert (tracker.custom_word_point () > 0);
*quote_char = tracker.quote_char ();
+ /* If use_custom_word_point is set then the completions have already
+ been calculated, in which case we don't need to have this flag
+ set correctly, which is lucky as we don't currently have any way
+ to know if the completion word included any backslash escapes. */
+ if (found_any_quoting != nullptr)
+ *found_any_quoting = false;
return text + tracker.custom_word_point ();
}
@@ -1996,7 +2447,8 @@ completion_find_completion_word (completion_tracker &tracker, const char *text,
info.quote_characters = rl_completer_quote_characters;
info.basic_quote_characters = rl_basic_quote_characters;
- return gdb_rl_find_completion_word (&info, quote_char, NULL, text);
+ return gdb_rl_find_completion_word (&info, quote_char, nullptr,
+ found_any_quoting, text);
}
/* See completer.h. */
@@ -2152,31 +2604,44 @@ completion_tracker::build_completion_result (const char *text,
/* Build replacement word, based on the LCD. */
recompute_lowest_common_denominator ();
- match_list[0]
- = expand_preserving_ws (text, end - start,
- m_lowest_common_denominator);
+ if (rl_filename_completion_desired)
+ match_list[0] = xstrdup (m_lowest_common_denominator);
+ else
+ match_list[0]
+ = expand_preserving_ws (text, end - start, m_lowest_common_denominator);
if (m_lowest_common_denominator_unique)
{
- /* We don't rely on readline appending the quote char as
- delimiter as then readline wouldn't append the ' ' after the
- completion. */
- char buf[2] = { (char) quote_char () };
+ bool completion_suppress_append;
- match_list[0] = reconcat (match_list[0], match_list[0],
- buf, (char *) NULL);
- match_list[1] = NULL;
+ /* For filename completion we rely on readline to append the closing
+ quote. While for other types of completion we append the closing
+ quote here. */
+ if (from_readline () && !rl_filename_completion_desired)
+ {
+ /* We don't rely on readline appending the quote char as
+ delimiter as then readline wouldn't append the ' ' after the
+ completion. */
+ char buf[2] = { (char) quote_char (), '\0' };
+
+ match_list[0] = reconcat (match_list[0], match_list[0], buf,
+ (char *) nullptr);
+
+ /* If the tracker wants to, or we already have a space at the end
+ of the match, tell readline to skip appending another. */
+ char *match = match_list[0];
+ completion_suppress_append
+ = (suppress_append_ws ()
+ || (match[0] != '\0'
+ && match[strlen (match) - 1] == ' '));
+ }
+ else
+ completion_suppress_append = false;
- /* If the tracker wants to, or we already have a space at the
- end of the match, tell readline to skip appending
- another. */
- char *match = match_list[0];
- bool completion_suppress_append
- = (suppress_append_ws ()
- || (match[0] != '\0'
- && match[strlen (match) - 1] == ' '));
+ match_list[1] = nullptr;
- return completion_result (match_list, 1, completion_suppress_append);
+ return completion_result (match_list, 1, completion_suppress_append,
+ m_match_format_func);
}
else
{
@@ -2213,7 +2678,8 @@ completion_tracker::build_completion_result (const char *text,
htab_traverse_noresize (m_entries_hash.get (), func, &builder);
match_list[builder.index] = NULL;
- return completion_result (match_list, builder.index - 1, false);
+ return completion_result (match_list, builder.index - 1, false,
+ m_match_format_func);
}
}
@@ -2221,18 +2687,23 @@ completion_tracker::build_completion_result (const char *text,
completion_result::completion_result ()
: match_list (NULL), number_matches (0),
- completion_suppress_append (false)
+ completion_suppress_append (false),
+ m_match_formatter (default_match_formatter)
{}
/* See completer.h */
completion_result::completion_result (char **match_list_,
size_t number_matches_,
- bool completion_suppress_append_)
+ bool completion_suppress_append_,
+ match_format_func_t match_formatter_)
: match_list (match_list_),
number_matches (number_matches_),
- completion_suppress_append (completion_suppress_append_)
-{}
+ completion_suppress_append (completion_suppress_append_),
+ m_match_formatter (match_formatter_)
+{
+ gdb_assert (m_match_formatter != nullptr);
+}
/* See completer.h */
@@ -2245,10 +2716,12 @@ completion_result::~completion_result ()
completion_result::completion_result (completion_result &&rhs) noexcept
: match_list (rhs.match_list),
- number_matches (rhs.number_matches)
+ number_matches (rhs.number_matches),
+ m_match_formatter (rhs.m_match_formatter)
{
rhs.match_list = NULL;
rhs.number_matches = 0;
+ rhs.m_match_formatter = default_match_formatter;
}
/* See completer.h */
@@ -2290,6 +2763,38 @@ completion_result::reset_match_list ()
}
}
+/* See completer.h */
+
+void
+completion_result::print_matches (const std::string &prefix,
+ const char *word, int quote_char)
+{
+ this->sort_match_list ();
+
+ size_t off = this->number_matches == 1 ? 0 : 1;
+
+ for (size_t i = 0; i < this->number_matches; i++)
+ {
+ gdb_assert (this->m_match_formatter != nullptr);
+ std::string formatted_match
+ = this->m_match_formatter (this->match_list[i + off],
+ (char) quote_char);
+
+ printf_unfiltered ("%s%s\n", prefix.c_str (),
+ formatted_match.c_str ());
+ }
+
+ if (this->number_matches == max_completions)
+ {
+ /* PREFIX and WORD are included in the output so that emacs will
+ include the message in the output. */
+ printf_unfiltered (_("%s%s %s\n"),
+ prefix.c_str (), word,
+ get_max_completions_reached_message ());
+ }
+
+}
+
/* Helper for gdb_rl_attempted_completion_function, which does most of
the work. This is called by readline to build the match list array
and to determine the lowest common denominator. The real matches
@@ -2469,10 +2974,10 @@ gdb_display_match_list_pager (int lines,
return 0;
}
-/* Return non-zero if FILENAME is a directory.
+/* Return true if FILENAME is a directory.
Based on readline/complete.c:path_isdir. */
-static int
+static bool
gdb_path_isdir (const char *filename)
{
struct stat finfo;
@@ -3017,6 +3522,12 @@ _initialize_completer ()
rl_attempted_completion_function = gdb_rl_attempted_completion_function;
set_rl_completer_word_break_characters (default_word_break_characters ());
+ /* Setup readline globals relating to filename completion. */
+ rl_filename_quote_characters = " \t\n\\\"'";
+ rl_filename_dequoting_function = gdb_completer_file_name_dequote;
+ rl_filename_quoting_function = gdb_completer_file_name_quote;
+ rl_directory_rewrite_hook = gdb_completer_directory_rewrite;
+
add_setshow_zuinteger_unlimited_cmd ("max-completions", no_class,
&max_completions, _("\
Set maximum number of completion candidates."), _("\
diff --git a/gdb/completer.h b/gdb/completer.h
index 98a12f3..44eafc4 100644
--- a/gdb/completer.h
+++ b/gdb/completer.h
@@ -247,12 +247,24 @@ struct completion_match_result
struct completion_result
{
+ /* The type of a function that is used to format completion results when
+ using the 'complete' command. MATCH is the completion word to be
+ printed, and QUOTE_CHAR is a trailing quote character to (possibly)
+ add at the end of MATCH. QUOTE_CHAR can be the null-character in
+ which case no trailing quote should be added.
+
+ Return the possibly modified completion match word which should be
+ presented to the user. */
+ using match_format_func_t = std::string (*) (const char *match,
+ char quote_char);
+
/* Create an empty result. */
completion_result ();
/* Create a result. */
completion_result (char **match_list, size_t number_matches,
- bool completion_suppress_append);
+ bool completion_suppress_append,
+ match_format_func_t match_format_func);
/* Destroy a result. */
~completion_result ();
@@ -268,6 +280,24 @@ struct completion_result
/* Sort the match list. */
void sort_match_list ();
+ /* Called to display all matches (used by the 'complete' command).
+ PREFIX is everything before the completion word. WORD is the word
+ being completed, this is only used if we reach the maximum number of
+ completions, otherwise, each line of output consists of PREFIX
+ followed by one of the possible completion words.
+
+ The QUOTE_CHAR is usually appended after each possible completion
+ word and should be the quote character that appears before the
+ completion word, or the null-character if there is no quote before
+ the completion word.
+
+ The QUOTE_CHAR is not always appended to the completion output. For
+ example, filename completions will not append QUOTE_CHAR if the
+ completion is a directory name. This is all handled by calling this
+ function. */
+ void print_matches (const std::string &prefix, const char *word,
+ int quote_char);
+
private:
/* Destroy the match list array and its contents. */
void reset_match_list ();
@@ -292,6 +322,12 @@ public:
/* Whether readline should suppress appending a whitespace, when
there's only one possible completion. */
bool completion_suppress_append;
+
+private:
+ /* A function which formats a single completion match ready for display
+ as part of the 'complete' command output. Different completion
+ functions can set different formatter functions. */
+ match_format_func_t m_match_formatter;
};
/* Object used by completers to build a completion match list to hand
@@ -428,6 +464,14 @@ public:
bool from_readline () const
{ return m_from_readline; }
+ /* Set the function used to format the completion word before displaying
+ it to the user to F, this is used by the 'complete' command. */
+ void set_match_format_func (completion_result::match_format_func_t f)
+ {
+ gdb_assert (f != nullptr);
+ m_match_format_func = f;
+ }
+
private:
/* The type that we place into the m_entries_hash hash table. */
@@ -522,6 +566,10 @@ private:
interactively. The 'complete' command is a way to generate completions
not to be displayed by readline. */
bool m_from_readline;
+
+ /* The function used to format the completion word before it is printed
+ in the 'complete' command output. */
+ completion_result::match_format_func_t m_match_format_func;
};
/* Return a string to hand off to readline as a completion match
@@ -563,19 +611,45 @@ extern completion_result
const char *advance_to_expression_complete_word_point
(completion_tracker &tracker, const char *text);
-/* Assuming TEXT is an filename, find the completion word point for
- TEXT, emulating the algorithm readline uses to find the word
- point. */
-extern const char *advance_to_filename_complete_word_point
+/* Assuming TEXT is a filename, find the completion word point for TEXT,
+ emulating the algorithm readline uses to find the word point. The
+ filenames that are located by this function assume no filename
+ quoting, this function should be paired with filename_completer. */
+extern const char *advance_to_deprecated_filename_complete_word_point
+ (completion_tracker &tracker, const char *text);
+
+/* Assuming TEXT is a filename, find the completion word point for TEXT,
+ emulating the algorithm readline uses to find the word point. The
+ filenames that are located by this function assume that filenames
+ can be quoted, this function should be paired with
+ filename_maybe_quoted_completer. */
+extern const char *advance_to_filename_maybe_quoted_complete_word_point
(completion_tracker &tracker, const char *text);
extern void noop_completer (struct cmd_list_element *,
completion_tracker &tracker,
const char *, const char *);
-extern void filename_completer (struct cmd_list_element *,
- completion_tracker &tracker,
- const char *, const char *);
+/* Filename completer for commands that don't accept quoted filenames.
+ This completer does support completing a list of filenames that are
+ separated with the path separator (':' for UNIX and ';' for MS-DOS).
+
+ When adding a new command it is better to write the command so it
+ accepts quoted filenames and use filename_maybe_quoted_completer, for
+ examples see the 'exec' and 'exec-file' commands. */
+
+extern void deprecated_filename_completer
+ (struct cmd_list_element *, completion_tracker &tracker,
+ const char *, const char *);
+
+/* Filename completer for commands where the filename argument can be
+ quoted. This completer also supports completing a list of filenames
+ that are separated with the path separator (':' for UNIX and ';' for
+ MS-DOS). */
+
+extern void filename_maybe_quoted_completer (struct cmd_list_element *,
+ completion_tracker &tracker,
+ const char *, const char *);
extern void expression_completer (struct cmd_list_element *,
completion_tracker &tracker,
diff --git a/gdb/config.in b/gdb/config.in
index 0c144c8..59a5da3 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -46,6 +46,9 @@
language is requested. */
#undef ENABLE_NLS
+/* Additional targets configured into GDB. */
+#undef ENABLE_TARGETS
+
/* The .gdbearlyinit filename. */
#undef GDBEARLYINIT
@@ -481,6 +484,9 @@
/* Define to 1 if `pl_tdname' is a member of `struct ptrace_lwpinfo'. */
#undef HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME
+/* Define to 1 if `variant.ptwrite' is a member of `struct pt_event'. */
+#undef HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE
+
/* Define to 1 if `enabled' is a member of `struct pt_insn'. */
#undef HAVE_STRUCT_PT_INSN_ENABLED
diff --git a/gdb/configure b/gdb/configure
index 15ececf..ec9bbd3 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -21512,6 +21512,17 @@ _ACEOF
fi
+ ac_fn_c_check_member "$LINENO" "struct pt_event" "variant.ptwrite" "ac_cv_member_struct_pt_event_variant_ptwrite" "#include <intel-pt.h>
+"
+if test "x$ac_cv_member_struct_pt_event_variant_ptwrite" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE 1
+_ACEOF
+
+
+fi
+
LIBS=$save_LIBS
fi
fi
@@ -24817,11 +24828,19 @@ if test "${enable_targets+set}" = set; then :
yes | "") as_fn_error $? "enable-targets option must specify target names or 'all'" "$LINENO" 5
;;
no) enable_targets= ;;
- *) enable_targets=$enableval ;;
+ *)
+ enable_targets=$enableval
+
+cat >>confdefs.h <<_ACEOF
+#define ENABLE_TARGETS "$enable_targets"
+_ACEOF
+
+ ;;
esac
fi
+
# Check whether --enable-64-bit-bfd was given.
if test "${enable_64_bit_bfd+set}" = set; then :
enableval=$enable_64_bit_bfd; case $enableval in #(
@@ -24993,19 +25012,19 @@ if test "$gdb_require_amd_dbgapi" = true \
# version of the library.
pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for amd-dbgapi >= 0.68.0" >&5
-$as_echo_n "checking for amd-dbgapi >= 0.68.0... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for amd-dbgapi >= 0.75.0" >&5
+$as_echo_n "checking for amd-dbgapi >= 0.75.0... " >&6; }
if test -n "$AMD_DBGAPI_CFLAGS"; then
pkg_cv_AMD_DBGAPI_CFLAGS="$AMD_DBGAPI_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"amd-dbgapi >= 0.68.0\""; } >&5
- ($PKG_CONFIG --exists --print-errors "amd-dbgapi >= 0.68.0") 2>&5
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"amd-dbgapi >= 0.75.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "amd-dbgapi >= 0.75.0") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
- pkg_cv_AMD_DBGAPI_CFLAGS=`$PKG_CONFIG --cflags "amd-dbgapi >= 0.68.0" 2>/dev/null`
+ pkg_cv_AMD_DBGAPI_CFLAGS=`$PKG_CONFIG --cflags "amd-dbgapi >= 0.75.0" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
@@ -25017,12 +25036,12 @@ if test -n "$AMD_DBGAPI_LIBS"; then
pkg_cv_AMD_DBGAPI_LIBS="$AMD_DBGAPI_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"amd-dbgapi >= 0.68.0\""; } >&5
- ($PKG_CONFIG --exists --print-errors "amd-dbgapi >= 0.68.0") 2>&5
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"amd-dbgapi >= 0.75.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "amd-dbgapi >= 0.75.0") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
- pkg_cv_AMD_DBGAPI_LIBS=`$PKG_CONFIG --libs "amd-dbgapi >= 0.68.0" 2>/dev/null`
+ pkg_cv_AMD_DBGAPI_LIBS=`$PKG_CONFIG --libs "amd-dbgapi >= 0.75.0" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
@@ -25067,9 +25086,9 @@ else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
- AMD_DBGAPI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "amd-dbgapi >= 0.68.0" 2>&1`
+ AMD_DBGAPI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "amd-dbgapi >= 0.75.0" 2>&1`
else
- AMD_DBGAPI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "amd-dbgapi >= 0.68.0" 2>&1`
+ AMD_DBGAPI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "amd-dbgapi >= 0.75.0" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$AMD_DBGAPI_PKG_ERRORS" >&5
@@ -31188,7 +31207,7 @@ build_warnings="-Wall -Wpointer-arith \
-Wredundant-move \
-Wmissing-declarations \
-Wstrict-null-sentinel \
--Wno-vla-cxx-extension \
+-Wvla \
"
# The -Wmissing-prototypes flag will be accepted by GCC, but results
diff --git a/gdb/configure.ac b/gdb/configure.ac
index e70edb7..21f5dc8 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -184,9 +184,14 @@ AS_HELP_STRING([--enable-targets=TARGETS], [alternative target configurations]),
yes | "") AC_MSG_ERROR(enable-targets option must specify target names or 'all')
;;
no) enable_targets= ;;
- *) enable_targets=$enableval ;;
+ *)
+ enable_targets=$enableval
+ AC_DEFINE_UNQUOTED(ENABLE_TARGETS, "$enable_targets",
+ Additional targets configured into GDB. )
+ ;;
esac])
+
BFD_64_BIT
# Provide defaults for some variables set by the per-host and per-target
@@ -281,7 +286,7 @@ if test "$gdb_require_amd_dbgapi" = true \
# stability until amd-dbgapi hits 1.0, but for convenience, still check for
# greater or equal that version. It can be handy when testing with a newer
# version of the library.
- PKG_CHECK_MODULES([AMD_DBGAPI], [amd-dbgapi >= 0.68.0],
+ PKG_CHECK_MODULES([AMD_DBGAPI], [amd-dbgapi >= 0.75.0],
[has_amd_dbgapi=yes], [has_amd_dbgapi=no])
if test "$has_amd_dbgapi" = "yes"; then
diff --git a/gdb/configure.host b/gdb/configure.host
index da71675..22855cd 100644
--- a/gdb/configure.host
+++ b/gdb/configure.host
@@ -110,7 +110,6 @@ i[34567]86-*-mingw32*) gdb_host=mingw
i[34567]86-*-msdosdjgpp*) gdb_host=go32 ;;
i[34567]86-*-linux*) gdb_host=linux ;;
i[34567]86-*-gnu*) gdb_host=i386gnu ;;
-i[3456]86-*-nto*) gdb_host=nto ;;
i[34567]86-*-openbsd*) gdb_host=obsd ;;
i[34567]86-*-solaris2* | x86_64-*-solaris2*)
gdb_host=sol2 ;;
diff --git a/gdb/configure.nat b/gdb/configure.nat
index f88c9c2..9e78091 100644
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -426,15 +426,6 @@ case ${gdb_host} in
esac
;;
- nto)
- case ${gdb_host_cpu} in
- i386)
- # Host: Intel 386 running QNX.
- NATDEPFILES='nto-procfs.o'
- NAT_FILE='config/nm-nto.h'
- ;;
- esac
- ;;
obsd)
case ${gdb_host_cpu} in
i386)
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 8326c45..8d85a59 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -59,7 +59,8 @@ amd64_tobjs="ravenscar-thread.o amd64-ravenscar-thread.o \
case "${targ}" in
aarch64*-*-*)
cpu_obs="aarch32-tdep.o aarch64-tdep.o arch/aarch32.o \
- arch/aarch64-insn.o arch/aarch64.o ravenscar-thread.o \
+ arch/aarch64-insn.o arch/aarch64.o arch/aarch64-mte.o \
+ ravenscar-thread.o \
aarch64-ravenscar-thread.o";;
alpha*-*-*)
@@ -304,11 +305,6 @@ i[34567]86-*-openbsd*)
# Target: OpenBSD/i386
gdb_target_obs="i386-bsd-tdep.o i386-obsd-tdep.o bsd-uthread.o"
;;
-i[34567]86-*-nto*)
- # Target: Intel 386 running qnx6.
- gdb_target_obs="solib-svr4.o \
- i386-nto-tdep.o nto-tdep.o"
- ;;
i[34567]86-*-solaris2* | x86_64-*-solaris2*)
# Target: Solaris x86_64
gdb_target_obs="${i386_tobjs} ${amd64_tobjs} \
@@ -808,7 +804,6 @@ case "${targ}" in
gdb_osabi=GDB_OSABI_FREEBSD ;;
*-*-linux* | *-*-uclinux*)
gdb_osabi=GDB_OSABI_LINUX ;;
-*-*-nto*) gdb_osabi=GDB_OSABI_QNXNTO ;;
m68*-*-openbsd* | m88*-*-openbsd* | vax-*-openbsd*) ;;
*-*-openbsd*) gdb_osabi=GDB_OSABI_OPENBSD ;;
*-*-solaris*) gdb_osabi=GDB_OSABI_SOLARIS ;;
diff --git a/gdb/contrib/ari/gdb_ari.sh b/gdb/contrib/ari/gdb_ari.sh
index d690d29..5ed7d61 100755
--- a/gdb/contrib/ari/gdb_ari.sh
+++ b/gdb/contrib/ari/gdb_ari.sh
@@ -243,7 +243,7 @@ END {
if (seen[file] && (skipped[bug_n_file] < skip[bug_n_file])) {
# ari.*.bug: <FILE>:<LINE>: <CATEGORY>: <BUG>: <DOC>
b = file " missing " bug
- print_bug(file, 0, "", "internal", file " missing " bug, "Expecting " skip[bug_n_file] " occurances of bug " bug " in file " file ", only found " skipped[bug_n_file])
+ print_bug(file, 0, "", "internal", file " missing " bug, "Expecting " skip[bug_n_file] " occurrences of bug " bug " in file " file ", only found " skipped[bug_n_file])
}
}
}
diff --git a/gdb/contrib/common-misspellings.txt b/gdb/contrib/common-misspellings.txt
new file mode 100644
index 0000000..62e2c51
--- /dev/null
+++ b/gdb/contrib/common-misspellings.txt
@@ -0,0 +1,18 @@
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Common spelling mistakes.
+
+inbetween->between, in between, in-between
+sofar->so far
diff --git a/gdb/contrib/gdb-add-index.sh b/gdb/contrib/gdb-add-index.sh
index 80bc495..bd5a8f7 100755
--- a/gdb/contrib/gdb-add-index.sh
+++ b/gdb/contrib/gdb-add-index.sh
@@ -113,7 +113,7 @@ trap "rm -f $tmp_files" 0
$GDB --batch -nx -iex 'set auto-load no' \
-iex 'set debuginfod enabled off' \
- -ex "file $file" -ex "save gdb-index $dwarf5 $dir" || {
+ -ex "file '$file'" -ex "save gdb-index $dwarf5 '$dir'" || {
# Just in case.
status=$?
echo "$myname: gdb error generating index for $file" 1>&2
@@ -143,35 +143,32 @@ handle_file ()
index="$index5"
section=".debug_names"
fi
- debugstradd=false
- debugstrupdate=false
if test -s "$debugstr"; then
if ! $OBJCOPY --dump-section .debug_str="$debugstrmerge" "$fpath" \
- /dev/null 2>$debugstrerr; then
- cat >&2 $debugstrerr
+ /dev/null 2> "$debugstrerr"; then
+ cat >&2 "$debugstrerr"
exit 1
fi
+ cat "$debugstr" >>"$debugstrmerge"
if grep -q "can't dump section '.debug_str' - it does not exist" \
- $debugstrerr; then
- debugstradd=true
+ "$debugstrerr"; then
+ $OBJCOPY --add-section $section="$index" \
+ --set-section-flags $section=readonly \
+ --add-section .debug_str="$debugstrmerge" \
+ --set-section-flags .debug_str=readonly \
+ "$fpath" "$fpath"
else
- debugstrupdate=true
- cat >&2 $debugstrerr
+ $OBJCOPY --add-section $section="$index" \
+ --set-section-flags $section=readonly \
+ --update-section .debug_str="$debugstrmerge" \
+ "$fpath" "$fpath"
fi
- cat "$debugstr" >>"$debugstrmerge"
+ else
+ $OBJCOPY --add-section $section="$index" \
+ --set-section-flags $section=readonly \
+ "$fpath" "$fpath"
fi
- $OBJCOPY --add-section $section="$index" \
- --set-section-flags $section=readonly \
- $(if $debugstradd; then \
- echo --add-section .debug_str="$debugstrmerge"; \
- echo --set-section-flags .debug_str=readonly; \
- fi; \
- if $debugstrupdate; then \
- echo --update-section .debug_str="$debugstrmerge"; \
- fi) \
- "$fpath" "$fpath"
-
status=$?
else
echo "$myname: No index was created for $fpath" 1>&2
diff --git a/gdb/contrib/spellcheck.sh b/gdb/contrib/spellcheck.sh
new file mode 100755
index 0000000..4203333
--- /dev/null
+++ b/gdb/contrib/spellcheck.sh
@@ -0,0 +1,353 @@
+#!/bin/bash
+
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Script to auto-correct common spelling mistakes.
+#
+# Example usage:
+# $ ./gdb/contrib/spellcheck.sh gdb*
+
+scriptdir=$(cd "$(dirname "$0")" || exit; pwd -P)
+
+url=https://en.wikipedia.org/wiki/Wikipedia:Lists_of_common_misspellings/For_machines
+cache_dir=$scriptdir/../../.git
+cache_file=wikipedia-common-misspellings.txt
+dictionary=$cache_dir/$cache_file
+local_dictionary=$scriptdir/common-misspellings.txt
+
+# Separators: space, slash, tab, colon, comma.
+declare -a grep_separators
+grep_separators=(
+ " "
+ "/"
+ " "
+ ":"
+ ","
+)
+declare -a sed_separators
+sed_separators=(
+ " "
+ "/"
+ "\t"
+ ":"
+ ","
+)
+
+join ()
+{
+ local or
+ or="$1"
+ shift
+
+ local res
+ res=""
+
+ local first
+ first=true
+
+ for item in "$@"; do
+ if $first; then
+ first=false
+ res="$item"
+ else
+ res="$res$or$item"
+ fi
+ done
+
+ echo "$res"
+}
+
+grep_or="|"
+sed_or="\|"
+grep_separator=$(join $grep_or "${grep_separators[@]}")
+sed_separator=$(join $sed_or "${sed_separators[@]}")
+
+usage ()
+{
+ echo "usage: $(basename "$0") <file|dir>+"
+}
+
+make_absolute ()
+{
+ local arg
+ arg="$1"
+
+ case "$arg" in
+ /*)
+ ;;
+ *)
+ arg=$(pwd -P)/"$arg"
+ ;;
+ esac
+
+ echo "$arg"
+}
+
+parse_args ()
+{
+ local files
+ files=$(mktemp)
+ trap 'rm -f "$files"' EXIT
+
+ if [ $# -eq -0 ]; then
+ usage
+ exit 1
+ fi
+
+ local arg
+ for arg in "$@"; do
+ if [ -f "$arg" ]; then
+ arg=$(make_absolute "$arg")
+ readlink -e "$arg" \
+ >> "$files"
+ elif [ -d "$arg" ]; then
+ arg=$(make_absolute "$arg")
+ local f
+ find "$arg" -type f -exec readlink -e {} \; \
+ >> "$files"
+ else
+ echo "Not a file or directory: $arg"
+ exit 1
+ fi
+ done
+
+ mapfile -t unique_files \
+ < <(sort -u "$files" \
+ | grep -v ChangeLog)
+
+ rm -f "$files"
+ trap "" EXIT
+}
+
+get_dictionary ()
+{
+ if [ -f "$dictionary" ]; then
+ return
+ fi
+
+ local webpage
+ webpage=$(mktemp)
+ trap 'rm -f "$webpage"' EXIT
+
+ # Download web page containing table.
+ wget $url -O "$webpage"
+
+ # Extract table from web page.
+ awk '/<pre>/,/<\/pre>/' "$webpage" \
+ | sed 's/<pre>//;s/<\/pre>//' \
+ | grep -E -v "^$" \
+ > "$dictionary"
+
+ rm -f "$webpage"
+ trap "" EXIT
+}
+
+output_local_dictionary ()
+{
+ # Filter out comments and empty lines.
+ grep -E -v \
+ "^#|^$" \
+ "$local_dictionary"
+}
+
+output_dictionaries ()
+{
+ output_local_dictionary
+ cat "$dictionary"
+}
+
+parse_dictionary ()
+{
+ # Parse dictionary.
+ mapfile -t words \
+ < <(awk -F '->' '{print $1}' <(output_dictionaries))
+ mapfile -t replacements \
+ < <(awk -F '->' '{print $2}' <(output_dictionaries))
+}
+
+find_files_matching_words ()
+{
+ local pat
+ pat=""
+ for word in "${words[@]}"; do
+ if [ "$pat" = "" ]; then
+ pat="$word"
+ else
+ pat="$pat|$word"
+ fi
+ done
+ pat="($pat)"
+
+ local sep
+ sep=$grep_separator
+
+ pat="(^|$sep)$pat($sep|$)"
+
+ grep -E \
+ -l \
+ "$pat" \
+ "$@"
+}
+
+find_files_matching_word ()
+{
+ local pat
+ pat="$1"
+ shift
+
+ local sep
+ sep=$grep_separator
+
+ pat="(^|$sep)$pat($sep|$)"
+
+ grep -E \
+ -l \
+ "$pat" \
+ "$@"
+}
+
+replace_word_in_file ()
+{
+ local word
+ word="$1"
+
+ local replacement
+ replacement="$2"
+
+ local file
+ file="$3"
+
+ local sep
+ sep=$sed_separator
+
+ # Save separator.
+ sep="\($sep\)"
+
+ local repl1 repl2 repl3
+
+ repl1="s%$sep$word$sep%\1$replacement\2%g"
+
+ repl2="s%^$word$sep%$replacement\1%"
+
+ repl3="s%$sep$word$%\1$replacement%"
+
+ sed -i \
+ "$repl1;$repl2;$repl3" \
+ "$file"
+}
+
+replace_word_in_files ()
+{
+ local word
+ word="$1"
+
+ local replacement
+ replacement="$2"
+
+ shift 2
+
+ local id
+ id="$word -> $replacement"
+
+ # Reduce set of files for sed to operate on.
+ local files_matching_word
+ declare -a files_matching_word
+ mapfile -t files_matching_word \
+ < <(find_files_matching_word "$word" "$@")
+
+ if [ ${#files_matching_word[@]} -eq 0 ]; then
+ return
+ fi
+
+ if echo "$replacement"| grep -q ","; then
+ echo "TODO: $id"
+ return
+ fi
+
+ declare -A md5sums
+
+ local changed f before after
+ changed=false
+ for f in "${files_matching_word[@]}"; do
+ if [ "${md5sums[$f]}" = "" ]; then
+ md5sums[$f]=$(md5sum "$f")
+ fi
+
+ before="${md5sums[$f]}"
+
+ replace_word_in_file \
+ "$word" \
+ "$replacement" \
+ "$f"
+
+ after=$(md5sum "$f")
+
+ if [ "$after" != "$before" ]; then
+ md5sums[$f]="$after"
+ changed=true
+ fi
+ done
+
+ if $changed; then
+ echo "$id"
+ fi
+
+ find_files_matching_word "$word" "${files_matching_word[@]}" \
+ | awk "{ printf \"TODO: $id: replacement failed: %s\n\", \$0}"
+}
+
+main ()
+{
+ declare -a unique_files
+ parse_args "$@"
+
+ get_dictionary
+
+ declare -a words
+ declare -a replacements
+ parse_dictionary
+
+ # Reduce set of files for sed to operate on.
+ local files_matching_words
+ declare -a files_matching_words
+ mapfile -t files_matching_words \
+ < <(find_files_matching_words "${unique_files[@]}")
+
+ if [ ${#files_matching_words[@]} -eq 0 ]; then
+ return
+ fi
+
+ declare -A words_done
+ local i word replacement
+ i=0
+ for word in "${words[@]}"; do
+ replacement=${replacements[$i]}
+ i=$((i + 1))
+
+ # Skip words that are already handled. This ensures that the local
+ # dictionary overrides the wiki dictionary.
+ if [ "${words_done[$word]}" == 1 ]; then
+ continue
+ fi
+ words_done[$word]=1
+
+ replace_word_in_files \
+ "$word" \
+ "$replacement" \
+ "${files_matching_words[@]}"
+ done
+}
+
+main "$@"
diff --git a/gdb/corefile.c b/gdb/corefile.c
index 96052cf..f6ec3cd 100644
--- a/gdb/corefile.c
+++ b/gdb/corefile.c
@@ -391,9 +391,8 @@ Use FILE as core dump for examining memory and registers.\n\
Usage: core-file FILE\n\
No arg means have no core file. This command has been superseded by the\n\
`target core' and `detach' commands."), &cmdlist);
- set_cmd_completer (core_file_cmd, filename_completer);
+ set_cmd_completer (core_file_cmd, deprecated_filename_completer);
-
set_show_commands set_show_gnutarget
= add_setshow_string_noescape_cmd ("gnutarget", class_files,
&gnutarget_string, _("\
diff --git a/gdb/corelow.c b/gdb/corelow.c
index 2b7a355..5820ffe 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -48,17 +48,130 @@
#include "gdbsupport/pathstuff.h"
#include "gdbsupport/scoped_fd.h"
#include "gdbsupport/x86-xstate.h"
-#include "debuginfod-support.h"
#include <unordered_map>
#include <unordered_set>
#include "cli/cli-cmds.h"
#include "xml-tdesc.h"
#include "memtag.h"
+#include "cli/cli-style.h"
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
+/* A mem_range and the build-id associated with the file mapped into the
+ given range. */
+
+struct mem_range_and_build_id
+{
+ mem_range_and_build_id (mem_range &&r, const bfd_build_id *id)
+ : range (r),
+ build_id (id)
+ { /* Nothing. */ }
+
+ /* A range of memory addresses. */
+ mem_range range;
+
+ /* The build-id of the file mapped into RANGE. */
+ const bfd_build_id *build_id;
+};
+
+/* An instance of this class is created within the core_target and is used
+ to hold all the information that relating to mapped files, their address
+ ranges, and their corresponding build-ids. */
+
+struct mapped_file_info
+{
+ /* See comment on function definition. */
+
+ void add (const char *soname, const char *expected_filename,
+ const char *actual_filename, std::vector<mem_range> &&ranges,
+ const bfd_build_id *build_id);
+
+ /* See comment on function definition. */
+
+ std::optional <core_target_mapped_file_info>
+ lookup (const char *filename, const std::optional<CORE_ADDR> &addr);
+
+private:
+
+ /* Helper for ::lookup. BUILD_ID is a build-id that was found in
+ one of the data structures within this class. Lookup the
+ corresponding filename in m_build_id_to_filename_map and return a pair
+ containing the build-id and filename.
+
+ If no corresponding filename is found in m_build_id_to_filename_map
+ then the returned pair contains BUILD_ID and an empty string.
+
+ If BUILD_ID is nullptr then the returned pair contains nullptr and an
+ empty string. */
+
+ struct core_target_mapped_file_info
+ make_result (const bfd_build_id *build_id)
+ {
+ if (build_id != nullptr)
+ {
+ auto it = m_build_id_to_filename_map.find (build_id);
+ if (it != m_build_id_to_filename_map.end ())
+ return { build_id, it->second };
+ }
+
+ return { build_id, {} };
+ }
+
+ /* A type that maps a string to a build-id. */
+ using string_to_build_id_map
+ = std::unordered_map<std::string, const bfd_build_id *>;
+
+ /* A type that maps a build-id to a string. */
+ using build_id_to_string_map
+ = std::unordered_map<const bfd_build_id *, std::string>;
+
+ /* When loading a core file, the build-ids are extracted based on the
+ file backed mappings. This map associates the name of a file that was
+ mapped into the core file with the corresponding build-id. The
+ build-id pointers in this map will never be nullptr as we only record
+ files if they have a build-id. */
+
+ string_to_build_id_map m_filename_to_build_id_map;
+
+ /* Map a build-id pointer back to the name of the file that was mapped
+ into the inferior's address space. If we lookup a matching build-id
+ using either a soname or an address then this map allows us to also
+ provide a full path to a file with a matching build-id. */
+
+ build_id_to_string_map m_build_id_to_filename_map;
+
+ /* If the file that was mapped into the core file was a shared library
+ then it might have a DT_SONAME tag in its .dynamic section, this tag
+ contains the name of a shared object. When opening a shared library,
+ if it's basename appears in this map then we can use the corresponding
+ build-id.
+
+ In the rare case that two different files have the same DT_SONAME
+ value then the build-id pointer in this map will be nullptr, this
+ indicates that it's not possible to find a build-id based on the given
+ DT_SONAME value. */
+
+ string_to_build_id_map m_soname_to_build_id_map;
+
+ /* This vector maps memory ranges onto an associated build-id. The
+ ranges are those of the files mapped into the core file.
+
+ Entries in this vector must not overlap, and are sorted be increasing
+ memory address. Within each entry the build-id pointer will not be
+ nullptr.
+
+ While building this vector the entries are not sorted, they are
+ sorted once after the table has finished being built. */
+
+ std::vector<mem_range_and_build_id> m_address_to_build_id_list;
+
+ /* False if address_to_build_id_list is unsorted, otherwise true. */
+
+ bool m_address_to_build_id_list_sorted = false;
+};
+
/* The core file target. */
static const target_info core_target_info = {
@@ -135,6 +248,13 @@ public:
/* See definition. */
void info_proc_mappings (struct gdbarch *gdbarch);
+ std::optional <core_target_mapped_file_info>
+ lookup_mapped_file_info (const char *filename,
+ const std::optional<CORE_ADDR> &addr)
+ {
+ return m_mapped_file_info.lookup (filename, addr);
+ }
+
private: /* per-core data */
/* Get rid of the core inferior. */
@@ -157,15 +277,14 @@ private: /* per-core data */
still be useful. */
std::vector<mem_range> m_core_unavailable_mappings;
- /* Build m_core_file_mappings. Called from the constructor. */
- void build_file_mappings ();
+ /* Data structure that holds information mapping filenames and address
+ ranges to the corresponding build-ids as well as the reverse build-id
+ to filename mapping. */
+ mapped_file_info m_mapped_file_info;
- /* Helper method for xfer_partial. */
- enum target_xfer_status xfer_memory_via_mappings (gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset,
- ULONGEST len,
- ULONGEST *xfered_len);
+ /* Build m_core_file_mappings and m_mapped_file_info. Called from the
+ constructor. */
+ void build_file_mappings ();
/* FIXME: kettenis/20031023: Eventually this field should
disappear. */
@@ -217,9 +336,51 @@ core_target::core_target ()
void
core_target::build_file_mappings ()
{
+ /* Type holding information about a single file mapped into the inferior
+ at the point when the core file was created. Associates a build-id
+ with the list of regions the file is mapped into. */
+ struct mapped_file
+ {
+ /* Type for a region of a file that was mapped into the inferior when
+ the core file was generated. */
+ struct region
+ {
+ /* Constructor. See member variables for argument descriptions. */
+ region (CORE_ADDR start_, CORE_ADDR end_, CORE_ADDR file_ofs_)
+ : start (start_),
+ end (end_),
+ file_ofs (file_ofs_)
+ { /* Nothing. */ }
+
+ /* The inferior address for the start of the mapped region. */
+ CORE_ADDR start;
+
+ /* The inferior address immediately after the mapped region. */
+ CORE_ADDR end;
+
+ /* The offset within the mapped file for this content. */
+ CORE_ADDR file_ofs;
+ };
+
+ /* If not nullptr, then this is the build-id associated with this
+ file. */
+ const bfd_build_id *build_id = nullptr;
+
+ /* If true then we have seen multiple different build-ids associated
+ with the same filename. The build_id field will have been set back
+ to nullptr, and we should not set build_id in future. */
+ bool ignore_build_id_p = false;
+
+ /* All the mapped regions of this file. */
+ std::vector<region> regions;
+ };
+
std::unordered_map<std::string, struct bfd *> bfd_map;
std::unordered_set<std::string> unavailable_paths;
+ /* All files mapped into the core file. The key is the filename. */
+ std::unordered_map<std::string, mapped_file> mapped_files;
+
/* See linux_read_core_file_mappings() in linux-tdep.c for an example
read_core_file_mappings method. */
gdbarch_read_core_file_mappings (m_core_gdbarch,
@@ -240,87 +401,193 @@ core_target::build_file_mappings ()
weed out non-file-backed mappings. */
gdb_assert (filename != nullptr);
- if (unavailable_paths.find (filename) != unavailable_paths.end ())
- {
- /* We have already seen some mapping for FILENAME but failed to
- find/open the file. There is no point in trying the same
- thing again so just record that the range [start, end) is
- unavailable. */
- m_core_unavailable_mappings.emplace_back (start, end - start);
- return;
- }
-
- struct bfd *bfd = bfd_map[filename];
- if (bfd == nullptr)
+ /* Add this mapped region to the data for FILENAME. */
+ mapped_file &file_data = mapped_files[filename];
+ file_data.regions.emplace_back (start, end, file_ofs);
+ if (build_id != nullptr && !file_data.ignore_build_id_p)
{
- /* Use exec_file_find() to do sysroot expansion. It'll
- also strip the potential sysroot "target:" prefix. If
- there is no sysroot, an equivalent (possibly more
- canonical) pathname will be provided. */
- gdb::unique_xmalloc_ptr<char> expanded_fname
- = exec_file_find (filename, NULL);
-
- if (expanded_fname == nullptr && build_id != nullptr)
- debuginfod_exec_query (build_id->data, build_id->size,
- filename, &expanded_fname);
-
- if (expanded_fname == nullptr)
+ if (file_data.build_id == nullptr)
+ file_data.build_id = build_id;
+ else if (!build_id_equal (build_id, file_data.build_id))
{
- m_core_unavailable_mappings.emplace_back (start, end - start);
- unavailable_paths.insert (filename);
- warning (_("Can't open file %s during file-backed mapping "
- "note processing"),
- filename);
- return;
+ warning (_("Multiple build-ids found for %ps"),
+ styled_string (file_name_style.style (), filename));
+ file_data.build_id = nullptr;
+ file_data.ignore_build_id_p = true;
}
+ }
+ });
+
+ for (const auto &iter : mapped_files)
+ {
+ const std::string &filename = iter.first;
+ const mapped_file &file_data = iter.second;
+
+ /* Use exec_file_find() to do sysroot expansion. It'll
+ also strip the potential sysroot "target:" prefix. If
+ there is no sysroot, an equivalent (possibly more
+ canonical) pathname will be provided. */
+ gdb::unique_xmalloc_ptr<char> expanded_fname
+ = exec_file_find (filename.c_str (), nullptr);
+
+ bool build_id_mismatch = false;
+ if (expanded_fname != nullptr && file_data.build_id != nullptr)
+ {
+ /* We temporarily open the bfd as a structured target, this
+ allows us to read the build-id from the bfd if there is one.
+ For this task it's OK if we reuse an already open bfd object,
+ so we make this call through GDB's bfd cache. Once we've
+ checked the build-id (if there is one) we'll drop this
+ reference and re-open the bfd using the "binary" target. */
+ gdb_bfd_ref_ptr tmp_bfd
+ = gdb_bfd_open (expanded_fname.get (), gnutarget);
+
+ if (tmp_bfd != nullptr
+ && bfd_check_format (tmp_bfd.get (), bfd_object)
+ && build_id_bfd_get (tmp_bfd.get ()) != nullptr)
+ {
+ /* The newly opened TMP_BFD has a build-id, and this mapped
+ file has a build-id extracted from the core-file. Check
+ the build-id's match, and if not, reject TMP_BFD. */
+ const struct bfd_build_id *found
+ = build_id_bfd_get (tmp_bfd.get ());
+ if (!build_id_equal (found, file_data.build_id))
+ build_id_mismatch = true;
+ }
+ }
+
+ gdb_bfd_ref_ptr abfd;
+ if (expanded_fname != nullptr && !build_id_mismatch)
+ {
+ struct bfd *b = bfd_openr (expanded_fname.get (), "binary");
+ abfd = gdb_bfd_ref_ptr::new_reference (b);
+ }
- bfd = bfd_openr (expanded_fname.get (), "binary");
+ if ((expanded_fname == nullptr
+ || abfd == nullptr
+ || !bfd_check_format (abfd.get (), bfd_object))
+ && file_data.build_id != nullptr)
+ {
+ abfd = find_objfile_by_build_id (file_data.build_id,
+ filename.c_str ());
- if (bfd == nullptr || !bfd_check_format (bfd, bfd_object))
- {
- m_core_unavailable_mappings.emplace_back (start, end - start);
- unavailable_paths.insert (filename);
- warning (_("Can't open file %s which was expanded to %s "
+ if (abfd != nullptr)
+ {
+ /* The find_objfile_by_build_id will have opened ABFD using
+ the GNUTARGET global bfd type, however, we need the bfd
+ opened as the binary type (see the function's header
+ comment), so now we reopen ABFD with the desired binary
+ type. */
+ expanded_fname
+ = make_unique_xstrdup (bfd_get_filename (abfd.get ()));
+ struct bfd *b = bfd_openr (expanded_fname.get (), "binary");
+ gdb_assert (b != nullptr);
+ abfd = gdb_bfd_ref_ptr::new_reference (b);
+ }
+ }
+
+ std::vector<mem_range> ranges;
+ for (const mapped_file::region &region : file_data.regions)
+ ranges.emplace_back (region.start, region.end - region.start);
+
+ if (expanded_fname == nullptr
+ || abfd == nullptr
+ || !bfd_check_format (abfd.get (), bfd_object))
+ {
+ /* If ABFD was opened, but the wrong format, close it now. */
+ abfd = nullptr;
+
+ /* Record all regions for this file as unavailable. */
+ for (const mapped_file::region &region : file_data.regions)
+ m_core_unavailable_mappings.emplace_back (region.start,
+ region.end
+ - region.start);
+
+ /* And give the user an appropriate warning. */
+ if (build_id_mismatch)
+ {
+ if (expanded_fname == nullptr
+ || filename == expanded_fname.get ())
+ warning (_("File %ps doesn't match build-id from core-file "
+ "during file-backed mapping processing"),
+ styled_string (file_name_style.style (),
+ filename.c_str ()));
+ else
+ warning (_("File %ps which was expanded to %ps, doesn't match "
+ "build-id from core-file during file-backed "
+ "mapping processing"),
+ styled_string (file_name_style.style (),
+ filename.c_str ()),
+ styled_string (file_name_style.style (),
+ expanded_fname.get ()));
+ }
+ else
+ {
+ if (expanded_fname == nullptr
+ || filename == expanded_fname.get ())
+ warning (_("Can't open file %ps during file-backed mapping "
+ "note processing"),
+ styled_string (file_name_style.style (),
+ filename.c_str ()));
+ else
+ warning (_("Can't open file %ps which was expanded to %ps "
"during file-backed mapping note processing"),
- filename, expanded_fname.get ());
+ styled_string (file_name_style.style (),
+ filename.c_str ()),
+ styled_string (file_name_style.style (),
+ expanded_fname.get ()));
+ }
+ }
+ else
+ {
+ /* Ensure that the bfd will be closed when core_bfd is closed.
+ This can be checked before/after a core file detach via "maint
+ info bfds". */
+ gdb_bfd_record_inclusion (current_program_space->core_bfd (),
+ abfd.get ());
+
+ /* Create sections for each mapped region. */
+ for (const mapped_file::region &region : file_data.regions)
+ {
+ /* Make new BFD section. All sections have the same name,
+ which is permitted by bfd_make_section_anyway(). */
+ asection *sec = bfd_make_section_anyway (abfd.get (), "load");
+ if (sec == nullptr)
+ error (_("Can't make section"));
+ sec->filepos = region.file_ofs;
+ bfd_set_section_flags (sec, SEC_READONLY | SEC_HAS_CONTENTS);
+ bfd_set_section_size (sec, region.end - region.start);
+ bfd_set_section_vma (sec, region.start);
+ bfd_set_section_lma (sec, region.start);
+ bfd_set_section_alignment (sec, 2);
+
+ /* Set target_section fields. */
+ m_core_file_mappings.emplace_back (region.start, region.end, sec);
+ }
+ }
- if (bfd != nullptr)
- bfd_close (bfd);
- return;
- }
- /* Ensure that the bfd will be closed when core_bfd is closed.
- This can be checked before/after a core file detach via
- "maint info bfds". */
- gdb_bfd_record_inclusion (current_program_space->core_bfd (), bfd);
- bfd_map[filename] = bfd;
- }
+ /* If this is a bfd with a build-id then record the filename,
+ optional soname (DT_SONAME .dynamic attribute), and the range of
+ addresses at which this bfd is mapped. This information can be
+ used to perform build-id checking when loading the shared
+ libraries. */
+ if (file_data.build_id != nullptr)
+ {
+ normalize_mem_ranges (&ranges);
- /* Make new BFD section. All sections have the same name,
- which is permitted by bfd_make_section_anyway(). */
- asection *sec = bfd_make_section_anyway (bfd, "load");
- if (sec == nullptr)
- error (_("Can't make section"));
- sec->filepos = file_ofs;
- bfd_set_section_flags (sec, SEC_READONLY | SEC_HAS_CONTENTS);
- bfd_set_section_size (sec, end - start);
- bfd_set_section_vma (sec, start);
- bfd_set_section_lma (sec, start);
- bfd_set_section_alignment (sec, 2);
-
- /* Set target_section fields. */
- m_core_file_mappings.emplace_back (start, end, sec);
-
- /* If this is a bfd of a shared library, record its soname
- and build id. */
- if (build_id != nullptr)
- {
- gdb::unique_xmalloc_ptr<char> soname
- = gdb_bfd_read_elf_soname (bfd->filename);
- if (soname != nullptr)
- set_cbfd_soname_build_id (current_program_space->cbfd,
- soname.get (), build_id);
- }
- });
+ const char *actual_filename = nullptr;
+ gdb::unique_xmalloc_ptr<char> soname;
+ if (abfd != nullptr)
+ {
+ actual_filename = bfd_get_filename (abfd.get ());
+ soname = gdb_bfd_read_elf_soname (actual_filename);
+ }
+
+ m_mapped_file_info.add (soname.get (), filename.c_str (),
+ actual_filename, std::move (ranges),
+ file_data.build_id);
+ }
+ }
normalize_mem_ranges (&m_core_unavailable_mappings);
}
@@ -572,28 +839,7 @@ locate_exec_from_corefile_build_id (bfd *abfd, int from_tty)
return;
gdb_bfd_ref_ptr execbfd
- = build_id_to_exec_bfd (build_id->size, build_id->data);
-
- if (execbfd == nullptr)
- {
- /* Attempt to query debuginfod for the executable. */
- gdb::unique_xmalloc_ptr<char> execpath;
- scoped_fd fd = debuginfod_exec_query (build_id->data, build_id->size,
- abfd->filename, &execpath);
-
- if (fd.get () >= 0)
- {
- execbfd = gdb_bfd_open (execpath.get (), gnutarget);
-
- if (execbfd == nullptr)
- warning (_("\"%s\" from debuginfod cannot be opened as bfd: %s"),
- execpath.get (),
- gdb_bfd_errmsg (bfd_get_error (), nullptr).c_str ());
- else if (!build_id_verify (execbfd.get (), build_id->size,
- build_id->data))
- execbfd.reset (nullptr);
- }
- }
+ = find_objfile_by_build_id (build_id, abfd->filename);
if (execbfd != nullptr)
{
@@ -614,7 +860,10 @@ core_target_open (const char *arg, int from_tty)
int flags;
target_preopen (from_tty);
- if (!arg)
+
+ std::string filename = extract_single_filename_arg (arg);
+
+ if (filename.empty ())
{
if (current_program_space->core_bfd ())
error (_("No core file specified. (Use `detach' "
@@ -623,25 +872,23 @@ core_target_open (const char *arg, int from_tty)
error (_("No core file specified."));
}
- gdb::unique_xmalloc_ptr<char> filename (tilde_expand (arg));
- if (strlen (filename.get ()) != 0
- && !IS_ABSOLUTE_PATH (filename.get ()))
- filename = make_unique_xstrdup (gdb_abspath (filename).c_str ());
+ if (!IS_ABSOLUTE_PATH (filename.c_str ()))
+ filename = gdb_abspath (filename);
flags = O_BINARY | O_LARGEFILE;
if (write_files)
flags |= O_RDWR;
else
flags |= O_RDONLY;
- scratch_chan = gdb_open_cloexec (filename.get (), flags, 0).release ();
+ scratch_chan = gdb_open_cloexec (filename.c_str (), flags, 0).release ();
if (scratch_chan < 0)
- perror_with_name (filename.get ());
+ perror_with_name (filename.c_str ());
- gdb_bfd_ref_ptr temp_bfd (gdb_bfd_fopen (filename.get (), gnutarget,
+ gdb_bfd_ref_ptr temp_bfd (gdb_bfd_fopen (filename.c_str (), gnutarget,
write_files ? FOPEN_RUB : FOPEN_RB,
scratch_chan));
if (temp_bfd == NULL)
- perror_with_name (filename.get ());
+ perror_with_name (filename.c_str ());
if (!bfd_check_format (temp_bfd.get (), bfd_core))
{
@@ -650,7 +897,7 @@ core_target_open (const char *arg, int from_tty)
thing, on error it does not free all the storage associated
with the bfd). */
error (_("\"%s\" is not a core dump: %s"),
- filename.get (), bfd_errmsg (bfd_get_error ()));
+ filename.c_str (), bfd_errmsg (bfd_get_error ()));
}
current_program_space->cbfd = std::move (temp_bfd);
@@ -964,55 +1211,6 @@ core_target::files_info ()
print_section_info (&m_core_section_table, current_program_space->core_bfd ());
}
-/* Helper method for core_target::xfer_partial. */
-
-enum target_xfer_status
-core_target::xfer_memory_via_mappings (gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len,
- ULONGEST *xfered_len)
-{
- enum target_xfer_status xfer_status;
-
- xfer_status = (section_table_xfer_memory_partial
- (readbuf, writebuf,
- offset, len, xfered_len,
- m_core_file_mappings));
-
- if (xfer_status == TARGET_XFER_OK || m_core_unavailable_mappings.empty ())
- return xfer_status;
-
- /* There are instances - e.g. when debugging within a docker
- container using the AUFS storage driver - where the pathnames
- obtained from the note section are incorrect. Despite the path
- being wrong, just knowing the start and end addresses of the
- mappings is still useful; we can attempt an access of the file
- stratum constrained to the address ranges corresponding to the
- unavailable mappings. */
-
- ULONGEST memaddr = offset;
- ULONGEST memend = offset + len;
-
- for (const auto &mr : m_core_unavailable_mappings)
- {
- if (mr.contains (memaddr))
- {
- if (!mr.contains (memend))
- len = mr.start + mr.length - memaddr;
-
- xfer_status = this->beneath ()->xfer_partial (TARGET_OBJECT_MEMORY,
- NULL,
- readbuf,
- writebuf,
- offset,
- len,
- xfered_len);
- break;
- }
- }
-
- return xfer_status;
-}
enum target_xfer_status
core_target::xfer_partial (enum target_object object, const char *annex,
@@ -1040,26 +1238,72 @@ core_target::xfer_partial (enum target_object object, const char *annex,
if (xfer_status == TARGET_XFER_OK)
return TARGET_XFER_OK;
- /* Check file backed mappings. If they're available, use
- core file provided mappings (e.g. from .note.linuxcore.file
- or the like) as this should provide a more accurate
- result. If not, check the stratum beneath us, which should
- be the file stratum.
+ /* Check file backed mappings. If they're available, use core file
+ provided mappings (e.g. from .note.linuxcore.file or the like)
+ as this should provide a more accurate result. */
+ if (!m_core_file_mappings.empty ())
+ {
+ xfer_status = section_table_xfer_memory_partial
+ (readbuf, writebuf, offset, len, xfered_len,
+ m_core_file_mappings);
+ if (xfer_status == TARGET_XFER_OK)
+ return xfer_status;
+ }
- We also check unavailable mappings due to Docker/AUFS driver
- issues. */
- if (!m_core_file_mappings.empty ()
- || !m_core_unavailable_mappings.empty ())
+ /* If the access is within an unavailable file mapping then we try
+ to check in the stratum below (the executable stratum). The
+ thinking here is that if the mapping was read/write then the
+ contents would have been written into the core file and the
+ access would have been satisfied by m_core_section_table.
+
+ But if the access has not yet been resolved then we can assume
+ the access is read-only. If the executable was not found
+ during the mapped file check then we'll have an unavailable
+ mapping entry, however, if the user has provided the executable
+ (maybe in a different location) then we might be able to
+ resolve the access from there.
+
+ If that fails, but the access is within an unavailable region,
+ then the access itself should fail. */
+ for (const auto &mr : m_core_unavailable_mappings)
{
- xfer_status = xfer_memory_via_mappings (readbuf, writebuf, offset,
+ if (mr.contains (offset))
+ {
+ if (!mr.contains (offset + len))
+ len = mr.start + mr.length - offset;
+
+ xfer_status
+ = this->beneath ()->xfer_partial (TARGET_OBJECT_MEMORY,
+ nullptr, readbuf,
+ writebuf, offset,
len, xfered_len);
+ if (xfer_status == TARGET_XFER_OK)
+ return TARGET_XFER_OK;
+
+ return TARGET_XFER_E_IO;
+ }
+ }
+
+ /* The following is acting as a fallback in case we encounter a
+ situation where the core file is lacking and mapped file
+ information. Here we query the exec file stratum to see if it
+ can resolve the access. Doing this when we are missing mapped
+ file information might be the best we can do, but there are
+ certainly cases this will get wrong, e.g. if an inferior created
+ a zero initialised mapping over the top of some data that exists
+ within the executable then this will return the executable data
+ rather than the zero data. Maybe we should just drop this
+ block? */
+ if (m_core_file_mappings.empty ()
+ && m_core_unavailable_mappings.empty ())
+ {
+ xfer_status
+ = this->beneath ()->xfer_partial (object, annex, readbuf,
+ writebuf, offset, len,
+ xfered_len);
+ if (xfer_status == TARGET_XFER_OK)
+ return TARGET_XFER_OK;
}
- else
- xfer_status = this->beneath ()->xfer_partial (object, annex, readbuf,
- writebuf, offset, len,
- xfered_len);
- if (xfer_status == TARGET_XFER_OK)
- return TARGET_XFER_OK;
/* Finally, attempt to access data in core file sections with
no contents. These will typically read as all zero. */
@@ -1454,24 +1698,19 @@ get_current_core_target ()
void
core_target::info_proc_mappings (struct gdbarch *gdbarch)
{
- if (!m_core_file_mappings.empty ())
- {
- gdb_printf (_("Mapped address spaces:\n\n"));
- if (gdbarch_addr_bit (gdbarch) == 32)
- {
- gdb_printf ("\t%10s %10s %10s %10s %s\n",
- "Start Addr",
- " End Addr",
- " Size", " Offset", "objfile");
- }
- else
- {
- gdb_printf (" %18s %18s %10s %10s %s\n",
- "Start Addr",
- " End Addr",
- " Size", " Offset", "objfile");
- }
- }
+ if (m_core_file_mappings.empty ())
+ return;
+
+ gdb_printf (_("Mapped address spaces:\n\n"));
+ ui_out_emit_table emitter (current_uiout, 5, -1, "ProcMappings");
+
+ int width = gdbarch_addr_bit (gdbarch) == 32 ? 10 : 18;
+ current_uiout->table_header (width, ui_left, "start", "Start Addr");
+ current_uiout->table_header (width, ui_left, "end", "End Addr");
+ current_uiout->table_header (width, ui_left, "size", "Size");
+ current_uiout->table_header (width, ui_left, "offset", "Offset");
+ current_uiout->table_header (0, ui_left, "objfile", "File");
+ current_uiout->table_body ();
for (const target_section &tsp : m_core_file_mappings)
{
@@ -1480,20 +1719,16 @@ core_target::info_proc_mappings (struct gdbarch *gdbarch)
ULONGEST file_ofs = tsp.the_bfd_section->filepos;
const char *filename = bfd_get_filename (tsp.the_bfd_section->owner);
- if (gdbarch_addr_bit (gdbarch) == 32)
- gdb_printf ("\t%10s %10s %10s %10s %s\n",
- paddress (gdbarch, start),
- paddress (gdbarch, end),
- hex_string (end - start),
- hex_string (file_ofs),
- filename);
- else
- gdb_printf (" %18s %18s %10s %10s %s\n",
- paddress (gdbarch, start),
- paddress (gdbarch, end),
- hex_string (end - start),
- hex_string (file_ofs),
- filename);
+ ui_out_emit_tuple tuple_emitter (current_uiout, nullptr);
+ current_uiout->field_core_addr ("start", gdbarch, start);
+ current_uiout->field_core_addr ("end", gdbarch, end);
+ /* These next two aren't really addresses and so shouldn't be
+ styled as such. */
+ current_uiout->field_string ("size", paddress (gdbarch, end - start));
+ current_uiout->field_string ("offset", paddress (gdbarch, file_ofs));
+ current_uiout->field_string ("objfile", filename,
+ file_name_style.style ());
+ current_uiout->text ("\n");
}
}
@@ -1516,11 +1751,188 @@ maintenance_print_core_file_backed_mappings (const char *args, int from_tty)
targ->info_proc_mappings (targ->core_gdbarch ());
}
+/* Add more details discovered while processing the core-file's mapped file
+ information, we're building maps between filenames and the corresponding
+ build-ids, between address ranges and the corresponding build-ids, and
+ also a reverse map between build-id and the corresponding filename.
+
+ SONAME is the DT_SONAME attribute extracted from the .dynamic section of
+ a shared library that was mapped into the core file. This can be
+ nullptr if the mapped files was not a shared library, or didn't have a
+ DT_SONAME attribute.
+
+ EXPECTED_FILENAME is the name of the file that was mapped into the
+ inferior as extracted from the core file, this should never be nullptr.
+
+ ACTUAL_FILENAME is the name of the actual file GDB found to provide the
+ mapped file information, this can be nullptr if GDB failed to find a
+ suitable file. This might be different to EXPECTED_FILENAME, e.g. GDB
+ might have downloaded the file from debuginfod and so ACTUAL_FILENAME
+ will be a file in the debuginfod client cache.
+
+ RANGES is the list of memory ranges at which this file was mapped into
+ the inferior.
+
+ BUILD_ID is the build-id for this mapped file, this will never be
+ nullptr. Not every mapped file will have a build-id, but there's no
+ point calling this function if we failed to find a build-id; this
+ structure only exists so we can lookup files based on their build-id. */
+
+void
+mapped_file_info::add (const char *soname,
+ const char *expected_filename,
+ const char *actual_filename,
+ std::vector<mem_range> &&ranges,
+ const bfd_build_id *build_id)
+{
+ gdb_assert (build_id != nullptr);
+ gdb_assert (expected_filename != nullptr);
+
+ if (soname != nullptr)
+ {
+ /* If we already have an entry with this SONAME then this indicates
+ that the inferior has two files mapped into memory with different
+ file names (and most likely different build-ids), but with the
+ same DT_SONAME attribute. In this case we can't use the
+ DT_SONAME to figure out the expected build-id of a shared
+ library, so poison the entry for this SONAME by setting the entry
+ to nullptr. */
+ auto it = m_soname_to_build_id_map.find (soname);
+ if (it != m_soname_to_build_id_map.end ()
+ && it->second != nullptr
+ && !build_id_equal (it->second, build_id))
+ m_soname_to_build_id_map[soname] = nullptr;
+ else
+ m_soname_to_build_id_map[soname] = build_id;
+ }
+
+ /* When the core file is initially opened and the mapped files are
+ parsed, we group the build-id information based on the file name. As
+ a consequence, we should see each EXPECTED_FILENAME value exactly
+ once. This means that each insertion should always succeed. */
+ const auto inserted
+ = m_filename_to_build_id_map.emplace (expected_filename, build_id).second;
+ gdb_assert (inserted);
+
+ /* Setup the reverse build-id to file name map. */
+ if (actual_filename != nullptr)
+ m_build_id_to_filename_map.emplace (build_id, actual_filename);
+
+ /* Setup the list of memory range to build-id objects. */
+ for (mem_range &r : ranges)
+ m_address_to_build_id_list.emplace_back (std::move (r), build_id);
+
+ /* At this point the m_address_to_build_id_list is unsorted (we just
+ added some entries to the end of the list). All entries should be
+ added before any look-ups are performed, and the list is only sorted
+ when the first look-up is performed. */
+ gdb_assert (!m_address_to_build_id_list_sorted);
+}
+
+/* FILENAME is the name of a file GDB is trying to load, and ADDR is
+ (optionally) an address within the file in the inferior's address space.
+
+ Search through the information gathered from the core-file's mapped file
+ information looking for a file named FILENAME, or for a file that covers
+ ADDR. If a match is found then return the build-id for the file along
+ with the location where GDB found the mapped file.
+
+ The location of the mapped file might be the empty string if GDB was
+ unable to find the mapped file.
+
+ If no build-id can be found for FILENAME then GDB will return a pair
+ containing nullptr (for the build-id) and an empty string for the file
+ name. */
+
+std::optional <core_target_mapped_file_info>
+mapped_file_info::lookup (const char *filename,
+ const std::optional<CORE_ADDR> &addr)
+{
+ if (filename != nullptr)
+ {
+ /* If there's a matching entry in m_filename_to_build_id_map then the
+ associated build-id will not be nullptr, and can be used to
+ validate that FILENAME is correct. */
+ auto it = m_filename_to_build_id_map.find (filename);
+ if (it != m_filename_to_build_id_map.end ())
+ return make_result (it->second);
+ }
+
+ if (addr.has_value ())
+ {
+ /* On the first lookup, sort the address_to_build_id_list. */
+ if (!m_address_to_build_id_list_sorted)
+ {
+ std::sort (m_address_to_build_id_list.begin (),
+ m_address_to_build_id_list.end (),
+ [] (const mem_range_and_build_id &a,
+ const mem_range_and_build_id &b) {
+ return a.range < b.range;
+ });
+ m_address_to_build_id_list_sorted = true;
+ }
+
+ /* Look for the first entry whose range's start address is not less
+ than, or equal too, the address ADDR. If we find such an entry,
+ then the previous entry's range might contain ADDR. If it does
+ then that previous entry's build-id can be used. */
+ auto it = std::lower_bound
+ (m_address_to_build_id_list.begin (),
+ m_address_to_build_id_list.end (),
+ *addr,
+ [] (const mem_range_and_build_id &a,
+ const CORE_ADDR &b) {
+ return a.range.start <= b;
+ });
+
+ if (it != m_address_to_build_id_list.begin ())
+ {
+ --it;
+
+ if (it->range.contains (*addr))
+ return make_result (it->build_id);
+ }
+ }
+
+ if (filename != nullptr)
+ {
+ /* If the basename of FILENAME appears in m_soname_to_build_id_map
+ then when the mapped files were processed, we saw a file with a
+ DT_SONAME attribute corresponding to FILENAME, use that build-id
+ to validate FILENAME.
+
+ However, the build-id in this map might be nullptr if we saw
+ multiple mapped files with the same DT_SONAME attribute (though
+ this should be pretty rare). */
+ auto it
+ = m_soname_to_build_id_map.find (lbasename (filename));
+ if (it != m_soname_to_build_id_map.end ()
+ && it->second != nullptr)
+ return make_result (it->second);
+ }
+
+ return {};
+}
+
+/* See gdbcore.h. */
+
+std::optional <core_target_mapped_file_info>
+core_target_find_mapped_file (const char *filename,
+ std::optional<CORE_ADDR> addr)
+{
+ core_target *targ = get_current_core_target ();
+ if (targ == nullptr || current_program_space->cbfd.get () == nullptr)
+ return {};
+
+ return targ->lookup_mapped_file_info (filename, addr);
+}
+
void _initialize_corelow ();
void
_initialize_corelow ()
{
- add_target (core_target_info, core_target_open, filename_completer);
+ add_target (core_target_info, core_target_open,
+ filename_maybe_quoted_completer);
add_cmd ("core-file-backed-mappings", class_maintenance,
maintenance_print_core_file_backed_mappings,
_("Print core file's file-backed mappings."),
diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c
index 692aa9a..8562def 100644
--- a/gdb/cris-tdep.c
+++ b/gdb/cris-tdep.c
@@ -3339,7 +3339,7 @@ get_data_from_address (unsigned short *inst, CORE_ADDR address,
return value;
}
-/* Handles the assign addresing mode for the ADD, SUB, CMP, AND, OR and MOVE
+/* Handles the assign addressing mode for the ADD, SUB, CMP, AND, OR and MOVE
instructions. The MOVE instruction is the move from source to register. */
static void
@@ -3398,7 +3398,7 @@ three_operand_add_sub_cmp_and_or_op (unsigned short inst,
inst_env->disable_interrupt = 0;
}
-/* Handles the index addresing mode for the ADD, SUB, CMP, AND, OR and MOVE
+/* Handles the index addressing mode for the ADD, SUB, CMP, AND, OR and MOVE
instructions. The MOVE instruction is the move from source to register. */
static void
@@ -3425,7 +3425,7 @@ handle_prefix_index_mode_for_aritm_op (unsigned short inst,
inst_env->disable_interrupt = 0;
}
-/* Handles the autoincrement and indirect addresing mode for the ADD, SUB,
+/* Handles the autoincrement and indirect addressing mode for the ADD, SUB,
CMP, AND OR and MOVE instruction. The MOVE instruction is the move from
source to register. */
@@ -3883,7 +3883,7 @@ set_cris_version (const char *ignore_args, int from_tty,
usr_cmd_cris_version_valid = 1;
/* Update the current architecture, if needed. */
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("cris_gdbarch_update: failed to update architecture."));
}
@@ -3894,7 +3894,7 @@ set_cris_mode (const char *ignore_args, int from_tty,
struct gdbarch_info info;
/* Update the current architecture, if needed. */
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error ("cris_gdbarch_update: failed to update architecture.");
}
@@ -3905,7 +3905,7 @@ set_cris_dwarf2_cfi (const char *ignore_args, int from_tty,
struct gdbarch_info info;
/* Update the current architecture, if needed. */
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("cris_gdbarch_update: failed to update architecture."));
}
diff --git a/gdb/csky-tdep.c b/gdb/csky-tdep.c
index 1b6c08e..d69b8e5 100644
--- a/gdb/csky-tdep.c
+++ b/gdb/csky-tdep.c
@@ -2097,7 +2097,7 @@ csky_frame_unwind_cache (const frame_info_ptr &this_frame)
func_size = bl->end () - bl->start ();
else
{
- struct bound_minimal_symbol msymbol
+ bound_minimal_symbol msymbol
= lookup_minimal_symbol_by_pc (prologue_start);
if (msymbol.minsym != NULL)
func_size = msymbol.minsym->size ();
diff --git a/gdb/ctfread.c b/gdb/ctfread.c
index d8606d3..ee7c30f 100644
--- a/gdb/ctfread.c
+++ b/gdb/ctfread.c
@@ -323,9 +323,8 @@ get_bitsize (ctf_dict_t *fp, ctf_id_t tid, uint32_t kind)
static void
set_symbol_address (struct objfile *of, struct symbol *sym, const char *name)
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol (name, nullptr, of);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, name, of);
if (msym.minsym != NULL)
{
sym->set_value_address (msym.value_address ());
@@ -1461,7 +1460,7 @@ ctf_psymtab_type_cb (ctf_id_t tid, void *arg)
{
struct ctf_context *ccp;
uint32_t kind;
- short section = -1;
+ int section = -1;
ccp = (struct ctf_context *) arg;
diff --git a/gdb/d-exp.y b/gdb/d-exp.y
index 13d2cfa..df89cb6 100644
--- a/gdb/d-exp.y
+++ b/gdb/d-exp.y
@@ -435,7 +435,7 @@ PrimaryExpression:
'(' Expression ')'
{ /* Do nothing. */ }
| IdentifierExp
- { struct bound_minimal_symbol msymbol;
+ {
std::string copy = copy_name ($1);
struct field_of_this_result is_a_field_of_this;
struct block_symbol sym;
@@ -463,10 +463,12 @@ PrimaryExpression:
else
{
/* Lookup foreign name in global static symbols. */
- msymbol = lookup_bound_minimal_symbol (copy.c_str ());
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space, copy.c_str ());
if (msymbol.minsym != NULL)
pstate->push_new<var_msym_value_operation> (msymbol);
- else if (!have_full_symbols () && !have_partial_symbols ())
+ else if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space))
error (_("No symbol table is loaded. Use the \"file\" command"));
else
error (_("No symbol \"%s\" in current context."),
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index d4f9956..32d9cc8 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -38,9 +38,8 @@ static const char D_MAIN[] = "D main";
const char *
d_main_name (void)
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol (D_MAIN, NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, D_MAIN);
if (msym.minsym != NULL)
return D_MAIN;
diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in
index f529656..1a17d23 100644
--- a/gdb/data-directory/Makefile.in
+++ b/gdb/data-directory/Makefile.in
@@ -79,6 +79,7 @@ PYTHON_FILE_LIST = \
gdb/missing_debug.py \
gdb/printing.py \
gdb/prompt.py \
+ gdb/ptwrite.py \
gdb/styling.py \
gdb/types.py \
gdb/unwinder.py \
@@ -119,8 +120,7 @@ PYTHON_FILE_LIST = \
gdb/function/as_string.py \
gdb/function/caller_is.py \
gdb/function/strfns.py \
- gdb/printer/__init__.py \
- gdb/printer/bound_registers.py
+ gdb/printer/__init__.py
@HAVE_PYTHON_TRUE@PYTHON_FILES = $(PYTHON_FILE_LIST)
@HAVE_PYTHON_FALSE@PYTHON_FILES =
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index 830dd1c..1b29d6e 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -54,228 +54,15 @@
#include "aout/aout64.h"
#include "aout/stab_gnu.h"
+/* Required for the following registry. */
+#include "gdb-stabs.h"
-/* Key for dbx-associated data. */
-
-const registry<objfile>::key<dbx_symfile_info> dbx_objfile_data_key;
-
-/* We put a pointer to this structure in the read_symtab_private field
- of the psymtab. */
-
-struct symloc
- {
- /* Offset within the file symbol table of first local symbol for this
- file. */
-
- int ldsymoff;
-
- /* Length (in bytes) of the section of the symbol table devoted to
- this file's symbols (actually, the section bracketed may contain
- more than just this file's symbols). If ldsymlen is 0, the only
- reason for this thing's existence is the dependency list. Nothing
- else will happen when it is read in. */
-
- int ldsymlen;
-
- /* The size of each symbol in the symbol file (in external form). */
-
- int symbol_size;
-
- /* Further information needed to locate the symbols if they are in
- an ELF file. */
-
- int symbol_offset;
- int string_offset;
- int file_string_offset;
- enum language pst_language;
- };
-
-#define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff)
-#define LDSYMLEN(p) (((struct symloc *)((p)->read_symtab_private))->ldsymlen)
-#define SYMLOC(p) ((struct symloc *)((p)->read_symtab_private))
-#define SYMBOL_SIZE(p) (SYMLOC(p)->symbol_size)
-#define SYMBOL_OFFSET(p) (SYMLOC(p)->symbol_offset)
-#define STRING_OFFSET(p) (SYMLOC(p)->string_offset)
-#define FILE_STRING_OFFSET(p) (SYMLOC(p)->file_string_offset)
-#define PST_LANGUAGE(p) (SYMLOC(p)->pst_language)
-
-/* The objfile we are currently reading. */
-
-static struct objfile *dbxread_objfile;
-
-/* Remember what we deduced to be the source language of this psymtab. */
-
-static enum language psymtab_language = language_unknown;
-
-/* The BFD for this file -- implicit parameter to next_symbol_text. */
-
-static bfd *symfile_bfd;
-
-/* The size of each symbol in the symbol file (in external form).
- This is set by dbx_symfile_read when building psymtabs, and by
- dbx_psymtab_to_symtab when building symtabs. */
-
-static unsigned symbol_size;
-
-/* This is the offset of the symbol table in the executable file. */
-
-static unsigned symbol_table_offset;
-
-/* This is the offset of the string table in the executable file. */
-
-static unsigned string_table_offset;
-
-/* For elf+stab executables, the n_strx field is not a simple index
- into the string table. Instead, each .o file has a base offset in
- the string table, and the associated symbols contain offsets from
- this base. The following two variables contain the base offset for
- the current and next .o files. */
-
-static unsigned int file_string_table_offset;
-static unsigned int next_file_string_table_offset;
-
-/* .o and NLM files contain unrelocated addresses which are based at
- 0. When non-zero, this flag disables some of the special cases for
- Solaris elf+stab text addresses at location 0. */
-
-static int symfile_relocatable = 0;
-
-/* When set, we are processing a .o file compiled by sun acc. This is
- misnamed; it refers to all stabs-in-elf implementations which use
- N_UNDF the way Sun does, including Solaris gcc. Hopefully all
- stabs-in-elf implementations ever invented will choose to be
- compatible. */
-
-static unsigned char processing_acc_compilation;
-
-/* The lowest text address we have yet encountered. This is needed
- because in an a.out file, there is no header field which tells us
- what address the program is actually going to be loaded at, so we
- need to make guesses based on the symbols (which *are* relocated to
- reflect the address it will be loaded at). */
-
-static unrelocated_addr lowest_text_address;
-
-/* Non-zero if there is any line number info in the objfile. Prevents
- dbx_end_psymtab from discarding an otherwise empty psymtab. */
-static int has_line_numbers;
-
-/* Complaints about the symbols we have encountered. */
-
-static void
-unknown_symtype_complaint (const char *arg1)
-{
- complaint (_("unknown symbol type %s"), arg1);
-}
-
-static void
-lbrac_mismatch_complaint (int arg1)
-{
- complaint (_("N_LBRAC/N_RBRAC symbol mismatch at symtab pos %d"), arg1);
-}
-
-static void
-repeated_header_complaint (const char *arg1, int arg2)
-{
- complaint (_("\"repeated\" header file %s not "
- "previously seen, at symtab pos %d"),
- arg1, arg2);
-}
-
-/* find_text_range --- find start and end of loadable code sections
-
- The find_text_range function finds the shortest address range that
- encloses all sections containing executable code, and stores it in
- objfile's text_addr and text_size members.
-
- dbx_symfile_read will use this to finish off the partial symbol
- table, in some cases. */
-
-static void
-find_text_range (bfd * sym_bfd, struct objfile *objfile)
-{
- asection *sec;
- int found_any = 0;
- CORE_ADDR start = 0;
- CORE_ADDR end = 0;
-
- for (sec = sym_bfd->sections; sec; sec = sec->next)
- if (bfd_section_flags (sec) & SEC_CODE)
- {
- CORE_ADDR sec_start = bfd_section_vma (sec);
- CORE_ADDR sec_end = sec_start + bfd_section_size (sec);
-
- if (found_any)
- {
- if (sec_start < start)
- start = sec_start;
- if (sec_end > end)
- end = sec_end;
- }
- else
- {
- start = sec_start;
- end = sec_end;
- }
-
- found_any = 1;
- }
-
- if (!found_any)
- error (_("Can't find any code sections in symbol file"));
-
- DBX_TEXT_ADDR (objfile) = start;
- DBX_TEXT_SIZE (objfile) = end - start;
-}
-
-
-
-/* During initial symbol readin, 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
- partial symbol table. */
-
-struct header_file_location
-{
- header_file_location (const char *name_, int instance_,
- legacy_psymtab *pst_)
- : name (name_),
- instance (instance_),
- pst (pst_)
- {
- }
-
- const char *name; /* Name of header file */
- int instance; /* See above */
- legacy_psymtab *pst; /* Partial symtab that has the
- BINCL/EINCL defs for this file. */
-};
-
-/* The list of bincls. */
-static std::vector<struct header_file_location> *bincl_list;
/* Local function prototypes. */
-static void read_ofile_symtab (struct objfile *, legacy_psymtab *);
-
-static void dbx_read_symtab (legacy_psymtab *self,
- struct objfile *objfile);
-
-static void dbx_expand_psymtab (legacy_psymtab *, struct objfile *);
-
-static void read_dbx_symtab (minimal_symbol_reader &, psymtab_storage *,
- struct objfile *);
-
-static legacy_psymtab *find_corresponding_bincl_psymtab (const char *,
- int);
-
-static const char *dbx_next_symbol_text (struct objfile *);
-
-static void fill_symbuf (bfd *);
-
static void dbx_symfile_init (struct objfile *);
static void dbx_new_init (struct objfile *);
@@ -284,128 +71,6 @@ static void dbx_symfile_read (struct objfile *, symfile_add_flags);
static void dbx_symfile_finish (struct objfile *);
-static void record_minimal_symbol (minimal_symbol_reader &,
- const char *, unrelocated_addr, int,
- struct objfile *);
-
-static void add_new_header_file (const char *, int);
-
-static void add_old_header_file (const char *, int);
-
-static void add_this_object_header_file (int);
-
-static legacy_psymtab *start_psymtab (psymtab_storage *, struct objfile *,
- const char *, unrelocated_addr, int);
-
-/* Free up old header file tables. */
-
-void
-free_header_files (void)
-{
- if (this_object_header_files)
- {
- xfree (this_object_header_files);
- this_object_header_files = NULL;
- }
- n_allocated_this_object_header_files = 0;
-}
-
-/* Allocate new header file tables. */
-
-void
-init_header_files (void)
-{
- n_allocated_this_object_header_files = 10;
- this_object_header_files = XNEWVEC (int, 10);
-}
-
-/* Add header file number I for this object file
- at the next successive FILENUM. */
-
-static void
-add_this_object_header_file (int i)
-{
- if (n_this_object_header_files == n_allocated_this_object_header_files)
- {
- n_allocated_this_object_header_files *= 2;
- this_object_header_files
- = (int *) xrealloc ((char *) this_object_header_files,
- n_allocated_this_object_header_files * sizeof (int));
- }
-
- this_object_header_files[n_this_object_header_files++] = i;
-}
-
-/* Add to this file an "old" header file, one already seen in
- a previous object file. NAME is the header file's name.
- INSTANCE is its instance code, to select among multiple
- symbol tables for the same header file. */
-
-static void
-add_old_header_file (const char *name, int instance)
-{
- struct header_file *p = HEADER_FILES (dbxread_objfile);
- int i;
-
- for (i = 0; i < N_HEADER_FILES (dbxread_objfile); i++)
- if (filename_cmp (p[i].name, name) == 0 && instance == p[i].instance)
- {
- add_this_object_header_file (i);
- return;
- }
- repeated_header_complaint (name, symnum);
-}
-
-/* Add to this file a "new" header file: definitions for its types follow.
- NAME is the header file's name.
- Most often this happens only once for each distinct header file,
- but not necessarily. If it happens more than once, INSTANCE has
- a different value each time, and references to the header file
- use INSTANCE values to select among them.
-
- dbx output contains "begin" and "end" markers for each new header file,
- but at this level we just need to know which files there have been;
- so we record the file when its "begin" is seen and ignore the "end". */
-
-static void
-add_new_header_file (const char *name, int instance)
-{
- int i;
- struct header_file *hfile;
-
- /* Make sure there is room for one more header file. */
-
- i = N_ALLOCATED_HEADER_FILES (dbxread_objfile);
-
- if (N_HEADER_FILES (dbxread_objfile) == i)
- {
- if (i == 0)
- {
- N_ALLOCATED_HEADER_FILES (dbxread_objfile) = 10;
- HEADER_FILES (dbxread_objfile) = (struct header_file *)
- xmalloc (10 * sizeof (struct header_file));
- }
- else
- {
- i *= 2;
- N_ALLOCATED_HEADER_FILES (dbxread_objfile) = i;
- HEADER_FILES (dbxread_objfile) = (struct header_file *)
- xrealloc ((char *) HEADER_FILES (dbxread_objfile),
- (i * sizeof (struct header_file)));
- }
- }
-
- /* Create an entry for this header file. */
-
- i = N_HEADER_FILES (dbxread_objfile)++;
- hfile = HEADER_FILES (dbxread_objfile) + i;
- hfile->name = xstrdup (name);
- hfile->instance = instance;
- hfile->length = 10;
- hfile->vector = XCNEWVEC (struct type *, 10);
-
- add_this_object_header_file (i);
-}
#if 0
static struct type **
@@ -425,91 +90,6 @@ explicit_lookup_type (int real_filenum, int index)
}
#endif
-static void
-record_minimal_symbol (minimal_symbol_reader &reader,
- const char *name, unrelocated_addr address, int type,
- struct objfile *objfile)
-{
- enum minimal_symbol_type ms_type;
- int section;
-
- switch (type)
- {
- case N_TEXT | N_EXT:
- ms_type = mst_text;
- section = SECT_OFF_TEXT (objfile);
- break;
- case N_DATA | N_EXT:
- ms_type = mst_data;
- section = SECT_OFF_DATA (objfile);
- break;
- case N_BSS | N_EXT:
- ms_type = mst_bss;
- section = SECT_OFF_BSS (objfile);
- break;
- case N_ABS | N_EXT:
- ms_type = mst_abs;
- section = -1;
- break;
-#ifdef N_SETV
- case N_SETV | N_EXT:
- ms_type = mst_data;
- section = SECT_OFF_DATA (objfile);
- break;
- case N_SETV:
- /* I don't think this type actually exists; since a N_SETV is the result
- of going over many .o files, it doesn't make sense to have one
- file local. */
- ms_type = mst_file_data;
- section = SECT_OFF_DATA (objfile);
- break;
-#endif
- case N_TEXT:
- case N_NBTEXT:
- case N_FN:
- case N_FN_SEQ:
- ms_type = mst_file_text;
- section = SECT_OFF_TEXT (objfile);
- break;
- case N_DATA:
- ms_type = mst_file_data;
-
- /* Check for __DYNAMIC, which is used by Sun shared libraries.
- Record it as global even if it's local, not global, so
- lookup_minimal_symbol can find it. We don't check symbol_leading_char
- because for SunOS4 it always is '_'. */
- if (strcmp ("__DYNAMIC", name) == 0)
- ms_type = mst_data;
-
- /* Same with virtual function tables, both global and static. */
- {
- const char *tempstring = name;
-
- if (*tempstring != '\0'
- && *tempstring == bfd_get_symbol_leading_char (objfile->obfd.get ()))
- ++tempstring;
- if (is_vtable_name (tempstring))
- ms_type = mst_data;
- }
- section = SECT_OFF_DATA (objfile);
- break;
- case N_BSS:
- ms_type = mst_file_bss;
- section = SECT_OFF_BSS (objfile);
- break;
- default:
- ms_type = mst_unknown;
- section = -1;
- break;
- }
-
- if ((ms_type == mst_file_text || ms_type == mst_text)
- && address < lowest_text_address)
- lowest_text_address = address;
-
- reader.record_with_info (name, address, ms_type, section);
-}
-
/* Scan and build partial symbols for a symbol file.
We have been initialized by a call to dbx_symfile_init, which
put all the relevant info into a "struct dbx_symfile_info",
@@ -518,39 +98,7 @@ record_minimal_symbol (minimal_symbol_reader &reader,
static void
dbx_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
{
- bfd *sym_bfd;
- int val;
-
- sym_bfd = objfile->obfd.get ();
-
- /* .o and .nlm files are relocatables with text, data and bss segs based at
- 0. This flag disables special (Solaris stabs-in-elf only) fixups for
- symbols with a value of 0. */
-
- symfile_relocatable = bfd_get_file_flags (sym_bfd) & HAS_RELOC;
-
- val = bfd_seek (sym_bfd, DBX_SYMTAB_OFFSET (objfile), SEEK_SET);
- if (val < 0)
- perror_with_name (objfile_name (objfile));
-
- symbol_size = DBX_SYMBOL_SIZE (objfile);
- symbol_table_offset = DBX_SYMTAB_OFFSET (objfile);
-
- scoped_free_pendings free_pending;
-
- minimal_symbol_reader reader (objfile);
-
- /* Read stabs data from executable file and define symbols. */
-
- psymbol_functions *psf = new psymbol_functions ();
- psymtab_storage *partial_symtabs = psf->get_partial_symtabs ().get ();
- objfile->qf.emplace_front (psf);
- read_dbx_symtab (reader, partial_symtabs, objfile);
-
- /* Install any minimal symbols that have been collected as the current
- minimal symbols for this objfile. */
-
- reader.install ();
+ read_stabs_symtab (objfile, symfile_flags);
}
/* Initialize anything that needs initializing when a completely new
@@ -699,2445 +247,10 @@ dbx_symfile_finish (struct objfile *objfile)
free_header_files ();
}
-dbx_symfile_info::~dbx_symfile_info ()
-{
- if (header_files != NULL)
- {
- int i = n_header_files;
- struct header_file *hfiles = header_files;
-
- while (--i >= 0)
- {
- xfree (hfiles[i].name);
- xfree (hfiles[i].vector);
- }
- xfree (hfiles);
- }
-}
-
-
-
-/* Buffer for reading the symbol table entries. */
-static struct external_nlist symbuf[4096];
-static int symbuf_idx;
-static int symbuf_end;
-
-/* Name of last function encountered. Used in Solaris to approximate
- object file boundaries. */
-static const char *last_function_name;
-
-/* The address in memory of the string table of the object file we are
- reading (which might not be the "main" object file, but might be a
- shared library or some other dynamically loaded thing). This is
- set by read_dbx_symtab when building psymtabs, and by
- read_ofile_symtab when building symtabs, and is used only by
- next_symbol_text. FIXME: If that is true, we don't need it when
- building psymtabs, right? */
-static char *stringtab_global;
-
-/* These variables are used to control fill_symbuf when the stabs
- symbols are not contiguous (as may be the case when a COFF file is
- linked using --split-by-reloc). */
-static const std::vector<asection *> *symbuf_sections;
-static size_t sect_idx;
-static unsigned int symbuf_left;
-static unsigned int symbuf_read;
-
-/* This variable stores a global stabs buffer, if we read stabs into
- memory in one chunk in order to process relocations. */
-static bfd_byte *stabs_data;
-
-/* Refill the symbol table input buffer
- and set the variables that control fetching entries from it.
- Reports an error if no data available.
- This function can read past the end of the symbol table
- (into the string table) but this does no harm. */
-
-static void
-fill_symbuf (bfd *sym_bfd)
-{
- unsigned int count;
- int nbytes;
-
- if (stabs_data)
- {
- nbytes = sizeof (symbuf);
- if (nbytes > symbuf_left)
- nbytes = symbuf_left;
- memcpy (symbuf, stabs_data + symbuf_read, nbytes);
- }
- else if (symbuf_sections == NULL)
- {
- count = sizeof (symbuf);
- nbytes = bfd_read (symbuf, count, sym_bfd);
- }
- else
- {
- if (symbuf_left <= 0)
- {
- file_ptr filepos = (*symbuf_sections)[sect_idx]->filepos;
-
- if (bfd_seek (sym_bfd, filepos, SEEK_SET) != 0)
- perror_with_name (bfd_get_filename (sym_bfd));
- symbuf_left = bfd_section_size ((*symbuf_sections)[sect_idx]);
- symbol_table_offset = filepos - symbuf_read;
- ++sect_idx;
- }
-
- count = symbuf_left;
- if (count > sizeof (symbuf))
- count = sizeof (symbuf);
- nbytes = bfd_read (symbuf, count, sym_bfd);
- }
-
- if (nbytes < 0)
- perror_with_name (bfd_get_filename (sym_bfd));
- else if (nbytes == 0)
- error (_("Premature end of file reading symbol table"));
- symbuf_end = nbytes / symbol_size;
- symbuf_idx = 0;
- symbuf_left -= nbytes;
- symbuf_read += nbytes;
-}
-
-static void
-stabs_seek (int sym_offset)
-{
- if (stabs_data)
- {
- symbuf_read += sym_offset;
- symbuf_left -= sym_offset;
- }
- else
- if (bfd_seek (symfile_bfd, sym_offset, SEEK_CUR) != 0)
- perror_with_name (bfd_get_filename (symfile_bfd));
-}
-
-#define INTERNALIZE_SYMBOL(intern, extern, abfd) \
- { \
- (intern).n_strx = bfd_h_get_32 (abfd, (extern)->e_strx); \
- (intern).n_type = bfd_h_get_8 (abfd, (extern)->e_type); \
- (intern).n_other = 0; \
- (intern).n_desc = bfd_h_get_16 (abfd, (extern)->e_desc); \
- if (bfd_get_sign_extend_vma (abfd)) \
- (intern).n_value = bfd_h_get_signed_32 (abfd, (extern)->e_value); \
- else \
- (intern).n_value = bfd_h_get_32 (abfd, (extern)->e_value); \
- }
-
-/* Invariant: The symbol pointed to by symbuf_idx is the first one
- that hasn't been swapped. Swap the symbol at the same time
- that symbuf_idx is incremented. */
-
-/* dbx allows the text of a symbol name to be continued into the
- next symbol name! When such a continuation is encountered
- (a \ at the end of the text of a name)
- call this function to get the continuation. */
-
-static const char *
-dbx_next_symbol_text (struct objfile *objfile)
-{
- struct internal_nlist nlist;
-
- if (symbuf_idx == symbuf_end)
- fill_symbuf (symfile_bfd);
-
- symnum++;
- INTERNALIZE_SYMBOL (nlist, &symbuf[symbuf_idx], symfile_bfd);
- OBJSTAT (objfile, n_stabs++);
-
- symbuf_idx++;
-
- return nlist.n_strx + stringtab_global + file_string_table_offset;
-}
-
-
-/* Given a name, value pair, find the corresponding
- bincl in the list. Return the partial symtab associated
- with that header_file_location. */
-
-static legacy_psymtab *
-find_corresponding_bincl_psymtab (const char *name, int instance)
-{
- for (const header_file_location &bincl : *bincl_list)
- if (bincl.instance == instance
- && strcmp (name, bincl.name) == 0)
- return bincl.pst;
-
- repeated_header_complaint (name, symnum);
- return (legacy_psymtab *) 0;
-}
-
-/* Set namestring based on nlist. If the string table index is invalid,
- give a fake name, and print a single error message per symbol file read,
- rather than abort the symbol reading or flood the user with messages. */
-
-static const char *
-set_namestring (struct objfile *objfile, const struct internal_nlist *nlist)
-{
- const char *namestring;
-
- if (nlist->n_strx + file_string_table_offset
- >= DBX_STRINGTAB_SIZE (objfile)
- || nlist->n_strx + file_string_table_offset < nlist->n_strx)
- {
- complaint (_("bad string table offset in symbol %d"),
- symnum);
- namestring = "<bad string table offset>";
- }
- else
- namestring = (nlist->n_strx + file_string_table_offset
- + DBX_STRINGTAB (objfile));
- return namestring;
-}
-
-static struct bound_minimal_symbol
-find_stab_function (const char *namestring, const char *filename,
- struct objfile *objfile)
-{
- struct bound_minimal_symbol msym;
- int n;
-
- const char *colon = strchr (namestring, ':');
- if (colon == NULL)
- n = 0;
- else
- n = colon - namestring;
-
- char *p = (char *) alloca (n + 2);
- strncpy (p, namestring, n);
- p[n] = 0;
-
- msym = lookup_minimal_symbol (p, filename, objfile);
- if (msym.minsym == NULL)
- {
- /* Sun Fortran appends an underscore to the minimal symbol name,
- try again with an appended underscore if the minimal symbol
- was not found. */
- p[n] = '_';
- p[n + 1] = 0;
- msym = lookup_minimal_symbol (p, filename, objfile);
- }
-
- if (msym.minsym == NULL && filename != NULL)
- {
- /* Try again without the filename. */
- p[n] = 0;
- msym = lookup_minimal_symbol (p, NULL, objfile);
- }
- if (msym.minsym == NULL && filename != NULL)
- {
- /* And try again for Sun Fortran, but without the filename. */
- p[n] = '_';
- p[n + 1] = 0;
- msym = lookup_minimal_symbol (p, NULL, objfile);
- }
-
- return msym;
-}
-
-static void
-function_outside_compilation_unit_complaint (const char *arg1)
-{
- complaint (_("function `%s' appears to be defined "
- "outside of all compilation units"),
- arg1);
-}
-
-/* Setup partial_symtab's describing each source file for which
- debugging information is available. */
-
-static void
-read_dbx_symtab (minimal_symbol_reader &reader,
- psymtab_storage *partial_symtabs,
- struct objfile *objfile)
-{
- struct gdbarch *gdbarch = objfile->arch ();
- struct external_nlist *bufp = 0; /* =0 avoids gcc -Wall glitch. */
- struct internal_nlist nlist;
- CORE_ADDR text_addr;
- int text_size;
- const char *sym_name;
- int sym_len;
-
- const char *namestring;
- int nsl;
- int past_first_source_file = 0;
- CORE_ADDR last_function_start = 0;
- bfd *abfd;
- int textlow_not_set;
- int data_sect_index;
-
- /* Current partial symtab. */
- legacy_psymtab *pst;
-
- /* List of current psymtab's include files. */
- const char **psymtab_include_list;
- int includes_allocated;
- int includes_used;
-
- /* Index within current psymtab dependency list. */
- legacy_psymtab **dependency_list;
- int dependencies_used, dependencies_allocated;
-
- text_addr = DBX_TEXT_ADDR (objfile);
- text_size = DBX_TEXT_SIZE (objfile);
-
- /* FIXME. We probably want to change stringtab_global rather than add this
- while processing every symbol entry. FIXME. */
- file_string_table_offset = 0;
- next_file_string_table_offset = 0;
-
- stringtab_global = DBX_STRINGTAB (objfile);
-
- pst = (legacy_psymtab *) 0;
-
- includes_allocated = 30;
- includes_used = 0;
- psymtab_include_list = (const char **) alloca (includes_allocated *
- sizeof (const char *));
-
- dependencies_allocated = 30;
- dependencies_used = 0;
- dependency_list =
- (legacy_psymtab **) alloca (dependencies_allocated *
- sizeof (legacy_psymtab *));
-
- /* Init bincl list */
- std::vector<struct header_file_location> bincl_storage;
- scoped_restore restore_bincl_global
- = make_scoped_restore (&bincl_list, &bincl_storage);
-
- set_last_source_file (NULL);
-
- lowest_text_address = (unrelocated_addr) -1;
-
- symfile_bfd = objfile->obfd.get (); /* For next_text_symbol. */
- abfd = objfile->obfd.get ();
- symbuf_end = symbuf_idx = 0;
- next_symbol_text_func = dbx_next_symbol_text;
- textlow_not_set = 1;
- has_line_numbers = 0;
-
- /* FIXME: jimb/2003-09-12: We don't apply the right section's offset
- to global and static variables. The stab for a global or static
- variable doesn't give us any indication of which section it's in,
- so we can't tell immediately which offset in
- objfile->section_offsets we should apply to the variable's
- address.
-
- We could certainly find out which section contains the variable
- by looking up the variable's unrelocated address with
- find_pc_section, but that would be expensive; this is the
- function that constructs the partial symbol tables by examining
- every symbol in the entire executable, and it's
- performance-critical. So that expense would not be welcome. I'm
- not sure what to do about this at the moment.
-
- What we have done for years is to simply assume that the .data
- section's offset is appropriate for all global and static
- variables. Recently, this was expanded to fall back to the .bss
- section's offset if there is no .data section, and then to the
- .rodata section's offset. */
- data_sect_index = objfile->sect_index_data;
- if (data_sect_index == -1)
- data_sect_index = SECT_OFF_BSS (objfile);
- if (data_sect_index == -1)
- data_sect_index = SECT_OFF_RODATA (objfile);
-
- /* If data_sect_index is still -1, that's okay. It's perfectly fine
- for the file to have no .data, no .bss, and no .text at all, if
- it also has no global or static variables. */
-
- for (symnum = 0; symnum < DBX_SYMCOUNT (objfile); symnum++)
- {
- /* Get the symbol for this run and pull out some info. */
- QUIT; /* Allow this to be interruptable. */
- if (symbuf_idx == symbuf_end)
- fill_symbuf (abfd);
- bufp = &symbuf[symbuf_idx++];
-
- /*
- * Special case to speed up readin.
- */
- if (bfd_h_get_8 (abfd, bufp->e_type) == N_SLINE)
- {
- has_line_numbers = 1;
- continue;
- }
-
- INTERNALIZE_SYMBOL (nlist, bufp, abfd);
- OBJSTAT (objfile, n_stabs++);
-
- /* Ok. There is a lot of code duplicated in the rest of this
- switch statement (for efficiency reasons). Since I don't
- like duplicating code, I will do my penance here, and
- describe the code which is duplicated:
-
- *) The assignment to namestring.
- *) The call to strchr.
- *) The addition of a partial symbol the two partial
- symbol lists. This last is a large section of code, so
- I've embedded it in the following macro. */
-
- switch (nlist.n_type)
- {
- /*
- * Standard, external, non-debugger, symbols
- */
-
- case N_TEXT | N_EXT:
- case N_NBTEXT | N_EXT:
- goto record_it;
-
- case N_DATA | N_EXT:
- case N_NBDATA | N_EXT:
- goto record_it;
-
- case N_BSS:
- case N_BSS | N_EXT:
- case N_NBBSS | N_EXT:
- case N_SETV | N_EXT: /* FIXME, is this in BSS? */
- goto record_it;
-
- case N_ABS | N_EXT:
- record_it:
- namestring = set_namestring (objfile, &nlist);
-
- record_minimal_symbol (reader, namestring,
- unrelocated_addr (nlist.n_value),
- nlist.n_type, objfile); /* Always */
- continue;
-
- /* Standard, local, non-debugger, symbols. */
-
- case N_NBTEXT:
-
- /* We need to be able to deal with both N_FN or N_TEXT,
- because we have no way of knowing whether the sys-supplied ld
- or GNU ld was used to make the executable. Sequents throw
- in another wrinkle -- they renumbered N_FN. */
-
- case N_FN:
- case N_FN_SEQ:
- case N_TEXT:
- namestring = set_namestring (objfile, &nlist);
-
- if ((namestring[0] == '-' && namestring[1] == 'l')
- || (namestring[(nsl = strlen (namestring)) - 1] == 'o'
- && namestring[nsl - 2] == '.'))
- {
- unrelocated_addr unrel_val = unrelocated_addr (nlist.n_value);
-
- if (past_first_source_file && pst
- /* The gould NP1 uses low values for .o and -l symbols
- which are not the address. */
- && unrel_val >= pst->unrelocated_text_low ())
- {
- dbx_end_psymtab (objfile, partial_symtabs,
- pst, psymtab_include_list,
- includes_used, symnum * symbol_size,
- unrel_val > pst->unrelocated_text_high ()
- ? unrel_val : pst->unrelocated_text_high (),
- dependency_list, dependencies_used,
- textlow_not_set);
- pst = (legacy_psymtab *) 0;
- includes_used = 0;
- dependencies_used = 0;
- has_line_numbers = 0;
- }
- else
- past_first_source_file = 1;
- }
- else
- goto record_it;
- continue;
-
- case N_DATA:
- goto record_it;
-
- case N_UNDF | N_EXT:
- /* The case (nlist.n_value != 0) is a "Fortran COMMON" symbol.
- We used to rely on the target to tell us whether it knows
- where the symbol has been relocated to, but none of the
- target implementations actually provided that operation.
- So we just ignore the symbol, the same way we would do if
- we had a target-side symbol lookup which returned no match.
-
- All other symbols (with nlist.n_value == 0), are really
- undefined, and so we ignore them too. */
- continue;
-
- case N_UNDF:
- if (processing_acc_compilation && nlist.n_strx == 1)
- {
- /* Deal with relative offsets in the string table
- used in ELF+STAB under Solaris. If we want to use the
- n_strx field, which contains the name of the file,
- we must adjust file_string_table_offset *before* calling
- set_namestring(). */
- past_first_source_file = 1;
- file_string_table_offset = next_file_string_table_offset;
- next_file_string_table_offset =
- file_string_table_offset + nlist.n_value;
- if (next_file_string_table_offset < file_string_table_offset)
- error (_("string table offset backs up at %d"), symnum);
- /* FIXME -- replace error() with complaint. */
- continue;
- }
- continue;
-
- /* Lots of symbol types we can just ignore. */
-
- case N_ABS:
- case N_NBDATA:
- case N_NBBSS:
- continue;
-
- /* Keep going . . . */
-
- /*
- * Special symbol types for GNU
- */
- case N_INDR:
- case N_INDR | N_EXT:
- case N_SETA:
- case N_SETA | N_EXT:
- case N_SETT:
- case N_SETT | N_EXT:
- case N_SETD:
- case N_SETD | N_EXT:
- case N_SETB:
- case N_SETB | N_EXT:
- case N_SETV:
- continue;
-
- /*
- * Debugger symbols
- */
-
- case N_SO:
- {
- CORE_ADDR valu;
- static int prev_so_symnum = -10;
- static int first_so_symnum;
- const char *p;
- static const char *dirname_nso;
- int prev_textlow_not_set;
-
- valu = nlist.n_value;
-
- prev_textlow_not_set = textlow_not_set;
-
- /* A zero value is probably an indication for the SunPRO 3.0
- compiler. dbx_end_psymtab explicitly tests for zero, so
- don't relocate it. */
-
- if (nlist.n_value == 0
- && gdbarch_sofun_address_maybe_missing (gdbarch))
- {
- textlow_not_set = 1;
- valu = 0;
- }
- else
- textlow_not_set = 0;
-
- past_first_source_file = 1;
-
- if (prev_so_symnum != symnum - 1)
- { /* Here if prev stab wasn't N_SO. */
- first_so_symnum = symnum;
-
- if (pst)
- {
- unrelocated_addr unrel_value = unrelocated_addr (valu);
- dbx_end_psymtab (objfile, partial_symtabs,
- pst, psymtab_include_list,
- includes_used, symnum * symbol_size,
- unrel_value > pst->unrelocated_text_high ()
- ? unrel_value
- : pst->unrelocated_text_high (),
- dependency_list, dependencies_used,
- prev_textlow_not_set);
- pst = (legacy_psymtab *) 0;
- includes_used = 0;
- dependencies_used = 0;
- has_line_numbers = 0;
- }
- }
-
- prev_so_symnum = symnum;
-
- /* End the current partial symtab and start a new one. */
-
- namestring = set_namestring (objfile, &nlist);
-
- /* Null name means end of .o file. Don't start a new one. */
- if (*namestring == '\000')
- continue;
-
- /* Some compilers (including gcc) emit a pair of initial N_SOs.
- The first one is a directory name; the second the file name.
- If pst exists, is empty, and has a filename ending in '/',
- we assume the previous N_SO was a directory name. */
-
- p = lbasename (namestring);
- if (p != namestring && *p == '\000')
- {
- /* Save the directory name SOs locally, then save it into
- the psymtab when it's created below. */
- dirname_nso = namestring;
- continue;
- }
-
- /* Some other compilers (C++ ones in particular) emit useless
- SOs for non-existant .c files. We ignore all subsequent SOs
- that immediately follow the first. */
-
- if (!pst)
- {
- pst = start_psymtab (partial_symtabs, objfile,
- namestring,
- unrelocated_addr (valu),
- first_so_symnum * symbol_size);
- pst->dirname = dirname_nso;
- dirname_nso = NULL;
- }
- continue;
- }
-
- case N_BINCL:
- {
- enum language tmp_language;
-
- /* Add this bincl to the bincl_list for future EXCLs. No
- need to save the string; it'll be around until
- read_dbx_symtab function returns. */
-
- namestring = set_namestring (objfile, &nlist);
- tmp_language = deduce_language_from_filename (namestring);
-
- /* Only change the psymtab's language if we've learned
- something useful (eg. tmp_language is not language_unknown).
- In addition, to match what start_subfile does, never change
- from C++ to C. */
- if (tmp_language != language_unknown
- && (tmp_language != language_c
- || psymtab_language != language_cplus))
- psymtab_language = tmp_language;
-
- if (pst == NULL)
- {
- /* FIXME: we should not get here without a PST to work on.
- Attempt to recover. */
- complaint (_("N_BINCL %s not in entries for "
- "any file, at symtab pos %d"),
- namestring, symnum);
- continue;
- }
- bincl_list->emplace_back (namestring, nlist.n_value, pst);
-
- /* Mark down an include file in the current psymtab. */
-
- goto record_include_file;
- }
-
- case N_SOL:
- {
- enum language tmp_language;
-
- /* Mark down an include file in the current psymtab. */
- namestring = set_namestring (objfile, &nlist);
- tmp_language = deduce_language_from_filename (namestring);
-
- /* Only change the psymtab's language if we've learned
- something useful (eg. tmp_language is not language_unknown).
- In addition, to match what start_subfile does, never change
- from C++ to C. */
- if (tmp_language != language_unknown
- && (tmp_language != language_c
- || psymtab_language != language_cplus))
- psymtab_language = tmp_language;
-
- /* In C++, one may expect the same filename to come round many
- times, when code is coming alternately from the main file
- and from inline functions in other files. So I check to see
- if this is a file we've seen before -- either the main
- source file, or a previously included file.
-
- This seems to be a lot of time to be spending on N_SOL, but
- things like "break c-exp.y:435" need to work (I
- suppose the psymtab_include_list could be hashed or put
- in a binary tree, if profiling shows this is a major hog). */
- if (pst && filename_cmp (namestring, pst->filename) == 0)
- continue;
- {
- int i;
-
- for (i = 0; i < includes_used; i++)
- if (filename_cmp (namestring, psymtab_include_list[i]) == 0)
- {
- i = -1;
- break;
- }
- if (i == -1)
- continue;
- }
-
- record_include_file:
-
- psymtab_include_list[includes_used++] = namestring;
- if (includes_used >= includes_allocated)
- {
- const char **orig = psymtab_include_list;
-
- psymtab_include_list = (const char **)
- alloca ((includes_allocated *= 2) * sizeof (const char *));
- memcpy (psymtab_include_list, orig,
- includes_used * sizeof (const char *));
- }
- continue;
- }
- case N_LSYM: /* Typedef or automatic variable. */
- case N_STSYM: /* Data seg var -- static. */
- case N_LCSYM: /* BSS " */
- case N_ROSYM: /* Read-only data seg var -- static. */
- case N_NBSTS: /* Gould nobase. */
- case N_NBLCS: /* symbols. */
- case N_FUN:
- case N_GSYM: /* Global (extern) variable; can be
- data or bss (sigh FIXME). */
-
- /* Following may probably be ignored; I'll leave them here
- for now (until I do Pascal and Modula 2 extensions). */
-
- case N_PC: /* I may or may not need this; I
- suspect not. */
- case N_M2C: /* I suspect that I can ignore this here. */
- case N_SCOPE: /* Same. */
- {
- const char *p;
-
- namestring = set_namestring (objfile, &nlist);
-
- /* See if this is an end of function stab. */
- if (pst && nlist.n_type == N_FUN && *namestring == '\000')
- {
- unrelocated_addr valu;
-
- /* It's value is the size (in bytes) of the function for
- function relative stabs, or the address of the function's
- end for old style stabs. */
- valu = unrelocated_addr (nlist.n_value + last_function_start);
- if (pst->unrelocated_text_high () == unrelocated_addr (0)
- || valu > pst->unrelocated_text_high ())
- pst->set_text_high (valu);
- break;
- }
-
- p = (char *) strchr (namestring, ':');
- if (!p)
- continue; /* Not a debugging symbol. */
-
- sym_len = 0;
- sym_name = NULL; /* pacify "gcc -Werror" */
- if (psymtab_language == language_cplus)
- {
- std::string name (namestring, p - namestring);
- gdb::unique_xmalloc_ptr<char> new_name
- = cp_canonicalize_string (name.c_str ());
- if (new_name != nullptr)
- {
- sym_len = strlen (new_name.get ());
- sym_name = obstack_strdup (&objfile->objfile_obstack,
- new_name.get ());
- }
- }
- else if (psymtab_language == language_c)
- {
- std::string name (namestring, p - namestring);
- gdb::unique_xmalloc_ptr<char> new_name
- = c_canonicalize_name (name.c_str ());
- if (new_name != nullptr)
- {
- sym_len = strlen (new_name.get ());
- sym_name = obstack_strdup (&objfile->objfile_obstack,
- new_name.get ());
- }
- }
-
- if (sym_len == 0)
- {
- sym_name = namestring;
- sym_len = p - namestring;
- }
-
- /* Main processing section for debugging symbols which
- the initial read through the symbol tables needs to worry
- about. If we reach this point, the symbol which we are
- considering is definitely one we are interested in.
- p must also contain the (valid) index into the namestring
- which indicates the debugging type symbol. */
-
- switch (p[1])
- {
- case 'S':
- if (pst != nullptr)
- pst->add_psymbol (std::string_view (sym_name, sym_len), true,
- VAR_DOMAIN, LOC_STATIC,
- data_sect_index,
- psymbol_placement::STATIC,
- unrelocated_addr (nlist.n_value),
- psymtab_language,
- partial_symtabs, objfile);
- else
- complaint (_("static `%*s' appears to be defined "
- "outside of all compilation units"),
- sym_len, sym_name);
- continue;
-
- case 'G':
- /* The addresses in these entries are reported to be
- wrong. See the code that reads 'G's for symtabs. */
- if (pst != nullptr)
- pst->add_psymbol (std::string_view (sym_name, sym_len), true,
- VAR_DOMAIN, LOC_STATIC,
- data_sect_index,
- psymbol_placement::GLOBAL,
- unrelocated_addr (nlist.n_value),
- psymtab_language,
- partial_symtabs, objfile);
- else
- complaint (_("global `%*s' appears to be defined "
- "outside of all compilation units"),
- sym_len, sym_name);
- continue;
-
- case 'T':
- /* When a 'T' entry is defining an anonymous enum, it
- may have a name which is the empty string, or a
- single space. Since they're not really defining a
- symbol, those shouldn't go in the partial symbol
- table. We do pick up the elements of such enums at
- 'check_enum:', below. */
- if (p >= namestring + 2
- || (p == namestring + 1
- && namestring[0] != ' '))
- {
- if (pst != nullptr)
- pst->add_psymbol (std::string_view (sym_name, sym_len),
- true, STRUCT_DOMAIN, LOC_TYPEDEF, -1,
- psymbol_placement::STATIC,
- unrelocated_addr (0),
- psymtab_language,
- partial_symtabs, objfile);
- else
- complaint (_("enum, struct, or union `%*s' appears "
- "to be defined outside of all "
- "compilation units"),
- sym_len, sym_name);
- if (p[2] == 't')
- {
- /* Also a typedef with the same name. */
- if (pst != nullptr)
- pst->add_psymbol (std::string_view (sym_name, sym_len),
- true, VAR_DOMAIN, LOC_TYPEDEF, -1,
- psymbol_placement::STATIC,
- unrelocated_addr (0),
- psymtab_language,
- partial_symtabs, objfile);
- else
- complaint (_("typedef `%*s' appears to be defined "
- "outside of all compilation units"),
- sym_len, sym_name);
- p += 1;
- }
- }
- goto check_enum;
-
- case 't':
- if (p != namestring) /* a name is there, not just :T... */
- {
- if (pst != nullptr)
- pst->add_psymbol (std::string_view (sym_name, sym_len),
- true, VAR_DOMAIN, LOC_TYPEDEF, -1,
- psymbol_placement::STATIC,
- unrelocated_addr (0),
- psymtab_language,
- partial_symtabs, objfile);
- else
- complaint (_("typename `%*s' appears to be defined "
- "outside of all compilation units"),
- sym_len, sym_name);
- }
- check_enum:
- /* If this is an enumerated type, we need to
- add all the enum constants to the partial symbol
- table. This does not cover enums without names, e.g.
- "enum {a, b} c;" in C, but fortunately those are
- rare. There is no way for GDB to find those from the
- enum type without spending too much time on it. Thus
- to solve this problem, the compiler needs to put out the
- enum in a nameless type. GCC2 does this. */
-
- /* We are looking for something of the form
- <name> ":" ("t" | "T") [<number> "="] "e"
- {<constant> ":" <value> ","} ";". */
-
- /* Skip over the colon and the 't' or 'T'. */
- p += 2;
- /* This type may be given a number. Also, numbers can come
- in pairs like (0,26). Skip over it. */
- while ((*p >= '0' && *p <= '9')
- || *p == '(' || *p == ',' || *p == ')'
- || *p == '=')
- p++;
-
- if (*p++ == 'e')
- {
- /* The aix4 compiler emits extra crud before the members. */
- if (*p == '-')
- {
- /* Skip over the type (?). */
- while (*p != ':')
- p++;
-
- /* Skip over the colon. */
- p++;
- }
-
- /* We have found an enumerated type. */
- /* According to comments in read_enum_type
- a comma could end it instead of a semicolon.
- I don't know where that happens.
- Accept either. */
- while (*p && *p != ';' && *p != ',')
- {
- const char *q;
-
- /* Check for and handle cretinous dbx symbol name
- continuation! */
- if (*p == '\\' || (*p == '?' && p[1] == '\0'))
- p = next_symbol_text (objfile);
-
- /* Point to the character after the name
- of the enum constant. */
- for (q = p; *q && *q != ':'; q++)
- ;
- /* Note that the value doesn't matter for
- enum constants in psymtabs, just in symtabs. */
- if (pst != nullptr)
- pst->add_psymbol (std::string_view (p, q - p), true,
- VAR_DOMAIN, LOC_CONST, -1,
- psymbol_placement::STATIC,
- unrelocated_addr (0),
- psymtab_language,
- partial_symtabs, objfile);
- else
- complaint (_("enum constant `%*s' appears to be defined "
- "outside of all compilation units"),
- ((int) (q - p)), p);
- /* Point past the name. */
- p = q;
- /* Skip over the value. */
- while (*p && *p != ',')
- p++;
- /* Advance past the comma. */
- if (*p)
- p++;
- }
- }
- continue;
-
- case 'c':
- /* Constant, e.g. from "const" in Pascal. */
- if (pst != nullptr)
- pst->add_psymbol (std::string_view (sym_name, sym_len), true,
- VAR_DOMAIN, LOC_CONST, -1,
- psymbol_placement::STATIC,
- unrelocated_addr (0),
- psymtab_language,
- partial_symtabs, objfile);
- else
- complaint (_("constant `%*s' appears to be defined "
- "outside of all compilation units"),
- sym_len, sym_name);
-
- continue;
-
- case 'f':
- if (! pst)
- {
- std::string name (namestring, (p - namestring));
- function_outside_compilation_unit_complaint (name.c_str ());
- }
- /* Kludges for ELF/STABS with Sun ACC. */
- last_function_name = namestring;
- /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
- value for the bottom of the text seg in those cases. */
- if (nlist.n_value == 0
- && gdbarch_sofun_address_maybe_missing (gdbarch))
- {
- struct bound_minimal_symbol minsym
- = find_stab_function (namestring,
- pst ? pst->filename : NULL,
- objfile);
- if (minsym.minsym != NULL)
- nlist.n_value
- = CORE_ADDR (minsym.minsym->unrelocated_address ());
- }
- if (pst && textlow_not_set
- && gdbarch_sofun_address_maybe_missing (gdbarch))
- {
- pst->set_text_low (unrelocated_addr (nlist.n_value));
- textlow_not_set = 0;
- }
- /* End kludge. */
-
- /* Keep track of the start of the last function so we
- can handle end of function symbols. */
- last_function_start = nlist.n_value;
-
- /* In reordered executables this function may lie outside
- the bounds created by N_SO symbols. If that's the case
- use the address of this function as the low bound for
- the partial symbol table. */
- if (pst
- && (textlow_not_set
- || (unrelocated_addr (nlist.n_value)
- < pst->unrelocated_text_low ()
- && (nlist.n_value != 0))))
- {
- pst->set_text_low (unrelocated_addr (nlist.n_value));
- textlow_not_set = 0;
- }
- if (pst != nullptr)
- pst->add_psymbol (std::string_view (sym_name, sym_len), true,
- VAR_DOMAIN, LOC_BLOCK,
- SECT_OFF_TEXT (objfile),
- psymbol_placement::STATIC,
- unrelocated_addr (nlist.n_value),
- psymtab_language,
- partial_symtabs, objfile);
- continue;
-
- /* Global functions were ignored here, but now they
- are put into the global psymtab like one would expect.
- They're also in the minimal symbol table. */
- case 'F':
- if (! pst)
- {
- std::string name (namestring, (p - namestring));
- function_outside_compilation_unit_complaint (name.c_str ());
- }
- /* Kludges for ELF/STABS with Sun ACC. */
- last_function_name = namestring;
- /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
- value for the bottom of the text seg in those cases. */
- if (nlist.n_value == 0
- && gdbarch_sofun_address_maybe_missing (gdbarch))
- {
- struct bound_minimal_symbol minsym
- = find_stab_function (namestring,
- pst ? pst->filename : NULL,
- objfile);
- if (minsym.minsym != NULL)
- nlist.n_value
- = CORE_ADDR (minsym.minsym->unrelocated_address ());
- }
- if (pst && textlow_not_set
- && gdbarch_sofun_address_maybe_missing (gdbarch))
- {
- pst->set_text_low (unrelocated_addr (nlist.n_value));
- textlow_not_set = 0;
- }
- /* End kludge. */
-
- /* Keep track of the start of the last function so we
- can handle end of function symbols. */
- last_function_start = nlist.n_value;
-
- /* In reordered executables this function may lie outside
- the bounds created by N_SO symbols. If that's the case
- use the address of this function as the low bound for
- the partial symbol table. */
- if (pst
- && (textlow_not_set
- || (unrelocated_addr (nlist.n_value)
- < pst->unrelocated_text_low ()
- && (nlist.n_value != 0))))
- {
- pst->set_text_low (unrelocated_addr (nlist.n_value));
- textlow_not_set = 0;
- }
- if (pst != nullptr)
- pst->add_psymbol (std::string_view (sym_name, sym_len), true,
- VAR_DOMAIN, LOC_BLOCK,
- SECT_OFF_TEXT (objfile),
- psymbol_placement::GLOBAL,
- unrelocated_addr (nlist.n_value),
- psymtab_language,
- partial_symtabs, objfile);
- continue;
-
- /* Two things show up here (hopefully); static symbols of
- local scope (static used inside braces) or extensions
- of structure symbols. We can ignore both. */
- case 'V':
- case '(':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '-':
- case '#': /* For symbol identification (used in live ranges). */
- continue;
-
- case ':':
- /* It is a C++ nested symbol. We don't need to record it
- (I don't think); if we try to look up foo::bar::baz,
- then symbols for the symtab containing foo should get
- read in, I think. */
- /* Someone says sun cc puts out symbols like
- /foo/baz/maclib::/usr/local/bin/maclib,
- which would get here with a symbol type of ':'. */
- continue;
-
- default:
- /* Unexpected symbol descriptor. The second and subsequent stabs
- of a continued stab can show up here. The question is
- whether they ever can mimic a normal stab--it would be
- nice if not, since we certainly don't want to spend the
- time searching to the end of every string looking for
- a backslash. */
-
- complaint (_("unknown symbol descriptor `%c'"),
- p[1]);
-
- /* Ignore it; perhaps it is an extension that we don't
- know about. */
- continue;
- }
- }
-
- case N_EXCL:
-
- namestring = set_namestring (objfile, &nlist);
-
- /* Find the corresponding bincl and mark that psymtab on the
- psymtab dependency list. */
- {
- legacy_psymtab *needed_pst =
- find_corresponding_bincl_psymtab (namestring, nlist.n_value);
-
- /* If this include file was defined earlier in this file,
- leave it alone. */
- if (needed_pst == pst)
- continue;
-
- if (needed_pst)
- {
- int i;
- int found = 0;
-
- for (i = 0; i < dependencies_used; i++)
- if (dependency_list[i] == needed_pst)
- {
- found = 1;
- break;
- }
-
- /* If it's already in the list, skip the rest. */
- if (found)
- continue;
-
- dependency_list[dependencies_used++] = needed_pst;
- if (dependencies_used >= dependencies_allocated)
- {
- legacy_psymtab **orig = dependency_list;
-
- dependency_list =
- (legacy_psymtab **)
- alloca ((dependencies_allocated *= 2)
- * sizeof (legacy_psymtab *));
- memcpy (dependency_list, orig,
- (dependencies_used
- * sizeof (legacy_psymtab *)));
-#ifdef DEBUG_INFO
- gdb_printf (gdb_stderr,
- "Had to reallocate "
- "dependency list.\n");
- gdb_printf (gdb_stderr,
- "New dependencies allocated: %d\n",
- dependencies_allocated);
-#endif
- }
- }
- }
- continue;
-
- case N_ENDM:
- /* Solaris 2 end of module, finish current partial symbol
- table. dbx_end_psymtab will set the high text address of
- PST to the proper value, which is necessary if a module
- compiled without debugging info follows this module. */
- if (pst && gdbarch_sofun_address_maybe_missing (gdbarch))
- {
- dbx_end_psymtab (objfile, partial_symtabs, pst,
- psymtab_include_list, includes_used,
- symnum * symbol_size,
- (unrelocated_addr) 0, dependency_list,
- dependencies_used, textlow_not_set);
- pst = (legacy_psymtab *) 0;
- includes_used = 0;
- dependencies_used = 0;
- has_line_numbers = 0;
- }
- continue;
-
- case N_RBRAC:
-#ifdef HANDLE_RBRAC
- HANDLE_RBRAC (nlist.n_value);
- continue;
-#endif
- case N_EINCL:
- case N_DSLINE:
- case N_BSLINE:
- case N_SSYM: /* Claim: Structure or union element.
- Hopefully, I can ignore this. */
- case N_ENTRY: /* Alternate entry point; can ignore. */
- case N_MAIN: /* Can definitely ignore this. */
- case N_CATCH: /* These are GNU C++ extensions */
- case N_EHDECL: /* that can safely be ignored here. */
- case N_LENG:
- case N_BCOMM:
- case N_ECOMM:
- case N_ECOML:
- case N_FNAME:
- case N_SLINE:
- case N_RSYM:
- case N_PSYM:
- case N_BNSYM:
- case N_ENSYM:
- case N_LBRAC:
- case N_NSYMS: /* Ultrix 4.0: symbol count */
- case N_DEFD: /* GNU Modula-2 */
- case N_ALIAS: /* SunPro F77: alias name, ignore for now. */
-
- case N_OBJ: /* Useless types from Solaris. */
- case N_OPT:
- case N_PATCH:
- /* These symbols aren't interesting; don't worry about them. */
- continue;
-
- default:
- /* If we haven't found it yet, ignore it. It's probably some
- new type we don't know about yet. */
- unknown_symtype_complaint (hex_string (nlist.n_type));
- continue;
- }
- }
-
- /* If there's stuff to be cleaned up, clean it up. */
- if (pst)
- {
- /* Don't set high text address of PST lower than it already
- is. */
- unrelocated_addr text_end
- = (unrelocated_addr
- ((lowest_text_address == (unrelocated_addr) -1
- ? text_addr
- : CORE_ADDR (lowest_text_address))
- + text_size));
-
- dbx_end_psymtab (objfile, partial_symtabs,
- pst, psymtab_include_list, includes_used,
- symnum * symbol_size,
- (text_end > pst->unrelocated_text_high ()
- ? text_end : pst->unrelocated_text_high ()),
- dependency_list, dependencies_used, textlow_not_set);
- }
-}
-
-/* Allocate and partially fill a partial symtab. It will be
- completely filled at the end of the symbol list.
-
- SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR
- is the address relative to which its symbols are (incremental) or 0
- (normal). */
-
-static legacy_psymtab *
-start_psymtab (psymtab_storage *partial_symtabs, struct objfile *objfile,
- const char *filename, unrelocated_addr textlow, int ldsymoff)
-{
- legacy_psymtab *result = new legacy_psymtab (filename, partial_symtabs,
- objfile->per_bfd, textlow);
-
- result->read_symtab_private =
- XOBNEW (&objfile->objfile_obstack, struct symloc);
- LDSYMOFF (result) = ldsymoff;
- result->legacy_read_symtab = dbx_read_symtab;
- result->legacy_expand_psymtab = dbx_expand_psymtab;
- SYMBOL_SIZE (result) = symbol_size;
- SYMBOL_OFFSET (result) = symbol_table_offset;
- STRING_OFFSET (result) = string_table_offset;
- FILE_STRING_OFFSET (result) = file_string_table_offset;
-
- /* Deduce the source language from the filename for this psymtab. */
- psymtab_language = deduce_language_from_filename (filename);
- PST_LANGUAGE (result) = psymtab_language;
-
- return result;
-}
-
-/* Close off the current usage of PST.
- Returns PST or NULL if the partial symtab was empty and thrown away.
-
- FIXME: List variables and peculiarities of same. */
-
-legacy_psymtab *
-dbx_end_psymtab (struct objfile *objfile, psymtab_storage *partial_symtabs,
- legacy_psymtab *pst,
- const char **include_list, int num_includes,
- int capping_symbol_offset, unrelocated_addr capping_text,
- legacy_psymtab **dependency_list,
- int number_dependencies,
- int textlow_not_set)
-{
- int i;
- struct gdbarch *gdbarch = objfile->arch ();
-
- if (capping_symbol_offset != -1)
- LDSYMLEN (pst) = capping_symbol_offset - LDSYMOFF (pst);
- pst->set_text_high (capping_text);
-
- /* Under Solaris, the N_SO symbols always have a value of 0,
- instead of the usual address of the .o file. Therefore,
- we have to do some tricks to fill in texthigh and textlow.
- The first trick is: if we see a static
- or global function, and the textlow for the current pst
- is not set (ie: textlow_not_set), then we use that function's
- address for the textlow of the pst. */
-
- /* Now, to fill in texthigh, we remember the last function seen
- in the .o file. Also, there's a hack in
- bfd/elf.c and gdb/elfread.c to pass the ELF st_size field
- to here via the misc_info field. Therefore, we can fill in
- a reliable texthigh by taking the address plus size of the
- last function in the file. */
-
- if (!pst->text_high_valid && last_function_name
- && gdbarch_sofun_address_maybe_missing (gdbarch))
- {
- int n;
- struct bound_minimal_symbol minsym;
-
- const char *colon = strchr (last_function_name, ':');
- if (colon == NULL)
- n = 0;
- else
- n = colon - last_function_name;
- char *p = (char *) alloca (n + 2);
- strncpy (p, last_function_name, n);
- p[n] = 0;
-
- minsym = lookup_minimal_symbol (p, pst->filename, objfile);
- if (minsym.minsym == NULL)
- {
- /* Sun Fortran appends an underscore to the minimal symbol name,
- try again with an appended underscore if the minimal symbol
- was not found. */
- p[n] = '_';
- p[n + 1] = 0;
- minsym = lookup_minimal_symbol (p, pst->filename, objfile);
- }
-
- if (minsym.minsym)
- pst->set_text_high
- (unrelocated_addr (CORE_ADDR (minsym.minsym->unrelocated_address ())
- + minsym.minsym->size ()));
-
- last_function_name = NULL;
- }
-
- if (!gdbarch_sofun_address_maybe_missing (gdbarch))
- ;
- /* This test will be true if the last .o file is only data. */
- else if (textlow_not_set)
- pst->set_text_low (pst->unrelocated_text_high ());
- else
- {
- /* If we know our own starting text address, then walk through all other
- psymtabs for this objfile, and if any didn't know their ending text
- address, set it to our starting address. Take care to not set our
- own ending address to our starting address. */
-
- for (partial_symtab *p1 : partial_symtabs->range ())
- if (!p1->text_high_valid && p1->text_low_valid && p1 != pst)
- p1->set_text_high (pst->unrelocated_text_low ());
- }
-
- /* End of kludge for patching Solaris textlow and texthigh. */
-
- pst->end ();
-
- pst->number_of_dependencies = number_dependencies;
- if (number_dependencies)
- {
- pst->dependencies
- = partial_symtabs->allocate_dependencies (number_dependencies);
- memcpy (pst->dependencies, dependency_list,
- number_dependencies * sizeof (legacy_psymtab *));
- }
- else
- pst->dependencies = 0;
-
- for (i = 0; i < num_includes; i++)
- {
- legacy_psymtab *subpst =
- new legacy_psymtab (include_list[i], partial_symtabs, objfile->per_bfd);
-
- subpst->read_symtab_private =
- XOBNEW (&objfile->objfile_obstack, struct symloc);
- LDSYMOFF (subpst) =
- LDSYMLEN (subpst) = 0;
-
- /* We could save slight bits of space by only making one of these,
- shared by the entire set of include files. FIXME-someday. */
- subpst->dependencies =
- partial_symtabs->allocate_dependencies (1);
- subpst->dependencies[0] = pst;
- subpst->number_of_dependencies = 1;
-
- subpst->legacy_read_symtab = pst->legacy_read_symtab;
- subpst->legacy_expand_psymtab = pst->legacy_expand_psymtab;
- }
-
- if (num_includes == 0
- && number_dependencies == 0
- && pst->empty ()
- && has_line_numbers == 0)
- {
- /* Throw away this psymtab, it's empty. */
- /* Empty psymtabs happen as a result of header files which don't have
- any symbols in them. There can be a lot of them. But this check
- is wrong, in that a psymtab with N_SLINE entries but nothing else
- is not empty, but we don't realize that. Fixing that without slowing
- things down might be tricky. */
-
- partial_symtabs->discard_psymtab (pst);
-
- /* Indicate that psymtab was thrown away. */
- pst = NULL;
- }
- return pst;
-}
-static void
-dbx_expand_psymtab (legacy_psymtab *pst, struct objfile *objfile)
-{
- gdb_assert (!pst->readin);
-
- /* Read in all partial symtabs on which this one is dependent. */
- pst->expand_dependencies (objfile);
-
- if (LDSYMLEN (pst)) /* Otherwise it's a dummy. */
- {
- /* Init stuff necessary for reading in symbols */
- stabsread_init ();
- scoped_free_pendings free_pending;
- file_string_table_offset = FILE_STRING_OFFSET (pst);
- symbol_size = SYMBOL_SIZE (pst);
-
- /* Read in this file's symbols. */
- if (bfd_seek (objfile->obfd.get (), SYMBOL_OFFSET (pst), SEEK_SET) == 0)
- read_ofile_symtab (objfile, pst);
- }
- pst->readin = true;
-}
-
-/* Read in all of the symbols for a given psymtab for real.
- Be verbose about it if the user wants that. SELF is not NULL. */
-
-static void
-dbx_read_symtab (legacy_psymtab *self, struct objfile *objfile)
-{
- gdb_assert (!self->readin);
-
- if (LDSYMLEN (self) || self->number_of_dependencies)
- {
- next_symbol_text_func = dbx_next_symbol_text;
-
- {
- scoped_restore restore_stabs_data = make_scoped_restore (&stabs_data);
- gdb::unique_xmalloc_ptr<gdb_byte> data_holder;
- if (DBX_STAB_SECTION (objfile))
- {
- stabs_data
- = symfile_relocate_debug_section (objfile,
- DBX_STAB_SECTION (objfile),
- NULL);
- data_holder.reset (stabs_data);
- }
-
- self->expand_psymtab (objfile);
- }
-
- /* Match with global symbols. This only needs to be done once,
- after all of the symtabs and dependencies have been read in. */
- scan_file_globals (objfile);
- }
-}
-
-/* Read in a defined section of a specific object file's symbols. */
-
-static void
-read_ofile_symtab (struct objfile *objfile, legacy_psymtab *pst)
-{
- const char *namestring;
- struct external_nlist *bufp;
- struct internal_nlist nlist;
- unsigned char type;
- unsigned max_symnum;
- bfd *abfd;
- int sym_offset; /* Offset to start of symbols to read */
- int sym_size; /* Size of symbols to read */
- CORE_ADDR text_offset; /* Start of text segment for symbols */
- int text_size; /* Size of text segment for symbols */
-
- sym_offset = LDSYMOFF (pst);
- sym_size = LDSYMLEN (pst);
- text_offset = pst->text_low (objfile);
- text_size = pst->text_high (objfile) - pst->text_low (objfile);
- const section_offsets &section_offsets = objfile->section_offsets;
-
- dbxread_objfile = objfile;
-
- stringtab_global = DBX_STRINGTAB (objfile);
- set_last_source_file (NULL);
-
- abfd = objfile->obfd.get ();
- symfile_bfd = objfile->obfd.get (); /* Implicit param to next_text_symbol. */
- symbuf_end = symbuf_idx = 0;
- symbuf_read = 0;
- symbuf_left = sym_offset + sym_size;
-
- /* It is necessary to actually read one symbol *before* the start
- of this symtab's symbols, because the GCC_COMPILED_FLAG_SYMBOL
- occurs before the N_SO symbol.
-
- Detecting this in read_dbx_symtab
- would slow down initial readin, so we look for it here instead. */
- if (!processing_acc_compilation && sym_offset >= (int) symbol_size)
- {
- stabs_seek (sym_offset - symbol_size);
- fill_symbuf (abfd);
- bufp = &symbuf[symbuf_idx++];
- INTERNALIZE_SYMBOL (nlist, bufp, abfd);
- OBJSTAT (objfile, n_stabs++);
-
- namestring = set_namestring (objfile, &nlist);
-
- processing_gcc_compilation = 0;
- if (nlist.n_type == N_TEXT)
- {
- const char *tempstring = namestring;
-
- if (strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL) == 0)
- processing_gcc_compilation = 1;
- else if (strcmp (namestring, GCC2_COMPILED_FLAG_SYMBOL) == 0)
- processing_gcc_compilation = 2;
- if (*tempstring != '\0'
- && *tempstring == bfd_get_symbol_leading_char (symfile_bfd))
- ++tempstring;
- if (startswith (tempstring, "__gnu_compiled"))
- processing_gcc_compilation = 2;
- }
- }
- else
- {
- /* The N_SO starting this symtab is the first symbol, so we
- better not check the symbol before it. I'm not this can
- happen, but it doesn't hurt to check for it. */
- stabs_seek (sym_offset);
- processing_gcc_compilation = 0;
- }
-
- if (symbuf_idx == symbuf_end)
- fill_symbuf (abfd);
- bufp = &symbuf[symbuf_idx];
- if (bfd_h_get_8 (abfd, bufp->e_type) != N_SO)
- error (_("First symbol in segment of executable not a source symbol"));
-
- max_symnum = sym_size / symbol_size;
-
- for (symnum = 0;
- symnum < max_symnum;
- symnum++)
- {
- QUIT; /* Allow this to be interruptable. */
- if (symbuf_idx == symbuf_end)
- fill_symbuf (abfd);
- bufp = &symbuf[symbuf_idx++];
- INTERNALIZE_SYMBOL (nlist, bufp, abfd);
- OBJSTAT (objfile, n_stabs++);
-
- type = bfd_h_get_8 (abfd, bufp->e_type);
-
- namestring = set_namestring (objfile, &nlist);
-
- if (type & N_STAB)
- {
- if (sizeof (nlist.n_value) > 4
- /* We are a 64-bit debugger debugging a 32-bit program. */
- && (type == N_LSYM || type == N_PSYM))
- /* We have to be careful with the n_value in the case of N_LSYM
- and N_PSYM entries, because they are signed offsets from frame
- pointer, but we actually read them as unsigned 32-bit values.
- This is not a problem for 32-bit debuggers, for which negative
- values end up being interpreted correctly (as negative
- offsets) due to integer overflow.
- But we need to sign-extend the value for 64-bit debuggers,
- or we'll end up interpreting negative values as very large
- positive offsets. */
- nlist.n_value = (nlist.n_value ^ 0x80000000) - 0x80000000;
- process_one_symbol (type, nlist.n_desc, nlist.n_value,
- namestring, section_offsets, objfile,
- PST_LANGUAGE (pst));
- }
- /* We skip checking for a new .o or -l file; that should never
- happen in this routine. */
- else if (type == N_TEXT)
- {
- /* I don't think this code will ever be executed, because
- the GCC_COMPILED_FLAG_SYMBOL usually is right before
- the N_SO symbol which starts this source file.
- However, there is no reason not to accept
- the GCC_COMPILED_FLAG_SYMBOL anywhere. */
-
- if (strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL) == 0)
- processing_gcc_compilation = 1;
- else if (strcmp (namestring, GCC2_COMPILED_FLAG_SYMBOL) == 0)
- processing_gcc_compilation = 2;
- }
- else if (type & N_EXT || type == (unsigned char) N_TEXT
- || type == (unsigned char) N_NBTEXT)
- {
- /* Global symbol: see if we came across a dbx definition for
- a corresponding symbol. If so, store the value. Remove
- syms from the chain when their values are stored, but
- search the whole chain, as there may be several syms from
- different files with the same name. */
- /* This is probably not true. Since the files will be read
- in one at a time, each reference to a global symbol will
- be satisfied in each file as it appears. So we skip this
- section. */
- ;
- }
- }
-
- /* In a Solaris elf file, this variable, which comes from the value
- of the N_SO symbol, will still be 0. Luckily, text_offset, which
- comes from low text address of PST, is correct. */
- if (get_last_source_start_addr () == 0)
- set_last_source_start_addr (text_offset);
-
- /* In reordered executables last_source_start_addr may not be the
- lower bound for this symtab, instead use text_offset which comes
- from the low text address of PST, which is correct. */
- if (get_last_source_start_addr () > text_offset)
- set_last_source_start_addr (text_offset);
-
- pst->compunit_symtab = end_compunit_symtab (text_offset + text_size);
-
- end_stabs ();
-
- dbxread_objfile = NULL;
-}
-
-/* Record the namespace that the function defined by SYMBOL was
- defined in, if necessary. BLOCK is the associated block; use
- OBSTACK for allocation. */
-
-static void
-cp_set_block_scope (const struct symbol *symbol,
- struct block *block,
- struct obstack *obstack)
-{
- if (symbol->demangled_name () != NULL)
- {
- /* Try to figure out the appropriate namespace from the
- demangled name. */
-
- /* FIXME: carlton/2003-04-15: If the function in question is
- a method of a class, the name will actually include the
- name of the class as well. This should be harmless, but
- is a little unfortunate. */
-
- const char *name = symbol->demangled_name ();
- unsigned int prefix_len = cp_entire_prefix_len (name);
-
- block->set_scope (obstack_strndup (obstack, name, prefix_len),
- obstack);
- }
-}
-
-/* This handles a single symbol from the symbol-file, building symbols
- into a GDB symtab. It takes these arguments and an implicit argument.
-
- TYPE is the type field of the ".stab" symbol entry.
- DESC is the desc field of the ".stab" entry.
- VALU is the value field of the ".stab" entry.
- NAME is the symbol name, in our address space.
- SECTION_OFFSETS is a set of amounts by which the sections of this
- object file were relocated when it was loaded into memory. Note
- that these section_offsets are not the objfile->section_offsets but
- the pst->section_offsets. All symbols that refer to memory
- locations need to be offset by these amounts.
- OBJFILE is the object file from which we are reading symbols. It
- is used in end_compunit_symtab.
- LANGUAGE is the language of the symtab.
-*/
-
-void
-process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
- const section_offsets &section_offsets,
- struct objfile *objfile, enum language language)
-{
- struct gdbarch *gdbarch = objfile->arch ();
- struct context_stack *newobj;
- struct context_stack cstk;
- /* This remembers the address of the start of a function. It is
- used because in Solaris 2, N_LBRAC, N_RBRAC, and N_SLINE entries
- are relative to the current function's start address. On systems
- other than Solaris 2, this just holds the SECT_OFF_TEXT value,
- and is used to relocate these symbol types rather than
- SECTION_OFFSETS. */
- static CORE_ADDR function_start_offset;
-
- /* This holds the address of the start of a function, without the
- system peculiarities of function_start_offset. */
- static CORE_ADDR last_function_start;
-
- /* If this is nonzero, we've seen an N_SLINE since the start of the
- current function. We use this to tell us to move the first sline
- to the beginning of the function regardless of what its given
- value is. */
- static int sline_found_in_function = 1;
-
- /* If this is nonzero, we've seen a non-gcc N_OPT symbol for this
- source file. Used to detect the SunPRO solaris compiler. */
- static int n_opt_found;
-
- /* The section index for this symbol. */
- int section_index = -1;
-
- /* Something is wrong if we see real data before seeing a source
- file name. */
-
- if (get_last_source_file () == NULL && type != (unsigned char) N_SO)
- {
- /* Ignore any symbols which appear before an N_SO symbol.
- Currently no one puts symbols there, but we should deal
- gracefully with the case. A complain()t might be in order,
- but this should not be an error (). */
- return;
- }
-
- switch (type)
- {
- case N_FUN:
- case N_FNAME:
-
- if (*name == '\000')
- {
- /* This N_FUN marks the end of a function. This closes off
- the current block. */
- struct block *block;
-
- if (outermost_context_p ())
- {
- lbrac_mismatch_complaint (symnum);
- break;
- }
-
- /* The following check is added before recording line 0 at
- end of function so as to handle hand-generated stabs
- which may have an N_FUN stabs at the end of the function,
- but no N_SLINE stabs. */
- if (sline_found_in_function)
- {
- CORE_ADDR addr = last_function_start + valu;
-
- record_line
- (get_current_subfile (), 0,
- unrelocated_addr (gdbarch_addr_bits_remove (gdbarch, addr)
- - objfile->text_section_offset ()));
- }
-
- within_function = 0;
- cstk = pop_context ();
-
- /* Make a block for the local symbols within. */
- block = finish_block (cstk.name,
- cstk.old_blocks, NULL,
- cstk.start_addr, cstk.start_addr + valu);
-
- /* For C++, set the block's scope. */
- if (cstk.name->language () == language_cplus)
- cp_set_block_scope (cstk.name, block, &objfile->objfile_obstack);
-
- /* May be switching to an assembler file which may not be using
- block relative stabs, so reset the offset. */
- function_start_offset = 0;
-
- break;
- }
-
- sline_found_in_function = 0;
-
- /* Relocate for dynamic loading. */
- section_index = SECT_OFF_TEXT (objfile);
- valu += section_offsets[SECT_OFF_TEXT (objfile)];
- valu = gdbarch_addr_bits_remove (gdbarch, valu);
- last_function_start = valu;
-
- goto define_a_symbol;
-
- case N_LBRAC:
- /* This "symbol" just indicates the start of an inner lexical
- context within a function. */
-
- /* Ignore extra outermost context from SunPRO cc and acc. */
- if (n_opt_found && desc == 1)
- break;
-
- valu += function_start_offset;
-
- push_context (desc, valu);
- break;
-
- case N_RBRAC:
- /* This "symbol" just indicates the end of an inner lexical
- context that was started with N_LBRAC. */
-
- /* Ignore extra outermost context from SunPRO cc and acc. */
- if (n_opt_found && desc == 1)
- break;
-
- valu += function_start_offset;
-
- if (outermost_context_p ())
- {
- lbrac_mismatch_complaint (symnum);
- break;
- }
-
- cstk = pop_context ();
- if (desc != cstk.depth)
- lbrac_mismatch_complaint (symnum);
-
- if (*get_local_symbols () != NULL)
- {
- /* GCC development snapshots from March to December of
- 2000 would output N_LSYM entries after N_LBRAC
- entries. As a consequence, these symbols are simply
- discarded. Complain if this is the case. */
- complaint (_("misplaced N_LBRAC entry; discarding local "
- "symbols which have no enclosing block"));
- }
- *get_local_symbols () = cstk.locals;
-
- if (get_context_stack_depth () > 1)
- {
- /* This is not the outermost LBRAC...RBRAC pair in the
- function, its local symbols preceded it, and are the ones
- just recovered from the context stack. Define the block
- for them (but don't bother if the block contains no
- symbols. Should we complain on blocks without symbols?
- I can't think of any useful purpose for them). */
- if (*get_local_symbols () != NULL)
- {
- /* Muzzle a compiler bug that makes end < start.
-
- ??? Which compilers? Is this ever harmful?. */
- if (cstk.start_addr > valu)
- {
- complaint (_("block start larger than block end"));
- cstk.start_addr = valu;
- }
- /* Make a block for the local symbols within. */
- finish_block (0, cstk.old_blocks, NULL,
- cstk.start_addr, valu);
- }
- }
- else
- {
- /* This is the outermost LBRAC...RBRAC pair. There is no
- need to do anything; leave the symbols that preceded it
- to be attached to the function's own block. We need to
- indicate that we just moved outside of the function. */
- within_function = 0;
- }
-
- break;
-
- case N_FN:
- case N_FN_SEQ:
- /* This kind of symbol indicates the start of an object file.
- Relocate for dynamic loading. */
- section_index = SECT_OFF_TEXT (objfile);
- valu += section_offsets[SECT_OFF_TEXT (objfile)];
- break;
-
- case N_SO:
- /* This type of symbol indicates the start of data for one
- source file. Finish the symbol table of the previous source
- file (if any) and start accumulating a new symbol table.
- Relocate for dynamic loading. */
- section_index = SECT_OFF_TEXT (objfile);
- valu += section_offsets[SECT_OFF_TEXT (objfile)];
-
- n_opt_found = 0;
-
- if (get_last_source_file ())
- {
- /* Check if previous symbol was also an N_SO (with some
- sanity checks). If so, that one was actually the
- directory name, and the current one is the real file
- name. Patch things up. */
- if (previous_stab_code == (unsigned char) N_SO)
- {
- patch_subfile_names (get_current_subfile (), name);
- break; /* Ignore repeated SOs. */
- }
- end_compunit_symtab (valu);
- end_stabs ();
- }
-
- /* Null name means this just marks the end of text for this .o
- file. Don't start a new symtab in this case. */
- if (*name == '\000')
- break;
-
- function_start_offset = 0;
-
- start_stabs ();
- start_compunit_symtab (objfile, name, NULL, valu, language);
- record_debugformat ("stabs");
- break;
-
- case N_SOL:
- /* This type of symbol indicates the start of data for a
- sub-source-file, one whose contents were copied or included
- in the compilation of the main source file (whose name was
- given in the N_SO symbol). Relocate for dynamic loading. */
- section_index = SECT_OFF_TEXT (objfile);
- valu += section_offsets[SECT_OFF_TEXT (objfile)];
- start_subfile (name);
- break;
-
- case N_BINCL:
- push_subfile ();
- add_new_header_file (name, valu);
- start_subfile (name);
- break;
-
- case N_EINCL:
- start_subfile (pop_subfile ());
- break;
-
- case N_EXCL:
- add_old_header_file (name, valu);
- break;
-
- case N_SLINE:
- /* This type of "symbol" really just records one line-number --
- core-address correspondence. Enter it in the line list for
- this symbol table. */
-
- /* Relocate for dynamic loading and for ELF acc
- function-relative symbols. */
- valu += function_start_offset;
-
- /* GCC 2.95.3 emits the first N_SLINE stab somewhere in the
- middle of the prologue instead of right at the start of the
- function. To deal with this we record the address for the
- first N_SLINE stab to be the start of the function instead of
- the listed location. We really shouldn't to this. When
- compiling with optimization, this first N_SLINE stab might be
- optimized away. Other (non-GCC) compilers don't emit this
- stab at all. There is no real harm in having an extra
- numbered line, although it can be a bit annoying for the
- user. However, it totally screws up our testsuite.
-
- So for now, keep adjusting the address of the first N_SLINE
- stab, but only for code compiled with GCC. */
-
- if (within_function && sline_found_in_function == 0)
- {
- CORE_ADDR addr = processing_gcc_compilation == 2 ?
- last_function_start : valu;
-
- record_line
- (get_current_subfile (), desc,
- unrelocated_addr (gdbarch_addr_bits_remove (gdbarch, addr)
- - objfile->text_section_offset ()));
- sline_found_in_function = 1;
- }
- else
- record_line
- (get_current_subfile (), desc,
- unrelocated_addr (gdbarch_addr_bits_remove (gdbarch, valu)
- - objfile->text_section_offset ()));
- break;
-
- case N_BCOMM:
- common_block_start (name, objfile);
- break;
-
- case N_ECOMM:
- common_block_end (objfile);
- break;
-
- /* The following symbol types need to have the appropriate
- offset added to their value; then we process symbol
- definitions in the name. */
-
- case N_STSYM: /* Static symbol in data segment. */
- case N_LCSYM: /* Static symbol in BSS segment. */
- case N_ROSYM: /* Static symbol in read-only data segment. */
- /* HORRID HACK DEPT. However, it's Sun's furgin' fault.
- Solaris 2's stabs-in-elf makes *most* symbols relative but
- leaves a few absolute (at least for Solaris 2.1 and version
- 2.0.1 of the SunPRO compiler). N_STSYM and friends sit on
- the fence. .stab "foo:S...",N_STSYM is absolute (ld
- relocates it) .stab "foo:V...",N_STSYM is relative (section
- base subtracted). This leaves us no choice but to search for
- the 'S' or 'V'... (or pass the whole section_offsets stuff
- down ONE MORE function call level, which we really don't want
- to do). */
- {
- const char *p;
-
- /* Normal object file and NLMs have non-zero text seg offsets,
- but don't need their static syms offset in this fashion.
- XXX - This is really a crock that should be fixed in the
- solib handling code so that I don't have to work around it
- here. */
-
- if (!symfile_relocatable)
- {
- p = strchr (name, ':');
- if (p != 0 && p[1] == 'S')
- {
- /* The linker relocated it. We don't want to add a
- Sun-stabs Tfoo.foo-like offset, but we *do*
- want to add whatever solib.c passed to
- symbol_file_add as addr (this is known to affect
- SunOS 4, and I suspect ELF too). Since there is no
- Ttext.text symbol, we can get addr from the text offset. */
- section_index = SECT_OFF_TEXT (objfile);
- valu += section_offsets[SECT_OFF_TEXT (objfile)];
- goto define_a_symbol;
- }
- }
- /* Since it's not the kludge case, re-dispatch to the right
- handler. */
- switch (type)
- {
- case N_STSYM:
- goto case_N_STSYM;
- case N_LCSYM:
- goto case_N_LCSYM;
- case N_ROSYM:
- goto case_N_ROSYM;
- default:
- internal_error (_("failed internal consistency check"));
- }
- }
-
- case_N_STSYM: /* Static symbol in data segment. */
- case N_DSLINE: /* Source line number, data segment. */
- section_index = SECT_OFF_DATA (objfile);
- valu += section_offsets[SECT_OFF_DATA (objfile)];
- goto define_a_symbol;
-
- case_N_LCSYM: /* Static symbol in BSS segment. */
- case N_BSLINE: /* Source line number, BSS segment. */
- /* N_BROWS: overlaps with N_BSLINE. */
- section_index = SECT_OFF_BSS (objfile);
- valu += section_offsets[SECT_OFF_BSS (objfile)];
- goto define_a_symbol;
-
- case_N_ROSYM: /* Static symbol in read-only data segment. */
- section_index = SECT_OFF_RODATA (objfile);
- valu += section_offsets[SECT_OFF_RODATA (objfile)];
- goto define_a_symbol;
-
- case N_ENTRY: /* Alternate entry point. */
- /* Relocate for dynamic loading. */
- section_index = SECT_OFF_TEXT (objfile);
- valu += section_offsets[SECT_OFF_TEXT (objfile)];
- goto define_a_symbol;
-
- /* The following symbol types we don't know how to process.
- Handle them in a "default" way, but complain to people who
- care. */
- default:
- case N_CATCH: /* Exception handler catcher. */
- case N_EHDECL: /* Exception handler name. */
- case N_PC: /* Global symbol in Pascal. */
- case N_M2C: /* Modula-2 compilation unit. */
- /* N_MOD2: overlaps with N_EHDECL. */
- case N_SCOPE: /* Modula-2 scope information. */
- case N_ECOML: /* End common (local name). */
- case N_NBTEXT: /* Gould Non-Base-Register symbols??? */
- case N_NBDATA:
- case N_NBBSS:
- case N_NBSTS:
- case N_NBLCS:
- unknown_symtype_complaint (hex_string (type));
-
- define_a_symbol:
- [[fallthrough]];
- /* These symbol types don't need the address field relocated,
- since it is either unused, or is absolute. */
- case N_GSYM: /* Global variable. */
- case N_NSYMS: /* Number of symbols (Ultrix). */
- case N_NOMAP: /* No map? (Ultrix). */
- case N_RSYM: /* Register variable. */
- case N_DEFD: /* Modula-2 GNU module dependency. */
- case N_SSYM: /* Struct or union element. */
- case N_LSYM: /* Local symbol in stack. */
- case N_PSYM: /* Parameter variable. */
- case N_LENG: /* Length of preceding symbol type. */
- if (name)
- {
- int deftype;
- const char *colon_pos = strchr (name, ':');
-
- if (colon_pos == NULL)
- deftype = '\0';
- else
- deftype = colon_pos[1];
-
- switch (deftype)
- {
- case 'f':
- case 'F':
- /* Deal with the SunPRO 3.0 compiler which omits the
- address from N_FUN symbols. */
- if (type == N_FUN
- && valu == section_offsets[SECT_OFF_TEXT (objfile)]
- && gdbarch_sofun_address_maybe_missing (gdbarch))
- {
- struct bound_minimal_symbol minsym
- = find_stab_function (name, get_last_source_file (),
- objfile);
- if (minsym.minsym != NULL)
- valu = minsym.value_address ();
- }
-
- /* These addresses are absolute. */
- function_start_offset = valu;
-
- within_function = 1;
-
- if (get_context_stack_depth () > 1)
- {
- complaint (_("unmatched N_LBRAC before symtab pos %d"),
- symnum);
- break;
- }
-
- if (!outermost_context_p ())
- {
- struct block *block;
-
- cstk = pop_context ();
- /* Make a block for the local symbols within. */
- block = finish_block (cstk.name,
- cstk.old_blocks, NULL,
- cstk.start_addr, valu);
-
- /* For C++, set the block's scope. */
- if (cstk.name->language () == language_cplus)
- cp_set_block_scope (cstk.name, block,
- &objfile->objfile_obstack);
- }
-
- newobj = push_context (0, valu);
- newobj->name = define_symbol (valu, name, desc, type, objfile);
- if (newobj->name != nullptr)
- newobj->name->set_section_index (section_index);
- break;
-
- default:
- {
- struct symbol *sym = define_symbol (valu, name, desc, type,
- objfile);
- if (sym != nullptr)
- sym->set_section_index (section_index);
- }
- break;
- }
- }
- break;
-
- /* We use N_OPT to carry the gcc2_compiled flag. Sun uses it
- for a bunch of other flags, too. Someday we may parse their
- flags; for now we ignore theirs and hope they'll ignore ours. */
- case N_OPT: /* Solaris 2: Compiler options. */
- if (name)
- {
- if (strcmp (name, GCC2_COMPILED_FLAG_SYMBOL) == 0)
- {
- processing_gcc_compilation = 2;
- }
- else
- n_opt_found = 1;
- }
- break;
-
- case N_MAIN: /* Name of main routine. */
- /* FIXME: If one has a symbol file with N_MAIN and then replaces
- it with a symbol file with "main" and without N_MAIN. I'm
- not sure exactly what rule to follow but probably something
- like: N_MAIN takes precedence over "main" no matter what
- objfile it is in; If there is more than one N_MAIN, choose
- the one in the symfile_objfile; If there is more than one
- N_MAIN within a given objfile, complain() and choose
- arbitrarily. (kingdon) */
- if (name != NULL)
- set_objfile_main_name (objfile, name, language_unknown);
- break;
-
- /* The following symbol types can be ignored. */
- case N_OBJ: /* Solaris 2: Object file dir and name. */
- case N_PATCH: /* Solaris 2: Patch Run Time Checker. */
- /* N_UNDF: Solaris 2: File separator mark. */
- /* N_UNDF: -- we will never encounter it, since we only process
- one file's symbols at once. */
- case N_ENDM: /* Solaris 2: End of module. */
- case N_ALIAS: /* SunPro F77: alias name, ignore for now. */
- break;
- }
-
- /* '#' is a GNU C extension to allow one symbol to refer to another
- related symbol.
-
- Generally this is used so that an alias can refer to its main
- symbol. */
- gdb_assert (name);
- if (name[0] == '#')
- {
- /* Initialize symbol reference names and determine if this is a
- definition. If a symbol reference is being defined, go ahead
- and add it. Otherwise, just return. */
-
- const char *s = name;
- int refnum;
-
- /* If this stab defines a new reference ID that is not on the
- reference list, then put it on the reference list.
-
- We go ahead and advance NAME past the reference, even though
- it is not strictly necessary at this time. */
- refnum = symbol_reference_defined (&s);
- if (refnum >= 0)
- if (!ref_search (refnum))
- ref_add (refnum, 0, name, valu);
- name = s;
- }
-
- previous_stab_code = type;
-}
-
-/* FIXME: The only difference between this and elfstab_build_psymtabs
- is the call to install_minimal_symbols for elf, and the support for
- split sections. If the differences are really that small, the code
- should be shared. */
-
-/* Scan and build partial symbols for an coff symbol file.
- The coff file has already been processed to get its minimal symbols.
-
- This routine is the equivalent of dbx_symfile_init and dbx_symfile_read
- rolled into one.
-
- OBJFILE is the object file we are reading symbols from.
- ADDR is the address relative to which the symbols are (e.g.
- the base address of the text segment).
- TEXTADDR is the address of the text section.
- TEXTSIZE is the size of the text section.
- STABSECTS is the list of .stab sections in OBJFILE.
- STABSTROFFSET and STABSTRSIZE define the location in OBJFILE where the
- .stabstr section exists.
-
- This routine is mostly copied from dbx_symfile_init and dbx_symfile_read,
- adjusted for coff details. */
-
-void
-coffstab_build_psymtabs (struct objfile *objfile,
- CORE_ADDR textaddr, unsigned int textsize,
- const std::vector<asection *> &stabsects,
- file_ptr stabstroffset, unsigned int stabstrsize)
-{
- int val;
- bfd *sym_bfd = objfile->obfd.get ();
- const char *name = bfd_get_filename (sym_bfd);
- unsigned int stabsize;
-
- /* Allocate struct to keep track of stab reading. */
- dbx_objfile_data_key.emplace (objfile);
-
- DBX_TEXT_ADDR (objfile) = textaddr;
- DBX_TEXT_SIZE (objfile) = textsize;
-
-#define COFF_STABS_SYMBOL_SIZE 12 /* XXX FIXME XXX */
- DBX_SYMBOL_SIZE (objfile) = COFF_STABS_SYMBOL_SIZE;
- DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
-
- if (stabstrsize > bfd_get_size (sym_bfd))
- error (_("ridiculous string table size: %d bytes"), stabstrsize);
- DBX_STRINGTAB (objfile) = (char *)
- obstack_alloc (&objfile->objfile_obstack, stabstrsize + 1);
- OBJSTAT (objfile, sz_strtab += stabstrsize + 1);
-
- /* Now read in the string table in one big gulp. */
-
- val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET);
- if (val < 0)
- perror_with_name (name);
- val = bfd_read (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd);
- if (val != stabstrsize)
- perror_with_name (name);
-
- stabsread_new_init ();
- free_header_files ();
- init_header_files ();
-
- processing_acc_compilation = 1;
-
- /* In a coff file, we've already installed the minimal symbols that came
- from the coff (non-stab) symbol table, so always act like an
- incremental load here. */
- scoped_restore save_symbuf_sections
- = make_scoped_restore (&symbuf_sections);
- if (stabsects.size () == 1)
- {
- stabsize = bfd_section_size (stabsects[0]);
- DBX_SYMCOUNT (objfile) = stabsize / DBX_SYMBOL_SIZE (objfile);
- DBX_SYMTAB_OFFSET (objfile) = stabsects[0]->filepos;
- }
- else
- {
- DBX_SYMCOUNT (objfile) = 0;
- for (asection *section : stabsects)
- {
- stabsize = bfd_section_size (section);
- DBX_SYMCOUNT (objfile) += stabsize / DBX_SYMBOL_SIZE (objfile);
- }
-
- DBX_SYMTAB_OFFSET (objfile) = stabsects[0]->filepos;
-
- sect_idx = 1;
- symbuf_sections = &stabsects;
- symbuf_left = bfd_section_size (stabsects[0]);
- symbuf_read = 0;
- }
-
- dbx_symfile_read (objfile, 0);
-}
-/* Scan and build partial symbols for an ELF symbol file.
- This ELF file has already been processed to get its minimal symbols.
-
- This routine is the equivalent of dbx_symfile_init and dbx_symfile_read
- rolled into one.
-
- OBJFILE is the object file we are reading symbols from.
- ADDR is the address relative to which the symbols are (e.g.
- the base address of the text segment).
- STABSECT is the BFD section information for the .stab section.
- STABSTROFFSET and STABSTRSIZE define the location in OBJFILE where the
- .stabstr section exists.
-
- This routine is mostly copied from dbx_symfile_init and dbx_symfile_read,
- adjusted for elf details. */
-
-void
-elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect,
- file_ptr stabstroffset, unsigned int stabstrsize)
-{
- int val;
- bfd *sym_bfd = objfile->obfd.get ();
- const char *name = bfd_get_filename (sym_bfd);
-
- stabsread_new_init ();
-
- /* Allocate struct to keep track of stab reading. */
- dbx_objfile_data_key.emplace (objfile);
-
- /* Find the first and last text address. dbx_symfile_read seems to
- want this. */
- find_text_range (sym_bfd, objfile);
-
-#define ELF_STABS_SYMBOL_SIZE 12 /* XXX FIXME XXX */
- DBX_SYMBOL_SIZE (objfile) = ELF_STABS_SYMBOL_SIZE;
- DBX_SYMCOUNT (objfile)
- = bfd_section_size (stabsect) / DBX_SYMBOL_SIZE (objfile);
- DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
- DBX_SYMTAB_OFFSET (objfile) = stabsect->filepos;
- DBX_STAB_SECTION (objfile) = stabsect;
-
- if (stabstrsize > bfd_get_size (sym_bfd))
- error (_("ridiculous string table size: %d bytes"), stabstrsize);
- DBX_STRINGTAB (objfile) = (char *)
- obstack_alloc (&objfile->objfile_obstack, stabstrsize + 1);
- OBJSTAT (objfile, sz_strtab += stabstrsize + 1);
-
- /* Now read in the string table in one big gulp. */
-
- val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET);
- if (val < 0)
- perror_with_name (name);
- val = bfd_read (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd);
- if (val != stabstrsize)
- perror_with_name (name);
-
- stabsread_new_init ();
- free_header_files ();
- init_header_files ();
-
- processing_acc_compilation = 1;
-
- symbuf_read = 0;
- symbuf_left = bfd_section_size (stabsect);
-
- scoped_restore restore_stabs_data = make_scoped_restore (&stabs_data);
- gdb::unique_xmalloc_ptr<gdb_byte> data_holder;
-
- stabs_data = symfile_relocate_debug_section (objfile, stabsect, NULL);
- if (stabs_data)
- data_holder.reset (stabs_data);
-
- /* In an elf file, we've already installed the minimal symbols that came
- from the elf (non-stab) symbol table, so always act like an
- incremental load here. dbx_symfile_read should not generate any new
- minimal symbols, since we will have already read the ELF dynamic symbol
- table and normal symbol entries won't be in the ".stab" section; but in
- case it does, it will install them itself. */
- dbx_symfile_read (objfile, 0);
-}
/* Scan and build partial symbols for a file with special sections for stabs
and stabstrings. The file has already been processed to get its minimal
@@ -3219,7 +332,7 @@ stabsect_build_psymtabs (struct objfile *objfile, char *stab_name,
/* Now, do an incremental load. */
- processing_acc_compilation = 1;
+ dbx_objfile_data_key.get (objfile)->ctx.processing_acc_compilation = 1;
dbx_symfile_read (objfile, 0);
}
diff --git a/gdb/dictionary.h b/gdb/dictionary.h
index 6f602f4..e09afb3 100644
--- a/gdb/dictionary.h
+++ b/gdb/dictionary.h
@@ -113,7 +113,7 @@ struct dict_iterator
struct mdict_iterator
{
- /* The multidictionary with whcih this iterator is associated. */
+ /* The multidictionary with which this iterator is associated. */
const struct multidictionary *mdict;
/* The iterator used to iterate through individual dictionaries. */
diff --git a/gdb/disasm-flags.h b/gdb/disasm-flags.h
index 4f71125..10cb95d 100644
--- a/gdb/disasm-flags.h
+++ b/gdb/disasm-flags.h
@@ -34,6 +34,7 @@ enum gdb_disassembly_flag : unsigned
DISASSEMBLY_SOURCE = (0x1 << 5),
DISASSEMBLY_SPECULATIVE = (0x1 << 6),
DISASSEMBLY_RAW_BYTES = (0x1 << 7),
+ DISASSEMBLY_OMIT_AUX_INSN = (0x1 << 8),
};
DEF_ENUM_FLAGS_TYPE (enum gdb_disassembly_flag, gdb_disassembly_flags);
diff --git a/gdb/disasm-selftests.c b/gdb/disasm-selftests.c
index 14b7fb3..dd849fb 100644
--- a/gdb/disasm-selftests.c
+++ b/gdb/disasm-selftests.c
@@ -165,7 +165,7 @@ get_test_insn (struct gdbarch *gdbarch, size_t *len)
kind = gdbarch_breakpoint_kind_from_pc (gdbarch, &pc);
insn = gdbarch_sw_breakpoint_from_kind (gdbarch, kind, &bplen);
}
- catch (...)
+ catch (const gdb_exception_error &)
{
continue;
}
diff --git a/gdb/disasm.c b/gdb/disasm.c
index 16736e5..541293a 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -197,7 +197,12 @@ gdb_disassembler_memory_reader::dis_asm_read_memory
(bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
struct disassemble_info *info) noexcept
{
- return target_read_code (memaddr, myaddr, len);
+ auto res = catch_exceptions<int, -1> ([&]
+ {
+ return target_read_code (memaddr, myaddr, len);
+ });
+
+ return res;
}
/* Wrapper of memory_error. */
@@ -894,7 +899,10 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch,
output includes the source specs for each line. */
if (sal.symtab != NULL)
{
- uiout->text (symtab_to_filename_for_display (sal.symtab));
+ auto filename = symtab_to_filename_for_display (sal.symtab);
+ uiout->message ("%ps",
+ styled_string (file_name_style.style (),
+ filename));
}
else
uiout->text ("unknown");
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 86cd420..554608d 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2742,7 +2742,7 @@ environment:
@end smallexample
This command is available when debugging locally on most targets, excluding
-@sc{djgpp}, Cygwin, MS Windows, and QNX Neutrino.
+@sc{djgpp}, Cygwin, and MS Windows.
@kindex set startup-with-shell
@anchor{set startup-with-shell}
@@ -4289,7 +4289,7 @@ includes changes in memory, registers, and even (within some limits)
system state. Effectively, it is like going back in time to the
moment when the checkpoint was saved.
-Thus, if you're stepping thru a program and you think you're
+Thus, if you're stepping through a program and you think you're
getting close to the point where things go wrong, you can save
a checkpoint. Then, if you accidentally go too far and miss
the critical statement, instead of having to restart your program
@@ -7077,33 +7077,6 @@ $1 = (void *) 0x7ffff7ff7000
Depending on target support, @code{$_siginfo} may also be writable.
-@cindex Intel MPX boundary violations
-@cindex boundary violations, Intel MPX
-On some targets, a @code{SIGSEGV} can be caused by a boundary
-violation, i.e., accessing an address outside of the allowed range.
-In those cases @value{GDBN} may displays additional information,
-depending on how @value{GDBN} has been told to handle the signal.
-With @code{handle stop SIGSEGV}, @value{GDBN} displays the violation
-kind: "Upper" or "Lower", the memory address accessed and the
-bounds, while with @code{handle nostop SIGSEGV} no additional
-information is displayed.
-
-The usual output of a segfault is:
-@smallexample
-Program received signal SIGSEGV, Segmentation fault
-0x0000000000400d7c in upper () at i386-mpx-sigsegv.c:68
-68 value = *(p + len);
-@end smallexample
-
-While a bound violation is presented as:
-@smallexample
-Program received signal SIGSEGV, Segmentation fault
-Upper bound violation while accessing address 0x7fffffffc3b3
-Bounds: [lower = 0x7fffffffc390, upper = 0x7fffffffc3a3]
-0x0000000000400d7c in upper () at i386-mpx-sigsegv.c:68
-68 value = *(p + len);
-@end smallexample
-
@node Thread Stops
@section Stopping and Starting Multi-thread Programs
@@ -7686,7 +7659,7 @@ the called function, stopping at the beginning of the @emph{last}
statement in the called function (typically a return statement).
Also, as with the @code{step} command, if non-debuggable functions are
-called, @code{reverse-step} will run thru them backward without stopping.
+called, @code{reverse-step} will run through them backward without stopping.
@kindex reverse-stepi
@kindex rsi @r{(@code{reverse-stepi})}
@@ -7784,6 +7757,9 @@ Moxie, PowerPC, PowerPC64, S/390, and x86 (i386/amd64) running
GNU/Linux. Process record and replay can be used both when native
debugging, and when remote debugging via @code{gdbserver}.
+When recording an inferior, @value{GDBN} may print auxiliary information
+during stepping commands and commands displaying the execution history.
+
For architecture environments that support process record and replay,
@value{GDBN} provides the following commands:
@@ -8113,6 +8089,16 @@ also need longer to process the branch trace data before it can be used.
Show the current setting of the requested ring buffer size for branch
tracing in Intel Processor Trace format.
+@item set record btrace pt event-tracing
+Enable or disable event tracing for branch tracing in Intel Processor
+Trace format. When enabled, events are recorded during execution as
+auxiliary information and will be printed during stepping commands and
+commands displaying the execution history. Changing this setting has no
+effect on an active recording. The default is off.
+
+@item show record btrace pt event-tracing
+Show the current setting of Intel Processor Trace event tracing.
+
@kindex info record
@item info record
Show various statistics about the recording depending on the recording
@@ -8199,6 +8185,9 @@ To better align the printed instructions when the trace contains
instructions from more than one function, the function name may be
omitted by specifying the @code{/f} modifier.
+Printing auxiliary information is enabled by default and can be
+omitted with the @code{/a} modifier.
+
Speculatively executed instructions are prefixed with @samp{?}. This
feature is not available for all recording formats.
@@ -8252,8 +8241,9 @@ that function, the source lines for this instruction sequence (if the
@code{/l} modifier is specified), and the instructions numbers that form
the sequence (if the @code{/i} modifier is specified). The function names
are indented to reflect the call stack depth if the @code{/c} modifier is
-specified. The @code{/l}, @code{/i}, and @code{/c} modifiers can be given
-together.
+specified. Printing auxiliary information is enabled by default and can be
+omitted with the @code{/a} modifier. The @code{/l}, @code{/i}, @code{/a},
+and @code{/c} modifiers can be given together.
@smallexample
(@value{GDBP}) @b{list 1, 10}
@@ -16238,6 +16228,9 @@ the data was saved, as well as the current trace frame you are examining.
Both @var{filename} and @var{dirname} must be on a filesystem accessible to
the host.
+The @var{filename} and @var{dirname} arguments supports escaping and
+quoting, see @ref{Filename Arguments,,Filenames As Command Arguments}.
+
@smallexample
(@value{GDBP}) target ctf ctf.ctf
(@value{GDBP}) tfind
@@ -18305,6 +18298,9 @@ All Modula-2 built-in procedures also return a result, described below.
@item ABS(@var{n})
Returns the absolute value of @var{n}.
+@item ADR(@var{n})
+Returns the memory address of @var{n}.
+
@item CAP(@var{c})
If @var{c} is a lower case letter, it returns its upper case
equivalent, otherwise it returns its argument.
@@ -20412,6 +20408,7 @@ libraries. When set to @code{off} no messages are printed.
Show whether messages will be printed when a @value{GDBN} command
entered from the keyboard causes symbol information to be loaded.
+@anchor{maint print symbols}
@kindex maint print symbols
@cindex symbol dump
@kindex maint print psymbols
@@ -21337,6 +21334,9 @@ Like @code{compile code}, but take the source code from @var{filename}.
@smallexample
compile file /home/user/example.c
@end smallexample
+
+The @var{filename} argument supports escaping and quoting, see
+@ref{Filename Arguments,,Filenames As Command Arguments}.
@end table
@table @code
@@ -21885,6 +21885,7 @@ Remove symbol table from file "/home/user/gdb/mylib.so"? (y or n) y
(@value{GDBP})
@end smallexample
+The @var{address} can be any expression which evaluates to an address.
@code{remove-symbol-file} does not repeat if you press @key{RET} after using it.
@@ -22011,7 +22012,7 @@ name and remembers it that way.
@cindex shared libraries
@anchor{Shared Libraries}
@value{GDBN} supports @sc{gnu}/Linux, MS-Windows, SunOS,
-Darwin/Mach-O, SVr4, IBM RS/6000 AIX, QNX Neutrino, FDPIC (FR-V), and
+Darwin/Mach-O, SVr4, IBM RS/6000 AIX, FDPIC (FR-V), and
DSBT (TIC6X) shared libraries.
On MS-Windows @value{GDBN} must be linked with the Expat library to support
@@ -22782,6 +22783,9 @@ the @option{-dwarf-5} option, it produces 2 files:
@file{@var{symbol-file}.debug_names} and
@file{@var{symbol-file}.debug_str}. The files are created in the
given @var{directory}.
+
+The @var{directory} argument supports escaping and quoting, see
+@ref{Filename Arguments,,Filenames As Command Arguments}.
@end table
Once you have created an index file you can merge it into your symbol
@@ -22861,6 +22865,19 @@ Print the number of cache hits and misses since the launch of @value{GDBN}.
@end table
+@subsection Building the index with GNU @command{gold}
+
+The GNU @command{gold} linker can write the index at link time into
+the resulting ELF file, by passing the @command{--gdb-index} flag to
+@command{gold}.
+
+This is especially helpful if you intend to build a program and immediately
+run it under @value{GDBN}. You may find that it is faster overall for
+the linker to write the index while it has the relevant information in
+memory anyways, rather than re-reloading the data from disk with
+@command{gdb-add-index}, or debugging the program without an index at
+all, especially for large programs.
+
@node Debug Names
@section Extensions to @samp{.debug_names}
@cindex index files
@@ -23152,11 +23169,17 @@ configuration):
An executable file. @samp{target exec @var{program}} is the same as
@samp{exec-file @var{program}}.
+The @var{program} argument supports escaping and quoting, see
+@ref{Filename Arguments,,Filenames As Command Arguments}.
+
@item target core @var{filename}
@cindex core dump file target
A core dump file. @samp{target core @var{filename}} is the same as
@samp{core-file @var{filename}}.
+The @var{filename} argument supports escaping and quoting, see
+@ref{Filename Arguments,,Filenames As Command Arguments}.
+
@item target remote @var{medium}
@cindex remote target
A remote system connected to @value{GDBN} via a serial line or network
@@ -24534,6 +24557,10 @@ future connections is shown. The available settings are:
@tab @code{vFile:fstat}
@tab Host I/O
+@item @code{hostio-stat-packet}
+@tab @code{vFile:stat}
+@tab Host I/O
+
@item @code{hostio-setfs-packet}
@tab @code{vFile:setfs}
@tab Host I/O
@@ -25203,16 +25230,6 @@ Show the file to which @code{procfs} API trace is written.
These commands enable and disable tracing of entries into and exits
from the @code{syscall} interface.
-@item info pidlist
-@kindex info pidlist
-@cindex process list, QNX Neutrino
-For QNX Neutrino only, this command displays the list of all the
-processes and all the threads within each process.
-
-@item info meminfo
-@kindex info meminfo
-@cindex mapinfo list, QNX Neutrino
-For QNX Neutrino only, this command displays the list of all mapinfos.
@end table
@node DJGPP Native
@@ -26775,91 +26792,6 @@ Show the current setting of the convention to return @code{struct}s
from functions.
@end table
-
-@subsubsection Intel @dfn{Memory Protection Extensions} (MPX).
-@cindex Intel Memory Protection Extensions (MPX).
-
-Memory Protection Extension (MPX) adds the bound registers @samp{BND0}
-@footnote{The register named with capital letters represent the architecture
-registers.} through @samp{BND3}. Bound registers store a pair of 64-bit values
-which are the lower bound and upper bound. Bounds are effective addresses or
-memory locations. The upper bounds are architecturally represented in 1's
-complement form. A bound having lower bound = 0, and upper bound = 0
-(1's complement of all bits set) will allow access to the entire address space.
-
-@samp{BND0} through @samp{BND3} are represented in @value{GDBN} as @samp{bnd0raw}
-through @samp{bnd3raw}. Pseudo registers @samp{bnd0} through @samp{bnd3}
-display the upper bound performing the complement of one operation on the
-upper bound value, i.e.@ when upper bound in @samp{bnd0raw} is 0 in the
-@value{GDBN} @samp{bnd0} it will be @code{0xfff@dots{}}. In this sense it
-can also be noted that the upper bounds are inclusive.
-
-As an example, assume that the register BND0 holds bounds for a pointer having
-access allowed for the range between 0x32 and 0x71. The values present on
-bnd0raw and bnd registers are presented as follows:
-
-@smallexample
- bnd0raw = @{0x32, 0xffffffff8e@}
- bnd0 = @{lbound = 0x32, ubound = 0x71@} : size 64
-@end smallexample
-
-This way the raw value can be accessed via bnd0raw@dots{}bnd3raw. Any
-change on bnd0@dots{}bnd3 or bnd0raw@dots{}bnd3raw is reflect on its
-counterpart. When the bnd0@dots{}bnd3 registers are displayed via
-Python, the display includes the memory size, in bits, accessible to
-the pointer.
-
-Bounds can also be stored in bounds tables, which are stored in
-application memory. These tables store bounds for pointers by specifying
-the bounds pointer's value along with its bounds. Evaluating and changing
-bounds located in bound tables is therefore interesting while investigating
-bugs on MPX context. @value{GDBN} provides commands for this purpose:
-
-@table @code
-@item show mpx bound @var{pointer}
-@kindex show mpx bound
-Display bounds of the given @var{pointer}.
-
-@item set mpx bound @var{pointer}, @var{lbound}, @var{ubound}
-@kindex set mpx bound
-Set the bounds of a pointer in the bound table.
-This command takes three parameters: @var{pointer} is the pointers
-whose bounds are to be changed, @var{lbound} and @var{ubound} are new values
-for lower and upper bounds respectively.
-@end table
-
-Both commands are deprecated and will be removed in future versions of
-@value{GDBN}. MPX itself was listed as removed by Intel in 2019.
-
-When you call an inferior function on an Intel MPX enabled program,
-GDB sets the inferior's bound registers to the init (disabled) state
-before calling the function. As a consequence, bounds checks for the
-pointer arguments passed to the function will always pass.
-
-This is necessary because when you call an inferior function, the
-program is usually in the middle of the execution of other function.
-Since at that point bound registers are in an arbitrary state, not
-clearing them would lead to random bound violations in the called
-function.
-
-You can still examine the influence of the bound registers on the
-execution of the called function by stopping the execution of the
-called function at its prologue, setting bound registers, and
-continuing the execution. For example:
-
-@smallexample
- $ break *upper
- Breakpoint 2 at 0x4009de: file i386-mpx-call.c, line 47.
- $ print upper (a, b, c, d, 1)
- Breakpoint 2, upper (a=0x0, b=0x6e0000005b, c=0x0, d=0x0, len=48)....
- $ print $bnd0
- @{lbound = 0x0, ubound = ffffffff@} : size -1
-@end smallexample
-
-At this last step the value of bnd0 can be changed for investigation of bound
-violations caused along the execution of the call. In order to know how to
-set the bound registers or bound table for the call consult the ABI.
-
@subsubsection x87 registers
@value{GDBN} provides access to the x87 state through the following registers:
@@ -27936,6 +27868,10 @@ if @value{GDBN} is using its builtin disassembler library for styling
(@pxref{style_disassembler_enabled,,@kbd{set style disassembler
enabled}}).
+@item line-number
+Control the styling of line numbers. By default, this style's
+intensity is dim.
+
@item variable
Control the styling of variable names. These are managed with the
@code{set style variable} family of commands. By default, this style's
@@ -29224,9 +29160,21 @@ files.
@cindex arguments, to user-defined commands
A @dfn{user-defined command} is a sequence of @value{GDBN} commands to
which you assign a new name as a command. This is done with the
-@code{define} command. User commands may accept an unlimited number of arguments
-separated by whitespace. Arguments are accessed within the user command
-via @code{$arg0@dots{}$argN}. A trivial example:
+@code{define} command.
+
+User commands may accept an unlimited number of arguments separated by
+whitespace. Arguments are accessed within the user command via
+@code{$arg0@dots{}$argN}. The arguments are text substitutions, so
+they may reference variables, use complex expressions, or even perform
+inferior functions calls. Note, however, that this textual
+substitution means that working with certain arguments is difficult.
+For example, there is no way for the user to pass an argument
+containing a space; and while stringifying an argument can be done
+using an expression like @code{"$arg1"}, this will fail if the
+argument contains a quote. For more complicated and robust commands,
+we recommend writing them in Python; see @ref{CLI Commands In Python}.
+
+A trivial example:
@smallexample
define adder
@@ -29243,9 +29191,7 @@ adder 1 2 3
@noindent
This defines the command @code{adder}, which prints the sum of
-its three arguments. Note the arguments are text substitutions, so they may
-reference variables, use complex expressions, or even perform inferior
-functions calls.
+its three arguments.
@cindex argument count in user-defined commands
@cindex how many arguments (user-defined commands)
@@ -39822,6 +39768,11 @@ corresponds to the @code{file} command. @xref{Files}.
If provided, this must be a boolean. When @samp{True}, @value{GDBN}
will set a temporary breakpoint at the program's main procedure, using
the same approach as the @code{start} command. @xref{Starting}.
+
+@item stopOnEntry
+If provided, this must be a boolean. When @samp{True}, @value{GDBN}
+will set a temporary breakpoint at the program's first instruction, using
+the same approach as the @code{starti} command. @xref{Starting}.
@end table
@value{GDBN} defines some parameters that can be passed to the
@@ -41430,7 +41381,8 @@ This command is useful for debugging the agent version of dynamic
printf (@pxref{Dynamic Printf}).
@kindex maint info breakpoints
-@item @anchor{maint info breakpoints}maint info breakpoints
+@anchor{maint info breakpoints}
+@item maint info breakpoints
Using the same format as @samp{info breakpoints}, display both the
breakpoints you've set explicitly, and those @value{GDBN} is using for
internal purposes. Internal breakpoints are shown with negative
@@ -41778,6 +41730,9 @@ target description being processed (either the default, or from
@var{file}) must only contain a single feature. The source file
produced is different in this case.
+The @var{file} argument supports escaping and quoting, see
+@ref{Filename Arguments,,Filenames As Command Arguments}.
+
@kindex maint print xml-tdesc
@item maint print xml-tdesc @r{[}@var{file}@r{]}
Print the target description (@pxref{Target Descriptions}) as an XML
@@ -41846,6 +41801,176 @@ frame-id for frame #0: @{stack=0x7fffffffac70,code=0x0000000000401106,!special@}
frame-id for frame #2: @{stack=0x7fffffffac90,code=0x000000000040111c,!special@}
@end smallexample
+@item maint info inline-frames
+@itemx maint info inline-frames @var{address}
+@cindex frames of inlined functions
+@kindex maint info inline-frames
+Print information about inlined frames which start at the current
+address, or @var{address} if specified.
+
+In order to allow the user to correctly step into inlined functions,
+@value{GDBN} needs to identify which inlined functions start at a
+particular address, and @value{GDBN} also needs to track which of
+these functions was last displayed to the user as the current frame.
+
+Imagine a situation where function @code{main} calls @code{foo}, which
+then calls @code{bar}, something like this:
+
+@smallexample
+@group
+int
+main ()
+@{
+ /* Some interesting code here... */
+
+ foo ();
+
+ /* More interesting code here... */
+@}
+
+void
+foo ()
+@{
+ bar ();
+@}
+
+void
+bar ()
+@{
+ /* Some interesting code here... */
+@}
+@end group
+@end smallexample
+
+As both @code{foo} and @code{bar} are inlined within @code{main} then
+there could be one address within @code{main} which is also the start
+of @code{foo} and also the start of @code{bar}. When the user stops
+at this address they will initially be told the inferior is in
+@code{main}, if the user does a @kbd{step} then @value{GDBN} doesn't
+actually step the inferior, instead the user is told the inferior
+entered @code{foo}. After the next @kbd{step} the user is told the
+inferior entered @code{bar}. The @kbd{maint info inline-frames}
+command can be used to view this internal @value{GDBN} state, like
+this:
+
+@smallexample
+@group
+(@value{GDBP}) step
+24 foo ();
+(@value{GDBP}) maintenance info inline-frames
+Cached inline state information for thread 1.
+program counter = 0x401137
+skipped frames = 2
+ bar
+ foo
+> main
+@end group
+@end smallexample
+
+Here the user is stopped in @code{main} at the call to @code{foo}. The
+inline-frames information shows that at this address @value{GDBN} has
+found the start of inlined functions @code{bar} and @code{foo}, but
+currently @value{GDBN} has skipped 2 frames and considers @code{main}
+to be the current frame, this is indicated with the @samp{>}.
+
+If the user performs a @kbd{step} to enter @code{foo} then the
+situation is updated:
+
+@smallexample
+@group
+(@value{GDBP}) step
+foo () at inline.c:14
+14 bar ();
+(@value{GDBP}) maintenance info inline-frames
+Cached inline state information for thread 1.
+program counter = 0x401137
+skipped frames = 1
+ bar
+> foo
+ main
+@end group
+@end smallexample
+
+Notice that the program counter value @code{0x401137} hasn't change,
+but now @value{GDBN} considers @code{foo} to be the current frame, and
+it is marked as such with the @samp{>}.
+
+Finally, the user performs another @kbd{step} to enter @code{bar}:
+
+@smallexample
+@group
+(@value{GDBP}) step
+bar () at inline.c:6
+6 ++global_counter;
+(@value{GDBP}) maintenance info inline-frames
+Cached inline state information for thread 1.
+program counter = 0x401137
+skipped frames = 0
+> bar
+ foo
+ main
+@end group
+@end smallexample
+
+@kindex maint info blocks
+@item maint info blocks
+@itemx maint info blocks @var{address}
+Print information about all blocks at @var{address}, or at the current
+@code{$pc} if @var{address} is not given.
+
+For information about what blocks are in @value{GDBN} see @ref{Blocks
+In Python}.
+
+Blocks are listed starting from the global block, then the static
+block, and then proceeding through progressively narrower scopes.
+
+Here is an example of the command's output:
+@smallexample
+@group
+(@value{GDBP}) maintenance info blocks
+Blocks at 0x401137:
+ from objfile: [(objfile *) 0x50507d0] /tmp/inline_func_demo
+
+[(block *) 0x504da90] 0x401106..0x40119a
+ entry pc: 0x401106
+ is global block
+ symbol count: 2
+ is contiguous
+@end group
+@group
+[(block *) 0x504d9f0] 0x401106..0x40119a
+ entry pc: 0x401106
+ is static block
+ symbol count: 1
+ is contiguous
+@end group
+@group
+[(block *) 0x504d9a0] 0x401106..0x40119a
+ entry pc: 0x401106
+ function: main
+ is contiguous
+@end group
+@group
+[(block *) 0x504d900] 0x401137..0x401166
+ entry pc: 0x401137
+ inline function: foo
+ symbol count: 1
+ is contiguous
+@end group
+@group
+[(block *) 0x504d860] 0x401137..0x401165
+ entry pc: 0x401137
+ inline function: bar
+ symbol count: 1
+ is contiguous
+@end group
+@end smallexample
+
+The command @kbd{maint info blocks} lists the symbol count for each
+block but doesn't print the symbols themselves. The symbol names can
+be found using @kbd{maint print symbols} (@pxref{maint print
+symbols}).
+
@kindex maint print registers
@kindex maint print raw-registers
@kindex maint print cooked-registers
@@ -41865,7 +41990,11 @@ including registers which aren't available on the target nor visible
to user; the command @code{maint print register-groups} includes the
groups that each register is a member of; and the command @code{maint
print remote-registers} includes the remote target's register numbers
-and offsets in the `G' packets.
+and offsets in the `G' packets, as well as an indication of which
+registers were included in the last stop reply packet received by
+@value{GDBN} (@pxref{Stop Reply Packets}). Please note that the list
+of registers included in a stop reply can change from one stop to the
+next.
These commands take an optional parameter, a file name to which to
write the information.
@@ -44795,6 +44924,16 @@ These are the currently defined stub features and their properties:
@tab @samp{-}
@tab Yes
+@item @samp{Qbtrace-conf:pt:ptwrite}
+@tab Yes
+@tab @samp{-}
+@tab Yes
+
+@item @samp{Qbtrace-conf:pt:event-tracing}
+@tab Yes
+@tab @samp{-}
+@tab Yes
+
@item @samp{QNonStop}
@tab No
@tab @samp{-}
@@ -45116,6 +45255,12 @@ The remote stub understands the @samp{Qbtrace-conf:bts:size} packet.
@item Qbtrace-conf:pt:size
The remote stub understands the @samp{Qbtrace-conf:pt:size} packet.
+@item Qbtrace-conf:pt:ptwrite
+The remote stub understands the @samp{Qbtrace-conf:pt:ptwrite} packet.
+
+@item Qbtrace-conf:pt:event-tracing
+The remote stub understands the @samp{Qbtrace-conf:pt:event-tracing} packet.
+
@item swbreak
The remote stub reports the @samp{swbreak} stop reason for memory
breakpoints.
@@ -45605,6 +45750,30 @@ Reply:
The ring buffer size has been set.
@end table
+@item Qbtrace-conf:pt:ptwrite=@var{(yes|no)}
+Indicate support for @code{PTWRITE} packets. This allows for backwards
+compatibility.
+
+Reply:
+@table @samp
+@item OK
+The ptwrite config parameter has been set.
+@item E.errtext
+A badly formed request or an error was encountered.
+@end table
+
+@item Qbtrace-conf:pt:event-tracing=@var{(yes|no)}
+Indicate support for event-tracing packets. This allows for backwards
+compatibility.
+
+Reply:
+@table @samp
+@item OK
+The event-tracing config parameter has been set.
+@item E.errtext
+A badly formed request or an error was encountered.
+@end table
+
@end table
@node Architecture-Specific Protocol Details
@@ -46326,6 +46495,13 @@ 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}.
+@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
+returned binary attachment is as described in @ref{struct stat}.
+
@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.
@@ -48231,14 +48407,16 @@ branch trace configuration discovery. @xref{Expat}.
The formal DTD for the branch trace configuration format is given below:
@smallexample
-<!ELEMENT btrace-conf (bts?, pt?)>
-<!ATTLIST btrace-conf version CDATA #FIXED "1.0">
+<!ELEMENT btrace-conf (bts?, pt?)>
+<!ATTLIST btrace-conf version CDATA #FIXED "1.0">
<!ELEMENT bts EMPTY>
-<!ATTLIST bts size CDATA #IMPLIED>
+<!ATTLIST bts size CDATA #IMPLIED>
<!ELEMENT pt EMPTY>
-<!ATTLIST pt size CDATA #IMPLIED>
+<!ATTLIST pt size CDATA #IMPLIED>
+<!ATTLIST pt ptwrite (yes | no) #IMPLIED>
+<!ATTLIST pt event-tracing (yes | no) #IMPLIED>
@end smallexample
@include agentexpr.texi
@@ -49476,16 +49654,6 @@ describe the upper 128 bits of @sc{ymm} registers:
@samp{ymm0h} through @samp{ymm15h} for amd64
@end itemize
-The @samp{org.gnu.gdb.i386.mpx} is an optional feature representing Intel
-Memory Protection Extension (MPX). It should describe the following registers:
-
-@itemize @minus
-@item
-@samp{bnd0raw} through @samp{bnd3raw} for i386 and amd64.
-@item
-@samp{bndcfgu} and @samp{bndstatus} for i386 and amd64.
-@end itemize
-
The @samp{org.gnu.gdb.i386.linux} feature is optional. It should
describe a single register, @samp{orig_eax}.
@@ -51011,7 +51179,7 @@ Richard M. Stallman and Roland H. Pesch, July 1991.
@format
@c man begin SYNOPSIS gcore
-gcore [-a] [-o @var{prefix}] @var{pid1} [@var{pid2}...@var{pidN}]
+gcore [-a] [-o @var{prefix}] [-d @var{directory}] @var{pid1} [@var{pid2}...@var{pidN}]
@c man end
@end format
@@ -51039,6 +51207,10 @@ when composing the file names of the core dumps. The file name is
composed as @file{@var{prefix}.@var{pid}}, where @var{pid} is the
process ID of the running program being analyzed by @command{gcore}.
If not specified, @var{prefix} defaults to @var{gcore}.
+
+@item -d @var{directory}
+Use @var{directory} as the data directory when invoking @value{GDBN} for running
+the gcore command. This argument is optional.
@end table
@c man end
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 86ccc14..22f0e6c 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -4314,6 +4314,11 @@ A @code{gdb.Record} object has the following methods:
Move the replay position to the given @var{instruction}.
@end defun
+@defun Record.clear ()
+Clear the trace data of the current recording. This forces re-decoding of the
+trace for successive commands.
+@end defun
+
The common @code{gdb.Instruction} class that recording method specific
instruction objects inherit from, has the following attributes:
@@ -4369,6 +4374,19 @@ the current recording method.
A human readable string with the reason for the gap.
@end defvar
+Some @value{GDBN} features write auxiliary information into the execution
+history. This information is represented by a @code{gdb.RecordAuxiliary} object
+in the instruction list. It has the following attributes:
+
+@defvar RecordAuxiliary.@var{number}
+An integer identifying this auxiliary. @var{number} corresponds to the numbers
+seen in @code{record instruction-history} (@pxref{Process Record and Replay}).
+@end defvar
+
+@defvar RecordAuxiliary.data
+A string representation of the auxiliary data.
+@end defvar
+
A @code{gdb.RecordFunctionSegment} object has the following attributes:
@defvar RecordFunctionSegment.number
@@ -7309,7 +7327,7 @@ contains the full contents of the window. This is similar to calling
@end defun
The factory function that you supply should return an object
-conforming to the TUI window protocol. These are the method that can
+conforming to the TUI window protocol. These are the methods that can
be called on this object, which is referred to below as the ``window
object''. The methods documented below are optional; if the object
does not implement one of these methods, @value{GDBN} will not attempt
@@ -8206,6 +8224,7 @@ registering objfile-specific pretty-printers and frame-filters.
* gdb.printing:: Building and registering pretty-printers.
* gdb.types:: Utilities for working with types.
* gdb.prompt:: Utilities for prompt value substitution.
+* gdb.ptwrite:: Utilities for PTWRITE filter registration.
@end menu
@node gdb.printing
@@ -8396,3 +8415,153 @@ substitute_prompt ("frame: \f, args: \p@{print frame-arguments@}")
"frame: main, args: scalars"
@end smallexample
@end table
+
+@node gdb.ptwrite
+@subsubsection gdb.ptwrite
+@cindex gdb.ptwrite
+
+This module provides additional functionality for recording programs that
+make use of the @code{PTWRITE} instruction. @code{PTWRITE} is a x86
+instruction that allows to write values into the Intel Processor Trace
+(@pxref{Process Record and Replay}).
+The @value{NGCC} intrinsics for it are:
+@smallexample
+void _ptwrite32 (unsigned int a)
+void _ptwrite64 (unsigned __int64 a)
+@end smallexample
+
+If an inferior uses the instruction, @value{GDBN} by default inserts the
+raw payload value as auxiliary information into the execution history.
+Auxiliary information is by default printed during
+@code{record instruction-history}, @code{record function-call-history},
+and all stepping commands, and is accessible in Python as a
+@code{RecordAuxiliary} object (@pxref{Recordings In Python}).
+
+@exdent Sample program:
+@smallexample
+@group
+#include <immintrin.h>
+
+void
+ptwrite64 (unsigned long long value)
+@{
+ _ptwrite64 (value);
+@}
+@end group
+
+@group
+int
+main (void)
+@{
+ ptwrite64 (0x42);
+ return 0; /* break here. */
+@}
+@end group
+@end smallexample
+
+
+@exdent @value{GDBN} output after recording the sample program in pt format:
+@smallexample
+@group
+(gdb) record instruction-history 12,14
+12 0x0040074c <ptwrite64+16>: ptwrite %rbx
+13 [0x42]
+14 0x00400751 <ptwrite64+21>: mov -0x8(%rbp),%rbx
+(gdb) record function-call-history
+1 main
+2 ptwrite64
+ [0x42]
+3 main
+@end group
+@end smallexample
+
+The @code{gdb.ptwrite} module allows customizing the default output of
+@code{PTWRITE} auxiliary information. A custom Python function can be
+registered as the @code{PTWRITE} filter function. This function will be
+called with the @code{PTWRITE} payload and PC as arguments during trace
+decoding. The function can return a string, which will be printed by
+@value{GDBN} during the aforementioned commands, or @code{None}, resulting
+in no output. To register such a filter function, the user needs to
+provide a filter factory function, which returns a new filter function
+object to be called by @value{GDBN}.
+
+@findex gdb.ptwrite.register_filter_factory
+@defun register_filter_factory (filter_factory)
+Used to register the @code{PTWRITE} filter factory. This filter factory can
+be any callable object that accepts one argument, the current thread as
+a @code{gdb.InferiorThread}.
+It can return None or a callable. This callable is the @code{PTWRITE} filter
+function for the specified thread. If @code{None} is returned by the factory
+function, the default auxiliary information will be printed.
+@end defun
+
+@findex gdb.ptwrite.get_filter
+@defun get_filter ()
+Return the currently active @code{PTWRITE} filter function.
+@end defun
+
+An example:
+
+@smallexample
+@group
+(gdb) python-interactive
+>>> class my_filter():
+... def __init__(self):
+... self.var = 0
+... def __call__(self, payload, ip):
+... self.var += 1
+... return f"counter: @{self.var@}, ip: @{ip:#x@}"
+...
+>>> def my_filter_factory(thread):
+... if thread.global_num == 1:
+... return my_filter()
+... else:
+... return None
+...
+>>> import gdb.ptwrite
+>>> gdb.ptwrite.register_filter_factory(my_filter_factory)
+>>>
+@end group
+
+@group
+(gdb) record function-call-history 59,64
+59 pthread_create@@GLIBC_2.2.5
+60 job()
+61 task(void*)
+62 ptwrite64(unsigned long)
+ [counter: 1, ip: 0x401156]
+63 task(void*)
+64 ptwrite32(unsigned int)
+ [counter: 2, ip: 0x40116c]
+@end group
+
+@group
+(gdb) info threads
+* 1 Thread 0x7ffff7fd8740 (LWP 25796) "ptw_threads" task ()
+ at bin/ptwrite/ptw_threads.c:45
+ 2 Thread 0x7ffff6eb8700 (LWP 25797) "ptw_threads" task ()
+ at bin/ptwrite/ptw_threads.c:45
+@end group
+
+@group
+(gdb) thread 2
+[Switching to thread 2 (Thread 0x7ffff6eb8700 (LWP 25797))]
+#0 task (arg=0x0) at ptwrite_threads.c:45
+45 return NULL;
+@end group
+
+@group
+(gdb) record function-call-history 10,14
+10 start_thread
+11 task(void*)
+12 ptwrite64(unsigned long)
+ [0x42]
+13 task(void*)
+14 ptwrite32(unsigned int)
+ [0x43]
+@end group
+@end smallexample
+
+This @value{GDBN} feature is dependent on hardware and operating system
+support and requires the Intel Processor Trace decoder library in version
+2.0.0 or newer.
diff --git a/gdb/dtrace-probe.c b/gdb/dtrace-probe.c
index 0f4e164..ac1b1c5 100644
--- a/gdb/dtrace-probe.c
+++ b/gdb/dtrace-probe.c
@@ -493,7 +493,7 @@ dtrace_process_dof_probe (struct objfile *objfile,
{
}
- if (expr != NULL && expr->first_opcode () == OP_TYPE)
+ if (expr != NULL && expr->type_p ())
type = expr->evaluate_type ()->type ();
args.emplace_back (type, std::move (type_str), std::move (expr));
diff --git a/gdb/dwarf2/abbrev-cache.c b/gdb/dwarf2/abbrev-cache.c
index b87206c..7e1ff9c 100644
--- a/gdb/dwarf2/abbrev-cache.c
+++ b/gdb/dwarf2/abbrev-cache.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 "dwarf2/read.h"
#include "dwarf2/abbrev-cache.h"
/* Hash function for an abbrev table. */
diff --git a/gdb/dwarf2/abbrev.c b/gdb/dwarf2/abbrev.c
index 359a009..c30db1e 100644
--- a/gdb/dwarf2/abbrev.c
+++ b/gdb/dwarf2/abbrev.c
@@ -24,9 +24,9 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include "dwarf2/read.h"
#include "dwarf2/abbrev.h"
#include "dwarf2/leb.h"
+#include "dwarf2/section.h"
#include "bfd.h"
/* Hash function for an abbrev. */
@@ -276,7 +276,8 @@ abbrev_table::read (struct dwarf2_section_info *section,
}
else if ((cur_abbrev->tag == DW_TAG_structure_type
|| cur_abbrev->tag == DW_TAG_class_type
- || cur_abbrev->tag == DW_TAG_union_type)
+ || cur_abbrev->tag == DW_TAG_union_type
+ || cur_abbrev->tag == DW_TAG_namespace)
&& cur_abbrev->has_children)
{
/* We have to record this as interesting, regardless of how
diff --git a/gdb/dwarf2/abbrev.h b/gdb/dwarf2/abbrev.h
index 1fb90fd..7eda951 100644
--- a/gdb/dwarf2/abbrev.h
+++ b/gdb/dwarf2/abbrev.h
@@ -27,7 +27,11 @@
#ifndef GDB_DWARF2_ABBREV_H
#define GDB_DWARF2_ABBREV_H
+#include "dwarf2.h"
+#include "gdbsupport/gdb-hashtab.h"
+#include "gdbsupport/gdb_obstack.h"
#include "hashtab.h"
+#include "types.h"
struct attr_abbrev
{
diff --git a/gdb/dwarf2/ada-imported.c b/gdb/dwarf2/ada-imported.c
index 9ec0d51..eabbab1 100644
--- a/gdb/dwarf2/ada-imported.c
+++ b/gdb/dwarf2/ada-imported.c
@@ -20,6 +20,7 @@
#include "symtab.h"
#include "value.h"
#include "dwarf2/loc.h"
+#include "objfiles.h"
/* Helper to get the imported symbol's real name. */
static const char *
@@ -34,7 +35,8 @@ static struct value *
ada_imported_read_variable (struct symbol *symbol, const frame_info_ptr &frame)
{
const char *name = get_imported_name (symbol);
- bound_minimal_symbol minsym = lookup_minimal_symbol_linkage (name, false);
+ bound_minimal_symbol minsym
+ = lookup_minimal_symbol_linkage (symbol->objfile ()->pspace (), name, false);
if (minsym.minsym == nullptr)
error (_("could not find imported name %s"), name);
return value_at (symbol->type (), minsym.value_address ());
diff --git a/gdb/dwarf2/attribute.h b/gdb/dwarf2/attribute.h
index 3b971ad..115d006 100644
--- a/gdb/dwarf2/attribute.h
+++ b/gdb/dwarf2/attribute.h
@@ -29,7 +29,6 @@
#include "dwarf2.h"
#include "dwarf2/types.h"
-#include <optional>
/* Blocks are a bunch of untyped bytes. */
struct dwarf_block
diff --git a/gdb/dwarf2/comp-unit-head.c b/gdb/dwarf2/comp-unit-head.c
index a26a6c0..1413971 100644
--- a/gdb/dwarf2/comp-unit-head.c
+++ b/gdb/dwarf2/comp-unit-head.c
@@ -29,6 +29,7 @@
#include "dwarf2/read.h"
#include "dwarf2/section.h"
#include "dwarf2/stringify.h"
+#include "dwarf2/error.h"
/* See comp-unit-head.h. */
@@ -49,8 +50,9 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
info_ptr += bytes_read;
unsigned version = read_2_bytes (abfd, info_ptr);
if (version < 2 || version > 5)
- error (_("Dwarf Error: wrong version in compilation unit header "
- "(is %d, should be 2, 3, 4 or 5) [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "wrong version in compilation unit header "
+ "(is %d, should be 2, 3, 4 or 5) [in module %s]"),
version, filename);
cu_header->version = version;
info_ptr += 2;
@@ -78,8 +80,9 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
case DW_UT_skeleton:
case DW_UT_split_compile:
if (section_kind != rcuh_kind::COMPILE)
- error (_("Dwarf Error: wrong unit_type in compilation unit header "
- "(is %s, should be %s) [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "wrong unit_type in compilation unit header "
+ "(is %s, should be %s) [in module %s]"),
dwarf_unit_type_name (cu_header->unit_type),
dwarf_unit_type_name (DW_UT_type), filename);
break;
@@ -88,10 +91,11 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
section_kind = rcuh_kind::TYPE;
break;
default:
- error (_("Dwarf Error: wrong unit_type in compilation unit header "
- "(is %#04x, should be one of: %s, %s, %s, %s or %s) "
- "[in module %s]"), cu_header->unit_type,
- dwarf_unit_type_name (DW_UT_compile),
+ error (_(DWARF_ERROR_PREFIX
+ "wrong unit_type in compilation unit header "
+ "(is %#04x, should be one of: %s, %s, %s, %s or %s) "
+ "[in module %s]"),
+ cu_header->unit_type, dwarf_unit_type_name (DW_UT_compile),
dwarf_unit_type_name (DW_UT_skeleton),
dwarf_unit_type_name (DW_UT_split_compile),
dwarf_unit_type_name (DW_UT_type),
@@ -131,9 +135,10 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
info_ptr += bytes_read;
cu_header->type_cu_offset_in_tu = (cu_offset) type_offset;
if (to_underlying (cu_header->type_cu_offset_in_tu) != type_offset)
- error (_("Dwarf Error: Too big type_offset in compilation unit "
- "header (is %s) [in module %s]"), plongest (type_offset),
- filename);
+ error (_(DWARF_ERROR_PREFIX
+ "Too big type_offset in compilation unit "
+ "header (is %s) [in module %s]"),
+ plongest (type_offset), filename);
}
return info_ptr;
@@ -153,8 +158,9 @@ error_check_comp_unit_head (dwarf2_per_objfile *per_objfile,
if (to_underlying (header->abbrev_sect_off)
>= abbrev_section->get_size (per_objfile->objfile))
- error (_("Dwarf Error: bad offset (%s) in compilation unit header "
- "(offset %s + 6) [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad offset (%s) in compilation unit header "
+ "(offset %s + 6) [in module %s]"),
sect_offset_str (header->abbrev_sect_off),
sect_offset_str (header->sect_off),
filename);
@@ -163,8 +169,9 @@ error_check_comp_unit_head (dwarf2_per_objfile *per_objfile,
avoid potential 32-bit overflow. */
if (((ULONGEST) header->sect_off + header->get_length_with_initial ())
> section->size)
- error (_("Dwarf Error: bad length (0x%x) in compilation unit header "
- "(offset %s + 0) [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad length (0x%x) in compilation unit header "
+ "(offset %s + 0) [in module %s]"),
header->get_length_without_initial (), sect_offset_str (header->sect_off),
filename);
}
diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c
index c9e46af..4073c92 100644
--- a/gdb/dwarf2/cooked-index.c
+++ b/gdb/dwarf2/cooked-index.c
@@ -24,6 +24,7 @@
#include "cp-support.h"
#include "c-lang.h"
#include "ada-lang.h"
+#include "dwarf2/tag.h"
#include "event-top.h"
#include "exceptions.h"
#include "split-name.h"
@@ -32,6 +33,8 @@
#include <algorithm>
#include "gdbsupport/gdb-safe-ctype.h"
#include "gdbsupport/selftest.h"
+#include "gdbsupport/task-group.h"
+#include "gdbsupport/thread-pool.h"
#include <chrono>
#include <unordered_set>
#include "cli/cli-cmds.h"
@@ -285,7 +288,7 @@ cooked_index_shard::add (sect_offset die_offset, enum dwarf_tag tag,
/* See cooked-index.h. */
-gdb::unique_xmalloc_ptr<char>
+void
cooked_index_shard::handle_gnat_encoded_entry (cooked_index_entry *entry,
htab_t gnat_entries)
{
@@ -295,7 +298,10 @@ cooked_index_shard::handle_gnat_encoded_entry (cooked_index_entry *entry,
source charset does not affect the indexer directly. */
std::string canonical = ada_decode (entry->name, false, false, false);
if (canonical.empty ())
- return {};
+ {
+ entry->canonical = entry->name;
+ return;
+ }
std::vector<std::string_view> names = split_name (canonical.c_str (),
split_style::DOT_STYLE);
std::string_view tail = names.back ();
@@ -326,7 +332,9 @@ cooked_index_shard::handle_gnat_encoded_entry (cooked_index_entry *entry,
}
entry->set_parent (parent);
- return make_unique_xstrndup (tail.data (), tail.length ());
+ auto new_canon = make_unique_xstrndup (tail.data (), tail.length ());
+ entry->canonical = new_canon.get ();
+ m_names.push_back (std::move (new_canon));
}
/* See cooked-index.h. */
@@ -386,17 +394,7 @@ cooked_index_shard::finalize (const parent_map_map *parent_maps)
if ((entry->flags & IS_LINKAGE) != 0)
entry->canonical = entry->name;
else if (entry->lang == language_ada)
- {
- gdb::unique_xmalloc_ptr<char> canon_name
- = handle_gnat_encoded_entry (entry, gnat_entries.get ());
- if (canon_name == nullptr)
- entry->canonical = entry->name;
- else
- {
- entry->canonical = canon_name.get ();
- m_names.push_back (std::move (canon_name));
- }
- }
+ handle_gnat_encoded_entry (entry, gnat_entries.get ());
else if (entry->lang == language_cplus || entry->lang == language_c)
{
void **slot = htab_find_slot (seen_names.get (), entry,
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
index efd03e6..0873e7d 100644
--- a/gdb/dwarf2/cooked-index.h
+++ b/gdb/dwarf2/cooked-index.h
@@ -24,22 +24,16 @@
#include "dwarf2/types.h"
#include "symtab.h"
#include "hashtab.h"
-#include "dwarf2/index-common.h"
-#include <string_view>
#include "quick-symbol.h"
#include "gdbsupport/gdb_obstack.h"
#include "addrmap.h"
#include "gdbsupport/iterator-range.h"
-#include "gdbsupport/thread-pool.h"
#include "dwarf2/mapped-index.h"
#include "dwarf2/read.h"
-#include "dwarf2/tag.h"
#include "dwarf2/abbrev-cache.h"
#include "dwarf2/parent-map.h"
#include "gdbsupport/range-chain.h"
-#include "gdbsupport/task-group.h"
#include "complaints.h"
-#include "run-on-main-thread.h"
#if CXX_STD_THREAD
#include <mutex>
@@ -233,8 +227,7 @@ struct cooked_index_entry : public allocate_on_obstack<cooked_index_entry>
linkage name -- two entries are created for DIEs which have both
attributes. */
const char *name;
- /* The canonical name. For C++ names, this may differ from NAME.
- In all other cases, this is equal to NAME. */
+ /* The canonical name. This may be equal to NAME. */
const char *canonical = nullptr;
/* The DWARF tag. */
enum dwarf_tag tag;
@@ -251,9 +244,10 @@ private:
/* A helper method for full_name. Emits the full scope of this
object, followed by the separator, to STORAGE. If this entry has
- a parent, its write_scope method is called first. */
+ a parent, its write_scope method is called first. FOR_MAIN is
+ true when computing the name of 'main'; see full_name. */
void write_scope (struct obstack *storage, const char *sep,
- bool for_name) const;
+ bool for_main) const;
/* The parent entry. This is NULL for top-level entries.
Otherwise, it points to the parent entry, such as a namespace or
@@ -344,9 +338,8 @@ private:
/* GNAT only emits mangled ("encoded") names in the DWARF, and does
not emit the module structure. However, we need this structure
to do lookups. This function recreates that structure for an
- existing entry. It returns the base name (last element) of the
- full decoded name. */
- gdb::unique_xmalloc_ptr<char> handle_gnat_encoded_entry
+ existing entry, modifying ENTRY as appropriate. */
+ void handle_gnat_encoded_entry
(cooked_index_entry *entry, htab_t gnat_entries);
/* Finalize the index. This should be called a single time, when
@@ -785,10 +778,12 @@ struct cooked_index_functions : public dwarf2_base_index_functions
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
block_search_flags search_flags,
- domain_search_flags domain) override;
+ domain_search_flags domain,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher)
+ override;
struct compunit_symtab *find_pc_sect_compunit_symtab
- (struct objfile *objfile, struct bound_minimal_symbol msymbol,
+ (struct objfile *objfile, bound_minimal_symbol msymbol,
CORE_ADDR pc, struct obj_section *section, int warn_if_readin) override
{
wait (objfile, true);
diff --git a/gdb/dwarf2/dwz.h b/gdb/dwarf2/dwz.h
index 5e6c1fa..3ec3af1 100644
--- a/gdb/dwarf2/dwz.h
+++ b/gdb/dwarf2/dwz.h
@@ -25,6 +25,7 @@
#include "dwarf2/section.h"
struct dwarf2_per_bfd;
+struct dwarf2_per_objfile;
/* This represents a '.dwz' file. */
diff --git a/gdb/config/nm-nto.h b/gdb/dwarf2/error.h
index 5a002df..f8861f2 100644
--- a/gdb/config/nm-nto.h
+++ b/gdb/dwarf2/error.h
@@ -1,8 +1,6 @@
-/* Native support for QNX Neutrino version 6.
+/* DWARF error handling utilities.
- Copyright (C) 2003-2024 Free Software Foundation, Inc.
-
- This code was donated by QNX Software Systems Ltd.
+ Copyright (C) 2024 Free Software Foundation, Inc.
This file is part of GDB.
@@ -19,11 +17,13 @@
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 CONFIG_NM_NTO_H
-#define CONFIG_NM_NTO_H
+#ifndef GDB_DWARF2_ERROR_H
+#define GDB_DWARF2_ERROR_H
+
+/* Canonical capitalization of "dwarf error". */
+#define DWARF_ERROR "DWARF Error"
-/* Setup the valid realtime signal range. */
-#define REALTIME_LO 41
-#define REALTIME_HI 56
+/* Prefix to be used in dwarf errors. */
+#define DWARF_ERROR_PREFIX DWARF_ERROR ": "
-#endif /* CONFIG_NM_NTO_H */
+#endif /* GDB_DWARF2_ERROR_H */
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index cb80dbf..5ad17ea 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -1593,8 +1593,9 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
uoffset)));
result_val = value_from_ulongest (address_type, result);
break;
+ case DW_OP_constx:
case DW_OP_GNU_const_index:
- ensure_have_per_cu (this->m_per_cu, "DW_OP_GNU_const_index");
+ ensure_have_per_cu (this->m_per_cu, "DW_OP_constx");
op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
result = (ULONGEST) dwarf2_read_addr_index (this->m_per_cu,
diff --git a/gdb/dwarf2/frame-tailcall.c b/gdb/dwarf2/frame-tailcall.c
index c489068..6ecf8a0 100644
--- a/gdb/dwarf2/frame-tailcall.c
+++ b/gdb/dwarf2/frame-tailcall.c
@@ -22,9 +22,7 @@
#include "dwarf2/frame-tailcall.h"
#include "dwarf2/loc.h"
#include "frame-unwind.h"
-#include "block.h"
#include "hashtab.h"
-#include "gdbtypes.h"
#include "regcache.h"
#include "value.h"
#include "dwarf2/frame.h"
diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c
index 9ebf3ac..841d2d4 100644
--- a/gdb/dwarf2/frame.c
+++ b/gdb/dwarf2/frame.c
@@ -25,7 +25,6 @@
#include "frame.h"
#include "frame-base.h"
#include "frame-unwind.h"
-#include "gdbcore.h"
#include "gdbtypes.h"
#include "symtab.h"
#include "objfiles.h"
@@ -37,7 +36,6 @@
#include "dwarf2/frame.h"
#include "dwarf2/read.h"
#include "dwarf2/public.h"
-#include "ax.h"
#include "dwarf2/loc.h"
#include "dwarf2/frame-tailcall.h"
#include "gdbsupport/gdb_binary_search.h"
@@ -913,7 +911,7 @@ dwarf2_frame_cache (const frame_info_ptr &this_frame, void **this_cache)
its return address. As a result the return address will
point at some random instruction, and the CFI for that
instruction is probably worthless to us. GCC's unwinder solves
- this problem by substracting 1 from the return address to get an
+ this problem by subtracting 1 from the return address to get an
address in the middle of a presumed call instruction (or the
instruction in the associated delay slot). This should only be
done for "normal" frames and not for resume-type frames (signal
@@ -1075,7 +1073,7 @@ incomplete CFI data; unspecified registers (e.g., %s) at %s"),
ULONGEST retaddr_column = fs.retaddr_column;
/* It seems rather bizarre to specify an "empty" column as
- the return adress column. However, this is exactly
+ the return address column. However, this is exactly
what GCC does on some targets. It turns out that GCC
assumes that the return address can be found in the
register corresponding to the return address column.
diff --git a/gdb/dwarf2/index-cache.c b/gdb/dwarf2/index-cache.c
index c11b016..a04d5d6 100644
--- a/gdb/dwarf2/index-cache.c
+++ b/gdb/dwarf2/index-cache.c
@@ -28,8 +28,6 @@
#include "dwarf2/index-write.h"
#include "dwarf2/read.h"
#include "dwarf2/dwz.h"
-#include "objfiles.h"
-#include "gdbsupport/selftest.h"
#include <string>
#include <stdlib.h>
#include "run-on-main-thread.h"
diff --git a/gdb/dwarf2/index-cache.h b/gdb/dwarf2/index-cache.h
index 95f217e..08a2d56 100644
--- a/gdb/dwarf2/index-cache.h
+++ b/gdb/dwarf2/index-cache.h
@@ -20,9 +20,7 @@
#ifndef DWARF_INDEX_CACHE_H
#define DWARF_INDEX_CACHE_H
-#include "dwarf2/index-common.h"
#include "gdbsupport/array-view.h"
-#include "symfile.h"
class dwarf2_per_bfd;
class index_cache;
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
index 2a50e3b..c01e274 100644
--- a/gdb/dwarf2/index-write.c
+++ b/gdb/dwarf2/index-write.c
@@ -28,7 +28,6 @@
#include "gdbsupport/gdb_unlinker.h"
#include "gdbsupport/pathstuff.h"
#include "gdbsupport/scoped_fd.h"
-#include "complaints.h"
#include "dwarf2/index-common.h"
#include "dwarf2/cooked-index.h"
#include "dwarf2.h"
@@ -44,9 +43,7 @@
#include <algorithm>
#include <cmath>
-#include <forward_list>
#include <map>
-#include <set>
#include <unordered_map>
#include <unordered_set>
@@ -1621,8 +1618,8 @@ gdb_save_index_cmd_completer (struct cmd_list_element *ignore,
(tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp))
return;
- word = advance_to_filename_complete_word_point (tracker, text);
- filename_completer (ignore, tracker, text, word);
+ word = advance_to_filename_maybe_quoted_complete_word_point (tracker, text);
+ filename_maybe_quoted_completer (ignore, tracker, text, word);
}
/* Implementation of the `save gdb-index' command.
@@ -1639,10 +1636,10 @@ save_gdb_index_command (const char *args, int from_tty)
gdb::option::process_options
(&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group);
- if (args == nullptr || *args == '\0')
+ std::string directory = extract_single_filename_arg (args);
+ if (directory.empty ())
error (_("usage: save gdb-index [-dwarf-5] DIRECTORY"));
- std::string directory (gdb_tilde_expand (args));
dw_index_kind index_kind
= (opts.dwarf_5 ? dw_index_kind::DEBUG_NAMES : dw_index_kind::GDB_INDEX);
diff --git a/gdb/dwarf2/line-header.h b/gdb/dwarf2/line-header.h
index c068dff..7da5972 100644
--- a/gdb/dwarf2/line-header.h
+++ b/gdb/dwarf2/line-header.h
@@ -20,6 +20,10 @@
#ifndef DWARF2_LINE_HEADER_H
#define DWARF2_LINE_HEADER_H
+#include "dwarf2/types.h"
+
+struct dwarf2_per_objfile;
+
/* dir_index is 1-based in DWARF 4 and before, and is 0-based in DWARF 5 and
later. */
typedef int dir_index;
diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c
index 5fea668..d515386 100644
--- a/gdb/dwarf2/loc.c
+++ b/gdb/dwarf2/loc.c
@@ -41,7 +41,6 @@
#include "dwarf2/frame.h"
#include "dwarf2/leb.h"
#include "compile/compile.h"
-#include "gdbsupport/selftest.h"
#include <algorithm>
#include <vector>
#include <unordered_set>
@@ -667,9 +666,8 @@ call_site_target::iterate_over_addresses (gdbarch *call_site_gdbarch,
dwarf_block = m_loc.dwarf_block;
if (dwarf_block == NULL)
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol_by_pc (call_site->pc () - 1);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol_by_pc (call_site->pc () - 1);
throw_error (NO_ENTRY_VALUE_ERROR,
_("DW_AT_call_target is not specified at %s in %s"),
paddress (call_site_gdbarch, call_site->pc ()),
@@ -679,9 +677,8 @@ call_site_target::iterate_over_addresses (gdbarch *call_site_gdbarch,
}
if (caller_frame == NULL)
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol_by_pc (call_site->pc () - 1);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol_by_pc (call_site->pc () - 1);
throw_error (NO_ENTRY_VALUE_ERROR,
_("DW_AT_call_target DWARF block resolving "
"requires known frame which is currently not "
@@ -708,12 +705,12 @@ call_site_target::iterate_over_addresses (gdbarch *call_site_gdbarch,
case call_site_target::PHYSNAME:
{
const char *physname;
- struct bound_minimal_symbol msym;
physname = m_loc.physname;
/* Handle both the mangled and demangled PHYSNAME. */
- msym = lookup_minimal_symbol (physname, NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, physname);
if (msym.minsym == NULL)
{
msym = lookup_minimal_symbol_by_pc (call_site->pc () - 1);
@@ -782,7 +779,7 @@ func_addr_to_tail_call_list (struct gdbarch *gdbarch, CORE_ADDR addr)
via its tail calls (incl. transitively). Throw NO_ENTRY_VALUE_ERROR if it
can call itself via tail calls.
- If a funtion can tail call itself its entry value based parameters are
+ If a function can tail call itself its entry value based parameters are
unreliable. There is no verification whether the value of some/all
parameters is unchanged through the self tail call, we expect if there is
a self tail call all the parameters can be modified. */
@@ -820,9 +817,8 @@ func_verify_no_selftailcall (struct gdbarch *gdbarch, CORE_ADDR verify_addr)
{
if (target_addr == verify_addr)
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol_by_pc (verify_addr);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol_by_pc (verify_addr);
throw_error (NO_ENTRY_VALUE_ERROR,
_("DW_OP_entry_value resolving has found "
"function \"%s\" at %s can call itself via tail "
@@ -846,7 +842,7 @@ static void
tailcall_dump (struct gdbarch *gdbarch, const struct call_site *call_site)
{
CORE_ADDR addr = call_site->pc ();
- struct bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (addr - 1);
+ bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (addr - 1);
gdb_printf (gdb_stdlog, " %s(%s)", paddress (gdbarch, addr),
(msym.minsym == NULL ? "???"
@@ -1064,10 +1060,10 @@ call_site_find_chain_1 (struct gdbarch *gdbarch, CORE_ADDR caller_pc,
if (retval == NULL)
{
- struct bound_minimal_symbol msym_caller, msym_callee;
-
- msym_caller = lookup_minimal_symbol_by_pc (caller_pc);
- msym_callee = lookup_minimal_symbol_by_pc (callee_pc);
+ bound_minimal_symbol msym_caller
+ = lookup_minimal_symbol_by_pc (caller_pc);
+ bound_minimal_symbol msym_callee
+ = lookup_minimal_symbol_by_pc (callee_pc);
throw_error (NO_ENTRY_VALUE_ERROR,
_("There are no unambiguously determinable intermediate "
"callers or callees between caller function \"%s\" at %s "
@@ -1165,8 +1161,7 @@ dwarf_expr_reg_to_entry_parameter (const frame_info_ptr &initial_frame,
caller_frame = get_prev_frame (frame);
if (gdbarch != frame_unwind_arch (frame))
{
- struct bound_minimal_symbol msym
- = lookup_minimal_symbol_by_pc (func_addr);
+ bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (func_addr);
struct gdbarch *caller_gdbarch = frame_unwind_arch (frame);
throw_error (NO_ENTRY_VALUE_ERROR,
@@ -1181,8 +1176,7 @@ dwarf_expr_reg_to_entry_parameter (const frame_info_ptr &initial_frame,
if (caller_frame == NULL)
{
- struct bound_minimal_symbol msym
- = lookup_minimal_symbol_by_pc (func_addr);
+ bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (func_addr);
throw_error (NO_ENTRY_VALUE_ERROR, _("DW_OP_entry_value resolving "
"requires caller of %s (%s)"),
@@ -1973,6 +1967,7 @@ dwarf2_get_symbol_read_needs (gdb::array_view<const gdb_byte> expr,
case DW_OP_GNU_reinterpret:
case DW_OP_addrx:
case DW_OP_GNU_addr_index:
+ case DW_OP_constx:
case DW_OP_GNU_const_index:
case DW_OP_constu:
case DW_OP_plus_uconst:
@@ -2253,7 +2248,7 @@ dwarf2_get_symbol_read_needs (gdb::array_view<const gdb_byte> expr,
/* A helper function that throws an unimplemented error mentioning a
given DWARF operator. */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
unimplemented (unsigned int op)
{
const char *name = get_DW_OP_name (op);
@@ -3271,10 +3266,13 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
/* With -gsplit-dwarf a TLS variable can also look like this:
DW_AT_location : 3 byte block: fc 4 e0
(DW_OP_GNU_const_index: 4;
- DW_OP_GNU_push_tls_address) */
+ DW_OP_GNU_push_tls_address) |
+ 3 byte block a2 4 e0
+ (DW_OP_constx: 4;
+ DW_OP_form_tls_address) */
else if (data + 3 <= end
&& data + 1 + (leb128_size = skip_leb128 (data + 1, end)) < end
- && data[0] == DW_OP_GNU_const_index
+ && (data[0] == DW_OP_constx || data[0] == DW_OP_GNU_const_index)
&& leb128_size > 0
&& (data[1 + leb128_size] == DW_OP_GNU_push_tls_address
|| data[1 + leb128_size] == DW_OP_form_tls_address)
@@ -3681,6 +3679,7 @@ disassemble_dwarf_expression (struct ui_file *stream,
gdb_printf (stream, " 0x%s", phex_nz (ul, addr_size));
break;
+ case DW_OP_constx:
case DW_OP_GNU_const_index:
data = safe_read_uleb128 (data, end, &ul);
ul = (uint64_t) dwarf2_read_addr_index (per_cu, per_objfile, ul);
diff --git a/gdb/dwarf2/macro.c b/gdb/dwarf2/macro.c
index bc781c2..5371acf 100644
--- a/gdb/dwarf2/macro.c
+++ b/gdb/dwarf2/macro.c
@@ -160,9 +160,7 @@ parse_macro_definition (struct macro_source_file *file, int line,
/* It's a function-like macro. */
gdb_assert (*p == '(');
std::string name (body, p - body);
- int argc = 0;
- int argv_size = 1;
- char **argv = XNEWVEC (char *, argv_size);
+ std::vector<std::string> argv;
p++;
@@ -178,18 +176,12 @@ parse_macro_definition (struct macro_source_file *file, int line,
p++;
if (! *p || p == arg_start)
- dwarf2_macro_malformed_definition_complaint (body);
- else
{
- /* Make sure argv has room for the new argument. */
- if (argc >= argv_size)
- {
- argv_size *= 2;
- argv = XRESIZEVEC (char *, argv, argv_size);
- }
-
- argv[argc++] = savestring (arg_start, p - arg_start);
+ dwarf2_macro_malformed_definition_complaint (body);
+ return;
}
+ else
+ argv.emplace_back (arg_start, p);
p = consume_improper_spaces (p, body);
@@ -208,16 +200,12 @@ parse_macro_definition (struct macro_source_file *file, int line,
if (*p == ' ')
/* Perfectly formed definition, no complaints. */
- macro_define_function (file, line, name.c_str (),
- argc, (const char **) argv,
- p + 1);
+ macro_define_function (file, line, name.c_str (), argv, p + 1);
else if (*p == '\0')
{
/* Complain, but do define it. */
dwarf2_macro_malformed_definition_complaint (body);
- macro_define_function (file, line, name.c_str (),
- argc, (const char **) argv,
- p);
+ macro_define_function (file, line, name.c_str (), argv, p);
}
else
/* Just complain. */
@@ -226,11 +214,6 @@ parse_macro_definition (struct macro_source_file *file, int line,
else
/* Just complain. */
dwarf2_macro_malformed_definition_complaint (body);
-
- for (int i = 0; i < argc; i++)
- xfree (argv[i]);
-
- xfree (argv);
}
/* Skip some bytes from BYTES according to the form given in FORM.
diff --git a/gdb/dwarf2/macro.h b/gdb/dwarf2/macro.h
index 586f5d5..7ef2134 100644
--- a/gdb/dwarf2/macro.h
+++ b/gdb/dwarf2/macro.h
@@ -21,6 +21,8 @@
#define GDB_DWARF2_MACRO_H
struct buildsym_compunit;
+struct dwarf2_per_objfile;
+struct dwarf2_section_info;
extern void dwarf_decode_macros (dwarf2_per_objfile *per_objfile,
buildsym_compunit *builder,
diff --git a/gdb/dwarf2/mapped-index.h b/gdb/dwarf2/mapped-index.h
index b4f6483..e7dd8e9 100644
--- a/gdb/dwarf2/mapped-index.h
+++ b/gdb/dwarf2/mapped-index.h
@@ -20,7 +20,9 @@
#ifndef GDB_DWARF2_MAPPED_INDEX_H
#define GDB_DWARF2_MAPPED_INDEX_H
+#include "dwarf2/index-common.h"
#include "language.h"
+#include "quick-symbol.h"
/* 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
diff --git a/gdb/dwarf2/parent-map.h b/gdb/dwarf2/parent-map.h
index f070d50..6cff548 100644
--- a/gdb/dwarf2/parent-map.h
+++ b/gdb/dwarf2/parent-map.h
@@ -20,7 +20,9 @@
#ifndef GDB_DWARF2_PARENT_MAP_H
#define GDB_DWARF2_PARENT_MAP_H
-#include <algorithm>
+#include "addrmap.h"
+#include "dwarf2/types.h"
+#include "gdbsupport/gdb_obstack.h"
class cooked_index_entry;
@@ -30,9 +32,31 @@ class cooked_index_entry;
The generated DWARF can sometimes have the declaration for a method
in a class (or perhaps namespace) scope, with the definition
appearing outside this scope... just one of the many bad things
- about DWARF. In order to handle this situation, we defer certain
- entries until the end of scanning, at which point we'll know the
- containing context of all the DIEs that we might have scanned. */
+ about DWARF.
+
+ For example, a program like this:
+
+ struct X { int method (); };
+ int X::method () { return 23; }
+
+ ... ends up with DWARF like:
+
+ <1><2e>: Abbrev Number: 2 (DW_TAG_structure_type)
+ <2f> DW_AT_name : X
+ ...
+ <2><39>: Abbrev Number: 3 (DW_TAG_subprogram)
+ <3a> DW_AT_external : 1
+ <3a> DW_AT_name : (indirect string, offset: 0xf): method
+ ...
+ <1><66>: Abbrev Number: 8 (DW_TAG_subprogram)
+ <67> DW_AT_specification: <0x39>
+
+ Here, the name of DIE 0x66 can't be determined without knowing the
+ parent of DIE 0x39.
+
+ In order to handle this situation, we defer certain entries until
+ the end of scanning, at which point we'll know the containing
+ context of all the DIEs that we might have scanned. */
class parent_map
{
public:
@@ -80,6 +104,9 @@ public:
return new (obstack) addrmap_fixed (obstack, &m_map);
}
+ /* Dump a human-readable form of this map. */
+ void dump () const;
+
private:
/* An addrmap that maps from section offsets to cooked_index_entry *. */
@@ -97,7 +124,8 @@ public:
DISABLE_COPY_AND_ASSIGN (parent_map_map);
- /* Add a parent_map to this map. */
+ /* Add a parent_map to this map. Note that a copy of MAP is made --
+ modifications to MAP after this call will have no effect. */
void add_map (const parent_map &map)
{
m_maps.push_back (map.to_fixed (&m_storage));
@@ -116,6 +144,9 @@ public:
return nullptr;
}
+ /* Dump a human-readable form of this collection of parent_maps. */
+ void dump () const;
+
private:
/* Storage for the convert maps. */
diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c
index 8cd665c..701cdec 100644
--- a/gdb/dwarf2/read-gdb-index.c
+++ b/gdb/dwarf2/read-gdb-index.c
@@ -158,7 +158,9 @@ struct dwarf2_gdb_index : public dwarf2_base_index_functions
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
block_search_flags search_flags,
- domain_search_flags domain) override;
+ domain_search_flags domain,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher)
+ override;
};
/* This dumps minimal information about the index.
@@ -187,7 +189,8 @@ dw2_expand_marked_cus
gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
block_search_flags search_flags,
- domain_search_flags kind)
+ domain_search_flags kind,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher)
{
offset_type vec_len, vec_idx;
bool global_seen = false;
@@ -268,7 +271,7 @@ dw2_expand_marked_cus
dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (cu_index);
if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
- expansion_notify))
+ expansion_notify, lang_matcher))
return false;
}
@@ -283,7 +286,8 @@ dwarf2_gdb_index::expand_symtabs_matching
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
block_search_flags search_flags,
- domain_search_flags domain)
+ domain_search_flags domain,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher)
{
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
@@ -300,7 +304,8 @@ dwarf2_gdb_index::expand_symtabs_matching
if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
file_matcher,
- expansion_notify))
+ expansion_notify,
+ lang_matcher))
return false;
}
return true;
@@ -316,10 +321,11 @@ dwarf2_gdb_index::expand_symtabs_matching
[&] (offset_type idx)
{
if (!dw2_expand_marked_cus (per_objfile, idx, file_matcher,
- expansion_notify, search_flags, domain))
+ expansion_notify, search_flags, domain,
+ lang_matcher))
return false;
return true;
- }, per_objfile);
+ }, per_objfile, lang_matcher);
return result;
}
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 71237d0..ea31d8d 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -48,6 +48,7 @@
#include "bfd.h"
#include "elf-bfd.h"
#include "event-top.h"
+#include "gdbsupport/task-group.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "objfiles.h"
@@ -70,7 +71,6 @@
#include "go-lang.h"
#include "valprint.h"
#include "gdbcore.h"
-#include "gdb/gdb-index.h"
#include "gdb_bfd.h"
#include "f-lang.h"
#include "source.h"
@@ -92,10 +92,11 @@
#include <unordered_set>
#include "dwarf2/abbrev-cache.h"
#include "cooked-index.h"
-#include "split-name.h"
#include "gdbsupport/thread-pool.h"
#include "run-on-main-thread.h"
#include "dwarf2/parent-map.h"
+#include "dwarf2/error.h"
+#include <variant>
/* When == 1, print basic high level tracing messages.
When > 1, be more verbose.
@@ -863,9 +864,10 @@ static struct type *read_type_die_1 (struct die_info *, struct dwarf2_cu *);
static const char *determine_prefix (struct die_info *die, struct dwarf2_cu *);
-static char *typename_concat (struct obstack *obs, const char *prefix,
- const char *suffix, int physname,
- struct dwarf2_cu *cu);
+static gdb::unique_xmalloc_ptr<char> typename_concat (const char *prefix,
+ const char *suffix,
+ int physname,
+ struct dwarf2_cu *cu);
static void read_file_scope (struct die_info *, struct dwarf2_cu *);
@@ -1422,12 +1424,11 @@ dwarf2_per_bfd::locate_sections (bfd *abfd, asection *sectp,
if ((aflag & SEC_HAS_CONTENTS) == 0)
{
}
- else if (elf_section_data (sectp)->this_hdr.sh_size
- > bfd_get_file_size (abfd))
+ else if (bfd_section_size_insane (abfd, sectp))
{
- bfd_size_type size = elf_section_data (sectp)->this_hdr.sh_size;
- warning (_("Discarding section %s which has a section size (%s"
- ") larger than the file size [in module %s]"),
+ 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_get_filename (abfd));
}
@@ -1644,7 +1645,9 @@ struct readnow_functions : public dwarf2_base_index_functions
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
block_search_flags search_flags,
- domain_search_flags domain) override
+ domain_search_flags domain,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher)
+ override
{
return true;
}
@@ -2296,7 +2299,8 @@ dw2_expand_symtabs_matching_symbol
const lookup_name_info &lookup_name_in,
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<bool (offset_type)> match_callback,
- dwarf2_per_objfile *per_objfile)
+ dwarf2_per_objfile *per_objfile,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher)
{
lookup_name_info lookup_name_without_params
= lookup_name_in.make_ignore_params ();
@@ -2332,6 +2336,8 @@ dw2_expand_symtabs_matching_symbol
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
@@ -2489,7 +2495,7 @@ check_match (const char *file, int line,
if (expected_str == NULL || strcmp (expected_str, matched_name) != 0)
mismatch (expected_str, matched_name);
return true;
- }, per_objfile);
+ }, per_objfile, nullptr);
const char *expected_str
= expected_it == expected_end ? NULL : *expected_it++;
@@ -2850,19 +2856,29 @@ dw2_expand_symtabs_matching_one
(dwarf2_per_cu_data *per_cu,
dwarf2_per_objfile *per_objfile,
gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
- gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify)
+ gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher)
{
- if (file_matcher == NULL || per_cu->mark)
+ if (file_matcher != nullptr && !per_cu->mark)
+ return true;
+
+ if (lang_matcher != nullptr)
{
- bool symtab_was_null = !per_objfile->symtab_set_p (per_cu);
+ /* Try to skip CUs with non-matching language. */
+ per_cu->ensure_lang (per_objfile);
+ if (!per_cu->maybe_multi_language ()
+ && !lang_matcher (per_cu->lang ()))
+ return true;
+ }
- compunit_symtab *symtab
- = dw2_instantiate_symtab (per_cu, per_objfile, false);
- gdb_assert (symtab != nullptr);
+ 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 (expansion_notify != NULL && symtab_was_null)
- return expansion_notify (symtab);
- }
return true;
}
@@ -2997,7 +3013,7 @@ recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust,
struct compunit_symtab *
dwarf2_base_index_functions::find_pc_sect_compunit_symtab
(struct objfile *objfile,
- struct bound_minimal_symbol msymbol,
+ bound_minimal_symbol msymbol,
CORE_ADDR pc,
struct obj_section *section,
int warn_if_readin)
@@ -3811,8 +3827,9 @@ read_cutu_die_from_dwo (dwarf2_cu *cu,
/* This is not an assert because it can be caused by bad debug info. */
if (sig_type->signature != cu->header.signature)
{
- error (_("Dwarf Error: signature mismatch %s vs %s while reading"
- " TU at offset %s [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "signature mismatch %s vs %s while reading TU at offset %s"
+ " [in module %s]"),
hex_string (sig_type->signature),
hex_string (cu->header.signature),
sect_offset_str (dwo_unit->sect_off),
@@ -3909,7 +3926,8 @@ lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die, const char *dwo_name)
std::optional<ULONGEST> signature = lookup_dwo_id (cu, comp_unit_die);
if (!signature.has_value ())
- error (_("Dwarf Error: missing dwo_id for dwo_name %s"
+ error (_(DWARF_ERROR_PREFIX
+ "missing dwo_id for dwo_name %s"
" [in module %s]"),
dwo_name, bfd_get_filename (per_cu->per_bfd->obfd));
@@ -4432,6 +4450,50 @@ cooked_index_storage::eq_cutu_reader (const void *a, const void *b)
return ra->cu->per_cu->index == *rb;
}
+/* Dump MAP as parent_map. */
+
+static void
+dump_parent_map (const struct addrmap *map)
+{
+ auto_obstack temp_storage;
+
+ auto annotate_cooked_index_entry
+ = [&] (struct ui_file *outfile, const void *value)
+ {
+ const cooked_index_entry *parent_entry
+ = (const cooked_index_entry *)value;
+ if (parent_entry == nullptr)
+ return;
+
+ gdb_printf (outfile, " (0x%" PRIx64 ": %s)",
+ to_underlying (parent_entry->die_offset),
+ parent_entry->full_name (&temp_storage, false));
+ };
+
+ addrmap_dump (const_cast<addrmap *> (map), gdb_stdlog, nullptr,
+ annotate_cooked_index_entry);
+}
+
+/* See parent-map.h. */
+
+void
+parent_map::dump () const
+{
+ dump_parent_map (&m_map);
+}
+
+/* See parent-map.h. */
+
+void
+parent_map_map::dump () const
+{
+ for (const auto &iter : m_maps)
+ {
+ gdb_printf (gdb_stdlog, "map start:\n");
+ dump_parent_map (iter);
+ }
+}
+
/* An instance of this is created to index a CU. */
class cooked_indexer
@@ -4469,7 +4531,7 @@ private:
bool is_dwz,
bool for_scanning);
- /* Index DIEs in the READER starting at INFO_PTR. PARENT_ENTRY is
+ /* Index DIEs in the READER starting at INFO_PTR. PARENT is
the entry for the enclosing scope (nullptr at top level). FULLY
is true when a full scan must be done -- in some languages,
function scopes must be fully explored in order to find nested
@@ -4477,7 +4539,8 @@ private:
reading stopped. */
const gdb_byte *index_dies (cutu_reader *reader,
const gdb_byte *info_ptr,
- const cooked_index_entry *parent_entry,
+ std::variant<const cooked_index_entry *,
+ parent_map::addr_type> parent,
bool fully);
/* Scan the attributes for a given DIE and update the out
@@ -4507,7 +4570,8 @@ private:
m_die_range_map and then calling index_dies. */
const gdb_byte *recurse (cutu_reader *reader,
const gdb_byte *info_ptr,
- const cooked_index_entry *parent_entry,
+ std::variant<const cooked_index_entry *,
+ parent_map::addr_type> parent_entry,
bool fully);
/* The storage object, where the results are kept. */
@@ -4532,28 +4596,35 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu,
dwarf2_per_objfile *per_objfile,
cooked_index_storage *storage)
{
- cutu_reader reader (this_cu, per_objfile, nullptr, nullptr, false,
- storage->get_abbrev_cache ());
+ cutu_reader *reader = storage->get_reader (this_cu);
+ if (reader == nullptr)
+ {
+ cutu_reader new_reader (this_cu, per_objfile, nullptr, nullptr, false,
+ storage->get_abbrev_cache ());
- if (reader.comp_unit_die == nullptr)
- return;
+ if (new_reader.comp_unit_die == nullptr || new_reader.dummy_p)
+ return;
- if (reader.dummy_p)
- {
- /* Nothing. */
+ std::unique_ptr<cutu_reader> copy
+ (new cutu_reader (std::move (new_reader)));
+ reader = storage->preserve (std::move (copy));
}
- else if (this_cu->is_debug_types)
- build_type_psymtabs_reader (&reader, storage);
- else if (reader.comp_unit_die->tag != DW_TAG_partial_unit)
+
+ if (reader->comp_unit_die == nullptr || reader->dummy_p)
+ return;
+
+ if (this_cu->is_debug_types)
+ build_type_psymtabs_reader (reader, storage);
+ else if (reader->comp_unit_die->tag != DW_TAG_partial_unit)
{
bool nope = false;
if (this_cu->scanned.compare_exchange_strong (nope, true))
{
- prepare_one_comp_unit (reader.cu, reader.comp_unit_die,
+ prepare_one_comp_unit (reader->cu, reader->comp_unit_die,
language_minimal);
gdb_assert (storage != nullptr);
- cooked_indexer indexer (storage, this_cu, reader.cu->lang ());
- indexer.make_index (&reader);
+ cooked_indexer indexer (storage, this_cu, reader->cu->lang ());
+ indexer.make_index (reader);
}
}
}
@@ -4817,6 +4888,11 @@ private:
{
if (dwarf_read_debug > 0)
print_tu_stats (m_per_objfile);
+ if (dwarf_read_debug > 1)
+ {
+ dwarf_read_debug_printf_v ("Final m_all_parents_map:");
+ m_all_parents_map.dump ();
+ }
}
/* After the last DWARF-reading task has finished, this function
@@ -5075,7 +5151,8 @@ create_all_units (dwarf2_per_objfile *per_objfile)
per_objfile->per_bfd->all_units.clear ();
/* See enhancement PR symtab/30838. */
- error (_("Dwarf Error: .debug_types section not supported in dwz file"));
+ error (_(DWARF_ERROR_PREFIX
+ ".debug_types section not supported in dwz file"));
}
}
@@ -5117,8 +5194,9 @@ peek_die_abbrev (const die_reader_specs &reader,
= reader.abbrev_table->lookup_abbrev (abbrev_number);
if (!abbrev)
{
- error (_("Dwarf Error: Could not find abbrev number %d in %s"
- " at offset %s [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "Could not find abbrev number %d in %s at offset %s"
+ " [in module %s]"),
abbrev_number, cu->per_cu->is_debug_types ? "TU" : "CU",
sect_offset_str (cu->header.sect_off), bfd_get_filename (abfd));
}
@@ -5302,8 +5380,8 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
goto skip_attribute;
default:
- error (_("Dwarf Error: Cannot handle %s "
- "in DWARF reader [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "Cannot handle %s in DWARF reader [in module %s]"),
dwarf_form_name (form),
bfd_get_filename (abfd));
}
@@ -6158,7 +6236,8 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language)
case DW_TAG_type_unit:
break;
default:
- error (_("Dwarf Error: unexpected tag '%s' at offset %s [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "unexpected tag '%s' at offset %s [in module %s]"),
dwarf_tag_name (cu->dies->tag),
sect_offset_str (cu->per_cu->sect_off),
objfile_name (per_objfile->objfile));
@@ -6322,8 +6401,9 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
/* For now we don't handle imported units in type units. */
if (cu->per_cu->is_debug_types)
{
- error (_("Dwarf Error: DW_TAG_imported_unit is not"
- " supported in type units [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "DW_TAG_imported_unit is not supported in type units"
+ " [in module %s]"),
objfile_name (cu->per_objfile->objfile));
}
@@ -6673,7 +6753,7 @@ dwarf2_compute_name (const char *name,
if (*prefix != '\0')
{
gdb::unique_xmalloc_ptr<char> prefixed_name
- (typename_concat (NULL, prefix, name, physname, cu));
+ = typename_concat (prefix, name, physname, cu);
buf.puts (prefixed_name.get ());
}
@@ -7779,8 +7859,9 @@ create_dwo_cu_reader (const struct die_reader_specs *reader,
std::optional<ULONGEST> signature = lookup_dwo_id (cu, comp_unit_die);
if (!signature.has_value ())
{
- complaint (_("Dwarf Error: debug entry at offset %s is missing"
- " its dwo_id [in module %s]"),
+ complaint (_(DWARF_ERROR_PREFIX
+ "debug entry at offset %s is missing its dwo_id"
+ " [in module %s]"),
sect_offset_str (sect_off), dwo_file->dwo_name.c_str ());
return;
}
@@ -8057,14 +8138,15 @@ create_dwp_hash_table (dwarf2_per_objfile *per_objfile,
if (version != 1 && version != 2 && version != 5)
{
- error (_("Dwarf Error: unsupported DWP file version (%s)"
- " [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "unsupported DWP file version (%s) [in module %s]"),
pulongest (version), dwp_file->name);
}
if (nr_slots != (nr_slots & -nr_slots))
{
- error (_("Dwarf Error: number of slots in DWP hash table (%s)"
- " is not power of 2 [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "number of slots in DWP hash table (%s) is not power of 2"
+ " [in module %s]"),
pulongest (nr_slots), dwp_file->name);
}
@@ -8111,14 +8193,16 @@ create_dwp_hash_table (dwarf2_per_objfile *per_objfile,
if (nr_columns < 2)
{
- error (_("Dwarf Error: bad DWP hash table, too few columns"
- " in section table [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, too few columns in section table"
+ " [in module %s]"),
dwp_file->name);
}
if (nr_columns > MAX_NR_V2_DWO_SECTIONS)
{
- error (_("Dwarf Error: bad DWP hash table, too many columns"
- " in section table [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, too many columns in section table"
+ " [in module %s]"),
dwp_file->name);
}
memset (ids, 255, sizeof_ids);
@@ -8129,13 +8213,15 @@ create_dwp_hash_table (dwarf2_per_objfile *per_objfile,
if (id < DW_SECT_MIN || id > DW_SECT_MAX)
{
- error (_("Dwarf Error: bad DWP hash table, bad section id %d"
- " in section table [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, bad section id %d in section table"
+ " [in module %s]"),
id, dwp_file->name);
}
if (ids_seen[id] != -1)
{
- error (_("Dwarf Error: bad DWP hash table, duplicate section"
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, duplicate section"
" id %d in section table [in module %s]"),
id, dwp_file->name);
}
@@ -8147,15 +8233,17 @@ create_dwp_hash_table (dwarf2_per_objfile *per_objfile,
+ (ids_seen[DW_SECT_TYPES] != -1))
!= 1)
{
- error (_("Dwarf Error: bad DWP hash table, missing/duplicate"
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, missing/duplicate"
" DWO info/types section [in module %s]"),
dwp_file->name);
}
/* Must have an abbrev section. */
if (ids_seen[DW_SECT_ABBREV] == -1)
{
- error (_("Dwarf Error: bad DWP hash table, missing DWO abbrev"
- " section [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, missing DWO abbrev section"
+ " [in module %s]"),
dwp_file->name);
}
htab->section_pool.v2.offsets = ids_ptr + sizeof (uint32_t) * nr_columns;
@@ -8166,8 +8254,8 @@ create_dwp_hash_table (dwarf2_per_objfile *per_objfile,
* nr_units * nr_columns))
> index_end)
{
- error (_("Dwarf Error: DWP index section is corrupt (too small)"
- " [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "DWP index section is corrupt (too small) [in module %s]"),
dwp_file->name);
}
}
@@ -8181,14 +8269,16 @@ create_dwp_hash_table (dwarf2_per_objfile *per_objfile,
if (nr_columns < 2)
{
- error (_("Dwarf Error: bad DWP hash table, too few columns"
- " in section table [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, too few columns in section table"
+ " [in module %s]"),
dwp_file->name);
}
if (nr_columns > MAX_NR_V5_DWO_SECTIONS)
{
- error (_("Dwarf Error: bad DWP hash table, too many columns"
- " in section table [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, too many columns in section table"
+ " [in module %s]"),
dwp_file->name);
}
memset (ids, 255, sizeof_ids);
@@ -8199,13 +8289,15 @@ create_dwp_hash_table (dwarf2_per_objfile *per_objfile,
if (id < DW_SECT_MIN || id > DW_SECT_MAX_V5)
{
- error (_("Dwarf Error: bad DWP hash table, bad section id %d"
- " in section table [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, bad section id %d in section table"
+ " [in module %s]"),
id, dwp_file->name);
}
if (ids_seen[id] != -1)
{
- error (_("Dwarf Error: bad DWP hash table, duplicate section"
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, duplicate section"
" id %d in section table [in module %s]"),
id, dwp_file->name);
}
@@ -8215,15 +8307,17 @@ create_dwp_hash_table (dwarf2_per_objfile *per_objfile,
/* Must have seen an info section. */
if (ids_seen[DW_SECT_INFO_V5] == -1)
{
- error (_("Dwarf Error: bad DWP hash table, missing/duplicate"
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, missing/duplicate"
" DWO info/types section [in module %s]"),
dwp_file->name);
}
/* Must have an abbrev section. */
if (ids_seen[DW_SECT_ABBREV_V5] == -1)
{
- error (_("Dwarf Error: bad DWP hash table, missing DWO abbrev"
- " section [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, missing DWO abbrev section"
+ " [in module %s]"),
dwp_file->name);
}
htab->section_pool.v5.offsets = ids_ptr + sizeof (uint32_t) * nr_columns;
@@ -8234,8 +8328,8 @@ create_dwp_hash_table (dwarf2_per_objfile *per_objfile,
* nr_units * nr_columns))
> index_end)
{
- error (_("Dwarf Error: DWP index section is corrupt (too small)"
- " [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "DWP index section is corrupt (too small) [in module %s]"),
dwp_file->name);
}
}
@@ -8378,7 +8472,8 @@ create_dwo_unit_in_dwp_v1 (dwarf2_per_objfile *per_objfile,
break;
if (section_nr >= dwp_file->num_sections)
{
- error (_("Dwarf Error: bad DWP hash table, section number too large"
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, section number too large"
" [in module %s]"),
dwp_file->name);
}
@@ -8386,8 +8481,8 @@ create_dwo_unit_in_dwp_v1 (dwarf2_per_objfile *per_objfile,
sectp = dwp_file->elf_sections[section_nr];
if (! locate_v1_virtual_dwo_sections (sectp, &sections))
{
- error (_("Dwarf Error: bad DWP hash table, invalid section found"
- " [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, invalid section found [in module %s]"),
dwp_file->name);
}
}
@@ -8396,14 +8491,14 @@ create_dwo_unit_in_dwp_v1 (dwarf2_per_objfile *per_objfile,
|| sections.info_or_types.empty ()
|| sections.abbrev.empty ())
{
- error (_("Dwarf Error: bad DWP hash table, missing DWO sections"
- " [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, missing DWO sections [in module %s]"),
dwp_file->name);
}
if (i == MAX_NR_V1_DWO_SECTIONS)
{
- error (_("Dwarf Error: bad DWP hash table, too many DWO sections"
- " [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, too many DWO sections [in module %s]"),
dwp_file->name);
}
@@ -8501,8 +8596,9 @@ create_dwp_v2_or_v5_section (dwarf2_per_objfile *per_objfile,
if (sectp == NULL
|| offset + size > bfd_section_size (sectp))
{
- error (_("Dwarf Error: Bad DWP V2 or V5 section info, doesn't fit"
- " in section %s [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "Bad DWP V2 or V5 section info, doesn't fit in section %s"
+ " [in module %s]"),
sectp ? bfd_section_name (sectp) : "<unknown>",
objfile_name (per_objfile->objfile));
}
@@ -8919,8 +9015,8 @@ lookup_dwo_unit_in_dwp (dwarf2_per_objfile *per_objfile,
hash = (hash + hash2) & mask;
}
- error (_("Dwarf Error: bad DWP hash table, lookup didn't terminate"
- " [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "bad DWP hash table, lookup didn't terminate [in module %s]"),
dwp_file->name);
}
@@ -9392,8 +9488,9 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile)
/* Technically speaking, we should try to limp along, but this is
pretty bizarre. We use pulongest here because that's the established
portability solution (e.g, we cannot use %u for uint32_t). */
- error (_("Dwarf Error: DWP file CU version %s doesn't match"
- " TU version %s [in DWP file %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "DWP file CU version %s doesn't match TU version %s"
+ " [in DWP file %s]"),
pulongest (dwp_file->cus->version),
pulongest (dwp_file->tus->version), dwp_name.c_str ());
}
@@ -13255,7 +13352,6 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
if (die->child != NULL)
{
struct die_info *child_die;
- const char *name;
child_die = die->child;
while (child_die && child_die->tag)
@@ -13265,11 +13361,7 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
process_die (child_die, cu);
}
else
- {
- name = dwarf2_name (child_die, cu);
- if (name)
- new_symbol (child_die, this_type, cu);
- }
+ new_symbol (child_die, this_type, cu);
child_die = child_die->sibling;
}
@@ -13986,9 +14078,12 @@ read_namespace_type (struct die_info *die, struct dwarf2_cu *cu)
/* Now build the name of the current namespace. */
previous_prefix = determine_prefix (die, cu);
+ gdb::unique_xmalloc_ptr<char> name_storage;
if (previous_prefix[0] != '\0')
- name = typename_concat (&objfile->objfile_obstack,
- previous_prefix, name, 0, cu);
+ {
+ name_storage = typename_concat (previous_prefix, name, 0, cu);
+ name = name_storage.get ();
+ }
/* Create the type. */
type = type_allocator (objfile, cu->lang ()).new_type (TYPE_CODE_NAMESPACE,
@@ -15876,7 +15971,8 @@ read_full_die_1 (const struct die_reader_specs *reader,
abbrev = reader->abbrev_table->lookup_abbrev (abbrev_number);
if (!abbrev)
- error (_("Dwarf Error: could not find abbrev number %d [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "could not find abbrev number %d [in module %s]"),
abbrev_number,
bfd_get_filename (abfd));
@@ -16027,8 +16123,6 @@ cooked_indexer::ensure_cu_exists (cutu_reader *reader,
if (!per_cu->scanned.compare_exchange_strong (nope, true))
return nullptr;
}
- if (per_cu == m_per_cu)
- return reader;
cutu_reader *result = m_index_storage->get_reader (per_cu);
if (result == nullptr)
@@ -16036,6 +16130,10 @@ cooked_indexer::ensure_cu_exists (cutu_reader *reader,
cutu_reader new_reader (per_cu, per_objfile, nullptr, nullptr, false,
m_index_storage->get_abbrev_cache ());
+ if (new_reader.dummy_p || new_reader.comp_unit_die == nullptr
+ || !new_reader.comp_unit_die->has_children)
+ return nullptr;
+
prepare_one_comp_unit (new_reader.cu, new_reader.comp_unit_die,
language_minimal);
std::unique_ptr<cutu_reader> copy
@@ -16043,7 +16141,8 @@ cooked_indexer::ensure_cu_exists (cutu_reader *reader,
result = m_index_storage->preserve (std::move (copy));
}
- if (result->dummy_p || !result->comp_unit_die->has_children)
+ if (result->dummy_p || result->comp_unit_die == nullptr
+ || !result->comp_unit_die->has_children)
return nullptr;
if (for_scanning)
@@ -16211,7 +16310,8 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
want to treat them as definitions. */
if ((abbrev->tag == DW_TAG_class_type
|| abbrev->tag == DW_TAG_structure_type
- || abbrev->tag == DW_TAG_union_type)
+ || abbrev->tag == DW_TAG_union_type
+ || abbrev->tag == DW_TAG_namespace)
&& abbrev->has_children)
*flags |= IS_TYPE_DECLARATION;
else
@@ -16229,42 +16329,53 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
cutu_reader *new_reader
= ensure_cu_exists (reader, reader->cu->per_objfile, origin_offset,
origin_is_dwz, false);
- if (new_reader != nullptr)
+ if (new_reader == nullptr)
+ error (_(DWARF_ERROR_PREFIX
+ "cannot follow reference to DIE at %s"
+ " [in module %s]"),
+ sect_offset_str (origin_offset),
+ bfd_get_filename (reader->abfd));
+
+ const gdb_byte *new_info_ptr = (new_reader->buffer
+ + to_underlying (origin_offset));
+
+ if (*parent_entry == nullptr)
{
- const gdb_byte *new_info_ptr = (new_reader->buffer
- + to_underlying (origin_offset));
+ /* We only perform immediate lookups of parents for DIEs
+ from earlier in this CU. This avoids any problem
+ with a NULL result when when we see a reference to a
+ DIE in another CU that we may or may not have
+ imported locally. */
+ parent_map::addr_type addr
+ = parent_map::form_addr (origin_offset, origin_is_dwz);
+ if (new_reader->cu != reader->cu || new_info_ptr > watermark_ptr)
+ *maybe_defer = addr;
+ else
+ *parent_entry = m_die_range_map->find (addr);
+ }
- if (*parent_entry == nullptr)
- {
- /* We only perform immediate lookups of parents for DIEs
- from earlier in this CU. This avoids any problem
- with a NULL result when when we see a reference to a
- DIE in another CU that we may or may not have
- imported locally. */
- parent_map::addr_type addr
- = parent_map::form_addr (origin_offset, origin_is_dwz);
- if (new_reader->cu != reader->cu || new_info_ptr > watermark_ptr)
- *maybe_defer = addr;
- else
- *parent_entry = m_die_range_map->find (addr);
- }
+ unsigned int bytes_read;
+ const abbrev_info *new_abbrev = peek_die_abbrev (*new_reader,
+ new_info_ptr,
+ &bytes_read);
- unsigned int bytes_read;
- const abbrev_info *new_abbrev = peek_die_abbrev (*new_reader,
- new_info_ptr,
- &bytes_read);
- new_info_ptr += bytes_read;
+ if (new_abbrev == nullptr)
+ error (_(DWARF_ERROR_PREFIX
+ "Unexpected null DIE at offset %s [in module %s]"),
+ sect_offset_str (origin_offset),
+ bfd_get_filename (new_reader->abfd));
- if (new_reader->cu == reader->cu && new_info_ptr == watermark_ptr)
- {
- /* Self-reference, we're done. */
- }
- else
- scan_attributes (scanning_per_cu, new_reader, new_info_ptr,
- new_info_ptr, new_abbrev, name, linkage_name,
- flags, nullptr, parent_entry, maybe_defer,
- is_enum_class, true);
+ new_info_ptr += bytes_read;
+
+ if (new_reader->cu == reader->cu && new_info_ptr == watermark_ptr)
+ {
+ /* Self-reference, we're done. */
}
+ else
+ scan_attributes (scanning_per_cu, new_reader, new_info_ptr,
+ new_info_ptr, new_abbrev, name, linkage_name,
+ flags, nullptr, parent_entry, maybe_defer,
+ is_enum_class, true);
}
if (!for_specification)
@@ -16359,10 +16470,16 @@ cooked_indexer::index_imported_unit (cutu_reader *reader,
const gdb_byte *
cooked_indexer::recurse (cutu_reader *reader,
const gdb_byte *info_ptr,
- const cooked_index_entry *parent_entry,
+ std::variant<const cooked_index_entry *,
+ parent_map::addr_type> parent,
bool fully)
{
- info_ptr = index_dies (reader, info_ptr, parent_entry, fully);
+ info_ptr = index_dies (reader, info_ptr, parent, fully);
+
+ if (!std::holds_alternative<const cooked_index_entry *> (parent))
+ return info_ptr;
+ const cooked_index_entry *parent_entry
+ = std::get<const cooked_index_entry *> (parent);
if (parent_entry != nullptr)
{
@@ -16383,7 +16500,8 @@ cooked_indexer::recurse (cutu_reader *reader,
const gdb_byte *
cooked_indexer::index_dies (cutu_reader *reader,
const gdb_byte *info_ptr,
- const cooked_index_entry *parent_entry,
+ std::variant<const cooked_index_entry *,
+ parent_map::addr_type> parent,
bool fully)
{
const gdb_byte *end_ptr = (reader->buffer
@@ -16410,15 +16528,20 @@ cooked_indexer::index_dies (cutu_reader *reader,
{
info_ptr = skip_one_die (reader, info_ptr, abbrev, !fully);
if (fully && abbrev->has_children)
- info_ptr = index_dies (reader, info_ptr, parent_entry, fully);
+ info_ptr = index_dies (reader, info_ptr, parent, fully);
continue;
}
const char *name = nullptr;
const char *linkage_name = nullptr;
parent_map::addr_type defer {};
+ if (std::holds_alternative<parent_map::addr_type> (parent))
+ defer = std::get<parent_map::addr_type> (parent);
cooked_index_flag flags = IS_STATIC;
sect_offset sibling {};
+ const cooked_index_entry *parent_entry = nullptr;
+ if (std::holds_alternative<const cooked_index_entry *> (parent))
+ parent_entry = std::get<const cooked_index_entry *> (parent);
const cooked_index_entry *this_parent_entry = parent_entry;
bool is_enum_class = false;
@@ -16437,12 +16560,6 @@ cooked_indexer::index_dies (cutu_reader *reader,
flags &= ~IS_STATIC;
flags |= parent_entry->flags & IS_STATIC;
}
- /* If the parent is an enum, but not an enum class, then use the
- grandparent instead. */
- if (this_parent_entry != nullptr
- && this_parent_entry->tag == DW_TAG_enumeration_type
- && !is_enum_class)
- this_parent_entry = this_parent_entry->get_parent ();
if (abbrev->tag == DW_TAG_namespace
&& m_language == language_cplus
@@ -16502,7 +16619,27 @@ cooked_indexer::index_dies (cutu_reader *reader,
break;
case DW_TAG_enumeration_type:
- info_ptr = recurse (reader, info_ptr, this_entry, fully);
+ /* We need to recurse even for an anonymous enumeration.
+ Which scope we record as the parent scope depends on
+ whether we're reading an "enum class". If so, we use
+ the enum itself as the parent, yielding names like
+ "enum_class::enumerator"; otherwise we inject the
+ names into our own parent scope. */
+ {
+ std::variant<const cooked_index_entry *,
+ parent_map::addr_type> recurse_parent;
+ if (is_enum_class)
+ {
+ gdb_assert (this_entry != nullptr);
+ recurse_parent = this_entry;
+ }
+ else if (defer != 0)
+ recurse_parent = defer;
+ else
+ recurse_parent = this_parent_entry;
+
+ info_ptr = recurse (reader, info_ptr, recurse_parent, fully);
+ }
continue;
case DW_TAG_module:
@@ -16583,7 +16720,8 @@ cooked_index_functions::expand_symtabs_matching
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
block_search_flags search_flags,
- domain_search_flags domain)
+ domain_search_flags domain,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher)
{
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
@@ -16602,7 +16740,8 @@ cooked_index_functions::expand_symtabs_matching
if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
file_matcher,
- expansion_notify))
+ expansion_notify,
+ lang_matcher))
return false;
}
return true;
@@ -16627,8 +16766,42 @@ cooked_index_functions::expand_symtabs_matching
symbol_name_match_type match_type
= lookup_name_without_params.match_type ();
+ std::bitset<nr_languages> unique_styles_used;
+ if (lang_matcher != nullptr)
+ for (unsigned iter = 0; iter < nr_languages; ++iter)
+ {
+ enum language lang = (enum language) iter;
+ if (!lang_matcher (lang))
+ continue;
+
+ switch (lang)
+ {
+ case language_cplus:
+ case language_rust:
+ unique_styles_used[language_cplus] = true;
+ break;
+ case language_d:
+ case language_go:
+ unique_styles_used[language_d] = true;
+ break;
+ case language_ada:
+ unique_styles_used[language_ada] = true;
+ break;
+ default:
+ unique_styles_used[language_c] = true;
+ }
+
+ if (unique_styles_used.count ()
+ == sizeof (unique_styles) / sizeof (unique_styles[0]))
+ break;
+ }
+
for (enum language lang : unique_styles)
{
+ if (lang_matcher != nullptr
+ && !unique_styles_used.test (lang))
+ continue;
+
std::vector<std::string_view> name_vec
= lookup_name_without_params.split_name (lang);
std::vector<std::string> name_str_vec (name_vec.begin (), name_vec.end ());
@@ -16659,6 +16832,15 @@ cooked_index_functions::expand_symtabs_matching
|| !entry->matches (domain))
continue;
+ if (lang_matcher != nullptr)
+ {
+ /* Try to skip CUs with non-matching language. */
+ entry->per_cu->ensure_lang (per_objfile);
+ if (!entry->per_cu->maybe_multi_language ()
+ && !lang_matcher (entry->per_cu->lang ()))
+ continue;
+ }
+
/* We've found the base name of the symbol; now walk its
parentage chain, ensuring that each component
matches. */
@@ -16727,7 +16909,7 @@ cooked_index_functions::expand_symtabs_matching
if (!dw2_expand_symtabs_matching_one (entry->per_cu, per_objfile,
file_matcher,
- expansion_notify))
+ expansion_notify, nullptr))
return false;
}
}
@@ -17241,7 +17423,8 @@ read_attribute_value (const struct die_reader_specs *reader,
}
break;
default:
- error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "Cannot handle %s in DWARF reader [in module %s]"),
dwarf_form_name (form),
bfd_get_filename (abfd));
}
@@ -17689,7 +17872,7 @@ dwarf2_string_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *c
str = attr->as_string ();
if (str == nullptr)
complaint (_("string type expected for attribute %s for "
- "DIE at %s in module %s"),
+ "DIE at %s [in module %s]"),
dwarf_attr_name (name), sect_offset_str (die->sect_off),
objfile_name (cu->per_objfile->objfile));
}
@@ -17727,7 +17910,7 @@ die_is_declaration (struct die_info *die, struct dwarf2_cu *cu)
which value is non-zero. However, we have to be careful with
DIEs having a DW_AT_specification attribute, because dwarf2_attr()
(via dwarf2_flag_true_p) follows this attribute. So we may
- end up accidently finding a declaration attribute that belongs
+ end up accidentally finding a declaration attribute that belongs
to a different DIE referenced by the specification attribute,
even though the given DIE does not have a declaration attribute. */
return (dwarf2_flag_true_p (die, DW_AT_declaration, cu)
@@ -17901,8 +18084,8 @@ public:
we're processing the end of a sequence. */
void record_line (bool end_sequence);
- /* Check ADDRESS is -1, or zero and less than UNRELOCATED_LOWPC, and if true
- nop-out rest of the lines in this 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,
@@ -18312,13 +18495,16 @@ lnp_state_machine::check_line_address (struct dwarf2_cu *cu,
unrelocated_addr unrelocated_lowpc,
unrelocated_addr address)
{
- /* Linkers resolve a symbolic relocation referencing a GC'd function to 0 or
- -1. If ADDRESS is 0, ignoring the opcode will err if the text section is
+ /* 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) -1
+ || address == (unrelocated_addr) -2)
{
/* This line table is for a function which has been
GCd by the linker. Ignore it. PR gdb/12528 */
@@ -19514,8 +19700,10 @@ die_containing_type (struct die_info *die, struct dwarf2_cu *cu)
type_attr = dwarf2_attr (die, DW_AT_containing_type, cu);
if (!type_attr)
- error (_("Dwarf Error: Problem turning containing type into gdb type "
- "[in module %s]"), objfile_name (objfile));
+ error (_(DWARF_ERROR_PREFIX
+ "Problem turning containing type into gdb type "
+ "[in module %s]"),
+ objfile_name (objfile));
return lookup_die_type (die, type_attr, cu);
}
@@ -19582,8 +19770,8 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
}
else
{
- complaint (_("Dwarf Error: Bad type attribute %s in DIE"
- " at %s [in module %s]"),
+ complaint (_(DWARF_ERROR_PREFIX
+ "Bad type attribute %s in DIE at %s [in module %s]"),
dwarf_attr_name (attr->name), sect_offset_str (die->sect_off),
objfile_name (objfile));
return build_error_marker_type (cu, die);
@@ -19998,17 +20186,15 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
}
}
-/* Return a newly-allocated string formed by concatenating PREFIX and SUFFIX
- with appropriate separator. If PREFIX or SUFFIX is NULL or empty, then
- simply copy the SUFFIX or PREFIX, respectively. If OBS is non-null, perform
- an obconcat, otherwise allocate storage for the result. The CU argument is
- used to determine the language and hence, the appropriate separator. */
-
-#define MAX_SEP_LEN 7 /* strlen ("__") + strlen ("_MOD_") */
+/* Return a newly-allocated string formed by concatenating PREFIX and
+ SUFFIX with appropriate separator. If PREFIX or SUFFIX is NULL or
+ empty, then simply copy the SUFFIX or PREFIX, respectively. The CU
+ argument is used to determine the language and hence, the
+ appropriate separator. */
-static char *
-typename_concat (struct obstack *obs, const char *prefix, const char *suffix,
- int physname, struct dwarf2_cu *cu)
+static gdb::unique_xmalloc_ptr<char>
+typename_concat (const char *prefix, const char *suffix, int physname,
+ struct dwarf2_cu *cu)
{
const char *lead = "";
const char *sep;
@@ -20044,23 +20230,8 @@ typename_concat (struct obstack *obs, const char *prefix, const char *suffix,
if (suffix == NULL)
suffix = "";
- if (obs == NULL)
- {
- char *retval
- = ((char *)
- xmalloc (strlen (prefix) + MAX_SEP_LEN + strlen (suffix) + 1));
-
- strcpy (retval, lead);
- strcat (retval, prefix);
- strcat (retval, sep);
- strcat (retval, suffix);
- return retval;
- }
- else
- {
- /* We have an obstack. */
- return obconcat (obs, lead, prefix, sep, suffix, (char *) NULL);
- }
+ return gdb::unique_xmalloc_ptr<char> (concat (lead, prefix, sep, suffix,
+ nullptr));
}
/* Return a generic name for a DW_TAG_template_type_param or
@@ -20267,7 +20438,8 @@ follow_die_ref_or_sig (struct die_info *src_die, const struct attribute *attr,
else
{
src_die->error_dump ();
- error (_("Dwarf Error: Expected reference attribute [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "Expected reference attribute [in module %s]"),
objfile_name ((*ref_cu)->per_objfile->objfile));
}
@@ -20329,7 +20501,12 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
false, cu->lang ());
target_cu = per_objfile->get_cu (per_cu);
- gdb_assert (target_cu != nullptr);
+ if (target_cu == nullptr)
+ error (_(DWARF_ERROR_PREFIX
+ "cannot follow reference to DIE at %s"
+ " [in module %s]"),
+ sect_offset_str (sect_off),
+ objfile_name (per_objfile->objfile));
}
else if (cu->dies == NULL)
{
@@ -20369,8 +20546,8 @@ follow_die_ref (struct die_info *src_die, const struct attribute *attr,
|| cu->per_cu->is_dwz),
ref_cu);
if (!die)
- error (_("Dwarf Error: Cannot find DIE at %s referenced from DIE "
- "at %s [in module %s]"),
+ 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));
@@ -20399,13 +20576,15 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off,
{
/* We shouldn't get here for a dummy CU, but don't crash on the user.
Instead just throw an error, not much else we can do. */
- error (_("Dwarf Error: Dummy CU at %s referenced in module %s"),
+ error (_(DWARF_ERROR_PREFIX
+ "Dummy CU at %s referenced [in module %s]"),
sect_offset_str (sect_off), objfile_name (objfile));
}
die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
if (!die)
- error (_("Dwarf Error: Cannot find DIE at %s referenced in module %s"),
+ error (_(DWARF_ERROR_PREFIX
+ "Cannot find DIE at %s referenced [in module %s]"),
sect_offset_str (sect_off), objfile_name (objfile));
attr = dwarf2_attr (die, DW_AT_location, cu);
@@ -20464,8 +20643,9 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off,
else
{
if (!attr->form_is_block ())
- error (_("Dwarf Error: DIE at %s referenced in module %s "
- "is neither DW_FORM_block* nor DW_FORM_exprloc"),
+ error (_(DWARF_ERROR_PREFIX
+ "DIE at %s is neither DW_FORM_block* nor DW_FORM_exprloc"
+ " [in module %s]"),
sect_offset_str (sect_off), objfile_name (objfile));
struct dwarf_block *block = attr->as_block ();
@@ -20538,13 +20718,15 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
{
/* We shouldn't get here for a dummy CU, but don't crash on the user.
Instead just throw an error, not much else we can do. */
- error (_("Dwarf Error: Dummy CU at %s referenced in module %s"),
+ error (_(DWARF_ERROR_PREFIX
+ "Dummy CU at %s referenced [in module %s]"),
sect_offset_str (sect_off), objfile_name (objfile));
}
die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
if (!die)
- error (_("Dwarf Error: Cannot find DIE at %s referenced in module %s"),
+ error (_(DWARF_ERROR_PREFIX
+ "Cannot find DIE at %s referenced [in module %s]"),
sect_offset_str (sect_off), objfile_name (objfile));
attr = dwarf2_attr (die, DW_AT_const_value, cu);
@@ -20760,8 +20942,9 @@ follow_die_sig (struct die_info *src_die, const struct attribute *attr,
the debug info. */
if (sig_type == NULL)
{
- error (_("Dwarf Error: Cannot find signatured DIE %s referenced"
- " from DIE at %s [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "Cannot find signatured DIE %s referenced from DIE at %s"
+ " [in module %s]"),
hex_string (signature), sect_offset_str (src_die->sect_off),
objfile_name ((*ref_cu)->per_objfile->objfile));
}
@@ -20770,8 +20953,9 @@ follow_die_sig (struct die_info *src_die, const struct attribute *attr,
if (die == NULL)
{
src_die->error_dump ();
- error (_("Dwarf Error: Problem reading signatured DIE %s referenced"
- " from DIE at %s [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "Problem reading signatured DIE %s referenced from DIE at %s"
+ " [in module %s]"),
hex_string (signature), sect_offset_str (src_die->sect_off),
objfile_name ((*ref_cu)->per_objfile->objfile));
}
@@ -20797,8 +20981,9 @@ get_signatured_type (struct die_info *die, ULONGEST signature,
the debug info. */
if (sig_type == NULL)
{
- complaint (_("Dwarf Error: Cannot find signatured DIE %s referenced"
- " from DIE at %s [in module %s]"),
+ complaint (_(DWARF_ERROR_PREFIX
+ "Cannot find signatured DIE %s referenced from DIE at %s"
+ " [in module %s]"),
hex_string (signature), sect_offset_str (die->sect_off),
objfile_name (per_objfile->objfile));
return build_error_marker_type (cu, die);
@@ -20819,7 +21004,8 @@ get_signatured_type (struct die_info *die, ULONGEST signature,
type = read_type_die (type_die, type_cu);
if (type == NULL)
{
- complaint (_("Dwarf Error: Cannot build signatured type %s"
+ complaint (_(DWARF_ERROR_PREFIX
+ "Cannot build signatured type %s"
" referenced from DIE at %s [in module %s]"),
hex_string (signature), sect_offset_str (die->sect_off),
objfile_name (per_objfile->objfile));
@@ -20828,7 +21014,8 @@ get_signatured_type (struct die_info *die, ULONGEST signature,
}
else
{
- complaint (_("Dwarf Error: Problem reading signatured DIE %s referenced"
+ complaint (_(DWARF_ERROR_PREFIX
+ "Problem reading signatured DIE %s referenced"
" from DIE at %s [in module %s]"),
hex_string (signature), sect_offset_str (die->sect_off),
objfile_name (per_objfile->objfile));
@@ -20863,8 +21050,9 @@ get_DW_AT_signature_type (struct die_info *die, const struct attribute *attr,
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
- complaint (_("Dwarf Error: DW_AT_signature has bad form %s in DIE"
- " at %s [in module %s]"),
+ complaint (_(DWARF_ERROR_PREFIX
+ "DW_AT_signature has bad form %s in DIE at %s"
+ " [in module %s]"),
dwarf_form_name (attr->form), sect_offset_str (die->sect_off),
objfile_name (per_objfile->objfile));
return build_error_marker_type (cu, die);
@@ -21107,6 +21295,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu,
case DW_OP_addrx:
case DW_OP_GNU_addr_index:
+ case DW_OP_constx:
case DW_OP_GNU_const_index:
stack[++stacki]
= (CORE_ADDR) read_addr_index_from_leb128 (cu, &data[i],
@@ -21425,6 +21614,24 @@ dwarf2_per_cu_data::set_lang (enum language lang,
gdb_assert (old_dw == 0 || old_dw == dw_lang);
}
+/* See read.h. */
+
+void
+dwarf2_per_cu_data::ensure_lang (dwarf2_per_objfile *per_objfile)
+{
+ if (lang (false) != language_unknown)
+ return;
+
+ cutu_reader reader (this, per_objfile);
+ if (reader.dummy_p)
+ {
+ set_lang (language_minimal, (dwarf_source_language)0);
+ return;
+ }
+
+ prepare_one_comp_unit (reader.cu, reader.comp_unit_die, language_minimal);
+}
+
/* 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
@@ -21473,8 +21680,8 @@ dwarf2_find_containing_comp_unit (sect_offset sect_off,
if (this_cu->is_dwz != offset_in_dwz || this_cu->sect_off > sect_off)
{
if (low == 0 || this_cu->is_dwz != offset_in_dwz)
- error (_("Dwarf Error: could not find CU containing "
- "offset %s [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "could not find CU containing offset %s [in module %s]"),
sect_offset_str (sect_off),
bfd_get_filename (per_bfd->obfd));
@@ -21588,6 +21795,14 @@ prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die,
cu->language_defn = language_def (lang);
+ /* Initialize the lto_artificial field. */
+ attr = dwarf2_attr (comp_unit_die, DW_AT_name, cu);
+ if (attr != nullptr
+ && cu->producer != nullptr
+ && strcmp (attr->as_string (), "<artificial>") == 0
+ && producer_is_gcc (cu->producer, nullptr, nullptr))
+ cu->per_cu->lto_artificial = true;
+
switch (comp_unit_die->tag)
{
case DW_TAG_compile_unit:
@@ -21600,7 +21815,8 @@ prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die,
cu->per_cu->set_unit_type (DW_UT_type);
break;
default:
- error (_("Dwarf Error: unexpected tag '%s' at offset %s"),
+ error (_(DWARF_ERROR_PREFIX
+ "unexpected tag '%s' at offset %s"),
dwarf_tag_name (comp_unit_die->tag),
sect_offset_str (cu->per_cu->sect_off));
}
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index e55d053..7c42017 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -28,7 +28,6 @@
#include "dwarf2/mapped-index.h"
#include "dwarf2/section.h"
#include "dwarf2/cu.h"
-#include "filename-seen-cache.h"
#include "gdbsupport/gdb_obstack.h"
#include "gdbsupport/hash_enum.h"
#include "gdbsupport/function-view.h"
@@ -103,6 +102,7 @@ struct dwarf2_per_cu_data
is_dwz (false),
reading_dwo_directly (false),
tu_read (false),
+ lto_artificial (false),
queued (false),
m_header_read_in (false),
mark (false),
@@ -149,6 +149,11 @@ public:
This flag is only valid if is_debug_types is true. */
unsigned int tu_read : 1;
+ /* Non-zero if the CU is produced by GCC and has name "<artificial>". GCC
+ uses this to indicate that the CU does not correspond to a single source
+ file. GCC produces this type of CU during LTO. */
+ unsigned int lto_artificial : 1;
+
/* Wrap the following in struct packed instead of bitfields to avoid
data races when the bitfields end up on the same memory location
(per C++ memory model). */
@@ -325,6 +330,9 @@ public:
return l;
}
+ /* Make sure that m_lang != language_unknown. */
+ void ensure_lang (dwarf2_per_objfile *per_objfile);
+
/* Return the language of this CU, as a DWARF DW_LANG_* value. This
may be 0 in some situations. */
dwarf_source_language dw_lang () const
@@ -336,6 +344,22 @@ public:
situation LANG would be set by the importing CU. */
void set_lang (enum language lang, dwarf_source_language dw_lang);
+ /* Return true if the CU may be a multi-language CU. */
+
+ bool maybe_multi_language () const
+ {
+ enum language lang = this->lang ();
+
+ if (!lto_artificial)
+ /* Assume multi-language CUs are generated only by GCC LTO. */
+ return false;
+
+ /* If GCC mixes different languages in an artificial LTO CU, it labels it C.
+ The exception to this is when it mixes C and C++, which it labels it C++.
+ For now, we don't consider the latter a multi-language CU. */
+ return lang == language_c;
+ }
+
/* Free any cached file names. */
void free_cached_file_names ();
};
@@ -844,7 +868,7 @@ struct dwarf2_base_index_functions : public quick_symbol_functions
void expand_all_symtabs (struct objfile *objfile) override;
struct compunit_symtab *find_pc_sect_compunit_symtab
- (struct objfile *objfile, struct bound_minimal_symbol msymbol,
+ (struct objfile *objfile, bound_minimal_symbol msymbol,
CORE_ADDR pc, struct obj_section *section, int warn_if_readin)
override;
@@ -868,7 +892,8 @@ extern bool dw2_expand_symtabs_matching_one
(dwarf2_per_cu_data *per_cu,
dwarf2_per_objfile *per_objfile,
gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
- gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify);
+ gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher);
/* Helper for dw2_expand_symtabs_matching that works with a
mapped_index_base instead of the containing objfile. This is split
@@ -882,7 +907,8 @@ extern bool dw2_expand_symtabs_matching_symbol
const lookup_name_info &lookup_name_in,
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<bool (offset_type)> match_callback,
- dwarf2_per_objfile *per_objfile);
+ dwarf2_per_objfile *per_objfile,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher);
/* If FILE_MATCHER is non-NULL, set all the
dwarf2_per_cu_quick_data::MARK of the current DWARF2_PER_OBJFILE
diff --git a/gdb/dwarf2/section.c b/gdb/dwarf2/section.c
index 6aab0b9..e0b63fd 100644
--- a/gdb/dwarf2/section.c
+++ b/gdb/dwarf2/section.c
@@ -28,6 +28,7 @@
#include "gdb_bfd.h"
#include "objfiles.h"
#include "complaints.h"
+#include "dwarf2/error.h"
void
dwarf2_section_info::overflow_complaint () const
@@ -140,8 +141,9 @@ dwarf2_section_info::read (struct objfile *objfile)
gdb_assert (sectp != NULL);
if ((sectp->flags & SEC_RELOC) != 0)
{
- error (_("Dwarf Error: DWP format V2 with relocations is not"
- " supported in section %s [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "DWP format V2 with relocations is not supported"
+ " in section %s [in module %s]"),
get_name (), get_file_name ());
}
containing_section->read (objfile);
@@ -183,8 +185,8 @@ dwarf2_section_info::read (struct objfile *objfile)
if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
|| bfd_read (buf, size, abfd) != size)
{
- error (_("Dwarf Error: Can't read DWARF data"
- " in section %s [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "Can't read DWARF data in section %s [in module %s]"),
bfd_section_name (sectp), bfd_get_filename (abfd));
}
}
@@ -197,10 +199,12 @@ dwarf2_section_info::read_string (struct objfile *objfile, LONGEST str_offset,
if (buffer == NULL)
{
if (get_bfd_section () == nullptr)
- error (_("Dwarf Error: %s used without required section"),
+ error (_(DWARF_ERROR_PREFIX
+ "%s used without required section"),
form_name);
else
- error (_("Dwarf Error: %s used without %s section [in module %s]"),
+ error (_(DWARF_ERROR_PREFIX
+ "%s used without %s section [in module %s]"),
form_name, get_name (), get_file_name ());
}
if (str_offset >= size)
diff --git a/gdb/dwarf2/tag.h b/gdb/dwarf2/tag.h
index 2ceae53..d82690b 100644
--- a/gdb/dwarf2/tag.h
+++ b/gdb/dwarf2/tag.h
@@ -30,7 +30,6 @@ tag_is_type (dwarf_tag tag)
{
switch (tag)
{
- case DW_TAG_padding:
case DW_TAG_array_type:
case DW_TAG_class_type:
case DW_TAG_enumeration_type:
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 7a6a8ca..2e68b0d 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -29,8 +29,6 @@
#include "symfile.h"
#include "objfiles.h"
#include "stabsread.h"
-#include "demangle.h"
-#include "filenames.h"
#include "probe.h"
#include "arch-utils.h"
#include "gdbtypes.h"
@@ -39,16 +37,15 @@
#include "gdbthread.h"
#include "inferior.h"
#include "regcache.h"
-#include "bcache.h"
#include "gdb_bfd.h"
#include "location.h"
#include "auxv.h"
#include "mdebugread.h"
#include "ctfread.h"
#include <string_view>
-#include "gdbsupport/scoped_fd.h"
#include "dwarf2/public.h"
#include "cli/cli-cmds.h"
+#include "gdb-stabs.h"
/* Whether ctf should always be read, or only if no dwarf is present. */
static bool always_read_ctf;
@@ -615,6 +612,8 @@ elf_rel_plt_read (minimal_symbol_reader &reader,
const size_t got_suffix_len = strlen (SYMBOL_GOT_PLT_SUFFIX);
name = bfd_asymbol_name (*relplt->relocation[reloc].sym_ptr_ptr);
+ if (!name)
+ continue;
address = relplt->relocation[reloc].address;
asection *msym_section;
@@ -694,13 +693,12 @@ elf_gnu_ifunc_cache_eq (const void *a_voidp, const void *b_voidp)
static int
elf_gnu_ifunc_record_cache (const char *name, CORE_ADDR addr)
{
- struct bound_minimal_symbol msym;
struct objfile *objfile;
htab_t htab;
struct elf_gnu_ifunc_cache entry_local, *entry_p;
void **slot;
- msym = lookup_minimal_symbol_by_pc (addr);
+ bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (addr);
if (msym.minsym == NULL)
return 0;
if (msym.value_address () != addr)
@@ -843,9 +841,10 @@ elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p)
CORE_ADDR pointer_address, addr;
asection *plt;
gdb_byte *buf = (gdb_byte *) alloca (ptr_size);
- bound_minimal_symbol msym;
- msym = lookup_minimal_symbol (name_got_plt, NULL, objfile);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, name_got_plt,
+ objfile);
if (msym.minsym == NULL)
return 0;
if (msym.minsym->type () != mst_slot_got_plt)
@@ -977,7 +976,7 @@ elf_gnu_ifunc_resolver_stop (code_breakpoint *b)
if (b_return == b)
{
/* No need to call find_pc_line for symbols resolving as this is only
- a helper breakpointer never shown to the user. */
+ a helper breakpoint never shown to the user. */
symtab_and_line sal;
sal.pspace = current_inferior ()->pspace;
@@ -1225,6 +1224,134 @@ elf_symfile_read_dwarf2 (struct objfile *objfile,
return has_dwarf2;
}
+/* find_text_range --- find start and end of loadable code sections
+
+ The find_text_range function finds the shortest address range that
+ encloses all sections containing executable code, and stores it in
+ objfile's text_addr and text_size members.
+
+ dbx_symfile_read will use this to finish off the partial symbol
+ table, in some cases. */
+
+static void
+find_text_range (bfd * sym_bfd, struct objfile *objfile)
+{
+ asection *sec;
+ int found_any = 0;
+ CORE_ADDR start = 0;
+ CORE_ADDR end = 0;
+
+ for (sec = sym_bfd->sections; sec; sec = sec->next)
+ if (bfd_section_flags (sec) & SEC_CODE)
+ {
+ CORE_ADDR sec_start = bfd_section_vma (sec);
+ CORE_ADDR sec_end = sec_start + bfd_section_size (sec);
+
+ if (found_any)
+ {
+ if (sec_start < start)
+ start = sec_start;
+ if (sec_end > end)
+ end = sec_end;
+ }
+ else
+ {
+ start = sec_start;
+ end = sec_end;
+ }
+
+ found_any = 1;
+ }
+
+ if (!found_any)
+ error (_("Can't find any code sections in symbol file"));
+
+ DBX_TEXT_ADDR (objfile) = start;
+ DBX_TEXT_SIZE (objfile) = end - start;
+}
+
+/* Scan and build partial symbols for an ELF symbol file.
+ This ELF file has already been processed to get its minimal symbols.
+
+ This routine is the equivalent of dbx_symfile_init and dbx_symfile_read
+ rolled into one.
+
+ OBJFILE is the object file we are reading symbols from.
+ ADDR is the address relative to which the symbols are (e.g.
+ the base address of the text segment).
+ STABSECT is the BFD section information for the .stab section.
+ STABSTROFFSET and STABSTRSIZE define the location in OBJFILE where the
+ .stabstr section exists.
+
+ This routine is mostly copied from dbx_symfile_init and dbx_symfile_read,
+ adjusted for elf details. */
+
+void
+elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect,
+ file_ptr stabstroffset, unsigned int stabstrsize)
+{
+ int val;
+ bfd *sym_bfd = objfile->obfd.get ();
+ const char *name = bfd_get_filename (sym_bfd);
+
+ stabsread_new_init ();
+
+ /* Allocate struct to keep track of stab reading. */
+ dbx_objfile_data_key.emplace (objfile);
+ dbx_symfile_info *key = dbx_objfile_data_key.get (objfile);
+
+ /* Find the first and last text address. dbx_symfile_read seems to
+ want this. */
+ find_text_range (sym_bfd, objfile);
+
+#define ELF_STABS_SYMBOL_SIZE 12 /* XXX FIXME XXX */
+ DBX_SYMBOL_SIZE (objfile) = ELF_STABS_SYMBOL_SIZE;
+ DBX_SYMCOUNT (objfile)
+ = bfd_section_size (stabsect) / DBX_SYMBOL_SIZE (objfile);
+ DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
+ DBX_SYMTAB_OFFSET (objfile) = stabsect->filepos;
+ DBX_STAB_SECTION (objfile) = stabsect;
+
+ if (stabstrsize > bfd_get_size (sym_bfd))
+ error (_("ridiculous string table size: %d bytes"), stabstrsize);
+ DBX_STRINGTAB (objfile) = (char *)
+ obstack_alloc (&objfile->objfile_obstack, stabstrsize + 1);
+ OBJSTAT (objfile, sz_strtab += stabstrsize + 1);
+
+ /* Now read in the string table in one big gulp. */
+
+ val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET);
+ if (val < 0)
+ perror_with_name (name);
+ val = bfd_read (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd);
+ if (val != stabstrsize)
+ perror_with_name (name);
+
+ stabsread_new_init ();
+ free_header_files ();
+ init_header_files ();
+
+ key->ctx.processing_acc_compilation = 1;
+
+ key->ctx.symbuf_read = 0;
+ key->ctx.symbuf_left = bfd_section_size (stabsect);
+
+ scoped_restore restore_stabs_data = make_scoped_restore (&key->ctx.stabs_data);
+ gdb::unique_xmalloc_ptr<gdb_byte> data_holder;
+
+ key->ctx.stabs_data = symfile_relocate_debug_section (objfile, stabsect, NULL);
+ if (key->ctx.stabs_data)
+ data_holder.reset (key->ctx.stabs_data);
+
+ /* In an elf file, we've already installed the minimal symbols that came
+ from the elf (non-stab) symbol table, so always act like an
+ incremental load here. dbx_symfile_read should not generate any new
+ minimal symbols, since we will have already read the ELF dynamic symbol
+ table and normal symbol entries won't be in the ".stab" section; but in
+ case it does, it will install them itself. */
+ read_stabs_symtab (objfile, 0);
+}
+
/* Scan and build partial symbols for a symbol file.
We have been initialized by a call to elf_symfile_init, which
currently does nothing.
diff --git a/gdb/eval.c b/gdb/eval.c
index 40640ae..457a436 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -622,11 +622,7 @@ evaluate_subexp_do_call (expression *exp, enum noside noside,
if (ftype->code () == TYPE_CODE_INTERNAL_FUNCTION)
{
- /* We don't know anything about what the internal
- function might return, but we have to return
- something. */
- return value::zero (builtin_type (exp->gdbarch)->builtin_int,
- not_lval);
+ /* The call to call_internal_function below handles noside. */
}
else if (ftype->code () == TYPE_CODE_XMETHOD)
{
@@ -666,7 +662,8 @@ evaluate_subexp_do_call (expression *exp, enum noside noside,
{
case TYPE_CODE_INTERNAL_FUNCTION:
return call_internal_function (exp->gdbarch, exp->language_defn,
- callee, argvec.size (), argvec.data ());
+ callee, argvec.size (), argvec.data (),
+ noside);
case TYPE_CODE_XMETHOD:
return callee->call_xmethod (argvec);
default:
@@ -1875,18 +1872,21 @@ eval_op_postdec (struct type *expect_type, struct expression *exp,
}
}
-/* A helper function for OP_TYPE. */
+namespace expr
+{
struct value *
-eval_op_type (struct type *expect_type, struct expression *exp,
- enum noside noside, struct type *type)
+type_operation::evaluate (struct type *expect_type, struct expression *exp,
+ enum noside noside)
{
if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return value::allocate (type);
+ return value::allocate (std::get<0> (m_storage));
else
error (_("Attempt to use a type name as an expression"));
}
+}
+
/* A helper function for BINOP_ASSIGN_MODIFY. */
struct value *
@@ -1957,7 +1957,8 @@ eval_op_objc_msgcall (struct type *expect_type, struct expression *exp,
if (value_as_long (target) == 0)
return value_from_longest (long_type, 0);
- if (lookup_minimal_symbol ("objc_msg_lookup", 0, 0).minsym)
+ if (lookup_minimal_symbol (current_program_space, "objc_msg_lookup").minsym
+ != nullptr)
gnu_runtime = 1;
/* Find the method dispatch (Apple runtime) or method lookup
@@ -2104,7 +2105,7 @@ eval_op_objc_msgcall (struct type *expect_type, struct expression *exp,
/* Found a function symbol. Now we will substitute its
value in place of the message dispatcher (obj_msgSend),
- so that we call the method directly instead of thru
+ so that we call the method directly instead of through
the dispatcher. The main reason for doing this is that
we can now evaluate the return value and parameter values
according to their known data types, in case we need to
diff --git a/gdb/event-top.c b/gdb/event-top.c
index b81970d..cdc7874 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -894,7 +894,7 @@ unblock_signal (int sig)
/* Called to handle fatal signals. SIG is the signal number. */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
handle_fatal_signal (int sig)
{
#ifdef TUI
diff --git a/gdb/event-top.h b/gdb/event-top.h
index 846d1e4..d590552 100644
--- a/gdb/event-top.h
+++ b/gdb/event-top.h
@@ -24,6 +24,8 @@
#include <signal.h>
+#include "extension.h"
+
struct cmd_list_element;
/* The current quit handler (and its type). This is called from the
@@ -81,6 +83,29 @@ extern void quit_serial_event_set ();
extern void quit_serial_event_clear ();
+/* Wrap f (args) and handle exceptions by:
+ - returning val, and
+ - calling set_quit_flag or set_force_quit_flag, if needed. */
+
+template <typename R, R val, typename F, typename... Args>
+static R
+catch_exceptions (F &&f, Args&&... args)
+{
+ try
+ {
+ return f (std::forward<Args> (args)...);
+ }
+ catch (const gdb_exception &ex)
+ {
+ if (ex.reason == RETURN_QUIT)
+ set_quit_flag ();
+ else if (ex.reason == RETURN_FORCED_QUIT)
+ set_force_quit_flag ();
+ }
+
+ return val;
+}
+
extern void display_gdb_prompt (const char *new_prompt);
extern void gdb_setup_readline (int);
extern void gdb_disable_readline (void);
diff --git a/gdb/exec.c b/gdb/exec.c
index 63eee42..82d9266 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -143,7 +143,10 @@ static void
exec_target_open (const char *args, int from_tty)
{
target_preopen (from_tty);
- exec_file_attach (args, from_tty);
+
+ std::string filename = extract_single_filename_arg (args);
+ exec_file_attach (filename.empty () ? nullptr : filename.c_str (),
+ from_tty);
}
/* This is the target_close implementation. Clears all target
@@ -294,7 +297,7 @@ validate_exec_file (int from_tty)
symbol_file_add_main (exec_file_target.c_str (), add_flags);
exec_file_attach (exec_file_target.c_str (), from_tty);
}
- catch (gdb_exception_error &err)
+ catch (const gdb_exception_error &err)
{
warning (_("loading %ps %s"),
styled_string (file_name_style.style (),
@@ -1074,14 +1077,14 @@ and it is the program executed when you use the `run' command.\n\
If FILE cannot be found as specified, your execution directory path\n\
($PATH) is searched for a command of that name.\n\
No arg means to have no executable file and no symbols."), &cmdlist);
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, filename_maybe_quoted_completer);
c = add_cmd ("exec-file", class_files, exec_file_command, _("\
Use FILE as program for getting contents of pure memory.\n\
If FILE cannot be found as specified, your execution directory path\n\
is searched for a command of that name.\n\
No arg means have no executable file."), &cmdlist);
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, filename_maybe_quoted_completer);
add_com ("section", class_files, set_section_command, _("\
Change the base address of section SECTION of the exec file to ADDR.\n\
@@ -1119,5 +1122,6 @@ will be loaded as well."),
show_exec_file_mismatch_command,
&setlist, &showlist);
- add_target (exec_target_info, exec_target_open, filename_completer);
+ add_target (exec_target_info, exec_target_open,
+ filename_maybe_quoted_completer);
}
diff --git a/gdb/exec.h b/gdb/exec.h
index 0c1f604..c08cb9f 100644
--- a/gdb/exec.h
+++ b/gdb/exec.h
@@ -62,7 +62,7 @@ extern enum target_xfer_status
noted above. See memory_xfer_partial_1() in target.c for an
example.
- Return the number of bytes actually transfered, or zero when no
+ Return the number of bytes actually transferred, or zero when no
data is available for the requested range.
This function is intended to be used from target_xfer_partial
diff --git a/gdb/expop.h b/gdb/expop.h
index 2d46a9d..af031f5 100644
--- a/gdb/expop.h
+++ b/gdb/expop.h
@@ -172,9 +172,6 @@ extern struct value *eval_op_ind (struct type *expect_type,
struct expression *exp,
enum noside noside,
struct value *arg1);
-extern struct value *eval_op_type (struct type *expect_type,
- struct expression *exp,
- enum noside noside, struct type *type);
extern struct value *eval_op_alignof (struct type *expect_type,
struct expression *exp,
enum noside noside,
@@ -1560,16 +1557,16 @@ public:
value *evaluate (struct type *expect_type,
struct expression *exp,
- enum noside noside) override
- {
- return eval_op_type (expect_type, exp, noside, std::get<0> (m_storage));
- }
+ enum noside noside) override;
enum exp_opcode opcode () const override
{ return OP_TYPE; }
bool constant_p () const override
{ return true; }
+
+ bool type_p () const override
+ { return true; }
};
/* Implement the "typeof" operation. */
@@ -1593,6 +1590,9 @@ public:
enum exp_opcode opcode () const override
{ return OP_TYPEOF; }
+
+ bool type_p () const override
+ { return true; }
};
/* Implement 'decltype'. */
@@ -1638,6 +1638,9 @@ public:
enum exp_opcode opcode () const override
{ return OP_DECLTYPE; }
+
+ bool type_p () const override
+ { return true; }
};
/* Implement 'typeid'. */
@@ -1652,9 +1655,8 @@ public:
struct expression *exp,
enum noside noside) override
{
- enum exp_opcode sub_op = std::get<0> (m_storage)->opcode ();
enum noside sub_noside
- = ((sub_op == OP_TYPE || sub_op == OP_DECLTYPE || sub_op == OP_TYPEOF)
+ = (std::get<0> (m_storage)->type_p ()
? EVAL_AVOID_SIDE_EFFECTS
: noside);
diff --git a/gdb/expression.h b/gdb/expression.h
index 5bfc74c..2eb866f 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -147,6 +147,11 @@ public:
virtual bool uses_objfile (struct objfile *objfile) const
{ return false; }
+ /* Some expression nodes represent a type, not a value. This method
+ should be overridden to return 'true' in these situations. */
+ virtual bool type_p () const
+ { return false; }
+
/* Generate agent expression bytecodes for this operation. */
void generate_ax (struct expression *exp, struct agent_expr *ax,
struct axs_value *value,
@@ -215,6 +220,11 @@ struct expression
op->dump (stream, 0);
}
+ /* Call the type_p method on the outermost sub-expression of this
+ expression, and return the result. */
+ bool type_p () const
+ { return op->type_p (); }
+
/* Return true if this expression uses OBJFILE (and will become
dangling when OBJFILE is unloaded), otherwise return false.
OBJFILE must not be a separate debug info file. */
diff --git a/gdb/extension-priv.h b/gdb/extension-priv.h
index 1365988..653fd51 100644
--- a/gdb/extension-priv.h
+++ b/gdb/extension-priv.h
@@ -188,6 +188,11 @@ struct extension_language_ops
enum ext_lang_frame_args args_type,
struct ui_out *out, int frame_low, int frame_high);
+ /* Used for registering the ptwrite filter to the current thread. */
+ void (*apply_ptwrite_filter)
+ (const struct extension_language_defn *extlang,
+ struct btrace_thread_info *btinfo);
+
/* Update values held by the extension language when OBJFILE is discarded.
New global types must be created for every such value, which must then be
updated to use the new types.
diff --git a/gdb/extension.c b/gdb/extension.c
index 99e7190..897bf25 100644
--- a/gdb/extension.c
+++ b/gdb/extension.c
@@ -562,6 +562,19 @@ apply_ext_lang_frame_filter (const frame_info_ptr &frame,
return EXT_LANG_BT_NO_FILTERS;
}
+/* Used for registering the ptwrite filter to the current thread. */
+
+void
+apply_ext_lang_ptwrite_filter (btrace_thread_info *btinfo)
+{
+ for (const struct extension_language_defn *extlang : extension_languages)
+ {
+ if (extlang->ops != nullptr
+ && extlang->ops->apply_ptwrite_filter != nullptr)
+ extlang->ops->apply_ptwrite_filter (extlang, btinfo);
+ }
+}
+
/* Update values held by the extension language when OBJFILE is discarded.
New global types must be created for every such value, which must then be
updated to use the new types.
@@ -667,7 +680,7 @@ static bool quit_flag;
/* The current extension language we've called out to, or
extension_language_gdb if there isn't one.
- This must be set everytime we call out to an extension language, and reset
+ This must be set every time we call out to an extension language, and reset
to the previous value when it returns. Note that the previous value may
be a different (or the same) extension language. */
static const struct extension_language_defn *active_ext_lang
diff --git a/gdb/extension.h b/gdb/extension.h
index 258a77d..5b0830b 100644
--- a/gdb/extension.h
+++ b/gdb/extension.h
@@ -303,6 +303,9 @@ extern enum ext_lang_bt_status apply_ext_lang_frame_filter
enum ext_lang_frame_args args_type,
struct ui_out *out, int frame_low, int frame_high);
+extern void apply_ext_lang_ptwrite_filter
+ (struct btrace_thread_info *btinfo);
+
extern void preserve_ext_lang_values (struct objfile *, htab_t copied_types);
extern const struct extension_language_defn *get_breakpoint_cond_ext_lang
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
index bdf9c32..259f274 100644
--- a/gdb/f-exp.y
+++ b/gdb/f-exp.y
@@ -754,7 +754,11 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
| REAL_S8_KEYWORD
{ $$ = parse_f_type (pstate)->builtin_real_s8; }
| REAL_S16_KEYWORD
- { $$ = parse_f_type (pstate)->builtin_real_s16; }
+ { $$ = parse_f_type (pstate)->builtin_real_s16;
+ if ($$->code () == TYPE_CODE_ERROR)
+ error (_("unsupported type %s"),
+ TYPE_SAFE_NAME ($$));
+ }
| COMPLEX_KEYWORD
{ $$ = parse_f_type (pstate)->builtin_complex; }
| COMPLEX_S4_KEYWORD
@@ -762,7 +766,11 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
| COMPLEX_S8_KEYWORD
{ $$ = parse_f_type (pstate)->builtin_complex_s8; }
| COMPLEX_S16_KEYWORD
- { $$ = parse_f_type (pstate)->builtin_complex_s16; }
+ { $$ = parse_f_type (pstate)->builtin_complex_s16;
+ if ($$->code () == TYPE_CODE_ERROR)
+ error (_("unsupported type %s"),
+ TYPE_SAFE_NAME ($$));
+ }
| SINGLE PRECISION
{ $$ = parse_f_type (pstate)->builtin_real;}
| DOUBLE PRECISION
@@ -1156,12 +1164,9 @@ push_kind_type (LONGEST val, struct type *type)
type_stack->push (tp_kind);
}
-/* Called when a type has a '(kind=N)' modifier after it, for example
- 'character(kind=1)'. The BASETYPE is the type described by 'character'
- in our example, and KIND is the integer '1'. This function returns a
- new type that represents the basetype of a specific kind. */
+/* Helper function for convert_to_kind_type. */
static struct type *
-convert_to_kind_type (struct type *basetype, int kind)
+convert_to_kind_type_1 (struct type *basetype, int kind)
{
if (basetype == parse_f_type (pstate)->builtin_character)
{
@@ -1211,13 +1216,25 @@ convert_to_kind_type (struct type *basetype, int kind)
return parse_f_type (pstate)->builtin_integer_s8;
}
- error (_("unsupported kind %d for type %s"),
- kind, TYPE_SAFE_NAME (basetype));
-
- /* Should never get here. */
return nullptr;
}
+/* Called when a type has a '(kind=N)' modifier after it, for example
+ 'character(kind=1)'. The BASETYPE is the type described by 'character'
+ in our example, and KIND is the integer '1'. This function returns a
+ new type that represents the basetype of a specific kind. */
+static struct type *
+convert_to_kind_type (struct type *basetype, int kind)
+{
+ struct type *res = convert_to_kind_type_1 (basetype, kind);
+
+ if (res == nullptr || res->code () == TYPE_CODE_ERROR)
+ error (_("unsupported kind %d for type %s"),
+ kind, TYPE_SAFE_NAME (basetype));
+
+ return res;
+}
+
struct f_token
{
/* The string to match against. */
diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c
index 367f641..e97ff52d 100644
--- a/gdb/fbsd-tdep.c
+++ b/gdb/fbsd-tdep.c
@@ -26,7 +26,6 @@
#include "regcache.h"
#include "regset.h"
#include "gdbthread.h"
-#include "objfiles.h"
#include "xml-syscall.h"
#include <sys/socket.h>
#include <arpa/inet.h>
@@ -1943,7 +1942,8 @@ fbsd_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread)
static LONGEST
fbsd_read_integer_by_name (struct gdbarch *gdbarch, const char *name)
{
- bound_minimal_symbol ms = lookup_minimal_symbol (name, NULL, NULL);
+ bound_minimal_symbol ms
+ = lookup_minimal_symbol (current_program_space, name);
if (ms.minsym == NULL)
error (_("Unable to resolve symbol '%s'"), name);
@@ -2034,21 +2034,23 @@ fbsd_get_thread_local_address (struct gdbarch *gdbarch, CORE_ADDR dtv_addr,
{
LONGEST tls_index = fbsd_get_tls_index (gdbarch, lm_addr);
- gdb_byte buf[gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT];
- if (target_read_memory (dtv_addr, buf, sizeof buf) != 0)
+ gdb::byte_vector buf (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT);
+ if (target_read_memory (dtv_addr, buf.data (), buf.size ()) != 0)
throw_error (TLS_GENERIC_ERROR,
_("Cannot find thread-local variables on this target"));
const struct builtin_type *builtin = builtin_type (gdbarch);
- CORE_ADDR addr = gdbarch_pointer_to_address (gdbarch,
- builtin->builtin_data_ptr, buf);
+ CORE_ADDR addr
+ = gdbarch_pointer_to_address (gdbarch, builtin->builtin_data_ptr,
+ buf.data ());
addr += (tls_index + 1) * builtin->builtin_data_ptr->length ();
- if (target_read_memory (addr, buf, sizeof buf) != 0)
+ if (target_read_memory (addr, buf.data (), buf.size ()) != 0)
throw_error (TLS_GENERIC_ERROR,
_("Cannot find thread-local variables on this target"));
- addr = gdbarch_pointer_to_address (gdbarch, builtin->builtin_data_ptr, buf);
+ addr = gdbarch_pointer_to_address (gdbarch, builtin->builtin_data_ptr,
+ buf.data ());
return addr + offset;
}
@@ -2057,7 +2059,8 @@ fbsd_get_thread_local_address (struct gdbarch *gdbarch, CORE_ADDR dtv_addr,
CORE_ADDR
fbsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- struct bound_minimal_symbol msym = lookup_bound_minimal_symbol ("_rtld_bind");
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, "_rtld_bind");
if (msym.minsym != nullptr && msym.value_address () == pc)
return frame_unwind_caller_pc (get_current_frame ());
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index ddf4ec2..01b327c 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -222,12 +222,10 @@ FEATURE_XMLFILES = aarch64-core.xml \
i386/32bit-sse.xml \
i386/32bit-linux.xml \
i386/32bit-avx.xml \
- i386/32bit-mpx.xml \
i386/32bit-avx512.xml \
i386/32bit-segments.xml \
i386/64bit-avx512.xml \
i386/64bit-core.xml \
- i386/64bit-mpx.xml \
i386/64bit-segments.xml \
i386/64bit-avx.xml \
i386/64bit-linux.xml \
diff --git a/gdb/features/btrace-conf.dtd b/gdb/features/btrace-conf.dtd
index 57300ea..c6f3f60 100644
--- a/gdb/features/btrace-conf.dtd
+++ b/gdb/features/btrace-conf.dtd
@@ -12,3 +12,5 @@
<!ELEMENT pt EMPTY>
<!ATTLIST pt size CDATA #IMPLIED>
+<!ATTLIST pt ptwrite (yes | no) #IMPLIED>
+<!ATTLIST pt event-tracing (yes | no) #IMPLIED>
diff --git a/gdb/features/i386/32bit-mpx.c b/gdb/features/i386/32bit-mpx.c
deleted file mode 100644
index 40b34ed..0000000
--- a/gdb/features/i386/32bit-mpx.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
- Original: 32bit-mpx.xml */
-
-#include "gdbsupport/tdesc.h"
-
-static int
-create_feature_i386_32bit_mpx (struct target_desc *result, long regnum)
-{
- struct tdesc_feature *feature;
-
- feature = tdesc_create_feature (result, "org.gnu.gdb.i386.mpx");
- tdesc_type_with_fields *type_with_fields;
- type_with_fields = tdesc_create_struct (feature, "br128");
- tdesc_type *field_type;
- field_type = tdesc_named_type (feature, "uint64");
- tdesc_add_field (type_with_fields, "lbound", field_type);
- field_type = tdesc_named_type (feature, "uint64");
- tdesc_add_field (type_with_fields, "ubound_raw", field_type);
-
- type_with_fields = tdesc_create_struct (feature, "_bndstatus");
- tdesc_set_struct_size (type_with_fields, 8);
- tdesc_add_bitfield (type_with_fields, "bde", 2, 31);
- tdesc_add_bitfield (type_with_fields, "error", 0, 1);
-
- type_with_fields = tdesc_create_union (feature, "status");
- field_type = tdesc_named_type (feature, "data_ptr");
- tdesc_add_field (type_with_fields, "raw", field_type);
- field_type = tdesc_named_type (feature, "_bndstatus");
- tdesc_add_field (type_with_fields, "status", field_type);
-
- type_with_fields = tdesc_create_struct (feature, "_bndcfgu");
- tdesc_set_struct_size (type_with_fields, 8);
- tdesc_add_bitfield (type_with_fields, "base", 12, 31);
- tdesc_add_bitfield (type_with_fields, "reserved", 2, 11);
- tdesc_add_bitfield (type_with_fields, "preserved", 1, 1);
- tdesc_add_bitfield (type_with_fields, "enabled", 0, 0);
-
- type_with_fields = tdesc_create_union (feature, "cfgu");
- field_type = tdesc_named_type (feature, "data_ptr");
- tdesc_add_field (type_with_fields, "raw", field_type);
- field_type = tdesc_named_type (feature, "_bndcfgu");
- tdesc_add_field (type_with_fields, "config", field_type);
-
- tdesc_create_reg (feature, "bnd0raw", regnum++, 1, NULL, 128, "br128");
- tdesc_create_reg (feature, "bnd1raw", regnum++, 1, NULL, 128, "br128");
- tdesc_create_reg (feature, "bnd2raw", regnum++, 1, NULL, 128, "br128");
- tdesc_create_reg (feature, "bnd3raw", regnum++, 1, NULL, 128, "br128");
- tdesc_create_reg (feature, "bndcfgu", regnum++, 1, NULL, 64, "cfgu");
- tdesc_create_reg (feature, "bndstatus", regnum++, 1, NULL, 64, "status");
- return regnum;
-}
diff --git a/gdb/features/i386/32bit-mpx.xml b/gdb/features/i386/32bit-mpx.xml
deleted file mode 100644
index 81eb2ee..0000000
--- a/gdb/features/i386/32bit-mpx.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0"?>
-<!-- Copyright (C) 2013-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.mpx">
- <struct id="br128">
- <field name="lbound" type="uint64"/>
- <field name="ubound_raw" type="uint64"/>
- </struct>
-
- <struct id="_bndstatus" size="8">
- <field name="bde" start="2" end="31"/>
- <field name="error" start="0" end="1"/>
- </struct>
-
- <union id="status">
- <field name="raw" type="data_ptr"/>
- <field name="status" type="_bndstatus"/>
- </union>
-
- <struct id="_bndcfgu" size="8">
- <field name="base" start="12" end="31" />
- <field name="reserved" start="2" end="11"/>
- <!-- Explicitly set the type here, otherwise it defaults to bool.
- Perhaps this should be uint32, but the container type has size 8. -->
- <field name="preserved" start="1" end="1" type="uint64"/>
- <field name="enabled" start="0" end="0" type="uint64"/>
- </struct>
-
- <union id="cfgu">
- <field name="raw" type="data_ptr"/>
- <field name="config" type="_bndcfgu"/>
- </union>
-
- <reg name="bnd0raw" bitsize="128" type="br128"/>
- <reg name="bnd1raw" bitsize="128" type="br128"/>
- <reg name="bnd2raw" bitsize="128" type="br128"/>
- <reg name="bnd3raw" bitsize="128" type="br128"/>
- <reg name="bndcfgu" bitsize="64" type="cfgu"/>
- <reg name="bndstatus" bitsize="64" type="status"/>
-</feature>
diff --git a/gdb/features/i386/64bit-mpx.c b/gdb/features/i386/64bit-mpx.c
deleted file mode 100644
index 3eabc9d..0000000
--- a/gdb/features/i386/64bit-mpx.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
- Original: 64bit-mpx.xml */
-
-#include "gdbsupport/tdesc.h"
-
-static int
-create_feature_i386_64bit_mpx (struct target_desc *result, long regnum)
-{
- struct tdesc_feature *feature;
-
- feature = tdesc_create_feature (result, "org.gnu.gdb.i386.mpx");
- tdesc_type_with_fields *type_with_fields;
- type_with_fields = tdesc_create_struct (feature, "br128");
- tdesc_type *field_type;
- field_type = tdesc_named_type (feature, "uint64");
- tdesc_add_field (type_with_fields, "lbound", field_type);
- field_type = tdesc_named_type (feature, "uint64");
- tdesc_add_field (type_with_fields, "ubound_raw", field_type);
-
- type_with_fields = tdesc_create_struct (feature, "_bndstatus");
- tdesc_set_struct_size (type_with_fields, 8);
- tdesc_add_bitfield (type_with_fields, "bde", 2, 63);
- tdesc_add_bitfield (type_with_fields, "error", 0, 1);
-
- type_with_fields = tdesc_create_union (feature, "status");
- field_type = tdesc_named_type (feature, "data_ptr");
- tdesc_add_field (type_with_fields, "raw", field_type);
- field_type = tdesc_named_type (feature, "_bndstatus");
- tdesc_add_field (type_with_fields, "status", field_type);
-
- type_with_fields = tdesc_create_struct (feature, "_bndcfgu");
- tdesc_set_struct_size (type_with_fields, 8);
- tdesc_add_bitfield (type_with_fields, "base", 12, 63);
- tdesc_add_bitfield (type_with_fields, "reserved", 2, 11);
- tdesc_add_bitfield (type_with_fields, "preserved", 1, 1);
- tdesc_add_bitfield (type_with_fields, "enabled", 0, 0);
-
- type_with_fields = tdesc_create_union (feature, "cfgu");
- field_type = tdesc_named_type (feature, "data_ptr");
- tdesc_add_field (type_with_fields, "raw", field_type);
- field_type = tdesc_named_type (feature, "_bndcfgu");
- tdesc_add_field (type_with_fields, "config", field_type);
-
- tdesc_create_reg (feature, "bnd0raw", regnum++, 1, NULL, 128, "br128");
- tdesc_create_reg (feature, "bnd1raw", regnum++, 1, NULL, 128, "br128");
- tdesc_create_reg (feature, "bnd2raw", regnum++, 1, NULL, 128, "br128");
- tdesc_create_reg (feature, "bnd3raw", regnum++, 1, NULL, 128, "br128");
- tdesc_create_reg (feature, "bndcfgu", regnum++, 1, NULL, 64, "cfgu");
- tdesc_create_reg (feature, "bndstatus", regnum++, 1, NULL, 64, "status");
- return regnum;
-}
diff --git a/gdb/features/i386/64bit-mpx.xml b/gdb/features/i386/64bit-mpx.xml
deleted file mode 100644
index 812c78c..0000000
--- a/gdb/features/i386/64bit-mpx.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0"?>
-<!-- Copyright (C) 2013-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.mpx">
- <struct id="br128">
- <field name="lbound" type="uint64"/>
- <field name="ubound_raw" type="uint64"/>
- </struct>
-
- <struct id="_bndstatus" size="8">
- <field name="bde" start="2" end="63"/>
- <field name="error" start="0" end="1"/>
- </struct>
-
- <union id="status">
- <field name="raw" type="data_ptr"/>
- <field name="status" type="_bndstatus"/>
- </union>
-
- <struct id="_bndcfgu" size="8">
- <field name="base" start="12" end="63"/>
- <field name="reserved" start="2" end="11"/>
- <!-- Explicitly set the type here, otherwise it defaults to bool. -->
- <field name="preserved" start="1" end="1" type="uint64"/>
- <field name="enabled" start="0" end="0" type="uint64"/>
- </struct>
-
- <union id="cfgu">
- <field name="raw" type="data_ptr"/>
- <field name="config" type="_bndcfgu"/>
- </union>
-
- <reg name="bnd0raw" bitsize="128" type="br128"/>
- <reg name="bnd1raw" bitsize="128" type="br128"/>
- <reg name="bnd2raw" bitsize="128" type="br128"/>
- <reg name="bnd3raw" bitsize="128" type="br128"/>
- <reg name="bndcfgu" bitsize="64" type="cfgu"/>
- <reg name="bndstatus" bitsize="64" type="status"/>
-</feature>
diff --git a/gdb/features/mips-dsp-linux.c b/gdb/features/mips-dsp-linux.c
index d8e4028..4873037 100644
--- a/gdb/features/mips-dsp-linux.c
+++ b/gdb/features/mips-dsp-linux.c
@@ -11,7 +11,7 @@ initialize_tdesc_mips_dsp_linux (void)
target_desc_up result = allocate_target_description ();
set_tdesc_architecture (result.get (), bfd_scan_arch ("mips"));
- set_tdesc_osabi (result.get (), osabi_from_tdesc_string ("GNU/Linux"));
+ set_tdesc_osabi (result.get (), GDB_OSABI_LINUX);
struct tdesc_feature *feature;
diff --git a/gdb/features/mips-linux.c b/gdb/features/mips-linux.c
index f93eef5..5ff2e5f 100644
--- a/gdb/features/mips-linux.c
+++ b/gdb/features/mips-linux.c
@@ -11,7 +11,7 @@ initialize_tdesc_mips_linux (void)
target_desc_up result = allocate_target_description ();
set_tdesc_architecture (result.get (), bfd_scan_arch ("mips"));
- set_tdesc_osabi (result.get (), osabi_from_tdesc_string ("GNU/Linux"));
+ set_tdesc_osabi (result.get (), GDB_OSABI_LINUX);
struct tdesc_feature *feature;
diff --git a/gdb/features/or1k-linux.c b/gdb/features/or1k-linux.c
index 2473145..85a681f 100644
--- a/gdb/features/or1k-linux.c
+++ b/gdb/features/or1k-linux.c
@@ -11,7 +11,7 @@ initialize_tdesc_or1k_linux (void)
target_desc_up result = allocate_target_description ();
set_tdesc_architecture (result.get (), bfd_scan_arch ("or1k"));
- set_tdesc_osabi (result.get (), osabi_from_tdesc_string ("GNU/Linux"));
+ set_tdesc_osabi (result.get (), GDB_OSABI_LINUX);
struct tdesc_feature *feature;
diff --git a/gdb/features/sparc/sparc32-solaris.c b/gdb/features/sparc/sparc32-solaris.c
index dce9685..70affdb 100644
--- a/gdb/features/sparc/sparc32-solaris.c
+++ b/gdb/features/sparc/sparc32-solaris.c
@@ -11,7 +11,7 @@ initialize_tdesc_sparc32_solaris (void)
target_desc_up result = allocate_target_description ();
set_tdesc_architecture (result.get (), bfd_scan_arch ("sparc"));
- set_tdesc_osabi (result.get (), osabi_from_tdesc_string ("Solaris"));
+ set_tdesc_osabi (result.get (), GDB_OSABI_SOLARIS);
struct tdesc_feature *feature;
diff --git a/gdb/features/sparc/sparc64-solaris.c b/gdb/features/sparc/sparc64-solaris.c
index d030df6..98edabe 100644
--- a/gdb/features/sparc/sparc64-solaris.c
+++ b/gdb/features/sparc/sparc64-solaris.c
@@ -11,7 +11,7 @@ initialize_tdesc_sparc64_solaris (void)
target_desc_up result = allocate_target_description ();
set_tdesc_architecture (result.get (), bfd_scan_arch ("sparc:v9"));
- set_tdesc_osabi (result.get (), osabi_from_tdesc_string ("Solaris"));
+ set_tdesc_osabi (result.get (), GDB_OSABI_SOLARIS);
struct tdesc_feature *feature;
diff --git a/gdb/findvar.c b/gdb/findvar.c
index df4ab1a..f7760aa 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -449,8 +449,8 @@ language_defn::read_var_value (struct symbol *var,
(var->arch (),
[var, &bmsym] (objfile *objfile)
{
- bmsym = lookup_minimal_symbol (var->linkage_name (), nullptr,
- objfile);
+ bmsym = lookup_minimal_symbol (current_program_space,
+ var->linkage_name (), objfile);
/* Stop if a match is found. */
return bmsym.minsym != nullptr;
diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
index e5f108d..fecd107 100644
--- a/gdb/frame-unwind.c
+++ b/gdb/frame-unwind.c
@@ -119,10 +119,10 @@ frame_unwind_append_unwinder (struct gdbarch *gdbarch,
}
/* Call SNIFFER from UNWINDER. If it succeeded set UNWINDER for
- THIS_FRAME and return 1. Otherwise the function keeps THIS_FRAME
- unchanged and returns 0. */
+ THIS_FRAME and return true. Otherwise the function keeps THIS_FRAME
+ unchanged and returns false. */
-static int
+static bool
frame_unwind_try_unwinder (const frame_info_ptr &this_frame, void **this_cache,
const struct frame_unwind *unwinder)
{
@@ -157,7 +157,7 @@ frame_unwind_try_unwinder (const frame_info_ptr &this_frame, void **this_cache,
thus most unwinders aren't able to determine if they're
the best fit. Keep trying. Fallback prologue unwinders
should always accept the frame. */
- return 0;
+ return false;
}
throw;
}
@@ -165,7 +165,7 @@ frame_unwind_try_unwinder (const frame_info_ptr &this_frame, void **this_cache,
if (res)
{
frame_debug_printf ("yes");
- return 1;
+ return true;
}
else
{
@@ -173,7 +173,7 @@ frame_unwind_try_unwinder (const frame_info_ptr &this_frame, void **this_cache,
/* Don't set *THIS_CACHE to NULL here, because sniffer has to do
so. */
frame_cleanup_after_sniffer (this_frame);
- return 0;
+ return false;
}
gdb_assert_not_reached ("frame_unwind_try_unwinder");
}
diff --git a/gdb/frame.c b/gdb/frame.c
index 43efac0..a6900b2 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2584,7 +2584,7 @@ inside_main_func (const frame_info_ptr &this_frame)
CORE_ADDR sym_addr = 0;
const char *name = main_name ();
bound_minimal_symbol msymbol
- = lookup_minimal_symbol (name, NULL,
+ = lookup_minimal_symbol (current_program_space, name,
current_program_space->symfile_object_file);
if (msymbol.minsym != nullptr)
@@ -2628,7 +2628,7 @@ inside_entry_func (const frame_info_ptr &this_frame)
{
CORE_ADDR entry_point;
- if (!entry_point_address_query (&entry_point))
+ if (!entry_point_address_query (current_program_space, &entry_point))
return false;
return get_frame_func (this_frame) == entry_point;
@@ -2859,7 +2859,7 @@ find_frame_sal (const frame_info_ptr &frame)
if (frame_inlined_callees (frame) > 0)
{
- struct symbol *sym;
+ const symbol *sym;
/* If the current frame has some inlined callees, and we have a next
frame, then that frame must be an inlined frame. In this case
diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c
index 1b5e15f..6ae3f0d 100644
--- a/gdb/frv-tdep.c
+++ b/gdb/frv-tdep.c
@@ -1062,14 +1062,13 @@ frv_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
LONGEST displ;
CORE_ADDR call_dest;
- struct bound_minimal_symbol s;
displ = ((op & 0xfe000000) >> 7) | (op & 0x0003ffff);
if ((displ & 0x00800000) != 0)
displ |= ~((LONGEST) 0x00ffffff);
call_dest = pc + 4 * displ;
- s = lookup_minimal_symbol_by_pc (call_dest);
+ bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest);
if (s.minsym != NULL
&& s.minsym->linkage_name () != NULL
@@ -1374,14 +1373,14 @@ frv_frame_this_id (const frame_info_ptr &this_frame,
= frv_frame_unwind_cache (this_frame, this_prologue_cache);
CORE_ADDR base;
CORE_ADDR func;
- struct bound_minimal_symbol msym_stack;
struct frame_id id;
/* The FUNC is easy. */
func = get_frame_func (this_frame);
/* Check if the stack is empty. */
- msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL);
+ bound_minimal_symbol msym_stack
+ = lookup_minimal_symbol (current_program_space, "_stack");
if (msym_stack.minsym && info->base == msym_stack.value_address ())
return;
diff --git a/gdb/ft32-tdep.c b/gdb/ft32-tdep.c
index 647c584..15a585a 100644
--- a/gdb/ft32-tdep.c
+++ b/gdb/ft32-tdep.c
@@ -174,8 +174,8 @@ ft32_analyze_prologue (CORE_ADDR start_addr, CORE_ADDR end_addr,
ULONGEST inst;
int isize = 0;
int regnum, pushreg;
- struct bound_minimal_symbol msymbol;
const int first_saved_reg = 13; /* The first saved register. */
+
/* PROLOGS are addresses of the subroutine prologs, PROLOGS[n]
is the address of __prolog_$rN.
__prolog_$rN pushes registers from 13 through n inclusive.
@@ -195,7 +195,8 @@ ft32_analyze_prologue (CORE_ADDR start_addr, CORE_ADDR end_addr,
snprintf (prolog_symbol, sizeof (prolog_symbol), "__prolog_$r%02d",
regnum);
- msymbol = lookup_minimal_symbol (prolog_symbol, NULL, NULL);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space, prolog_symbol);
if (msymbol.minsym)
prologs[regnum] = msymbol.value_address ();
else
diff --git a/gdb/gcore.c b/gdb/gcore.c
index 2ab00a0..969a854 100644
--- a/gdb/gcore.c
+++ b/gdb/gcore.c
@@ -269,13 +269,14 @@ call_target_sbrk (int sbrk_arg)
struct value *sbrk_fn, *ret;
bfd_vma tmp;
- if (lookup_minimal_symbol ("sbrk", NULL, NULL).minsym != NULL)
+ if (lookup_minimal_symbol (current_program_space, "sbrk").minsym != nullptr)
{
sbrk_fn = find_function_in_inferior ("sbrk", &sbrk_objf);
if (sbrk_fn == NULL)
return (bfd_vma) 0;
}
- else if (lookup_minimal_symbol ("_sbrk", NULL, NULL).minsym != NULL)
+ else if (lookup_minimal_symbol (current_program_space, "_sbrk").minsym
+ != nullptr)
{
sbrk_fn = find_function_in_inferior ("_sbrk", &sbrk_objf);
if (sbrk_fn == NULL)
diff --git a/gdb/gcore.in b/gdb/gcore.in
index 982c854..0c40e5a 100644
--- a/gdb/gcore.in
+++ b/gdb/gcore.in
@@ -27,7 +27,9 @@ prefix=core
# to ensure gdb dumps all mappings (OS dependent).
dump_all_cmds=()
-while getopts :ao: opt; do
+data_directory_opt=()
+
+while getopts :ao:d: opt; do
case "$opt" in
a)
case "$OSTYPE" in
@@ -40,8 +42,11 @@ while getopts :ao: opt; do
o)
prefix=$OPTARG
;;
+ d)
+ data_directory_opt=("--data-directory" "$OPTARG")
+ ;;
*)
- echo "usage: @GCORE_TRANSFORM_NAME@ [-a] [-o prefix] pid1 [pid2...pidN]"
+ echo "usage: @GCORE_TRANSFORM_NAME@ [-a] [-o prefix] [-d data-directory] pid1 [pid2...pidN]"
exit 2
;;
esac
@@ -51,7 +56,7 @@ shift $((OPTIND-1))
if [ "$#" -eq "0" ]
then
- echo "usage: @GCORE_TRANSFORM_NAME@ [-a] [-o prefix] pid1 [pid2...pidN]"
+ echo "usage: @GCORE_TRANSFORM_NAME@ [-a] [-o prefix] [-d data-directory] pid1 [pid2...pidN]"
exit 2
fi
@@ -98,6 +103,7 @@ do
# `</dev/null' to avoid touching interactive terminal if it is
# available but not accessible as GDB would get stopped on SIGTTIN.
"$binary_path/@GDB_TRANSFORM_NAME@" </dev/null \
+ "${data_directory_opt[@]}" \
--nx --batch --readnever -iex 'set debuginfod enabled off' \
-ex "set pagination off" -ex "set height 0" -ex "set width 0" \
"${dump_all_cmds[@]}" \
diff --git a/gdb/gdb-gdb.py.in b/gdb/gdb-gdb.py.in
index b5a7fa4..7cab694 100644
--- a/gdb/gdb-gdb.py.in
+++ b/gdb/gdb-gdb.py.in
@@ -342,7 +342,7 @@ class IntrusiveListPrinter:
corresponding intrusive_list_node.
"""
- assert elem_ptr.type.code == gdb.TYPE_CODE_PTR
+ assert elem_ptr.type.strip_typedefs().code == gdb.TYPE_CODE_PTR
if self._uses_member_node():
# Node as a member: add the member node offset from to the element's
diff --git a/gdb/gdb-stabs.h b/gdb/gdb-stabs.h
index 3786ad6..20fb8fa 100644
--- a/gdb/gdb-stabs.h
+++ b/gdb/gdb-stabs.h
@@ -20,12 +20,108 @@
#ifndef GDB_STABS_H
#define GDB_STABS_H
+/* During initial symbol readin, 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
+ partial symbol table. */
+struct legacy_psymtab;
+
+struct header_file_location
+{
+ header_file_location (const char *name_, int instance_,
+ legacy_psymtab *pst_)
+ : name (name_),
+ instance (instance_),
+ pst (pst_)
+ {
+ }
+
+ const char *name; /* Name of header file */
+ int instance; /* See above */
+ legacy_psymtab *pst; /* Partial symtab that has the
+ BINCL/EINCL defs for this file. */
+};
+
/* This file exists to hold the common definitions required of most of
the symbol-readers that end up using stabs. The common use of
these `symbol-type-specific' customizations of the generic data
structures makes the stabs-oriented symbol readers able to call
each others' functions as required. */
+struct stabsread_context {
+ /* Remember what we deduced to be the source language of this psymtab. */
+ enum language psymtab_language = language_unknown;
+
+ /* The size of each symbol in the symbol file (in external form).
+ This is set by dbx_symfile_read when building psymtabs, and by
+ dbx_psymtab_to_symtab when building symtabs. */
+ unsigned symbol_size = 0;
+
+ /* This is the offset of the symbol table in the executable file. */
+ unsigned symbol_table_offset = 0;
+
+ /* This is the offset of the string table in the executable file. */
+ unsigned string_table_offset = 0;
+
+ /* For elf+stab executables, the n_strx field is not a simple index
+ into the string table. Instead, each .o file has a base offset in
+ the string table, and the associated symbols contain offsets from
+ this base. The following two variables contain the base offset for
+ the current and next .o files. */
+ unsigned int file_string_table_offset = 0;
+
+ /* .o and NLM files contain unrelocated addresses which are based at
+ 0. When non-zero, this flag disables some of the special cases for
+ Solaris elf+stab text addresses at location 0. */
+ int symfile_relocatable = 0;
+
+ /* When set, we are processing a .o file compiled by sun acc. This is
+ misnamed; it refers to all stabs-in-elf implementations which use
+ N_UNDF the way Sun does, including Solaris gcc. Hopefully all
+ stabs-in-elf implementations ever invented will choose to be
+ compatible. */
+ unsigned char processing_acc_compilation = 0;
+
+ /* The lowest text address we have yet encountered. This is needed
+ because in an a.out file, there is no header field which tells us
+ what address the program is actually going to be loaded at, so we
+ need to make guesses based on the symbols (which *are* relocated to
+ reflect the address it will be loaded at). */
+ unrelocated_addr lowest_text_address;
+
+ /* Non-zero if there is any line number info in the objfile. Prevents
+ dbx_end_psymtab from discarding an otherwise empty psymtab. */
+ int has_line_numbers = 0;
+
+ /* The list of bincls. */
+ std::vector<struct header_file_location> bincl_list;
+
+ /* Name of last function encountered. Used in Solaris to approximate
+ object file boundaries. */
+ const char *last_function_name = nullptr;
+
+ /* The address in memory of the string table of the object file we are
+ reading (which might not be the "main" object file, but might be a
+ shared library or some other dynamically loaded thing). This is
+ set by read_dbx_symtab when building psymtabs, and by
+ read_ofile_symtab when building symtabs, and is used only by
+ next_symbol_text. FIXME: If that is true, we don't need it when
+ building psymtabs, right? */
+ char *stringtab_global = nullptr;
+
+ /* These variables are used to control fill_symbuf when the stabs
+ symbols are not contiguous (as may be the case when a COFF file is
+ linked using --split-by-reloc). */
+ const std::vector<asection *> *symbuf_sections;
+ size_t sect_idx = 0;
+ unsigned int symbuf_left = 0;
+ unsigned int symbuf_read = 0;
+
+ /* This variable stores a global stabs buffer, if we read stabs into
+ memory in one chunk in order to process relocations. */
+ bfd_byte *stabs_data = nullptr;
+};
+
/* Information is passed among various dbxread routines for accessing
symbol files. A pointer to this structure is kept in the objfile,
@@ -43,6 +139,8 @@ struct dbx_symfile_info
file_ptr symtab_offset = 0; /* Offset in file to symbol table */
int symbol_size = 0; /* Bytes in a single symbol */
+ stabsread_context ctx; /* Context for the symfile being read. */
+
/* See stabsread.h for the use of the following. */
struct header_file *header_files = nullptr;
int n_header_files = 0;
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 7e272c7..0854d57 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -930,29 +930,6 @@ gdb_bfd_openw (const char *filename, const char *target)
return gdb_bfd_ref_ptr::new_reference (result);
}
-/* Wrap f (args) and handle exceptions by:
- - returning val, and
- - calling set_quit_flag or set_force_quit_flag, if needed. */
-
-template <typename R, R val, typename F, typename... Args>
-static R
-catch_exceptions (F &&f, Args&&... args)
-{
- try
- {
- return f (std::forward<Args> (args)...);
- }
- catch (const gdb_exception &ex)
- {
- if (ex.reason == RETURN_QUIT)
- set_quit_flag ();
- else if (ex.reason == RETURN_FORCED_QUIT)
- set_force_quit_flag ();
- }
-
- return val;
-}
-
/* See gdb_bfd.h. */
gdb_bfd_ref_ptr
diff --git a/gdb/gdbarch.c b/gdb/gdbarch-gen.c
index 58e9ebb..0d00cd7 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch-gen.c
@@ -297,144 +297,144 @@ verify_gdbarch (struct gdbarch *gdbarch)
if (gdbarch->bfd_arch_info == NULL)
log.puts ("\n\tbfd_arch_info");
/* Check those that need to be defined for the given multi-arch level. */
- /* Skip verify of short_bit, invalid_p == 0 */
- /* Skip verify of int_bit, invalid_p == 0 */
- /* Skip verify of long_bit, invalid_p == 0 */
- /* Skip verify of long_long_bit, invalid_p == 0 */
- /* Skip verify of bfloat16_bit, invalid_p == 0 */
- /* Skip verify of bfloat16_format, invalid_p == 0 */
- /* Skip verify of half_bit, invalid_p == 0 */
- /* Skip verify of half_format, invalid_p == 0 */
- /* Skip verify of float_bit, invalid_p == 0 */
- /* Skip verify of float_format, invalid_p == 0 */
- /* Skip verify of double_bit, invalid_p == 0 */
- /* Skip verify of double_format, invalid_p == 0 */
- /* Skip verify of long_double_bit, invalid_p == 0 */
- /* Skip verify of long_double_format, invalid_p == 0 */
- /* Skip verify of wchar_bit, invalid_p == 0 */
+ /* Skip verify of short_bit, invalid_p == 0. */
+ /* Skip verify of int_bit, invalid_p == 0. */
+ /* Skip verify of long_bit, invalid_p == 0. */
+ /* Skip verify of long_long_bit, invalid_p == 0. */
+ /* Skip verify of bfloat16_bit, invalid_p == 0. */
+ /* Skip verify of bfloat16_format, invalid_p == 0. */
+ /* Skip verify of half_bit, invalid_p == 0. */
+ /* Skip verify of half_format, invalid_p == 0. */
+ /* Skip verify of float_bit, invalid_p == 0. */
+ /* Skip verify of float_format, invalid_p == 0. */
+ /* Skip verify of double_bit, invalid_p == 0. */
+ /* Skip verify of double_format, invalid_p == 0. */
+ /* Skip verify of long_double_bit, invalid_p == 0. */
+ /* Skip verify of long_double_format, invalid_p == 0. */
+ /* Skip verify of wchar_bit, invalid_p == 0. */
if (gdbarch->wchar_signed == -1)
gdbarch->wchar_signed = 1;
- /* Skip verify of wchar_signed, invalid_p == 0 */
- /* Skip verify of floatformat_for_type, invalid_p == 0 */
- /* Skip verify of ptr_bit, invalid_p == 0 */
+ /* Skip verify of wchar_signed, invalid_p == 0. */
+ /* Skip verify of floatformat_for_type, invalid_p == 0. */
+ /* Skip verify of ptr_bit, invalid_p == 0. */
if (gdbarch->addr_bit == 0)
gdbarch->addr_bit = gdbarch_ptr_bit (gdbarch);
- /* Skip verify of addr_bit, invalid_p == 0 */
+ /* Skip verify of addr_bit, invalid_p == 0. */
if (gdbarch->dwarf2_addr_size == 0)
gdbarch->dwarf2_addr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
- /* Skip verify of dwarf2_addr_size, invalid_p == 0 */
+ /* Skip verify of dwarf2_addr_size, invalid_p == 0. */
if (gdbarch->char_signed == -1)
gdbarch->char_signed = 1;
- /* Skip verify of char_signed, invalid_p == 0 */
+ /* Skip verify of char_signed, invalid_p == 0. */
/* Skip verify of read_pc, has predicate. */
/* Skip verify of write_pc, has predicate. */
- /* Skip verify of virtual_frame_pointer, invalid_p == 0 */
+ /* Skip verify of virtual_frame_pointer, invalid_p == 0. */
/* Skip verify of pseudo_register_read, has predicate. */
/* Skip verify of pseudo_register_read_value, has predicate. */
/* Skip verify of pseudo_register_write, has predicate. */
/* Skip verify of deprecated_pseudo_register_write, has predicate. */
if (gdbarch->num_regs == -1)
log.puts ("\n\tnum_regs");
- /* Skip verify of num_pseudo_regs, invalid_p == 0 */
+ /* Skip verify of num_pseudo_regs, invalid_p == 0. */
/* Skip verify of ax_pseudo_register_collect, has predicate. */
/* Skip verify of ax_pseudo_register_push_stack, has predicate. */
/* Skip verify of report_signal_info, has predicate. */
- /* Skip verify of sp_regnum, invalid_p == 0 */
- /* Skip verify of pc_regnum, invalid_p == 0 */
- /* Skip verify of ps_regnum, invalid_p == 0 */
- /* Skip verify of fp0_regnum, invalid_p == 0 */
- /* Skip verify of stab_reg_to_regnum, invalid_p == 0 */
- /* Skip verify of ecoff_reg_to_regnum, invalid_p == 0 */
- /* Skip verify of sdb_reg_to_regnum, invalid_p == 0 */
- /* Skip verify of dwarf2_reg_to_regnum, invalid_p == 0 */
+ /* Skip verify of sp_regnum, invalid_p == 0. */
+ /* Skip verify of pc_regnum, invalid_p == 0. */
+ /* Skip verify of ps_regnum, invalid_p == 0. */
+ /* Skip verify of fp0_regnum, invalid_p == 0. */
+ /* Skip verify of stab_reg_to_regnum, invalid_p == 0. */
+ /* Skip verify of ecoff_reg_to_regnum, invalid_p == 0. */
+ /* Skip verify of sdb_reg_to_regnum, invalid_p == 0. */
+ /* Skip verify of dwarf2_reg_to_regnum, invalid_p == 0. */
if (gdbarch->register_name == 0)
log.puts ("\n\tregister_name");
if (gdbarch->register_type == 0)
log.puts ("\n\tregister_type");
- /* Skip verify of dummy_id, invalid_p == 0 */
- /* Skip verify of deprecated_fp_regnum, invalid_p == 0 */
+ /* Skip verify of dummy_id, invalid_p == 0. */
+ /* Skip verify of deprecated_fp_regnum, invalid_p == 0. */
/* Skip verify of push_dummy_call, has predicate. */
- /* Skip verify of call_dummy_location, invalid_p == 0 */
+ /* Skip verify of call_dummy_location, invalid_p == 0. */
/* Skip verify of push_dummy_code, has predicate. */
- /* Skip verify of code_of_frame_writable, invalid_p == 0 */
- /* Skip verify of print_registers_info, invalid_p == 0 */
- /* Skip verify of print_float_info, invalid_p == 0 */
+ /* Skip verify of code_of_frame_writable, invalid_p == 0. */
+ /* Skip verify of print_registers_info, invalid_p == 0. */
+ /* Skip verify of print_float_info, invalid_p == 0. */
/* Skip verify of print_vector_info, has predicate. */
- /* Skip verify of register_sim_regno, invalid_p == 0 */
- /* Skip verify of cannot_fetch_register, invalid_p == 0 */
- /* Skip verify of cannot_store_register, invalid_p == 0 */
+ /* Skip verify of register_sim_regno, invalid_p == 0. */
+ /* Skip verify of cannot_fetch_register, invalid_p == 0. */
+ /* Skip verify of cannot_store_register, invalid_p == 0. */
/* Skip verify of get_longjmp_target, has predicate. */
- /* Skip verify of believe_pcc_promotion, invalid_p == 0 */
- /* Skip verify of convert_register_p, invalid_p == 0 */
- /* Skip verify of register_to_value, invalid_p == 0 */
- /* Skip verify of value_to_register, invalid_p == 0 */
- /* Skip verify of value_from_register, invalid_p == 0 */
- /* Skip verify of pointer_to_address, invalid_p == 0 */
- /* Skip verify of address_to_pointer, invalid_p == 0 */
+ /* Skip verify of believe_pcc_promotion, invalid_p == 0. */
+ /* Skip verify of convert_register_p, invalid_p == 0. */
+ /* Skip verify of register_to_value, invalid_p == 0. */
+ /* Skip verify of value_to_register, invalid_p == 0. */
+ /* Skip verify of value_from_register, invalid_p == 0. */
+ /* Skip verify of pointer_to_address, invalid_p == 0. */
+ /* Skip verify of address_to_pointer, invalid_p == 0. */
/* Skip verify of integer_to_address, has predicate. */
- /* Skip verify of return_value, invalid_p == 0 */
+ /* Skip verify of return_value, invalid_p == 0. */
if ((gdbarch->return_value_as_value == default_gdbarch_return_value) == (gdbarch->return_value == nullptr))
log.puts ("\n\treturn_value_as_value");
- /* Skip verify of get_return_buf_addr, invalid_p == 0 */
- /* Skip verify of dwarf2_omit_typedef_p, invalid_p == 0 */
- /* Skip verify of update_call_site_pc, invalid_p == 0 */
- /* Skip verify of return_in_first_hidden_param_p, invalid_p == 0 */
+ /* Skip verify of get_return_buf_addr, invalid_p == 0. */
+ /* Skip verify of dwarf2_omit_typedef_p, invalid_p == 0. */
+ /* Skip verify of update_call_site_pc, invalid_p == 0. */
+ /* Skip verify of return_in_first_hidden_param_p, invalid_p == 0. */
if (gdbarch->skip_prologue == 0)
log.puts ("\n\tskip_prologue");
/* Skip verify of skip_main_prologue, has predicate. */
/* Skip verify of skip_entrypoint, has predicate. */
if (gdbarch->inner_than == 0)
log.puts ("\n\tinner_than");
- /* Skip verify of breakpoint_from_pc, invalid_p == 0 */
+ /* Skip verify of breakpoint_from_pc, invalid_p == 0. */
if (gdbarch->breakpoint_kind_from_pc == 0)
log.puts ("\n\tbreakpoint_kind_from_pc");
- /* Skip verify of sw_breakpoint_from_kind, invalid_p == 0 */
- /* Skip verify of breakpoint_kind_from_current_state, invalid_p == 0 */
+ /* Skip verify of sw_breakpoint_from_kind, invalid_p == 0. */
+ /* Skip verify of breakpoint_kind_from_current_state, invalid_p == 0. */
/* Skip verify of adjust_breakpoint_address, has predicate. */
- /* Skip verify of memory_insert_breakpoint, invalid_p == 0 */
- /* Skip verify of memory_remove_breakpoint, invalid_p == 0 */
- /* Skip verify of decr_pc_after_break, invalid_p == 0 */
- /* Skip verify of deprecated_function_start_offset, invalid_p == 0 */
- /* Skip verify of remote_register_number, invalid_p == 0 */
+ /* Skip verify of memory_insert_breakpoint, invalid_p == 0. */
+ /* Skip verify of memory_remove_breakpoint, invalid_p == 0. */
+ /* Skip verify of decr_pc_after_break, invalid_p == 0. */
+ /* Skip verify of deprecated_function_start_offset, invalid_p == 0. */
+ /* Skip verify of remote_register_number, invalid_p == 0. */
/* Skip verify of fetch_tls_load_module_address, has predicate. */
/* Skip verify of get_thread_local_address, has predicate. */
- /* Skip verify of frame_args_skip, invalid_p == 0 */
- /* Skip verify of unwind_pc, invalid_p == 0 */
- /* Skip verify of unwind_sp, invalid_p == 0 */
+ /* Skip verify of frame_args_skip, invalid_p == 0. */
+ /* Skip verify of unwind_pc, invalid_p == 0. */
+ /* Skip verify of unwind_sp, invalid_p == 0. */
/* Skip verify of frame_num_args, has predicate. */
/* Skip verify of frame_align, has predicate. */
- /* Skip verify of stabs_argument_has_addr, invalid_p == 0 */
- /* Skip verify of frame_red_zone_size, invalid_p == 0 */
- /* Skip verify of convert_from_func_ptr_addr, invalid_p == 0 */
- /* Skip verify of addr_bits_remove, invalid_p == 0 */
- /* Skip verify of remove_non_address_bits, invalid_p == 0 */
- /* Skip verify of memtag_to_string, invalid_p == 0 */
- /* Skip verify of tagged_address_p, invalid_p == 0 */
- /* Skip verify of memtag_matches_p, invalid_p == 0 */
- /* 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 stabs_argument_has_addr, invalid_p == 0. */
+ /* Skip verify of frame_red_zone_size, invalid_p == 0. */
+ /* Skip verify of convert_from_func_ptr_addr, invalid_p == 0. */
+ /* Skip verify of addr_bits_remove, invalid_p == 0. */
+ /* Skip verify of remove_non_address_bits, invalid_p == 0. */
+ /* Skip verify of memtag_to_string, invalid_p == 0. */
+ /* Skip verify of tagged_address_p, invalid_p == 0. */
+ /* Skip verify of memtag_matches_p, invalid_p == 0. */
+ /* 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 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 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 */
- /* Skip verify of stack_frame_destroyed_p, invalid_p == 0 */
+ /* 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 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. */
+ /* Skip verify of stack_frame_destroyed_p, invalid_p == 0. */
/* Skip verify of elf_make_msymbol_special, has predicate. */
- /* Skip verify of coff_make_msymbol_special, invalid_p == 0 */
- /* Skip verify of make_symbol_special, invalid_p == 0 */
- /* Skip verify of adjust_dwarf2_addr, invalid_p == 0 */
- /* Skip verify of adjust_dwarf2_line, invalid_p == 0 */
- /* Skip verify of cannot_step_breakpoint, invalid_p == 0 */
- /* Skip verify of have_nonsteppable_watchpoint, invalid_p == 0 */
+ /* Skip verify of coff_make_msymbol_special, invalid_p == 0. */
+ /* Skip verify of make_symbol_special, invalid_p == 0. */
+ /* Skip verify of adjust_dwarf2_addr, invalid_p == 0. */
+ /* Skip verify of adjust_dwarf2_line, invalid_p == 0. */
+ /* Skip verify of cannot_step_breakpoint, invalid_p == 0. */
+ /* Skip verify of have_nonsteppable_watchpoint, invalid_p == 0. */
/* Skip verify of address_class_type_flags, has predicate. */
/* Skip verify of address_class_type_flags_to_name, has predicate. */
- /* Skip verify of execute_dwarf_cfa_vendor_op, invalid_p == 0 */
+ /* Skip verify of execute_dwarf_cfa_vendor_op, invalid_p == 0. */
/* Skip verify of address_class_name_to_type_flags, has predicate. */
- /* Skip verify of register_reggroup_p, invalid_p == 0 */
+ /* Skip verify of register_reggroup_p, invalid_p == 0. */
/* Skip verify of fetch_pointer_argument, has predicate. */
/* Skip verify of iterate_over_regset_sections, has predicate. */
/* Skip verify of make_corefile_notes, has predicate. */
@@ -449,19 +449,19 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of core_xfer_siginfo, has predicate. */
/* Skip verify of core_read_x86_xsave_layout, has predicate. */
/* Skip verify of gcore_bfd_target, has predicate. */
- /* Skip verify of vtable_function_descriptors, invalid_p == 0 */
- /* Skip verify of vbit_in_delta, invalid_p == 0 */
- /* Skip verify of skip_permanent_breakpoint, invalid_p == 0 */
+ /* Skip verify of vtable_function_descriptors, invalid_p == 0. */
+ /* Skip verify of vbit_in_delta, invalid_p == 0. */
+ /* Skip verify of skip_permanent_breakpoint, invalid_p == 0. */
/* Skip verify of max_insn_length, has predicate. */
/* Skip verify of displaced_step_copy_insn, has predicate. */
- /* Skip verify of displaced_step_hw_singlestep, invalid_p == 0 */
+ /* Skip verify of displaced_step_hw_singlestep, invalid_p == 0. */
if ((gdbarch->displaced_step_copy_insn == nullptr) != (gdbarch->displaced_step_fixup == nullptr))
log.puts ("\n\tdisplaced_step_fixup");
/* Skip verify of displaced_step_prepare, has predicate. */
if ((! gdbarch->displaced_step_finish) != (! gdbarch->displaced_step_prepare))
log.puts ("\n\tdisplaced_step_finish");
/* Skip verify of displaced_step_copy_insn_closure_by_addr, has predicate. */
- /* Skip verify of displaced_step_restore_all_in_ptid, invalid_p == 0 */
+ /* Skip verify of displaced_step_restore_all_in_ptid, invalid_p == 0. */
if (gdbarch->displaced_step_buffer_length == 0)
gdbarch->displaced_step_buffer_length = gdbarch->max_insn_length;
if (gdbarch->displaced_step_buffer_length < gdbarch->max_insn_length)
@@ -469,7 +469,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of relocate_instruction, has predicate. */
/* Skip verify of overlay_update, has predicate. */
/* Skip verify of core_read_description, has predicate. */
- /* Skip verify of sofun_address_maybe_missing, invalid_p == 0 */
+ /* Skip verify of sofun_address_maybe_missing, invalid_p == 0. */
/* Skip verify of process_record, has predicate. */
/* Skip verify of process_record_signal, has predicate. */
/* Skip verify of gdb_signal_from_target, has predicate. */
@@ -477,16 +477,16 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of get_siginfo_type, has predicate. */
/* Skip verify of record_special_symbol, has predicate. */
/* Skip verify of get_syscall_number, has predicate. */
- /* Skip verify of xml_syscall_file, invalid_p == 0 */
- /* Skip verify of syscalls_info, invalid_p == 0 */
- /* Skip verify of stap_integer_prefixes, invalid_p == 0 */
- /* Skip verify of stap_integer_suffixes, invalid_p == 0 */
- /* Skip verify of stap_register_prefixes, invalid_p == 0 */
- /* Skip verify of stap_register_suffixes, invalid_p == 0 */
- /* Skip verify of stap_register_indirection_prefixes, invalid_p == 0 */
- /* Skip verify of stap_register_indirection_suffixes, invalid_p == 0 */
- /* Skip verify of stap_gdb_register_prefix, invalid_p == 0 */
- /* Skip verify of stap_gdb_register_suffix, invalid_p == 0 */
+ /* Skip verify of xml_syscall_file, invalid_p == 0. */
+ /* Skip verify of syscalls_info, invalid_p == 0. */
+ /* Skip verify of stap_integer_prefixes, invalid_p == 0. */
+ /* Skip verify of stap_integer_suffixes, invalid_p == 0. */
+ /* Skip verify of stap_register_prefixes, invalid_p == 0. */
+ /* Skip verify of stap_register_suffixes, invalid_p == 0. */
+ /* Skip verify of stap_register_indirection_prefixes, invalid_p == 0. */
+ /* Skip verify of stap_register_indirection_suffixes, invalid_p == 0. */
+ /* Skip verify of stap_gdb_register_prefix, invalid_p == 0. */
+ /* Skip verify of stap_gdb_register_suffix, invalid_p == 0. */
/* Skip verify of stap_is_single_operand, has predicate. */
/* Skip verify of stap_parse_special_token, has predicate. */
/* Skip verify of stap_adjust_register, has predicate. */
@@ -494,39 +494,39 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of dtrace_probe_is_enabled, has predicate. */
/* Skip verify of dtrace_enable_probe, has predicate. */
/* Skip verify of dtrace_disable_probe, has predicate. */
- /* Skip verify of has_global_solist, invalid_p == 0 */
- /* Skip verify of has_global_breakpoints, invalid_p == 0 */
- /* Skip verify of has_shared_address_space, invalid_p == 0 */
- /* Skip verify of fast_tracepoint_valid_at, invalid_p == 0 */
- /* Skip verify of guess_tracepoint_registers, invalid_p == 0 */
- /* Skip verify of auto_charset, invalid_p == 0 */
- /* Skip verify of auto_wide_charset, invalid_p == 0 */
- /* Skip verify of solib_symbols_extension, invalid_p == 0 */
- /* Skip verify of has_dos_based_file_system, invalid_p == 0 */
- /* Skip verify of gen_return_address, invalid_p == 0 */
+ /* Skip verify of has_global_solist, invalid_p == 0. */
+ /* Skip verify of has_global_breakpoints, invalid_p == 0. */
+ /* Skip verify of has_shared_address_space, invalid_p == 0. */
+ /* Skip verify of fast_tracepoint_valid_at, invalid_p == 0. */
+ /* Skip verify of guess_tracepoint_registers, invalid_p == 0. */
+ /* Skip verify of auto_charset, invalid_p == 0. */
+ /* Skip verify of auto_wide_charset, invalid_p == 0. */
+ /* Skip verify of solib_symbols_extension, invalid_p == 0. */
+ /* Skip verify of has_dos_based_file_system, invalid_p == 0. */
+ /* 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 */
- /* Skip verify of insn_is_jump, invalid_p == 0 */
- /* Skip verify of program_breakpoint_here_p, invalid_p == 0 */
+ /* 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. */
+ /* Skip verify of insn_is_jump, invalid_p == 0. */
+ /* Skip verify of program_breakpoint_here_p, invalid_p == 0. */
/* Skip verify of auxv_parse, has predicate. */
- /* Skip verify of print_auxv_entry, invalid_p == 0 */
- /* Skip verify of vsyscall_range, invalid_p == 0 */
- /* Skip verify of infcall_mmap, invalid_p == 0 */
- /* Skip verify of infcall_munmap, invalid_p == 0 */
- /* Skip verify of gcc_target_options, invalid_p == 0 */
- /* Skip verify of gnu_triplet_regexp, invalid_p == 0 */
- /* Skip verify of addressable_memory_unit_size, invalid_p == 0 */
- /* Skip verify of disassembler_options_implicit, invalid_p == 0 */
- /* Skip verify of disassembler_options, invalid_p == 0 */
- /* Skip verify of valid_disassembler_options, invalid_p == 0 */
- /* Skip verify of type_align, invalid_p == 0 */
- /* Skip verify of get_pc_address_flags, invalid_p == 0 */
- /* 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 print_auxv_entry, invalid_p == 0. */
+ /* Skip verify of vsyscall_range, invalid_p == 0. */
+ /* Skip verify of infcall_mmap, invalid_p == 0. */
+ /* Skip verify of infcall_munmap, invalid_p == 0. */
+ /* Skip verify of gcc_target_options, invalid_p == 0. */
+ /* Skip verify of gnu_triplet_regexp, invalid_p == 0. */
+ /* Skip verify of addressable_memory_unit_size, invalid_p == 0. */
+ /* Skip verify of disassembler_options_implicit, invalid_p == 0. */
+ /* Skip verify of disassembler_options, invalid_p == 0. */
+ /* Skip verify of valid_disassembler_options, invalid_p == 0. */
+ /* Skip verify of type_align, invalid_p == 0. */
+ /* Skip verify of get_pc_address_flags, invalid_p == 0. */
+ /* Skip verify of read_core_file_mappings, invalid_p == 0. */
+ /* Skip verify of use_target_description_from_corefile_notes, invalid_p == 0. */
if (!log.empty ())
internal_error (_("verify_gdbarch: the following are invalid ...%s"),
log.c_str ());
@@ -1440,7 +1440,7 @@ int
gdbarch_short_bit (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of short_bit, invalid_p == 0 */
+ /* Skip verify of short_bit, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_short_bit called\n");
return gdbarch->short_bit;
@@ -1457,7 +1457,7 @@ int
gdbarch_int_bit (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of int_bit, invalid_p == 0 */
+ /* Skip verify of int_bit, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_int_bit called\n");
return gdbarch->int_bit;
@@ -1474,7 +1474,7 @@ int
gdbarch_long_bit (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of long_bit, invalid_p == 0 */
+ /* Skip verify of long_bit, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_long_bit called\n");
return gdbarch->long_bit;
@@ -1491,7 +1491,7 @@ int
gdbarch_long_long_bit (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of long_long_bit, invalid_p == 0 */
+ /* Skip verify of long_long_bit, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_long_long_bit called\n");
return gdbarch->long_long_bit;
@@ -1508,7 +1508,7 @@ int
gdbarch_bfloat16_bit (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of bfloat16_bit, invalid_p == 0 */
+ /* Skip verify of bfloat16_bit, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_bfloat16_bit called\n");
return gdbarch->bfloat16_bit;
@@ -1525,7 +1525,7 @@ const struct floatformat **
gdbarch_bfloat16_format (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of bfloat16_format, invalid_p == 0 */
+ /* Skip verify of bfloat16_format, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_bfloat16_format called\n");
return gdbarch->bfloat16_format;
@@ -1542,7 +1542,7 @@ int
gdbarch_half_bit (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of half_bit, invalid_p == 0 */
+ /* Skip verify of half_bit, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_half_bit called\n");
return gdbarch->half_bit;
@@ -1559,7 +1559,7 @@ const struct floatformat **
gdbarch_half_format (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of half_format, invalid_p == 0 */
+ /* Skip verify of half_format, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_half_format called\n");
return gdbarch->half_format;
@@ -1576,7 +1576,7 @@ int
gdbarch_float_bit (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of float_bit, invalid_p == 0 */
+ /* Skip verify of float_bit, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_float_bit called\n");
return gdbarch->float_bit;
@@ -1593,7 +1593,7 @@ const struct floatformat **
gdbarch_float_format (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of float_format, invalid_p == 0 */
+ /* Skip verify of float_format, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_float_format called\n");
return gdbarch->float_format;
@@ -1610,7 +1610,7 @@ int
gdbarch_double_bit (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of double_bit, invalid_p == 0 */
+ /* Skip verify of double_bit, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_double_bit called\n");
return gdbarch->double_bit;
@@ -1627,7 +1627,7 @@ const struct floatformat **
gdbarch_double_format (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of double_format, invalid_p == 0 */
+ /* Skip verify of double_format, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_double_format called\n");
return gdbarch->double_format;
@@ -1644,7 +1644,7 @@ int
gdbarch_long_double_bit (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of long_double_bit, invalid_p == 0 */
+ /* Skip verify of long_double_bit, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_long_double_bit called\n");
return gdbarch->long_double_bit;
@@ -1661,7 +1661,7 @@ const struct floatformat **
gdbarch_long_double_format (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of long_double_format, invalid_p == 0 */
+ /* Skip verify of long_double_format, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_long_double_format called\n");
return gdbarch->long_double_format;
@@ -1678,7 +1678,7 @@ int
gdbarch_wchar_bit (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of wchar_bit, invalid_p == 0 */
+ /* Skip verify of wchar_bit, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_wchar_bit called\n");
return gdbarch->wchar_bit;
@@ -1730,7 +1730,7 @@ int
gdbarch_ptr_bit (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of ptr_bit, invalid_p == 0 */
+ /* Skip verify of ptr_bit, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_ptr_bit called\n");
return gdbarch->ptr_bit;
@@ -1980,7 +1980,7 @@ int
gdbarch_num_pseudo_regs (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of num_pseudo_regs, invalid_p == 0 */
+ /* Skip verify of num_pseudo_regs, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_num_pseudo_regs called\n");
return gdbarch->num_pseudo_regs;
@@ -2069,7 +2069,7 @@ int
gdbarch_sp_regnum (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of sp_regnum, invalid_p == 0 */
+ /* Skip verify of sp_regnum, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_sp_regnum called\n");
return gdbarch->sp_regnum;
@@ -2086,7 +2086,7 @@ int
gdbarch_pc_regnum (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of pc_regnum, invalid_p == 0 */
+ /* Skip verify of pc_regnum, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_pc_regnum called\n");
return gdbarch->pc_regnum;
@@ -2103,7 +2103,7 @@ int
gdbarch_ps_regnum (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of ps_regnum, invalid_p == 0 */
+ /* Skip verify of ps_regnum, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_ps_regnum called\n");
return gdbarch->ps_regnum;
@@ -2120,7 +2120,7 @@ int
gdbarch_fp0_regnum (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of fp0_regnum, invalid_p == 0 */
+ /* Skip verify of fp0_regnum, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_fp0_regnum called\n");
return gdbarch->fp0_regnum;
@@ -2260,7 +2260,7 @@ int
gdbarch_deprecated_fp_regnum (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of deprecated_fp_regnum, invalid_p == 0 */
+ /* Skip verify of deprecated_fp_regnum, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_deprecated_fp_regnum called\n");
return gdbarch->deprecated_fp_regnum;
@@ -2301,7 +2301,7 @@ enum call_dummy_location_type
gdbarch_call_dummy_location (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of call_dummy_location, invalid_p == 0 */
+ /* Skip verify of call_dummy_location, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_call_dummy_location called\n");
return gdbarch->call_dummy_location;
@@ -2492,7 +2492,7 @@ int
gdbarch_believe_pcc_promotion (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of believe_pcc_promotion, invalid_p == 0 */
+ /* Skip verify of believe_pcc_promotion, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_believe_pcc_promotion called\n");
return gdbarch->believe_pcc_promotion;
@@ -2935,7 +2935,7 @@ CORE_ADDR
gdbarch_decr_pc_after_break (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of decr_pc_after_break, invalid_p == 0 */
+ /* Skip verify of decr_pc_after_break, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_decr_pc_after_break called\n");
return gdbarch->decr_pc_after_break;
@@ -2952,7 +2952,7 @@ CORE_ADDR
gdbarch_deprecated_function_start_offset (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of deprecated_function_start_offset, invalid_p == 0 */
+ /* Skip verify of deprecated_function_start_offset, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_deprecated_function_start_offset called\n");
return gdbarch->deprecated_function_start_offset;
@@ -3034,7 +3034,7 @@ CORE_ADDR
gdbarch_frame_args_skip (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of frame_args_skip, invalid_p == 0 */
+ /* Skip verify of frame_args_skip, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_frame_args_skip called\n");
return gdbarch->frame_args_skip;
@@ -3150,7 +3150,7 @@ int
gdbarch_frame_red_zone_size (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of frame_red_zone_size, invalid_p == 0 */
+ /* Skip verify of frame_red_zone_size, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_frame_red_zone_size called\n");
return gdbarch->frame_red_zone_size;
@@ -3303,7 +3303,7 @@ CORE_ADDR
gdbarch_memtag_granule_size (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of memtag_granule_size, invalid_p == 0 */
+ /* Skip verify of memtag_granule_size, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_memtag_granule_size called\n");
return gdbarch->memtag_granule_size;
@@ -3402,7 +3402,7 @@ const solib_ops *
gdbarch_so_ops (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of so_ops, invalid_p == 0 */
+ /* Skip verify of so_ops, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_so_ops called\n");
return gdbarch->so_ops;
@@ -3579,7 +3579,7 @@ int
gdbarch_cannot_step_breakpoint (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of cannot_step_breakpoint, invalid_p == 0 */
+ /* Skip verify of cannot_step_breakpoint, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_cannot_step_breakpoint called\n");
return gdbarch->cannot_step_breakpoint;
@@ -3596,7 +3596,7 @@ int
gdbarch_have_nonsteppable_watchpoint (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of have_nonsteppable_watchpoint, invalid_p == 0 */
+ /* Skip verify of have_nonsteppable_watchpoint, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_have_nonsteppable_watchpoint called\n");
return gdbarch->have_nonsteppable_watchpoint;
@@ -4056,7 +4056,7 @@ int
gdbarch_vtable_function_descriptors (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of vtable_function_descriptors, invalid_p == 0 */
+ /* Skip verify of vtable_function_descriptors, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_vtable_function_descriptors called\n");
return gdbarch->vtable_function_descriptors;
@@ -4073,7 +4073,7 @@ int
gdbarch_vbit_in_delta (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of vbit_in_delta, invalid_p == 0 */
+ /* Skip verify of vbit_in_delta, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_vbit_in_delta called\n");
return gdbarch->vbit_in_delta;
@@ -4363,7 +4363,7 @@ int
gdbarch_sofun_address_maybe_missing (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of sofun_address_maybe_missing, invalid_p == 0 */
+ /* Skip verify of sofun_address_maybe_missing, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_sofun_address_maybe_missing called\n");
return gdbarch->sofun_address_maybe_missing;
@@ -4548,7 +4548,7 @@ const char *
gdbarch_xml_syscall_file (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of xml_syscall_file, invalid_p == 0 */
+ /* Skip verify of xml_syscall_file, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_xml_syscall_file called\n");
return gdbarch->xml_syscall_file;
@@ -4565,7 +4565,7 @@ struct syscalls_info *
gdbarch_syscalls_info (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of syscalls_info, invalid_p == 0 */
+ /* Skip verify of syscalls_info, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_syscalls_info called\n");
return gdbarch->syscalls_info;
@@ -4582,7 +4582,7 @@ const char *const *
gdbarch_stap_integer_prefixes (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of stap_integer_prefixes, invalid_p == 0 */
+ /* Skip verify of stap_integer_prefixes, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_stap_integer_prefixes called\n");
return gdbarch->stap_integer_prefixes;
@@ -4599,7 +4599,7 @@ const char *const *
gdbarch_stap_integer_suffixes (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of stap_integer_suffixes, invalid_p == 0 */
+ /* Skip verify of stap_integer_suffixes, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_stap_integer_suffixes called\n");
return gdbarch->stap_integer_suffixes;
@@ -4616,7 +4616,7 @@ const char *const *
gdbarch_stap_register_prefixes (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of stap_register_prefixes, invalid_p == 0 */
+ /* Skip verify of stap_register_prefixes, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_stap_register_prefixes called\n");
return gdbarch->stap_register_prefixes;
@@ -4633,7 +4633,7 @@ const char *const *
gdbarch_stap_register_suffixes (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of stap_register_suffixes, invalid_p == 0 */
+ /* Skip verify of stap_register_suffixes, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_stap_register_suffixes called\n");
return gdbarch->stap_register_suffixes;
@@ -4650,7 +4650,7 @@ const char *const *
gdbarch_stap_register_indirection_prefixes (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of stap_register_indirection_prefixes, invalid_p == 0 */
+ /* Skip verify of stap_register_indirection_prefixes, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_stap_register_indirection_prefixes called\n");
return gdbarch->stap_register_indirection_prefixes;
@@ -4667,7 +4667,7 @@ const char *const *
gdbarch_stap_register_indirection_suffixes (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of stap_register_indirection_suffixes, invalid_p == 0 */
+ /* Skip verify of stap_register_indirection_suffixes, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_stap_register_indirection_suffixes called\n");
return gdbarch->stap_register_indirection_suffixes;
@@ -4684,7 +4684,7 @@ const char *
gdbarch_stap_gdb_register_prefix (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of stap_gdb_register_prefix, invalid_p == 0 */
+ /* Skip verify of stap_gdb_register_prefix, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_stap_gdb_register_prefix called\n");
return gdbarch->stap_gdb_register_prefix;
@@ -4701,7 +4701,7 @@ const char *
gdbarch_stap_gdb_register_suffix (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of stap_gdb_register_suffix, invalid_p == 0 */
+ /* Skip verify of stap_gdb_register_suffix, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_stap_gdb_register_suffix called\n");
return gdbarch->stap_gdb_register_suffix;
@@ -4886,7 +4886,7 @@ int
gdbarch_has_global_solist (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of has_global_solist, invalid_p == 0 */
+ /* Skip verify of has_global_solist, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_has_global_solist called\n");
return gdbarch->has_global_solist;
@@ -4903,7 +4903,7 @@ int
gdbarch_has_global_breakpoints (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of has_global_breakpoints, invalid_p == 0 */
+ /* Skip verify of has_global_breakpoints, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_has_global_breakpoints called\n");
return gdbarch->has_global_breakpoints;
@@ -5005,7 +5005,7 @@ const char *
gdbarch_solib_symbols_extension (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of solib_symbols_extension, invalid_p == 0 */
+ /* Skip verify of solib_symbols_extension, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_solib_symbols_extension called\n");
return gdbarch->solib_symbols_extension;
@@ -5022,7 +5022,7 @@ int
gdbarch_has_dos_based_file_system (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of has_dos_based_file_system, invalid_p == 0 */
+ /* Skip verify of has_dos_based_file_system, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_has_dos_based_file_system called\n");
return gdbarch->has_dos_based_file_system;
@@ -5121,7 +5121,7 @@ struct ravenscar_arch_ops *
gdbarch_ravenscar_ops (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of ravenscar_ops, invalid_p == 0 */
+ /* Skip verify of ravenscar_ops, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_ravenscar_ops called\n");
return gdbarch->ravenscar_ops;
@@ -5349,7 +5349,7 @@ const char *
gdbarch_disassembler_options_implicit (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of disassembler_options_implicit, invalid_p == 0 */
+ /* Skip verify of disassembler_options_implicit, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_disassembler_options_implicit called\n");
return gdbarch->disassembler_options_implicit;
@@ -5366,7 +5366,7 @@ std::string *
gdbarch_disassembler_options (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of disassembler_options, invalid_p == 0 */
+ /* Skip verify of disassembler_options, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_disassembler_options called\n");
return gdbarch->disassembler_options;
@@ -5383,7 +5383,7 @@ const disasm_options_and_args_t *
gdbarch_valid_disassembler_options (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- /* Skip verify of valid_disassembler_options, invalid_p == 0 */
+ /* Skip verify of valid_disassembler_options, invalid_p == 0. */
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_valid_disassembler_options called\n");
return gdbarch->valid_disassembler_options;
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 5175ef7..60a0f60 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -316,7 +316,7 @@ extern obstack *gdbarch_obstack (gdbarch *arch);
extern char *gdbarch_obstack_strdup (struct gdbarch *arch, const char *string);
-/* Helper function. Force an update of the current architecture.
+/* Helper function. Force an update of INF's architecture.
The actual architecture selected is determined by INFO, ``(gdb) set
architecture'' et.al., the existing architecture and BFD's default
@@ -325,8 +325,7 @@ extern char *gdbarch_obstack_strdup (struct gdbarch *arch, const char *string);
Returns non-zero if the update succeeds. */
-extern int gdbarch_update_p (struct gdbarch_info info);
-
+extern int gdbarch_update_p (inferior *inf, gdbarch_info info);
/* Helper function. Find an architecture matching info.
diff --git a/gdb/gdbarch.py b/gdb/gdbarch.py
index 4b4db66..dd1658d 100755
--- a/gdb/gdbarch.py
+++ b/gdb/gdbarch.py
@@ -119,7 +119,7 @@ with open("gdbarch-gen.h", "w") as f:
file=f,
)
-with open("gdbarch.c", "w") as f:
+with open("gdbarch-gen.c", "w") as f:
print(copyright, file=f)
print(file=f)
print(file=f)
@@ -233,7 +233,7 @@ with open("gdbarch.c", "w") as f:
print(f" if (gdbarch->{c.name} == {init_value})", file=f)
print(f""" log.puts ("\\n\\t{c.name}");""", file=f)
else:
- print(f" /* Skip verify of {c.name}, invalid_p == 0 */", file=f)
+ print(f" /* Skip verify of {c.name}, invalid_p == 0. */", file=f)
print(" if (!log.empty ())", file=f)
print(
""" internal_error (_("verify_gdbarch: the following are invalid ...%s"),""",
@@ -361,7 +361,7 @@ with open("gdbarch.c", "w") as f:
print(" /* Check variable changed from its initial value. */", file=f)
print(f" gdb_assert (gdbarch->{c.name} != {init_value});", file=f)
else:
- print(f" /* Skip verify of {c.name}, invalid_p == 0 */", file=f)
+ print(f" /* Skip verify of {c.name}, invalid_p == 0. */", file=f)
print(" if (gdbarch_debug >= 2)", file=f)
print(
f""" gdb_printf (gdb_stdlog, "gdbarch_{c.name} called\\n");""",
diff --git a/gdb/gdbcore.h b/gdb/gdbcore.h
index d6aeb35..782643a 100644
--- a/gdb/gdbcore.h
+++ b/gdb/gdbcore.h
@@ -196,4 +196,70 @@ private:
std::string m_storage;
};
+/* Type returned from core_target_find_mapped_file. Holds information
+ about a mapped file that was processed when a core file was initially
+ loaded. */
+struct core_target_mapped_file_info
+{
+ /* Constructor. BUILD_ID is not nullptr, and is the build-id for the
+ mapped file. FILENAME is the location of the file that GDB loaded to
+ provide the mapped file. This might be different from the name of the
+ mapped file mentioned in the core file, e.g. if GDB downloads a file
+ from debuginfod then FILENAME would point into the debuginfod client
+ cache. The FILENAME can be the empty string if GDB was unable to find
+ a file to provide the mapped file. */
+
+ core_target_mapped_file_info (const bfd_build_id *build_id,
+ const std::string filename)
+ : m_build_id (build_id),
+ m_filename (filename)
+ {
+ gdb_assert (m_build_id != nullptr);
+ }
+
+ /* The build-id for this mapped file. */
+
+ const bfd_build_id *
+ build_id () const
+ {
+ return m_build_id;
+ }
+
+ /* The file GDB used to provide this mapped file. */
+
+ const std::string &
+ filename () const
+ {
+ return m_filename;
+ }
+
+private:
+ const bfd_build_id *m_build_id = nullptr;
+ const std::string m_filename;
+};
+
+/* If the current inferior has a core_target for its process target, then
+ lookup information about a mapped file that was discovered when the
+ core file was loaded.
+
+ The FILENAME is the file we're looking for. The ADDR, if provided, is a
+ mapped address within the inferior which is known to be part of the file
+ we are looking for.
+
+ As an example, when loading shared libraries this function can be
+ called, in that case FILENAME will be the name of the shared library
+ that GDB is trying to load and ADDR will be an inferior address which is
+ part of the shared library we are looking for.
+
+ This function looks for a mapped file which matches FILENAME and/or
+ which covers ADDR and returns information about that file.
+
+ The returned information includes the name of the mapped file if known
+ and the build-id for the mapped file if known.
+
+ */
+std::optional<core_target_mapped_file_info>
+core_target_find_mapped_file (const char *filename,
+ std::optional<CORE_ADDR> addr);
+
#endif /* !defined (GDBCORE_H) */
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index f39fe3d..323f15d 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -631,7 +631,7 @@ address_space_name_to_type_instance_flags (struct gdbarch *gdbarch,
}
/* Identify address space identifier by type_instance_flags and return
- the string version of the adress space name. */
+ the string version of the address space name. */
const char *
address_space_type_instance_flags_to_name (struct gdbarch *gdbarch,
@@ -733,7 +733,7 @@ make_type_with_address_space (struct type *type,
If TYPEPTR and *TYPEPTR are non-zero, then *TYPEPTR points to
storage to hold the new qualified type; *TYPEPTR and TYPE must be
in the same objfile. Otherwise, allocate fresh memory for the new
- type whereever TYPE lives. If TYPEPTR is non-zero, set it to the
+ type wherever TYPE lives. If TYPEPTR is non-zero, set it to the
new type we construct. */
struct type *
@@ -816,7 +816,7 @@ make_atomic_type (struct type *type)
/* Replace the contents of ntype with the type *type. This changes the
contents, rather than the pointer for TYPE_MAIN_TYPE (ntype); thus
- the changes are propogated to all types in the TYPE_CHAIN.
+ the changes are propagated to all types in the TYPE_CHAIN.
In order to build recursive types, it's inevitable that we'll need
to update types in place --- but this sort of indiscriminate
@@ -1371,7 +1371,7 @@ create_array_type_with_stride (type_allocator &alloc,
undefined by setting it to zero. Although we are not expected
to trust TYPE_LENGTH in this case, setting the size to zero
allows us to avoid allocating objects of random sizes in case
- we accidently do. */
+ we accidentally do. */
result_type->set_length (0);
}
@@ -1553,7 +1553,7 @@ set_type_self_type (struct type *type, struct type *self_type)
}
/* Smash TYPE to be a type of pointers to members of SELF_TYPE with type
- TO_TYPE. A member pointer is a wierd thing -- it amounts to a
+ TO_TYPE. A member pointer is a weird thing -- it amounts to a
typed offset into a struct, e.g. "an int at offset 8". A MEMBER
TYPE doesn't include the offset (that's the value of the MEMBER
itself), but does include the structure type into which it points
diff --git a/gdb/glibc-tdep.c b/gdb/glibc-tdep.c
index 48e080a..e3bf00c 100644
--- a/gdb/glibc-tdep.c
+++ b/gdb/glibc-tdep.c
@@ -52,18 +52,20 @@ glibc_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
of GNU/Linux will provide a portable, efficient interface for
debugging programs that use shared libraries. */
- struct bound_minimal_symbol resolver
- = lookup_bound_minimal_symbol ("_dl_runtime_resolve");
+ bound_minimal_symbol resolver
+ = lookup_minimal_symbol (current_program_space, "_dl_runtime_resolve");
if (resolver.minsym)
{
/* The dynamic linker began using this name in early 2005. */
- struct bound_minimal_symbol fixup
- = lookup_minimal_symbol ("_dl_fixup", NULL, resolver.objfile);
-
+ bound_minimal_symbol fixup
+ = lookup_minimal_symbol (current_program_space, "_dl_fixup",
+ resolver.objfile);
+
/* This is the name used in older versions. */
if (! fixup.minsym)
- fixup = lookup_minimal_symbol ("fixup", NULL, resolver.objfile);
+ fixup = lookup_minimal_symbol (current_program_space, "fixup",
+ resolver.objfile);
if (fixup.minsym && fixup.value_address () == pc)
return frame_unwind_caller_pc (get_current_frame ());
diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c
index 7f1614c..6cfac08 100644
--- a/gdb/gnu-nat.c
+++ b/gdb/gnu-nat.c
@@ -1221,7 +1221,7 @@ inf_update_signal_thread (struct inf *inf)
}
-/* Detachs from INF's inferior task, letting it run once again... */
+/* Detach from INF's inferior task, letting it run once again... */
void
gnu_nat_target::inf_detach (struct inf *inf)
{
diff --git a/gdb/gnu-v2-abi.c b/gdb/gnu-v2-abi.c
index 7b511ea..0a9c09e 100644
--- a/gdb/gnu-v2-abi.c
+++ b/gdb/gnu-v2-abi.c
@@ -186,7 +186,6 @@ gnuv2_value_rtti_type (struct value *v, int *full, LONGEST *top, int *using_enc)
struct type *known_type;
struct type *rtti_type;
CORE_ADDR vtbl;
- struct bound_minimal_symbol minsym;
char *p;
const char *linkage_name;
struct type *btype;
@@ -239,7 +238,7 @@ gnuv2_value_rtti_type (struct value *v, int *full, LONGEST *top, int *using_enc)
vtbl = value_as_address (value_field (v, known_type_vptr_fieldno));
/* Try to find a symbol that is the vtable. */
- minsym=lookup_minimal_symbol_by_pc(vtbl);
+ bound_minimal_symbol minsym = lookup_minimal_symbol_by_pc (vtbl);
if (minsym.minsym==NULL
|| (linkage_name=minsym.minsym->linkage_name ())==NULL
|| !is_vtable_name (linkage_name))
diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c
index 1311a99..aefbee5 100644
--- a/gdb/gnu-v3-abi.c
+++ b/gdb/gnu-v3-abi.c
@@ -1161,7 +1161,7 @@ gnuv3_get_typeid (struct value *value)
{
std::string sym_name = std::string ("typeinfo for ") + name;
bound_minimal_symbol minsym
- = lookup_minimal_symbol (sym_name.c_str (), NULL, NULL);
+ = lookup_minimal_symbol (current_program_space, sym_name.c_str ());
if (minsym.minsym == NULL)
error (_("could not find typeinfo symbol for '%s'"), name);
@@ -1178,14 +1178,13 @@ static std::string
gnuv3_get_typename_from_type_info (struct value *type_info_ptr)
{
struct gdbarch *gdbarch = type_info_ptr->type ()->arch ();
- struct bound_minimal_symbol typeinfo_sym;
CORE_ADDR addr;
const char *symname;
const char *class_name;
const char *atsign;
addr = value_as_address (type_info_ptr);
- typeinfo_sym = lookup_minimal_symbol_by_pc (addr);
+ bound_minimal_symbol typeinfo_sym = lookup_minimal_symbol_by_pc (addr);
if (typeinfo_sym.minsym == NULL)
error (_("could not find minimal symbol for typeinfo address %s"),
paddress (gdbarch, addr));
@@ -1229,7 +1228,6 @@ gnuv3_skip_trampoline (const frame_info_ptr &frame, CORE_ADDR stop_pc)
{
CORE_ADDR real_stop_pc, method_stop_pc, func_addr;
struct gdbarch *gdbarch = get_frame_arch (frame);
- struct bound_minimal_symbol thunk_sym, fn_sym;
struct obj_section *section;
const char *thunk_name, *fn_name;
@@ -1238,7 +1236,7 @@ gnuv3_skip_trampoline (const frame_info_ptr &frame, CORE_ADDR stop_pc)
real_stop_pc = stop_pc;
/* Find the linker symbol for this potential thunk. */
- thunk_sym = lookup_minimal_symbol_by_pc (real_stop_pc);
+ bound_minimal_symbol thunk_sym = lookup_minimal_symbol_by_pc (real_stop_pc);
section = find_pc_section (real_stop_pc);
if (thunk_sym.minsym == NULL || section == NULL)
return 0;
@@ -1251,7 +1249,8 @@ gnuv3_skip_trampoline (const frame_info_ptr &frame, CORE_ADDR stop_pc)
return 0;
fn_name = strstr (thunk_name, " thunk to ") + strlen (" thunk to ");
- fn_sym = lookup_minimal_symbol (fn_name, NULL, section->objfile);
+ bound_minimal_symbol fn_sym
+ = lookup_minimal_symbol (current_program_space, fn_name, section->objfile);
if (fn_sym.minsym == NULL)
return 0;
diff --git a/gdb/go-exp.y b/gdb/go-exp.y
index 1a6ebbe..8fd6737 100644
--- a/gdb/go-exp.y
+++ b/gdb/go-exp.y
@@ -569,16 +569,15 @@ variable: name_not_typename
}
else
{
- struct bound_minimal_symbol msymbol;
std::string arg = copy_name ($1.stoken);
- msymbol =
- lookup_bound_minimal_symbol (arg.c_str ());
+ bound_minimal_symbol msymbol =
+ lookup_minimal_symbol (current_program_space, arg.c_str ());
if (msymbol.minsym != NULL)
pstate->push_new<var_msym_value_operation>
(msymbol);
- else if (!have_full_symbols ()
- && !have_partial_symbols ())
+ else if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space))
error (_("No symbol table is loaded. "
"Use the \"file\" command."));
else
diff --git a/gdb/go-lang.c b/gdb/go-lang.c
index 8b4250b..18d3fc1 100644
--- a/gdb/go-lang.c
+++ b/gdb/go-lang.c
@@ -54,9 +54,8 @@ static const char GO_MAIN_MAIN[] = "main.main";
const char *
go_main_name (void)
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol (GO_MAIN_MAIN, NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, GO_MAIN_MAIN);
if (msym.minsym != NULL)
return GO_MAIN_MAIN;
diff --git a/gdb/guile/guile-internal.h b/gdb/guile/guile-internal.h
index be16fee..dea7884 100644
--- a/gdb/guile/guile-internal.h
+++ b/gdb/guile/guile-internal.h
@@ -326,32 +326,32 @@ extern SCM gdbscm_make_type_error (const char *subr, int arg_pos,
extern SCM gdbscm_make_invalid_object_error (const char *subr, int arg_pos,
SCM bad_value, const char *error);
-extern void gdbscm_invalid_object_error (const char *subr, int arg_pos,
- SCM bad_value, const char *error)
- ATTRIBUTE_NORETURN;
+[[noreturn]] extern void gdbscm_invalid_object_error (const char *subr,
+ int arg_pos,
+ SCM bad_value,
+ const char *error);
extern SCM gdbscm_make_out_of_range_error (const char *subr, int arg_pos,
SCM bad_value, const char *error);
-extern void gdbscm_out_of_range_error (const char *subr, int arg_pos,
- SCM bad_value, const char *error)
- ATTRIBUTE_NORETURN;
+[[noreturn]] extern void gdbscm_out_of_range_error (const char *subr,
+ int arg_pos, SCM bad_value,
+ const char *error);
extern SCM gdbscm_make_misc_error (const char *subr, int arg_pos,
SCM bad_value, const char *error);
-extern void gdbscm_misc_error (const char *subr, int arg_pos,
- SCM bad_value, const char *error)
- ATTRIBUTE_NORETURN;
+[[noreturn]] extern void gdbscm_misc_error (const char *subr, int arg_pos,
+ SCM bad_value, const char *error);
-extern void gdbscm_throw (SCM exception) ATTRIBUTE_NORETURN;
+[[noreturn]] extern void gdbscm_throw (SCM exception);
struct gdbscm_gdb_exception;
extern SCM gdbscm_scm_from_gdb_exception
(const gdbscm_gdb_exception &exception);
-extern void gdbscm_throw_gdb_exception (gdbscm_gdb_exception exception)
- ATTRIBUTE_NORETURN;
+[[noreturn]] extern void gdbscm_throw_gdb_exception
+ (gdbscm_gdb_exception exception);
extern void gdbscm_print_exception_with_stack (SCM port, SCM stack,
SCM key, SCM args);
@@ -368,8 +368,8 @@ extern excp_matcher_func gdbscm_user_error_p;
extern SCM gdbscm_make_memory_error (const char *subr, const char *msg,
SCM args);
-extern void gdbscm_memory_error (const char *subr, const char *msg, SCM args)
- ATTRIBUTE_NORETURN;
+[[noreturn]] extern void gdbscm_memory_error (const char *subr,
+ const char *msg, SCM args);
/* scm-safe-call.c */
diff --git a/gdb/guile/guile.c b/gdb/guile/guile.c
index dbbb96e..432093b 100644
--- a/gdb/guile/guile.c
+++ b/gdb/guile/guile.c
@@ -124,6 +124,7 @@ static const struct extension_language_ops guile_extension_ops =
gdbscm_apply_val_pretty_printer,
NULL, /* gdbscm_apply_frame_filter, */
+ NULL, /* gdbscm_load_ptwrite_filter, */
gdbscm_preserve_values,
diff --git a/gdb/guile/scm-cmd.c b/gdb/guile/scm-cmd.c
index 2a55076..8255529 100644
--- a/gdb/guile/scm-cmd.c
+++ b/gdb/guile/scm-cmd.c
@@ -110,7 +110,7 @@ struct cmdscm_completer
static const struct cmdscm_completer cmdscm_completers[] =
{
{ "COMPLETE_NONE", noop_completer },
- { "COMPLETE_FILENAME", filename_completer },
+ { "COMPLETE_FILENAME", filename_maybe_quoted_completer },
{ "COMPLETE_LOCATION", location_completer },
{ "COMPLETE_COMMAND", command_completer },
{ "COMPLETE_SYMBOL", symbol_completer },
diff --git a/gdb/guile/scm-objfile.c b/gdb/guile/scm-objfile.c
index bccf6ba..d6c0559 100644
--- a/gdb/guile/scm-objfile.c
+++ b/gdb/guile/scm-objfile.c
@@ -250,7 +250,7 @@ gdbscm_objfile_progspace (SCM self)
objfile_smob *o_smob
= ofscm_get_valid_objfile_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
- return psscm_scm_from_pspace (o_smob->objfile->pspace);
+ return psscm_scm_from_pspace (o_smob->objfile->pspace ());
}
/* (objfile-pretty-printers <gdb:objfile>) -> list
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c
index c15a9fc..ad93c2b 100644
--- a/gdb/hppa-tdep.c
+++ b/gdb/hppa-tdep.c
@@ -194,9 +194,8 @@ hppa_extract_17 (unsigned word)
CORE_ADDR
hppa_symbol_address(const char *sym)
{
- struct bound_minimal_symbol minsym;
-
- minsym = lookup_minimal_symbol (sym, NULL, NULL);
+ bound_minimal_symbol minsym
+ = lookup_minimal_symbol (current_program_space, sym);
if (minsym.minsym)
return minsym.value_address ();
else
diff --git a/gdb/i386-darwin-nat.c b/gdb/i386-darwin-nat.c
index 5965599..55c6123 100644
--- a/gdb/i386-darwin-nat.c
+++ b/gdb/i386-darwin-nat.c
@@ -499,7 +499,7 @@ darwin_check_osabi (darwin_inferior *inf, thread_t thread)
else
info.bfd_arch_info = bfd_lookup_arch (bfd_arch_i386,
bfd_mach_i386_i386);
- gdbarch_update_p (info);
+ gdbarch_update_p (current_inferior (), info);
}
}
diff --git a/gdb/i386-fbsd-nat.c b/gdb/i386-fbsd-nat.c
index f4538fb..d9f4067 100644
--- a/gdb/i386-fbsd-nat.c
+++ b/gdb/i386-fbsd-nat.c
@@ -254,7 +254,7 @@ i386_fbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
request = PT_CONTINUE;
}
- /* An addres of (caddr_t) 1 tells ptrace to continue from where it
+ /* An address of (caddr_t) 1 tells ptrace to continue from where it
was. (If GDB wanted it to start some other way, we have already
written a new PC value to the child.) */
if (ptrace (request, pid, (caddr_t) 1,
diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
index bfe3fb8..41c1113 100644
--- a/gdb/i386-linux-nat.c
+++ b/gdb/i386-linux-nat.c
@@ -259,7 +259,7 @@ fill_fpregset (const struct regcache *regcache,
#ifdef HAVE_PTRACE_GETREGS
/* Fetch all floating-point registers from process/thread TID and store
- thier values in GDB's register array. */
+ their values in GDB's register array. */
static void
fetch_fpregs (struct regcache *regcache, int tid)
@@ -315,19 +315,19 @@ fetch_xstateregs (struct regcache *regcache, int tid)
{
struct gdbarch *gdbarch = regcache->arch ();
const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
- char xstateregs[tdep->xsave_layout.sizeof_xsave];
+ gdb::byte_vector xstateregs (tdep->xsave_layout.sizeof_xsave);
struct iovec iov;
if (have_ptrace_getregset != TRIBOOL_TRUE)
return 0;
- iov.iov_base = xstateregs;
- iov.iov_len = sizeof(xstateregs);
+ iov.iov_base = xstateregs.data ();
+ iov.iov_len = xstateregs.size ();
if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE,
&iov) < 0)
perror_with_name (_("Couldn't read extended state status"));
- i387_supply_xsave (regcache, -1, xstateregs);
+ i387_supply_xsave (regcache, -1, xstateregs.data ());
return 1;
}
@@ -340,19 +340,19 @@ store_xstateregs (const struct regcache *regcache, int tid, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
- char xstateregs[tdep->xsave_layout.sizeof_xsave];
+ gdb::byte_vector xstateregs (tdep->xsave_layout.sizeof_xsave);
struct iovec iov;
if (have_ptrace_getregset != TRIBOOL_TRUE)
return 0;
-
- iov.iov_base = xstateregs;
- iov.iov_len = sizeof(xstateregs);
+
+ iov.iov_base = xstateregs.data ();
+ iov.iov_len = xstateregs.size ();
if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE,
&iov) < 0)
perror_with_name (_("Couldn't read extended state status"));
- i387_collect_xsave (regcache, regno, xstateregs, 0);
+ i387_collect_xsave (regcache, regno, xstateregs.data (), 0);
if (ptrace (PTRACE_SETREGSET, tid, (unsigned int) NT_X86_XSTATE,
(int) &iov) < 0)
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index 6debed2..9dec83a 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -390,62 +390,6 @@ i386_canonicalize_syscall (int syscall)
#define SIG_CODE_BOUNDARY_FAULT 3
-/* i386 GNU/Linux implementation of the report_signal_info
- gdbarch hook. Displays information related to MPX bound
- violations. */
-void
-i386_linux_report_signal_info (struct gdbarch *gdbarch, struct ui_out *uiout,
- enum gdb_signal siggnal)
-{
- /* -Wmaybe-uninitialized */
- CORE_ADDR lower_bound = 0, upper_bound = 0, access = 0;
- int is_upper;
- long sig_code = 0;
-
- if (!i386_mpx_enabled () || siggnal != GDB_SIGNAL_SEGV)
- return;
-
- try
- {
- /* Sigcode evaluates if the actual segfault is a boundary violation. */
- sig_code = parse_and_eval_long ("$_siginfo.si_code\n");
-
- lower_bound
- = parse_and_eval_long ("$_siginfo._sifields._sigfault._addr_bnd._lower");
- upper_bound
- = parse_and_eval_long ("$_siginfo._sifields._sigfault._addr_bnd._upper");
- access
- = parse_and_eval_long ("$_siginfo._sifields._sigfault.si_addr");
- }
- catch (const gdb_exception_error &exception)
- {
- return;
- }
-
- /* If this is not a boundary violation just return. */
- if (sig_code != SIG_CODE_BOUNDARY_FAULT)
- return;
-
- is_upper = (access > upper_bound ? 1 : 0);
-
- uiout->text ("\n");
- if (is_upper)
- uiout->field_string ("sigcode-meaning", _("Upper bound violation"));
- else
- uiout->field_string ("sigcode-meaning", _("Lower bound violation"));
-
- uiout->text (_(" while accessing address "));
- uiout->field_core_addr ("bound-access", gdbarch, access);
-
- uiout->text (_("\nBounds: [lower = "));
- uiout->field_core_addr ("lower-bound", gdbarch, lower_bound);
-
- uiout->text (_(", upper = "));
- uiout->field_core_addr ("upper-bound", gdbarch, upper_bound);
-
- uiout->text (_("]"));
-}
-
/* Parse the arguments of current system call instruction and record
the values of the registers and memory that will be changed into
"record_arch_list". This instruction is "int 0x80" (Linux
@@ -608,6 +552,8 @@ int i386_linux_gregset_reg_offset[] =
-1, -1, -1, -1, -1, -1, -1, -1,
-1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ /* MPX is deprecated. Yet we keep this to not give the registers below
+ a new number. That could break older gdbservers. */
-1, -1, -1, -1, /* MPX registers BND0 ... BND3. */
-1, -1, /* MPX registers BNDCFGU, BNDSTATUS. */
-1, -1, -1, -1, -1, -1, -1, -1, /* k0 ... k7 (AVX512) */
@@ -721,12 +667,6 @@ i386_linux_supply_xstateregset (const struct regset *regset,
i387_supply_xsave (regcache, regnum, xstateregs);
}
-struct type *
-x86_linux_get_siginfo_type (struct gdbarch *gdbarch)
-{
- return linux_get_siginfo_type_with_fields (gdbarch, LINUX_SIGINFO_FIELD_ADDR_BND);
-}
-
/* Similar to i386_collect_fpregset, but use XSAVE extended state. */
static void
@@ -1064,9 +1004,6 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_I386);
set_gdbarch_get_syscall_number (gdbarch,
i386_linux_get_syscall_number);
-
- set_gdbarch_get_siginfo_type (gdbarch, x86_linux_get_siginfo_type);
- set_gdbarch_report_signal_info (gdbarch, i386_linux_report_signal_info);
}
void _initialize_i386_linux_tdep ();
diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h
index e8691cd..e169c1d 100644
--- a/gdb/i386-linux-tdep.h
+++ b/gdb/i386-linux-tdep.h
@@ -49,15 +49,6 @@ extern uint64_t i386_linux_core_read_xsave_info (bfd *abfd,
extern bool i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
x86_xsave_layout &layout);
-/* Handle and display information related to the MPX bound violation
- to the user. */
-extern void i386_linux_report_signal_info (struct gdbarch *gdbarch,
- struct ui_out *uiout,
- enum gdb_signal siggnal);
-
extern int i386_linux_gregset_reg_offset[];
-/* Return x86 siginfo type. */
-extern struct type *x86_linux_get_siginfo_type (struct gdbarch *gdbarch);
-
#endif /* i386-linux-tdep.h */
diff --git a/gdb/i386-nto-tdep.c b/gdb/i386-nto-tdep.c
deleted file mode 100644
index 6f34415..0000000
--- a/gdb/i386-nto-tdep.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/* Target-dependent code for QNX Neutrino x86.
-
- Copyright (C) 2003-2024 Free Software Foundation, Inc.
-
- Contributed by QNX Software Systems Ltd.
-
- 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 "extract-store-integer.h"
-#include "frame.h"
-#include "osabi.h"
-#include "regcache.h"
-#include "target.h"
-
-#include "i386-tdep.h"
-#include "i387-tdep.h"
-#include "nto-tdep.h"
-#include "solib.h"
-#include "solib-svr4.h"
-
-#ifndef X86_CPU_FXSR
-#define X86_CPU_FXSR (1L << 12)
-#endif
-
-/* Why 13? Look in our /usr/include/x86/context.h header at the
- x86_cpu_registers structure and you'll see an 'exx' junk register
- that is just filler. Don't ask me, ask the kernel guys. */
-#define NUM_GPREGS 13
-
-/* Mapping between the general-purpose registers in `struct xxx'
- format and GDB's register cache layout. */
-
-/* From <x86/context.h>. */
-static int i386nto_gregset_reg_offset[] =
-{
- 7 * 4, /* %eax */
- 6 * 4, /* %ecx */
- 5 * 4, /* %edx */
- 4 * 4, /* %ebx */
- 11 * 4, /* %esp */
- 2 * 4, /* %epb */
- 1 * 4, /* %esi */
- 0 * 4, /* %edi */
- 8 * 4, /* %eip */
- 10 * 4, /* %eflags */
- 9 * 4, /* %cs */
- 12 * 4, /* %ss */
- -1 /* filler */
-};
-
-/* Given a GDB register number REGNUM, return the offset into
- Neutrino's register structure or -1 if the register is unknown. */
-
-static int
-nto_reg_offset (int regnum)
-{
- if (regnum >= 0 && regnum < ARRAY_SIZE (i386nto_gregset_reg_offset))
- return i386nto_gregset_reg_offset[regnum];
-
- return -1;
-}
-
-static void
-i386nto_supply_gregset (struct regcache *regcache, char *gpregs)
-{
- struct gdbarch *gdbarch = regcache->arch ();
- i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
-
- gdb_assert (tdep->gregset_reg_offset == i386nto_gregset_reg_offset);
- i386_gregset.supply_regset (&i386_gregset, regcache, -1,
- gpregs, NUM_GPREGS * 4);
-}
-
-static void
-i386nto_supply_fpregset (struct regcache *regcache, char *fpregs)
-{
- if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
- i387_supply_fxsave (regcache, -1, fpregs);
- else
- i387_supply_fsave (regcache, -1, fpregs);
-}
-
-static void
-i386nto_supply_regset (struct regcache *regcache, int regset, char *data)
-{
- switch (regset)
- {
- case NTO_REG_GENERAL:
- i386nto_supply_gregset (regcache, data);
- break;
- case NTO_REG_FLOAT:
- i386nto_supply_fpregset (regcache, data);
- break;
- }
-}
-
-static int
-i386nto_regset_id (int regno)
-{
- if (regno == -1)
- return NTO_REG_END;
- else if (regno < I386_NUM_GREGS)
- return NTO_REG_GENERAL;
- else if (regno < I386_NUM_GREGS + I387_NUM_REGS)
- return NTO_REG_FLOAT;
- else if (regno < I386_SSE_NUM_REGS)
- return NTO_REG_FLOAT; /* We store xmm registers in fxsave_area. */
-
- return -1; /* Error. */
-}
-
-static int
-i386nto_register_area (struct gdbarch *gdbarch,
- int regno, int regset, unsigned *off)
-{
- i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
-
- *off = 0;
- if (regset == NTO_REG_GENERAL)
- {
- if (regno == -1)
- return NUM_GPREGS * 4;
-
- *off = nto_reg_offset (regno);
- if (*off == -1)
- return 0;
- return 4;
- }
- else if (regset == NTO_REG_FLOAT)
- {
- unsigned off_adjust, regsize, regset_size, regno_base;
- /* The following are flags indicating number in our fxsave_area. */
- int first_four = (regno >= I387_FCTRL_REGNUM (tdep)
- && regno <= I387_FISEG_REGNUM (tdep));
- int second_four = (regno > I387_FISEG_REGNUM (tdep)
- && regno <= I387_FOP_REGNUM (tdep));
- int st_reg = (regno >= I387_ST0_REGNUM (tdep)
- && regno < I387_ST0_REGNUM (tdep) + 8);
- int xmm_reg = (regno >= I387_XMM0_REGNUM (tdep)
- && regno < I387_MXCSR_REGNUM (tdep));
-
- if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
- {
- off_adjust = 32;
- regsize = 16;
- regset_size = 512;
- /* fxsave_area structure. */
- if (first_four)
- {
- /* fpu_control_word, fpu_status_word, fpu_tag_word, fpu_operand
- registers. */
- regsize = 2; /* Two bytes each. */
- off_adjust = 0;
- regno_base = I387_FCTRL_REGNUM (tdep);
- }
- else if (second_four)
- {
- /* fpu_ip, fpu_cs, fpu_op, fpu_ds registers. */
- regsize = 4;
- off_adjust = 8;
- regno_base = I387_FISEG_REGNUM (tdep) + 1;
- }
- else if (st_reg)
- {
- /* ST registers. */
- regsize = 16;
- off_adjust = 32;
- regno_base = I387_ST0_REGNUM (tdep);
- }
- else if (xmm_reg)
- {
- /* XMM registers. */
- regsize = 16;
- off_adjust = 160;
- regno_base = I387_XMM0_REGNUM (tdep);
- }
- else if (regno == I387_MXCSR_REGNUM (tdep))
- {
- regsize = 4;
- off_adjust = 24;
- regno_base = I387_MXCSR_REGNUM (tdep);
- }
- else
- {
- /* Whole regset. */
- gdb_assert (regno == -1);
- off_adjust = 0;
- regno_base = 0;
- regsize = regset_size;
- }
- }
- else
- {
- regset_size = 108;
- /* fsave_area structure. */
- if (first_four || second_four)
- {
- /* fpu_control_word, ... , fpu_ds registers. */
- regsize = 4;
- off_adjust = 0;
- regno_base = I387_FCTRL_REGNUM (tdep);
- }
- else if (st_reg)
- {
- /* One of ST registers. */
- regsize = 10;
- off_adjust = 7 * 4;
- regno_base = I387_ST0_REGNUM (tdep);
- }
- else
- {
- /* Whole regset. */
- gdb_assert (regno == -1);
- off_adjust = 0;
- regno_base = 0;
- regsize = regset_size;
- }
- }
-
- if (regno != -1)
- *off = off_adjust + (regno - regno_base) * regsize;
- else
- *off = 0;
- return regsize;
- }
- return -1;
-}
-
-static int
-i386nto_regset_fill (const struct regcache *regcache, int regset, char *data)
-{
- if (regset == NTO_REG_GENERAL)
- {
- int regno;
-
- for (regno = 0; regno < NUM_GPREGS; regno++)
- {
- int offset = nto_reg_offset (regno);
- if (offset != -1)
- regcache->raw_collect (regno, data + offset);
- }
- }
- else if (regset == NTO_REG_FLOAT)
- {
- if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
- i387_collect_fxsave (regcache, -1, data);
- else
- i387_collect_fsave (regcache, -1, data);
- }
- else
- return -1;
-
- return 0;
-}
-
-/* Return whether THIS_FRAME corresponds to a QNX Neutrino sigtramp
- routine. */
-
-static int
-i386nto_sigtramp_p (const frame_info_ptr &this_frame)
-{
- CORE_ADDR pc = get_frame_pc (this_frame);
- const char *name;
-
- find_pc_partial_function (pc, &name, NULL, NULL);
- return name && strcmp ("__signalstub", name) == 0;
-}
-
-/* Assuming THIS_FRAME is a QNX Neutrino sigtramp routine, return the
- address of the associated sigcontext structure. */
-
-static CORE_ADDR
-i386nto_sigcontext_addr (const frame_info_ptr &this_frame)
-{
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- gdb_byte buf[4];
- CORE_ADDR ptrctx;
-
- /* We store __ucontext_t addr in EDI register. */
- get_frame_register (this_frame, I386_EDI_REGNUM, buf);
- ptrctx = extract_unsigned_integer (buf, 4, byte_order);
- ptrctx += 24 /* Context pointer is at this offset. */;
-
- return ptrctx;
-}
-
-static void
-init_i386nto_ops (void)
-{
- nto_regset_id = i386nto_regset_id;
- nto_supply_gregset = i386nto_supply_gregset;
- nto_supply_fpregset = i386nto_supply_fpregset;
- nto_supply_altregset = nto_dummy_supply_regset;
- nto_supply_regset = i386nto_supply_regset;
- nto_register_area = i386nto_register_area;
- nto_regset_fill = i386nto_regset_fill;
- nto_fetch_link_map_offsets =
- svr4_ilp32_fetch_link_map_offsets;
-}
-
-static void
-i386nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
-{
- i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
- static solib_ops nto_svr4_so_ops;
-
- /* Deal with our strange signals. */
- nto_initialize_signals ();
-
- /* NTO uses ELF. */
- i386_elf_init_abi (info, gdbarch);
-
- /* Neutrino rewinds to look more normal. Need to override the i386
- default which is [unfortunately] to decrement the PC. */
- set_gdbarch_decr_pc_after_break (gdbarch, 0);
-
- tdep->gregset_reg_offset = i386nto_gregset_reg_offset;
- tdep->gregset_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
- tdep->sizeof_gregset = NUM_GPREGS * 4;
-
- tdep->sigtramp_p = i386nto_sigtramp_p;
- tdep->sigcontext_addr = i386nto_sigcontext_addr;
- tdep->sc_reg_offset = i386nto_gregset_reg_offset;
- tdep->sc_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
-
- /* Setjmp()'s return PC saved in EDX (5). */
- tdep->jb_pc_offset = 20; /* 5x32 bit ints in. */
-
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
-
- /* Initialize this lazily, to avoid an initialization order
- dependency on solib-svr4.c's _initialize routine. */
- if (nto_svr4_so_ops.in_dynsym_resolve_code == NULL)
- {
- nto_svr4_so_ops = svr4_so_ops;
-
- /* Our loader handles solib relocations differently than svr4. */
- nto_svr4_so_ops.relocate_section_addresses
- = nto_relocate_section_addresses;
-
- /* Supply a nice function to find our solibs. */
- nto_svr4_so_ops.find_and_open_solib
- = nto_find_and_open_solib;
-
- /* Our linker code is in libc. */
- nto_svr4_so_ops.in_dynsym_resolve_code
- = nto_in_dynsym_resolve_code;
- }
- set_gdbarch_so_ops (gdbarch, &nto_svr4_so_ops);
-
- set_gdbarch_wchar_bit (gdbarch, 32);
- set_gdbarch_wchar_signed (gdbarch, 0);
-}
-
-void _initialize_i386nto_tdep ();
-void
-_initialize_i386nto_tdep ()
-{
- init_i386nto_ops ();
- gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
- i386nto_init_abi);
- gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
- nto_elf_osabi_sniffer);
-}
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index f1f909e..d2c3efb 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -117,23 +117,12 @@ static const char * const i386_ymmh_names[] =
"ymm4h", "ymm5h", "ymm6h", "ymm7h",
};
-static const char * const i386_mpx_names[] =
-{
- "bnd0raw", "bnd1raw", "bnd2raw", "bnd3raw", "bndcfgu", "bndstatus"
-};
static const char * const i386_pkeys_names[] =
{
"pkru"
};
-/* Register names for MPX pseudo-registers. */
-
-static const char * const i386_bnd_names[] =
-{
- "bnd0", "bnd1", "bnd2", "bnd3"
-};
-
/* Register names for MMX pseudo-registers. */
static const char * const i386_mmx_names[] =
@@ -311,21 +300,6 @@ i386_ymm_avx512_regnum_p (struct gdbarch *gdbarch, int regnum)
return regnum >= 0 && regnum < tdep->num_ymm_avx512_regs;
}
-/* BND register? */
-
-int
-i386_bnd_regnum_p (struct gdbarch *gdbarch, int regnum)
-{
- i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
- int bnd0_regnum = tdep->bnd0_regnum;
-
- if (bnd0_regnum < 0)
- return 0;
-
- regnum -= bnd0_regnum;
- return regnum >= 0 && regnum < I387_NUM_BND_REGS;
-}
-
/* SSE register? */
int
@@ -393,34 +367,6 @@ i386_fpc_regnum_p (struct gdbarch *gdbarch, int regnum)
&& regnum < I387_XMM0_REGNUM (tdep));
}
-/* BNDr (raw) register? */
-
-static int
-i386_bndr_regnum_p (struct gdbarch *gdbarch, int regnum)
-{
- i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
-
- if (I387_BND0R_REGNUM (tdep) < 0)
- return 0;
-
- regnum -= tdep->bnd0r_regnum;
- return regnum >= 0 && regnum < I387_NUM_BND_REGS;
-}
-
-/* BND control register? */
-
-static int
-i386_mpx_ctrl_regnum_p (struct gdbarch *gdbarch, int regnum)
-{
- i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
-
- if (I387_BNDCFGU_REGNUM (tdep) < 0)
- return 0;
-
- regnum -= I387_BNDCFGU_REGNUM (tdep);
- return regnum >= 0 && regnum < I387_NUM_MPX_CTRL_REGS;
-}
-
/* PKRU register? */
bool
@@ -463,8 +409,6 @@ const char *
i386_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
{
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
- if (i386_bnd_regnum_p (gdbarch, regnum))
- return i386_bnd_names[regnum - tdep->bnd0_regnum];
if (i386_mmx_regnum_p (gdbarch, regnum))
return i386_mmx_names[regnum - I387_MM0_REGNUM (tdep)];
else if (i386_ymm_regnum_p (gdbarch, regnum))
@@ -1946,12 +1890,11 @@ i386_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
/* Make sure address is computed correctly as a 32bit
integer even if CORE_ADDR is 64 bit wide. */
- struct bound_minimal_symbol s;
CORE_ADDR call_dest;
call_dest = pc + 5 + extract_signed_integer (buf, 4, byte_order);
call_dest = call_dest & 0xffffffffU;
- s = lookup_minimal_symbol_by_pc (call_dest);
+ bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest);
if (s.minsym != NULL
&& s.minsym->linkage_name () != NULL
&& strcmp (s.minsym->linkage_name (), "__main") == 0)
@@ -2739,13 +2682,6 @@ i386_thiscall_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
int write_pass;
int args_space = 0;
- /* BND registers can be in arbitrary values at the moment of the
- inferior call. This can cause boundary violations that are not
- due to a real bug or even desired by the user. The best to be done
- is set the BND registers to allow access to the whole memory, INIT
- state, before pushing the inferior call. */
- i387_reset_bnd_regs (gdbarch, regcache);
-
/* Determine the total space required for arguments and struct
return address in a first pass (allowing for 16-byte-aligned
arguments), then push arguments in a second pass. */
@@ -3162,43 +3098,6 @@ i387_ext_type (struct gdbarch *gdbarch)
return tdep->i387_ext_type;
}
-/* Construct type for pseudo BND registers. We can't use
- tdesc_find_type since a complement of one value has to be used
- to describe the upper bound. */
-
-static struct type *
-i386_bnd_type (struct gdbarch *gdbarch)
-{
- i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
-
-
- if (!tdep->i386_bnd_type)
- {
- struct type *t;
- const struct builtin_type *bt = builtin_type (gdbarch);
-
- /* The type we're building is described bellow: */
-#if 0
- struct __bound128
- {
- void *lbound;
- void *ubound; /* One complement of raw ubound field. */
- };
-#endif
-
- t = arch_composite_type (gdbarch,
- "__gdb_builtin_type_bound128", TYPE_CODE_STRUCT);
-
- append_composite_type_field (t, "lbound", bt->builtin_data_ptr);
- append_composite_type_field (t, "ubound", bt->builtin_data_ptr);
-
- t->set_name ("builtin_type_bound128");
- tdep->i386_bnd_type = t;
- }
-
- return tdep->i386_bnd_type;
-}
-
/* Construct vector type for pseudo ZMM registers. We can't use
tdesc_find_type since ZMM isn't described in target description. */
@@ -3365,8 +3264,6 @@ i386_mmx_type (struct gdbarch *gdbarch)
struct type *
i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
{
- if (i386_bnd_regnum_p (gdbarch, regnum))
- return i386_bnd_type (gdbarch);
if (i386_mmx_regnum_p (gdbarch, regnum))
return i386_mmx_type (gdbarch);
else if (i386_ymm_regnum_p (gdbarch, regnum))
@@ -3426,39 +3323,7 @@ i386_pseudo_register_read_value (gdbarch *gdbarch, const frame_info_ptr &next_fr
else
{
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
- if (i386_bnd_regnum_p (gdbarch, pseudo_reg_num))
- {
- int i = pseudo_reg_num - tdep->bnd0_regnum;
-
- /* Extract (always little endian). Read lower 128bits. */
- value *bndr_value
- = value_of_register (I387_BND0R_REGNUM (tdep) + i, next_frame);
- int size = builtin_type (gdbarch)->builtin_data_ptr->length ();
- value *result
- = value::allocate_register (next_frame, pseudo_reg_num);
-
- /* Copy the lower. */
- bndr_value->contents_copy (result, 0, 0, size);
-
- /* Copy the upper. */
- bndr_value->contents_copy (result, size, 8, size);
-
- /* If upper bytes are available, compute ones' complement. */
- if (result->bytes_available (size, size))
- {
- bfd_endian byte_order
- = gdbarch_byte_order (frame_unwind_arch (next_frame));
- gdb::array_view<gdb_byte> upper_bytes
- = result->contents_raw ().slice (size, size);
- ULONGEST upper
- = extract_unsigned_integer (upper_bytes, byte_order);
- upper = ~upper;
- store_unsigned_integer (upper_bytes, byte_order, upper);
- }
-
- return result;
- }
- else if (i386_zmm_regnum_p (gdbarch, pseudo_reg_num))
+ if (i386_zmm_regnum_p (gdbarch, pseudo_reg_num))
{
/* Which register is it, relative to zmm0. */
int i_0 = pseudo_reg_num - tdep->zmm0_regnum;
@@ -3531,33 +3396,7 @@ i386_pseudo_register_write (gdbarch *gdbarch, const frame_info_ptr &next_frame,
{
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
- if (i386_bnd_regnum_p (gdbarch, pseudo_reg_num))
- {
- int size = builtin_type (gdbarch)->builtin_data_ptr->length ();
- bfd_endian byte_order
- = gdbarch_byte_order (current_inferior ()->arch ());
-
- /* New values from input value. */
- int reg_index = pseudo_reg_num - tdep->bnd0_regnum;
- int raw_regnum = I387_BND0R_REGNUM (tdep) + reg_index;
-
- value *bndr_value = value_of_register (raw_regnum, next_frame);
- gdb::array_view<gdb_byte> bndr_view
- = bndr_value->contents_writeable ();
-
- /* Copy lower bytes directly. */
- copy (buf.slice (0, size), bndr_view.slice (0, size));
-
- /* Convert and then copy upper bytes. */
- ULONGEST upper
- = extract_unsigned_integer (buf.slice (size, size), byte_order);
- upper = ~upper;
- store_unsigned_integer (bndr_view.slice (8, size), byte_order,
- upper);
-
- put_frame_register (next_frame, raw_regnum, bndr_view);
- }
- else if (i386_zmm_regnum_p (gdbarch, pseudo_reg_num))
+ if (i386_zmm_regnum_p (gdbarch, pseudo_reg_num))
{
/* Which register is it, relative to zmm0. */
int reg_index_0 = pseudo_reg_num - tdep->zmm0_regnum;
@@ -3628,12 +3467,6 @@ i386_ax_pseudo_register_collect (struct gdbarch *gdbarch,
ax_reg_mask (ax, I387_ST0_REGNUM (tdep) + i);
return 0;
}
- else if (i386_bnd_regnum_p (gdbarch, regnum))
- {
- regnum -= tdep->bnd0_regnum;
- ax_reg_mask (ax, I387_BND0R_REGNUM (tdep) + regnum);
- return 0;
- }
else if (i386_zmm_regnum_p (gdbarch, regnum))
{
regnum -= tdep->zmm0_regnum;
@@ -4481,9 +4314,8 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
int fp_regnum_p, mmx_regnum_p, xmm_regnum_p, mxcsr_regnum_p,
ymm_regnum_p, ymmh_regnum_p, ymm_avx512_regnum_p, ymmh_avx512_regnum_p,
- bndr_regnum_p, bnd_regnum_p, zmm_regnum_p, zmmh_regnum_p,
- mpx_ctrl_regnum_p, xmm_avx512_regnum_p,
- avx512_p, avx_p, sse_p, pkru_regnum_p;
+ zmm_regnum_p, zmmh_regnum_p, xmm_avx512_regnum_p, avx512_p, avx_p,
+ sse_p, pkru_regnum_p;
/* Don't include pseudo registers, except for MMX, in any register
groups. */
@@ -4543,21 +4375,6 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
|| zmmh_regnum_p))
return 0;
- bnd_regnum_p = i386_bnd_regnum_p (gdbarch, regnum);
- if (group == all_reggroup
- && ((bnd_regnum_p && (tdep->xcr0 & X86_XSTATE_MPX_MASK))))
- return bnd_regnum_p;
-
- bndr_regnum_p = i386_bndr_regnum_p (gdbarch, regnum);
- if (group == all_reggroup
- && ((bndr_regnum_p && (tdep->xcr0 & X86_XSTATE_MPX_MASK))))
- return 0;
-
- mpx_ctrl_regnum_p = i386_mpx_ctrl_regnum_p (gdbarch, regnum);
- if (group == all_reggroup
- && ((mpx_ctrl_regnum_p && (tdep->xcr0 & X86_XSTATE_MPX_MASK))))
- return mpx_ctrl_regnum_p;
-
if (group == general_reggroup)
return (!fp_regnum_p
&& !mmx_regnum_p
@@ -4568,9 +4385,6 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
&& !ymmh_regnum_p
&& !ymm_avx512_regnum_p
&& !ymmh_avx512_regnum_p
- && !bndr_regnum_p
- && !bnd_regnum_p
- && !mpx_ctrl_regnum_p
&& !zmm_regnum_p
&& !zmmh_regnum_p
&& !pkru_regnum_p);
@@ -8187,7 +8001,7 @@ i386_xcr0_from_tdesc (const struct target_desc *tdesc)
const struct tdesc_feature *feature_core;
- const struct tdesc_feature *feature_sse, *feature_avx, *feature_mpx,
+ const struct tdesc_feature *feature_sse, *feature_avx,
*feature_avx512, *feature_pkeys;
/* Get core registers. */
@@ -8201,9 +8015,6 @@ i386_xcr0_from_tdesc (const struct target_desc *tdesc)
/* Try AVX registers. */
feature_avx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx");
- /* Try MPX registers. */
- feature_mpx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx");
-
/* Try AVX512 registers. */
feature_avx512 = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx512");
@@ -8225,9 +8036,6 @@ i386_xcr0_from_tdesc (const struct target_desc *tdesc)
xcr0 |= X86_XSTATE_AVX;
}
- if (feature_mpx)
- xcr0 |= X86_XSTATE_MPX_MASK;
-
if (feature_avx512)
{
/* AVX512 register description requires AVX register description. */
@@ -8250,8 +8058,8 @@ i386_validate_tdesc_p (i386_gdbarch_tdep *tdep,
const struct target_desc *tdesc = tdep->tdesc;
const struct tdesc_feature *feature_core;
- const struct tdesc_feature *feature_sse, *feature_avx, *feature_mpx,
- *feature_avx512, *feature_pkeys, *feature_segments;
+ const struct tdesc_feature *feature_sse, *feature_avx, *feature_avx512,
+ *feature_pkeys, *feature_segments;
int i, num_regs, valid_p;
if (! tdesc_has_registers (tdesc))
@@ -8268,9 +8076,6 @@ i386_validate_tdesc_p (i386_gdbarch_tdep *tdep,
/* Try AVX registers. */
feature_avx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx");
- /* Try MPX registers. */
- feature_mpx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx");
-
/* Try AVX512 registers. */
feature_avx512 = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx512");
@@ -8369,23 +8174,6 @@ i386_validate_tdesc_p (i386_gdbarch_tdep *tdep,
tdep->register_names[i]);
}
- if (feature_mpx)
- {
- tdep->xcr0 |= X86_XSTATE_MPX_MASK;
-
- if (tdep->bnd0r_regnum < 0)
- {
- tdep->mpx_register_names = i386_mpx_names;
- tdep->bnd0r_regnum = I386_BND0R_REGNUM;
- tdep->bndcfgu_regnum = I386_BNDCFGU_REGNUM;
- }
-
- for (i = 0; i < I387_NUM_MPX_REGS; i++)
- valid_p &= tdesc_numbered_register (feature_mpx, tdesc_data,
- I387_BND0R_REGNUM (tdep) + i,
- tdep->mpx_register_names[i]);
- }
-
if (feature_segments)
{
if (tdep->fsbase_regnum < 0)
@@ -8449,8 +8237,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
const struct target_desc *tdesc;
int mm0_regnum;
int ymm0_regnum;
- int bnd0_regnum;
- int num_bnd_cooked;
x86_xsave_layout xsave_layout = target_fetch_x86_xsave_layout ();
@@ -8499,7 +8285,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->st0_regnum = I386_ST0_REGNUM;
- /* I386_NUM_XREGS includes %mxcsr, so substract one. */
+ /* I386_NUM_XREGS includes %mxcsr, so subtract one. */
tdep->num_xmm_regs = I386_NUM_XREGS - 1;
tdep->jb_pc_offset = -1;
@@ -8656,7 +8442,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Even though the default ABI only includes general-purpose registers,
floating-point registers and the SSE registers, we have to leave a
- gap for the upper AVX, MPX and AVX512 registers. */
+ gap for the upper AVX, (deprecated) MPX and AVX512 registers. */
set_gdbarch_num_regs (gdbarch, I386_NUM_REGS);
set_gdbarch_gnu_triplet_regexp (gdbarch, i386_gnu_triplet_regexp);
@@ -8692,10 +8478,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->num_mmx_regs = 8;
tdep->num_ymm_regs = 0;
- /* No MPX registers. */
- tdep->bnd0r_regnum = -1;
- tdep->bndcfgu_regnum = -1;
-
/* No AVX512 registers. */
tdep->k0_regnum = -1;
tdep->num_zmm_regs = 0;
@@ -8732,8 +8514,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
}
tdep->xsave_layout = xsave_layout;
- num_bnd_cooked = (tdep->bnd0r_regnum > 0 ? I387_NUM_BND_REGS : 0);
-
/* Wire in pseudo registers. Number of pseudo registers may be
changed. */
set_gdbarch_num_pseudo_regs (gdbarch, (tdep->num_byte_regs
@@ -8741,7 +8521,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ tdep->num_dword_regs
+ tdep->num_mmx_regs
+ tdep->num_ymm_regs
- + num_bnd_cooked
+ tdep->num_ymm_avx512_regs
+ tdep->num_zmm_regs));
@@ -8795,21 +8574,14 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
else
tdep->zmm0_regnum = -1;
- bnd0_regnum = mm0_regnum;
if (tdep->num_mmx_regs != 0)
{
/* Support MMX pseudo-register if MMX hasn't been disabled. */
tdep->mm0_regnum = mm0_regnum;
- bnd0_regnum += tdep->num_mmx_regs;
}
else
tdep->mm0_regnum = -1;
- if (tdep->bnd0r_regnum > 0)
- tdep->bnd0_regnum = bnd0_regnum;
- else
- tdep-> bnd0_regnum = -1;
-
/* Hook in the legacy prologue-based unwinders last (fallback). */
if (info.bfd_arch_info->bits_per_word == 32)
{
@@ -8839,12 +8611,11 @@ const struct target_desc *
i386_target_description (uint64_t xcr0, bool segments)
{
static target_desc *i386_tdescs \
- [2/*SSE*/][2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
+ [2/*SSE*/][2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
target_desc **tdesc;
tdesc = &i386_tdescs[(xcr0 & X86_XSTATE_SSE) ? 1 : 0]
[(xcr0 & X86_XSTATE_AVX) ? 1 : 0]
- [(xcr0 & X86_XSTATE_MPX) ? 1 : 0]
[(xcr0 & X86_XSTATE_AVX512) ? 1 : 0]
[(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]
[segments ? 1 : 0];
@@ -8855,245 +8626,6 @@ i386_target_description (uint64_t xcr0, bool segments)
return *tdesc;
}
-#define MPX_BASE_MASK (~(ULONGEST) 0xfff)
-
-/* Find the bound directory base address. */
-
-static unsigned long
-i386_mpx_bd_base (void)
-{
- ULONGEST ret;
- enum register_status regstatus;
-
- regcache *rcache = get_thread_regcache (inferior_thread ());
- gdbarch *arch = rcache->arch ();
- i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (arch);
-
- regstatus = regcache_raw_read_unsigned (rcache, tdep->bndcfgu_regnum, &ret);
-
- if (regstatus != REG_VALID)
- error (_("BNDCFGU register invalid, read status %d."), regstatus);
-
- return ret & MPX_BASE_MASK;
-}
-
-int
-i386_mpx_enabled (void)
-{
- gdbarch *arch = get_current_arch ();
- i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (arch);
- const struct target_desc *tdesc = tdep->tdesc;
-
- return (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx") != NULL);
-}
-
-#define MPX_BD_MASK 0xfffffff00000ULL /* select bits [47:20] */
-#define MPX_BT_MASK 0x0000000ffff8 /* select bits [19:3] */
-#define MPX_BD_MASK_32 0xfffff000 /* select bits [31:12] */
-#define MPX_BT_MASK_32 0x00000ffc /* select bits [11:2] */
-
-/* Find the bound table entry given the pointer location and the base
- address of the table. */
-
-static CORE_ADDR
-i386_mpx_get_bt_entry (CORE_ADDR ptr, CORE_ADDR bd_base)
-{
- CORE_ADDR offset1;
- CORE_ADDR offset2;
- CORE_ADDR mpx_bd_mask, bd_ptr_r_shift, bd_ptr_l_shift;
- CORE_ADDR bt_mask, bt_select_r_shift, bt_select_l_shift;
- CORE_ADDR bd_entry_addr;
- CORE_ADDR bt_addr;
- CORE_ADDR bd_entry;
- struct gdbarch *gdbarch = get_current_arch ();
- struct type *data_ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
-
-
- if (gdbarch_ptr_bit (gdbarch) == 64)
- {
- mpx_bd_mask = (CORE_ADDR) MPX_BD_MASK;
- bd_ptr_r_shift = 20;
- bd_ptr_l_shift = 3;
- bt_select_r_shift = 3;
- bt_select_l_shift = 5;
- bt_mask = (CORE_ADDR) MPX_BT_MASK;
-
- if ( sizeof (CORE_ADDR) == 4)
- error (_("bound table examination not supported\
- for 64-bit process with 32-bit GDB"));
- }
- else
- {
- mpx_bd_mask = MPX_BD_MASK_32;
- bd_ptr_r_shift = 12;
- bd_ptr_l_shift = 2;
- bt_select_r_shift = 2;
- bt_select_l_shift = 4;
- bt_mask = MPX_BT_MASK_32;
- }
-
- offset1 = ((ptr & mpx_bd_mask) >> bd_ptr_r_shift) << bd_ptr_l_shift;
- bd_entry_addr = bd_base + offset1;
- bd_entry = read_memory_typed_address (bd_entry_addr, data_ptr_type);
-
- if ((bd_entry & 0x1) == 0)
- error (_("Invalid bounds directory entry at %s."),
- paddress (get_current_arch (), bd_entry_addr));
-
- /* Clearing status bit. */
- bd_entry--;
- bt_addr = bd_entry & ~bt_select_r_shift;
- offset2 = ((ptr & bt_mask) >> bt_select_r_shift) << bt_select_l_shift;
-
- return bt_addr + offset2;
-}
-
-/* Print routine for the mpx bounds. */
-
-static void
-i386_mpx_print_bounds (const CORE_ADDR bt_entry[4])
-{
- struct ui_out *uiout = current_uiout;
- LONGEST size;
- struct gdbarch *gdbarch = get_current_arch ();
- CORE_ADDR onecompl = ~((CORE_ADDR) 0);
- int bounds_in_map = ((~bt_entry[1] == 0 && bt_entry[0] == onecompl) ? 1 : 0);
-
- if (bounds_in_map == 1)
- {
- uiout->text ("Null bounds on map:");
- uiout->text (" pointer value = ");
- uiout->field_core_addr ("pointer-value", gdbarch, bt_entry[2]);
- uiout->text (".");
- uiout->text ("\n");
- }
- else
- {
- uiout->text ("{lbound = ");
- uiout->field_core_addr ("lower-bound", gdbarch, bt_entry[0]);
- uiout->text (", ubound = ");
-
- /* The upper bound is stored in 1's complement. */
- uiout->field_core_addr ("upper-bound", gdbarch, ~bt_entry[1]);
- uiout->text ("}: pointer value = ");
- uiout->field_core_addr ("pointer-value", gdbarch, bt_entry[2]);
-
- if (gdbarch_ptr_bit (gdbarch) == 64)
- size = ( (~(int64_t) bt_entry[1]) - (int64_t) bt_entry[0]);
- else
- size = ( ~((int32_t) bt_entry[1]) - (int32_t) bt_entry[0]);
-
- /* In case the bounds are 0x0 and 0xffff... the difference will be -1.
- -1 represents in this sense full memory access, and there is no need
- one to the size. */
-
- size = (size > -1 ? size + 1 : size);
- uiout->text (", size = ");
- uiout->field_string ("size", plongest (size));
-
- uiout->text (", metadata = ");
- uiout->field_core_addr ("metadata", gdbarch, bt_entry[3]);
- uiout->text ("\n");
- }
-}
-
-/* Implement the command "show mpx bound". */
-
-static void
-i386_mpx_info_bounds (const char *args, int from_tty)
-{
- CORE_ADDR bd_base = 0;
- CORE_ADDR addr;
- CORE_ADDR bt_entry_addr = 0;
- CORE_ADDR bt_entry[4];
- int i;
- struct gdbarch *gdbarch = get_current_arch ();
- struct type *data_ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
-
- if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_i386
- || !i386_mpx_enabled ())
- {
- gdb_printf (_("Intel Memory Protection Extensions not "
- "supported on this target.\n"));
- return;
- }
-
- if (args == NULL)
- {
- gdb_printf (_("Address of pointer variable expected.\n"));
- return;
- }
-
- addr = parse_and_eval_address (args);
-
- bd_base = i386_mpx_bd_base ();
- bt_entry_addr = i386_mpx_get_bt_entry (addr, bd_base);
-
- memset (bt_entry, 0, sizeof (bt_entry));
-
- for (i = 0; i < 4; i++)
- bt_entry[i] = read_memory_typed_address (bt_entry_addr
- + i * data_ptr_type->length (),
- data_ptr_type);
-
- i386_mpx_print_bounds (bt_entry);
-}
-
-/* Implement the command "set mpx bound". */
-
-static void
-i386_mpx_set_bounds (const char *args, int from_tty)
-{
- CORE_ADDR bd_base = 0;
- CORE_ADDR addr, lower, upper;
- CORE_ADDR bt_entry_addr = 0;
- CORE_ADDR bt_entry[2];
- const char *input = args;
- int i;
- struct gdbarch *gdbarch = get_current_arch ();
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct type *data_ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
-
- if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_i386
- || !i386_mpx_enabled ())
- error (_("Intel Memory Protection Extensions not supported\
- on this target."));
-
- if (args == NULL)
- error (_("Pointer value expected."));
-
- addr = value_as_address (parse_to_comma_and_eval (&input));
-
- if (input[0] == ',')
- ++input;
- if (input[0] == '\0')
- error (_("wrong number of arguments: missing lower and upper bound."));
- lower = value_as_address (parse_to_comma_and_eval (&input));
-
- if (input[0] == ',')
- ++input;
- if (input[0] == '\0')
- error (_("Wrong number of arguments; Missing upper bound."));
- upper = value_as_address (parse_to_comma_and_eval (&input));
-
- bd_base = i386_mpx_bd_base ();
- bt_entry_addr = i386_mpx_get_bt_entry (addr, bd_base);
- for (i = 0; i < 2; i++)
- bt_entry[i] = read_memory_typed_address (bt_entry_addr
- + i * data_ptr_type->length (),
- data_ptr_type);
- bt_entry[0] = (uint64_t) lower;
- bt_entry[1] = ~(uint64_t) upper;
-
- for (i = 0; i < 2; i++)
- write_memory_unsigned_integer (bt_entry_addr
- + i * data_ptr_type->length (),
- data_ptr_type->length (), byte_order,
- bt_entry[i]);
-}
-
-static struct cmd_list_element *mpx_set_cmdlist, *mpx_show_cmdlist;
-
void _initialize_i386_tdep ();
void
_initialize_i386_tdep ()
@@ -9122,30 +8654,6 @@ is \"default\"."),
NULL, /* FIXME: i18n: */
&setlist, &showlist);
- /* Add "mpx" prefix for the set and show commands. */
-
- add_setshow_prefix_cmd
- ("mpx", class_support,
- _("Set Intel Memory Protection Extensions specific variables."),
- _("Show Intel Memory Protection Extensions specific variables."),
- &mpx_set_cmdlist, &mpx_show_cmdlist, &setlist, &showlist);
-
- /* Add "bound" command for the show mpx commands list. */
-
- cmd_list_element *c = add_cmd ("bound", no_class, i386_mpx_info_bounds,
- "Show the memory bounds for a given array/pointer storage\
- in the bound table.",
- &mpx_show_cmdlist);
- deprecate_cmd (c, nullptr);
-
- /* Add "bound" command for the set mpx commands list. */
-
- c = add_cmd ("bound", no_class, i386_mpx_set_bounds,
- "Set the memory bounds for a given array/pointer storage\
- in the bound table.",
- &mpx_set_cmdlist);
- deprecate_cmd (c, nullptr);
-
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_SVR4,
i386_svr4_init_abi);
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index a85e0a9..82676c2 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -166,21 +166,6 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base
/* YMM16-31 register names. Only used for tdesc_numbered_register. */
const char * const *ymm16h_register_names = nullptr;
- /* Register number for %bnd0r. Set this to -1 to indicate the absence
- bound registers. */
- int bnd0r_regnum = 0;
-
- /* Register number for pseudo register %bnd0. Set this to -1 to indicate the absence
- bound registers. */
- int bnd0_regnum = 0;
-
- /* Register number for %bndcfgu. Set this to -1 to indicate the absence
- bound control registers. */
- int bndcfgu_regnum = 0;
-
- /* MPX register names. Only used for tdesc_numbered_register. */
- const char * const *mpx_register_names = nullptr;
-
/* Register number for %zmm0h. Set this to -1 to indicate the absence
of ZMM_HI256 register support. */
int zmm0h_regnum = 0;
@@ -246,7 +231,6 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base
struct type *i386_ymm_type = nullptr;
struct type *i386_zmm_type = nullptr;
struct type *i387_ext_type = nullptr;
- struct type *i386_bnd_type = nullptr;
/* Process record/replay target. */
/* The map for registers because the AMD64's registers order
@@ -298,6 +282,8 @@ enum i386_regnum
I386_MXCSR_REGNUM = 40, /* %mxcsr */
I386_YMM0H_REGNUM, /* %ymm0h */
I386_YMM7H_REGNUM = I386_YMM0H_REGNUM + 7,
+ /* MPX is deprecated. Yet we keep this to not give the registers below
+ a new number. That could break older gdbservers. */
I386_BND0R_REGNUM,
I386_BND3R_REGNUM = I386_BND0R_REGNUM + 3,
I386_BNDCFGU_REGNUM,
@@ -346,7 +332,6 @@ enum record_i386_regnum
#define I386_SSE_NUM_REGS (I386_MXCSR_REGNUM + 1)
#define I386_AVX_NUM_REGS (I386_YMM7H_REGNUM + 1)
-#define I386_MPX_NUM_REGS (I386_BNDSTATUS_REGNUM + 1)
#define I386_AVX512_NUM_REGS (I386_ZMM7H_REGNUM + 1)
#define I386_PKEYS_NUM_REGS (I386_PKRU_REGNUM + 1)
#define I386_NUM_REGS (I386_GSBASE_REGNUM + 1)
@@ -365,7 +350,6 @@ extern int i386_xmm_regnum_p (struct gdbarch *gdbarch, int regnum);
extern int i386_xmm_avx512_regnum_p (struct gdbarch * gdbarch, int regnum);
extern int i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum);
extern int i386_ymm_avx512_regnum_p (struct gdbarch *gdbarch, int regnum);
-extern int i386_bnd_regnum_p (struct gdbarch *gdbarch, int regnum);
extern int i386_k_regnum_p (struct gdbarch *gdbarch, int regnum);
extern int i386_zmm_regnum_p (struct gdbarch *gdbarch, int regnum);
extern int i386_zmmh_regnum_p (struct gdbarch *gdbarch, int regnum);
@@ -468,10 +452,6 @@ extern int i386_process_record (struct gdbarch *gdbarch,
extern const struct target_desc *i386_target_description (uint64_t xcr0,
bool segments);
-/* Return true iff the current target is MPX enabled. */
-extern int i386_mpx_enabled (void);
-
-
/* Functions and variables exported from i386-bsd-tdep.c. */
extern void i386bsd_init_abi (struct gdbarch_info, struct gdbarch *);
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index 675ee8d..3bda888 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -818,30 +818,6 @@ static int xsave_xmm_avx512_offset[] =
(xsave + (tdep)->xsave_layout.zmm_offset \
+ xsave_xmm_avx512_offset[regnum - I387_XMM16_REGNUM (tdep)])
-/* At xsave_bndregs_offset[REGNUM] you'll find the relative offset
- within the BNDREGS region of the XSAVE extended state where the GDB
- register BND0R + REGNUM is stored. */
-
-static int xsave_bndregs_offset[] = {
- 0 * 16, /* bnd0r...bnd3r registers. */
- 1 * 16,
- 2 * 16,
- 3 * 16
-};
-
-#define XSAVE_BNDREGS_ADDR(tdep, xsave, regnum) \
- (xsave + (tdep)->xsave_layout.bndregs_offset \
- + xsave_bndregs_offset[regnum - I387_BND0R_REGNUM (tdep)])
-
-static int xsave_bndcfg_offset[] = {
- 0 * 8, /* bndcfg ... bndstatus. */
- 1 * 8,
-};
-
-#define XSAVE_BNDCFG_ADDR(tdep, xsave, regnum) \
- (xsave + (tdep)->xsave_layout.bndcfg_offset \
- + xsave_bndcfg_offset[regnum - I387_BNDCFGU_REGNUM (tdep)])
-
/* At xsave_avx512_k_offset[REGNUM] you'll find the relative offset
within the K region of the XSAVE extended state where the AVX512
opmask register K0 + REGNUM is stored. */
@@ -944,8 +920,6 @@ i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size,
{
/* Intel CPUs supporting PKRU. */
layout.avx_offset = 576;
- layout.bndregs_offset = 960;
- layout.bndcfg_offset = 1024;
layout.k_offset = 1088;
layout.zmm_h_offset = 1152;
layout.zmm_offset = 1664;
@@ -964,20 +938,14 @@ i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size,
{
/* Intel CPUs supporting AVX512. */
layout.avx_offset = 576;
- layout.bndregs_offset = 960;
- layout.bndcfg_offset = 1024;
layout.k_offset = 1088;
layout.zmm_h_offset = 1152;
layout.zmm_offset = 1664;
}
- else if (HAS_MPX (xcr0) && xsave_size == 1088)
- {
- /* Intel CPUs supporting MPX. */
- layout.avx_offset = 576;
- layout.bndregs_offset = 960;
- layout.bndcfg_offset = 1024;
- }
- else if (HAS_AVX (xcr0) && xsave_size == 832)
+ /* As MPX has been removed, we need the additional check
+ (xsave_size == 1088) to allow reading AVX registers from corefiles
+ on CPUs with MPX as the highest supported feature. */
+ else if (HAS_AVX (xcr0) && (xsave_size == 832 || xsave_size == 1088))
{
/* Intel and AMD CPUs supporting AVX. */
layout.avx_offset = 576;
@@ -1000,8 +968,6 @@ i387_fallback_xsave_layout (uint64_t xcr0)
{
/* Intel CPUs supporting PKRU. */
layout.avx_offset = 576;
- layout.bndregs_offset = 960;
- layout.bndcfg_offset = 1024;
layout.k_offset = 1088;
layout.zmm_h_offset = 1152;
layout.zmm_offset = 1664;
@@ -1012,21 +978,11 @@ i387_fallback_xsave_layout (uint64_t xcr0)
{
/* Intel CPUs supporting AVX512. */
layout.avx_offset = 576;
- layout.bndregs_offset = 960;
- layout.bndcfg_offset = 1024;
layout.k_offset = 1088;
layout.zmm_h_offset = 1152;
layout.zmm_offset = 1664;
layout.sizeof_xsave = 2688;
}
- else if (HAS_MPX (xcr0))
- {
- /* Intel CPUs supporting MPX. */
- layout.avx_offset = 576;
- layout.bndregs_offset = 960;
- layout.bndcfg_offset = 1024;
- layout.sizeof_xsave = 1088;
- }
else if (HAS_AVX (xcr0))
{
/* Intel and AMD CPUs supporting AVX. */
@@ -1082,16 +1038,14 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
x87 = 0x1,
sse = 0x2,
avxh = 0x4,
- bndregs = 0x8,
- bndcfg = 0x10,
- avx512_k = 0x20,
- avx512_zmm0_h = 0x40,
- avx512_zmm16_h = 0x80,
- avx512_ymmh_avx512 = 0x100,
- avx512_xmm_avx512 = 0x200,
- pkeys = 0x400,
- all = x87 | sse | avxh | bndregs | bndcfg | avx512_k | avx512_zmm0_h
- | avx512_zmm16_h | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
+ avx512_k = 0x8,
+ avx512_zmm0_h = 0x10,
+ avx512_zmm16_h = 0x20,
+ avx512_ymmh_avx512 = 0x40,
+ avx512_xmm_avx512 = 0x80,
+ pkeys = 0x100,
+ all = x87 | sse | avxh | avx512_k | avx512_zmm0_h | avx512_zmm16_h
+ | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
} regclass;
gdb_assert (regs != NULL);
@@ -1121,12 +1075,6 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
else if (regnum >= I387_YMM0H_REGNUM (tdep)
&& regnum < I387_YMMENDH_REGNUM (tdep))
regclass = avxh;
- else if (regnum >= I387_BND0R_REGNUM (tdep)
- && regnum < I387_BNDCFGU_REGNUM (tdep))
- regclass = bndregs;
- else if (regnum >= I387_BNDCFGU_REGNUM (tdep)
- && regnum < I387_MPXEND_REGNUM (tdep))
- regclass = bndcfg;
else if (regnum >= I387_XMM0_REGNUM (tdep)
&& regnum < I387_MXCSR_REGNUM (tdep))
regclass = sse;
@@ -1205,20 +1153,6 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
regcache->raw_supply (regnum, XSAVE_AVXH_ADDR (tdep, regs, regnum));
return;
- case bndcfg:
- if ((clear_bv & X86_XSTATE_BNDCFG))
- regcache->raw_supply (regnum, zero);
- else
- regcache->raw_supply (regnum, XSAVE_BNDCFG_ADDR (tdep, regs, regnum));
- return;
-
- case bndregs:
- if ((clear_bv & X86_XSTATE_BNDREGS))
- regcache->raw_supply (regnum, zero);
- else
- regcache->raw_supply (regnum, XSAVE_BNDREGS_ADDR (tdep, regs, regnum));
- return;
-
case sse:
if ((clear_bv & X86_XSTATE_SSE))
regcache->raw_supply (regnum, zero);
@@ -1341,40 +1275,6 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
}
}
- /* Handle the MPX registers. */
- if ((tdep->xcr0 & X86_XSTATE_BNDREGS))
- {
- if (clear_bv & X86_XSTATE_BNDREGS)
- {
- for (i = I387_BND0R_REGNUM (tdep);
- i < I387_BNDCFGU_REGNUM (tdep); i++)
- regcache->raw_supply (i, zero);
- }
- else
- {
- for (i = I387_BND0R_REGNUM (tdep);
- i < I387_BNDCFGU_REGNUM (tdep); i++)
- regcache->raw_supply (i, XSAVE_BNDREGS_ADDR (tdep, regs, i));
- }
- }
-
- /* Handle the MPX registers. */
- if ((tdep->xcr0 & X86_XSTATE_BNDCFG))
- {
- if (clear_bv & X86_XSTATE_BNDCFG)
- {
- for (i = I387_BNDCFGU_REGNUM (tdep);
- i < I387_MPXEND_REGNUM (tdep); i++)
- regcache->raw_supply (i, zero);
- }
- else
- {
- for (i = I387_BNDCFGU_REGNUM (tdep);
- i < I387_MPXEND_REGNUM (tdep); i++)
- regcache->raw_supply (i, XSAVE_BNDCFG_ADDR (tdep, regs, i));
- }
- }
-
/* Handle the XMM registers. */
if ((tdep->xcr0 & X86_XSTATE_SSE))
{
@@ -1527,16 +1427,14 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
x87 = 0x2,
sse = 0x4,
avxh = 0x8,
- bndregs = 0x10,
- bndcfg = 0x20,
- avx512_k = 0x40,
- avx512_zmm0_h = 0x80,
- avx512_zmm16_h = 0x100,
- avx512_ymmh_avx512 = 0x200,
- avx512_xmm_avx512 = 0x400,
- pkeys = 0x800,
- all = x87 | sse | avxh | bndregs | bndcfg | avx512_k | avx512_zmm0_h
- | avx512_zmm16_h | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
+ avx512_k = 0x10,
+ avx512_zmm0_h = 0x20,
+ avx512_zmm16_h = 0x40,
+ avx512_ymmh_avx512 = 0x80,
+ avx512_xmm_avx512 = 0x100,
+ pkeys = 0x200,
+ all = x87 | sse | avxh | avx512_k | avx512_zmm0_h | avx512_zmm16_h
+ | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
} regclass;
gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
@@ -1565,12 +1463,6 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
else if (regnum >= I387_YMM0H_REGNUM (tdep)
&& regnum < I387_YMMENDH_REGNUM (tdep))
regclass = avxh;
- else if (regnum >= I387_BND0R_REGNUM (tdep)
- && regnum < I387_BNDCFGU_REGNUM (tdep))
- regclass = bndregs;
- else if (regnum >= I387_BNDCFGU_REGNUM (tdep)
- && regnum < I387_MPXEND_REGNUM (tdep))
- regclass = bndcfg;
else if (regnum >= I387_XMM0_REGNUM (tdep)
&& regnum < I387_MXCSR_REGNUM (tdep))
regclass = sse;
@@ -1619,16 +1511,6 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
i < I387_PKEYSEND_REGNUM (tdep); i++)
memset (XSAVE_PKEYS_ADDR (tdep, regs, i), 0, 4);
- if ((clear_bv & X86_XSTATE_BNDREGS))
- for (i = I387_BND0R_REGNUM (tdep);
- i < I387_BNDCFGU_REGNUM (tdep); i++)
- memset (XSAVE_BNDREGS_ADDR (tdep, regs, i), 0, 16);
-
- if ((clear_bv & X86_XSTATE_BNDCFG))
- for (i = I387_BNDCFGU_REGNUM (tdep);
- i < I387_MPXEND_REGNUM (tdep); i++)
- memset (XSAVE_BNDCFG_ADDR (tdep, regs, i), 0, 8);
-
if ((clear_bv & X86_XSTATE_ZMM_H))
for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++)
memset (XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, i), 0, 32);
@@ -1771,34 +1653,6 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
}
}
- /* Check if any upper MPX registers are changed. */
- if ((tdep->xcr0 & X86_XSTATE_BNDREGS))
- for (i = I387_BND0R_REGNUM (tdep);
- i < I387_BNDCFGU_REGNUM (tdep); i++)
- {
- regcache->raw_collect (i, raw);
- p = XSAVE_BNDREGS_ADDR (tdep, regs, i);
- if (memcmp (raw, p, 16))
- {
- xstate_bv |= X86_XSTATE_BNDREGS;
- memcpy (p, raw, 16);
- }
- }
-
- /* Check if any upper MPX registers are changed. */
- if ((tdep->xcr0 & X86_XSTATE_BNDCFG))
- for (i = I387_BNDCFGU_REGNUM (tdep);
- i < I387_MPXEND_REGNUM (tdep); i++)
- {
- regcache->raw_collect (i, raw);
- p = XSAVE_BNDCFG_ADDR (tdep, regs, i);
- if (memcmp (raw, p, 8))
- {
- xstate_bv |= X86_XSTATE_BNDCFG;
- memcpy (p, raw, 8);
- }
- }
-
/* Check if any upper YMM registers are changed. */
if ((tdep->xcr0 & X86_XSTATE_AVX))
for (i = I387_YMM0H_REGNUM (tdep);
@@ -1940,22 +1794,6 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
}
break;
- case bndregs:
- regcache->raw_collect (regnum, raw);
- p = XSAVE_BNDREGS_ADDR (tdep, regs, regnum);
- if (memcmp (raw, p, 16))
- {
- xstate_bv |= X86_XSTATE_BNDREGS;
- memcpy (p, raw, 16);
- }
- break;
-
- case bndcfg:
- p = XSAVE_BNDCFG_ADDR (tdep, regs, regnum);
- xstate_bv |= X86_XSTATE_BNDCFG;
- memcpy (p, raw, 8);
- break;
-
case sse:
/* This is an SSE register. */
p = FXSAVE_ADDR (tdep, regs, regnum);
@@ -2143,20 +1981,3 @@ i387_return_value (struct gdbarch *gdbarch, struct regcache *regcache)
regcache_raw_write_unsigned (regcache, I387_FTAG_REGNUM (tdep), 0x3fff);
}
-
-/* See i387-tdep.h. */
-
-void
-i387_reset_bnd_regs (struct gdbarch *gdbarch, struct regcache *regcache)
-{
- i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
-
- if (I387_BND0R_REGNUM (tdep) > 0)
- {
- gdb_byte bnd_buf[16];
-
- memset (bnd_buf, 0, 16);
- for (int i = 0; i < I387_NUM_BND_REGS; i++)
- regcache->raw_write (I387_BND0R_REGNUM (tdep) + i, bnd_buf);
- }
-}
diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
index 30d7694..7b2c3b1 100644
--- a/gdb/i387-tdep.h
+++ b/gdb/i387-tdep.h
@@ -37,13 +37,7 @@ struct x86_xsave_layout;
#define I387_NUM_YMM_REGS(tdep) ((tdep)->num_ymm_regs)
#define I387_YMM0H_REGNUM(tdep) ((tdep)->ymm0h_regnum)
-#define I387_BND0R_REGNUM(tdep) ((tdep)->bnd0r_regnum)
-#define I387_BNDCFGU_REGNUM(tdep) ((tdep)->bndcfgu_regnum)
-
/* Set of constants used for 32 and 64-bit. */
-#define I387_NUM_MPX_REGS 6
-#define I387_NUM_BND_REGS 4
-#define I387_NUM_MPX_CTRL_REGS 2
#define I387_NUM_K_REGS 8
#define I387_NUM_PKEYS_REGS 1
@@ -71,8 +65,6 @@ struct x86_xsave_layout;
#define I387_YMMENDH_REGNUM(tdep) \
(I387_YMM0H_REGNUM (tdep) + I387_NUM_YMM_REGS (tdep))
-#define I387_MPXEND_REGNUM(tdep) \
- (I387_BND0R_REGNUM (tdep) + I387_NUM_MPX_REGS)
#define I387_KEND_REGNUM(tdep) \
(I387_K0_REGNUM (tdep) + I387_NUM_K_REGS)
@@ -181,8 +173,4 @@ extern ULONGEST i387_xsave_get_clear_bv (struct gdbarch *gdbarch,
extern void i387_return_value (struct gdbarch *gdbarch,
struct regcache *regcache);
-/* Set all bnd registers to the INIT state. INIT state means
- all memory range can be accessed. */
-extern void i387_reset_bnd_regs (struct gdbarch *gdbarch,
- struct regcache *regcache);
#endif /* i387-tdep.h */
diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
index 6376cf8..b0c1ad3 100644
--- a/gdb/ia64-tdep.c
+++ b/gdb/ia64-tdep.c
@@ -3615,9 +3615,7 @@ ia64_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
/* There are also descriptors embedded in vtables. */
if (s)
{
- struct bound_minimal_symbol minsym;
-
- minsym = lookup_minimal_symbol_by_pc (addr);
+ bound_minimal_symbol minsym = lookup_minimal_symbol_by_pc (addr);
if (minsym.minsym
&& is_vtable_name (minsym.minsym->linkage_name ()))
@@ -3846,7 +3844,7 @@ ia64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
a dummy code sequence pushed on the stack to make the call, and
this sequence doesn't need b0 to be set in order for our dummy
breakpoint to be hit. Nonetheless, this doesn't interfere, and
- it's needed for other OSes, so we do this unconditionaly. */
+ it's needed for other OSes, so we do this unconditionally. */
regcache_cooked_write_unsigned (regcache, IA64_BR0_REGNUM, bp_addr);
regcache_cooked_write_unsigned (regcache, sp_regnum, sp);
diff --git a/gdb/ia64-tdep.h b/gdb/ia64-tdep.h
index 64be38b..3d5b56e 100644
--- a/gdb/ia64-tdep.h
+++ b/gdb/ia64-tdep.h
@@ -156,7 +156,7 @@
/* Predicate registers: There are 64 of these 1-bit registers. We
define a single register which is used to communicate these values
to/from the target. We will somehow contrive to make it appear
- that IA64_PR0_REGNUM thru IA64_PR63_REGNUM hold the actual values. */
+ that IA64_PR0_REGNUM through IA64_PR63_REGNUM hold the actual values. */
#define IA64_PR_REGNUM 330
/* Instruction pointer: 64 bits wide. */
diff --git a/gdb/inf-child.c b/gdb/inf-child.c
index 1318d6b..df993b6 100644
--- a/gdb/inf-child.c
+++ b/gdb/inf-child.c
@@ -320,6 +320,21 @@ inf_child_target::fileio_fstat (int fd, struct stat *sb, fileio_error *target_er
return ret;
}
+/* Implementation of to_fileio_stat. */
+
+int
+inf_child_target::fileio_stat (struct inferior *inf, const char *filename,
+ struct stat *sb, fileio_error *target_errno)
+{
+ int ret;
+
+ ret = lstat (filename, sb);
+ if (ret == -1)
+ *target_errno = host_to_fileio_error (errno);
+
+ return ret;
+}
+
/* Implementation of to_fileio_close. */
int
diff --git a/gdb/inf-child.h b/gdb/inf-child.h
index 91955a6..65d42e1 100644
--- a/gdb/inf-child.h
+++ b/gdb/inf-child.h
@@ -81,6 +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_close (int fd, fileio_error *target_errno) override;
int fileio_unlink (struct inferior *inf,
const char *filename,
diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c
index acb80af..36d6e2a 100644
--- a/gdb/inf-ptrace.c
+++ b/gdb/inf-ptrace.c
@@ -475,7 +475,7 @@ inf_ptrace_target::xfer_partial (enum target_object object,
case TARGET_OBJECT_AUXV:
#if defined (PT_IO) && defined (PIOD_READ_AUXV)
/* OpenBSD 4.5 has a new PIOD_READ_AUXV operation for the PT_IO
- request that allows us to read the auxilliary vector. Other
+ request that allows us to read the auxiliary vector. Other
BSD's may follow if they feel the need to support PIE. */
{
struct ptrace_io_desc piod;
diff --git a/gdb/infcall.c b/gdb/infcall.c
index edac9a7..02e3b38 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -488,7 +488,7 @@ get_function_name (CORE_ADDR funaddr, char *buf, int buf_size)
{
/* Try the minimal symbols. */
- struct bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (funaddr);
+ bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (funaddr);
if (msymbol.minsym)
return msymbol.minsym->print_name ();
@@ -1271,7 +1271,7 @@ call_function_by_hand_dummy (struct value *function,
CORE_ADDR dummy_addr;
real_pc = funaddr;
- dummy_addr = entry_point_address ();
+ dummy_addr = entry_point_address (current_program_space);
/* A call dummy always consists of just a single breakpoint, so
its address is the same as the address of the dummy.
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 71514d5..74873b9 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -383,7 +383,7 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
/* Clean up any leftovers from other runs. Some other things from
this function should probably be moved into target_pre_inferior. */
- target_pre_inferior (from_tty);
+ target_pre_inferior ();
/* The comment here used to read, "The exec file is re-read every
time we do a generic_mourn_inferior, so we just have to worry
@@ -519,7 +519,7 @@ start_command (const char *args, int from_tty)
/* Some languages such as Ada need to search inside the program
minimal symbols for the location where to put the temporary
breakpoint before starting. */
- if (!have_minimal_symbols ())
+ if (!have_minimal_symbols (current_program_space))
error (_("No symbol table loaded. Use the \"file\" command."));
/* Run the program until reaching the main procedure... */
@@ -992,7 +992,7 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
Use inlined_subroutine info to make the range more narrow. */
if (inline_skipped_frames (tp) > 0)
{
- symbol *sym = inline_skipped_symbol (tp);
+ const symbol *sym = inline_skipped_symbol (tp);
if (sym->aclass () == LOC_BLOCK)
{
const block *block = sym->value_block ();
@@ -1078,7 +1078,8 @@ jump_command (const char *arg, int from_tty)
{
/* If multiple sal-objects were found, try dropping those that aren't
from the current symtab. */
- struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+ symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
sals.erase (std::remove_if (sals.begin (), sals.end (),
[&] (const symtab_and_line &sal)
{
@@ -1102,7 +1103,9 @@ jump_command (const char *arg, int from_tty)
find_pc_mapped_section (sal.pc));
if (fn != nullptr && sfn != fn)
{
- if (!query (_("Line %d is not in `%s'. Jump anyway? "), sal.line,
+ if (!query (_("Line %ps is not in `%s'. Jump anyway? "),
+ styled_string (line_number_style.style (),
+ pulongest (sal.line)),
fn->print_name ()))
{
error (_("Not confirmed."));
@@ -1359,7 +1362,7 @@ until_next_command (int from_tty)
if (!func)
{
- struct bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (pc);
if (msymbol.minsym == nullptr)
error (_("Execution is not within a known function."));
@@ -2628,7 +2631,7 @@ attach_command (const char *args, int from_tty)
/* Clean up any leftovers from other runs. Some other things from
this function should probably be moved into target_pre_inferior. */
- target_pre_inferior (from_tty);
+ target_pre_inferior ();
gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec);
args = stripped.get ();
@@ -2827,7 +2830,7 @@ detach_command (const char *args, int from_tty)
/* If the solist is global across inferiors, don't clear it when we
detach from a single inferior. */
if (!gdbarch_has_global_solist (inf->arch ()))
- no_shared_libraries (nullptr, from_tty);
+ no_shared_libraries (inf->pspace);
if (deprecated_detach_hook)
deprecated_detach_hook ();
@@ -2853,7 +2856,7 @@ disconnect_command (const char *args, int from_tty)
query_if_trace_running (from_tty);
disconnect_tracing ();
target_disconnect (args, from_tty);
- no_shared_libraries (nullptr, from_tty);
+ no_shared_libraries (current_program_space);
init_thread_list ();
update_previous_thread ();
if (deprecated_detach_hook)
@@ -3112,7 +3115,7 @@ Follow this command with any number of args, to be passed to the program."),
get_args_value,
show_args_command,
&setlist, &showlist);
- set_cmd_completer (args_set_show.set, filename_completer);
+ set_cmd_completer (args_set_show.set, deprecated_filename_completer);
auto cwd_set_show
= add_setshow_string_noescape_cmd ("cwd", class_run, _("\
@@ -3128,7 +3131,7 @@ working directory."),
set_cwd_value, get_inferior_cwd,
show_cwd_command,
&setlist, &showlist);
- set_cmd_completer (cwd_set_show.set, filename_completer);
+ set_cmd_completer (cwd_set_show.set, deprecated_filename_completer);
c = add_cmd ("environment", no_class, environment_info, _("\
The environment to give the program, or one variable's value.\n\
@@ -3162,7 +3165,7 @@ This path is equivalent to the $PATH shell variable. It is a list of\n\
directories, separated by colons. These directories are searched to find\n\
fully linked executable files and separately compiled object files as \
needed."));
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, deprecated_filename_completer);
c = add_cmd ("paths", no_class, path_info, _("\
Current search path for finding object files.\n\
@@ -3312,18 +3315,18 @@ Specifying -a and an ignore count simultaneously is an error."));
= add_com ("run", class_run, run_command, _("\
Start debugged program.\n"
RUN_ARGS_HELP));
- set_cmd_completer (run_cmd, filename_completer);
+ set_cmd_completer (run_cmd, deprecated_filename_completer);
add_com_alias ("r", run_cmd, class_run, 1);
c = add_com ("start", class_run, start_command, _("\
Start the debugged program stopping at the beginning of the main procedure.\n"
RUN_ARGS_HELP));
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, deprecated_filename_completer);
c = add_com ("starti", class_run, starti_command, _("\
Start the debugged program stopping at the first instruction.\n"
RUN_ARGS_HELP));
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, deprecated_filename_completer);
add_com ("interrupt", class_run, interrupt_command,
_("Interrupt the execution of the debugged program.\n\
diff --git a/gdb/inferior.c b/gdb/inferior.c
index 6a19767..21f37c8 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -790,6 +790,10 @@ inferior_command (const char *args, int from_tty)
notify_user_selected_context_changed
(USER_SELECTED_INFERIOR);
}
+
+ /* Switching current inferior may have made one of the inferiors
+ prunable, so prune it. */
+ prune_inferiors ();
}
}
@@ -1112,7 +1116,7 @@ as main program.\n\
By default, the new inferior inherits the current inferior's connection.\n\
If -no-connection is specified, the new inferior begins with\n\
no target connection yet."));
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, deprecated_filename_completer);
add_com ("remove-inferiors", no_class, remove_inferior_command, _("\
Remove inferior ID (or list of IDs).\n\
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 1f32a63..4ca1545 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1317,7 +1317,7 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
/* Also, loading a symbol file below may trigger symbol lookups, and
we don't want those to be satisfied by the libraries of the
previous incarnation of this process. */
- no_shared_libraries (nullptr, 0);
+ no_shared_libraries (current_program_space);
inferior *execing_inferior = current_inferior ();
inferior *following_inferior;
@@ -8245,7 +8245,8 @@ process_event_stop_test (struct execution_control_state *ecs)
"it's not the start of a statement");
}
}
- else if (execution_direction == EXEC_REVERSE
+
+ if (execution_direction == EXEC_REVERSE
&& *curr_frame_id != original_frame_id
&& original_frame_id.code_addr_p && curr_frame_id->code_addr_p
&& original_frame_id.code_addr == curr_frame_id->code_addr)
@@ -9266,8 +9267,15 @@ print_no_history_reason (struct ui_out *uiout)
{
if (uiout->is_mi_like_p ())
uiout->field_string ("reason", async_reason_lookup (EXEC_ASYNC_NO_HISTORY));
+ else if (execution_direction == EXEC_FORWARD)
+ uiout->text ("\nReached end of recorded history; stopping.\nFollowing "
+ "forward execution will be added to history.\n");
else
- uiout->text ("\nNo more reverse-execution history.\n");
+ {
+ gdb_assert (execution_direction == EXEC_REVERSE);
+ uiout->text ("\nReached end of recorded history; stopping.\nBackward "
+ "execution from here not possible.\n");
+ }
}
/* Print current location without a level number, if we have changed
@@ -9296,12 +9304,24 @@ print_stop_location (const target_waitstatus &ws)
&& (tp->control.step_start_function
== find_pc_function (tp->stop_pc ())))
{
- /* Finished step, just print source line. */
- source_flag = SRC_LINE;
+ symtab_and_line sal = find_frame_sal (get_selected_frame (nullptr));
+ if (sal.symtab != tp->current_symtab)
+ {
+ /* Finished step in same frame but into different file, print
+ location and source line. */
+ source_flag = SRC_AND_LOC;
+ }
+ else
+ {
+ /* Finished step in same frame and same file, just print source
+ line. */
+ source_flag = SRC_LINE;
+ }
}
else
{
- /* Print location and source line. */
+ /* Finished step into different frame, print location and source
+ line. */
source_flag = SRC_AND_LOC;
}
break;
diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c
index f65f39b..8ba886c 100644
--- a/gdb/inline-frame.c
+++ b/gdb/inline-frame.c
@@ -27,6 +27,8 @@
#include "regcache.h"
#include "symtab.h"
#include "frame.h"
+#include "cli/cli-cmds.h"
+#include "cli/cli-style.h"
#include <algorithm>
/* We need to save a few variables for every thread stopped at the
@@ -36,9 +38,9 @@
struct inline_state
{
inline_state (thread_info *thread_, int skipped_frames_, CORE_ADDR saved_pc_,
- std::vector<symbol *> &&skipped_symbols_)
+ std::vector<const symbol *> &&function_symbols_)
: thread (thread_), skipped_frames (skipped_frames_), saved_pc (saved_pc_),
- skipped_symbols (std::move (skipped_symbols_))
+ function_symbols (std::move (function_symbols_))
{}
/* The thread this data relates to. It should be a currently
@@ -49,16 +51,19 @@ struct inline_state
functions can be stepped in to. */
int skipped_frames;
- /* Only valid if SKIPPED_FRAMES is non-zero. This is the PC used
- when calculating SKIPPED_FRAMES; used to check whether we have
- moved to a new location by user request. If so, we invalidate
- any skipped frames. */
+ /* This is the PC used when calculating FUNCTION_SYMBOLS; used to check
+ whether we have moved to a new location by user request. If so, we
+ invalidate any skipped frames. */
CORE_ADDR saved_pc;
- /* Only valid if SKIPPED_FRAMES is non-zero. This is the list of all
- function symbols that have been skipped, from inner most to outer
- most. It is used to find the call site of the current frame. */
- std::vector<struct symbol *> skipped_symbols;
+ /* The list of all inline functions that start at SAVED_PC, except for
+ the last entry which will either be a non-inline function, or an
+ inline function that doesn't start at SAVED_PC. This last entry is
+ the function that "contains" all of the earlier functions.
+
+ This list can be empty if SAVED_PC is for a code region which is not
+ covered by any function (inline or non-inline). */
+ std::vector<const symbol *> function_symbols;
};
static std::vector<inline_state> inline_states;
@@ -303,10 +308,11 @@ block_starting_point_at (CORE_ADDR pc, const struct block *block)
/* Loop over the stop chain and determine if execution stopped in an
inlined frame because of a breakpoint with a user-specified location
- set at FRAME_BLOCK. */
+ set at FRAME_SYMBOL. */
static bool
-stopped_by_user_bp_inline_frame (const block *frame_block, bpstat *stop_chain)
+stopped_by_user_bp_inline_frame (const symbol *frame_symbol,
+ bpstat *stop_chain)
{
for (bpstat *s = stop_chain; s != nullptr; s = s->next)
{
@@ -327,7 +333,7 @@ stopped_by_user_bp_inline_frame (const block *frame_block, bpstat *stop_chain)
to presenting the stop at the innermost inline
function. */
if (loc->symbol == nullptr
- || frame_block == loc->symbol->value_block ())
+ || frame_symbol == loc->symbol)
return true;
}
}
@@ -336,58 +342,109 @@ stopped_by_user_bp_inline_frame (const block *frame_block, bpstat *stop_chain)
return false;
}
+/* Return a list of all the inline function symbols that start at THIS_PC
+ and the symbol for the function which contains all of the inline
+ functions.
+
+ The function symbols are ordered such that the most inner function is
+ first.
+
+ The returned list can be empty if there are no function at THIS_PC. Or
+ the returned list may have only a single entry if there are no inline
+ functions starting at THIS_PC. */
+
+static std::vector<const symbol *>
+gather_inline_frames (CORE_ADDR this_pc)
+{
+ /* Build the list of inline frames starting at THIS_PC. After the loop,
+ CUR_BLOCK is expected to point at the first function symbol (inlined or
+ not) "containing" the inline frames starting at THIS_PC. */
+ const block *cur_block = block_for_pc (this_pc);
+ if (cur_block == nullptr)
+ return {};
+
+ std::vector<const symbol *> function_symbols;
+ while (cur_block != nullptr)
+ {
+ if (cur_block->inlined_p ())
+ {
+ gdb_assert (cur_block->function () != nullptr);
+
+ /* See comments in inline_frame_this_id about this use
+ of BLOCK_ENTRY_PC. */
+ if (cur_block->entry_pc () == this_pc
+ || block_starting_point_at (this_pc, cur_block))
+ function_symbols.push_back (cur_block->function ());
+ else
+ break;
+ }
+ else if (cur_block->function () != nullptr)
+ break;
+
+ cur_block = cur_block->superblock ();
+ }
+
+ /* If we have a code region for which we have no function blocks,
+ possibly due to bad debug, or possibly just when some debug
+ information has been stripped, then we can end up in a situation where
+ there are global and static blocks for an address, but no function
+ blocks. In this case the early return above will not trigger as we
+ will find the static block for THIS_PC, but in the loop above we will
+ fail to find any function blocks (inline or non-inline) and so
+ CUR_BLOCK will eventually become NULL. If this happens then
+ FUNCTION_SYMBOLS must be empty (as we found no function blocks).
+
+ Otherwise, if we did find a function block, then we should only leave
+ the above loop when CUR_BLOCK is pointing to a non-inline function
+ that possibly contains some inline functions, or CUR_BLOCK should
+ point to an inline function that doesn't start at THIS_PC. */
+ if (cur_block != nullptr)
+ {
+ gdb_assert (cur_block->function () != nullptr);
+ function_symbols.push_back (cur_block->function ());
+ }
+ else
+ gdb_assert (function_symbols.empty ());
+
+ return function_symbols;
+}
+
/* See inline-frame.h. */
void
skip_inline_frames (thread_info *thread, bpstat *stop_chain)
{
- const struct block *frame_block, *cur_block;
- std::vector<struct symbol *> skipped_syms;
- int skip_count = 0;
+ gdb_assert (find_inline_frame_state (thread) == nullptr);
- /* This function is called right after reinitializing the frame
- cache. We try not to do more unwinding than absolutely
- necessary, for performance. */
CORE_ADDR this_pc = get_frame_pc (get_current_frame ());
- frame_block = block_for_pc (this_pc);
- if (frame_block != NULL)
+ std::vector<const symbol *> function_symbols
+ = gather_inline_frames (this_pc);
+
+ /* Figure out how many of the inlined frames to skip. Do not skip an
+ inlined frame (and its callers) if execution stopped because of a user
+ breakpoint for this specific function.
+
+ By default, skip all the found inlined frames.
+
+ The last entry in FUNCTION_SYMBOLS is special, this is the function
+ which contains all of the inlined functions, we never skip this. */
+ int skipped_frames = 0;
+
+ for (const auto sym : function_symbols)
{
- cur_block = frame_block;
- while (cur_block->superblock ())
- {
- if (cur_block->inlined_p ())
- {
- /* See comments in inline_frame_this_id about this use
- of BLOCK_ENTRY_PC. */
- if (cur_block->entry_pc () == this_pc
- || block_starting_point_at (this_pc, cur_block))
- {
- /* Do not skip the inlined frame if execution
- stopped in an inlined frame because of a user
- breakpoint for this inline function. */
- if (stopped_by_user_bp_inline_frame (cur_block, stop_chain))
- break;
-
- skip_count++;
- skipped_syms.push_back (cur_block->function ());
- }
- else
- break;
- }
- else if (cur_block->function () != NULL)
- break;
+ if (stopped_by_user_bp_inline_frame (sym, stop_chain)
+ || sym == function_symbols.back ())
+ break;
- cur_block = cur_block->superblock ();
- }
+ ++skipped_frames;
}
- gdb_assert (find_inline_frame_state (thread) == NULL);
- inline_states.emplace_back (thread, skip_count, this_pc,
- std::move (skipped_syms));
-
- if (skip_count != 0)
+ if (skipped_frames > 0)
reinit_frame_cache ();
+
+ inline_states.emplace_back (thread, skipped_frames, this_pc,
+ std::move (function_symbols));
}
/* Step into an inlined function by unhiding it. */
@@ -419,20 +476,23 @@ inline_skipped_frames (thread_info *thread)
/* If one or more inlined functions are hidden, return the symbol for
the function inlined into the current frame. */
-struct symbol *
+const symbol *
inline_skipped_symbol (thread_info *thread)
{
inline_state *state = find_inline_frame_state (thread);
gdb_assert (state != NULL);
/* This should only be called when we are skipping at least one frame,
- hence SKIPPED_FRAMES will be greater than zero when we get here.
- We initialise SKIPPED_FRAMES at the same time as we build
- SKIPPED_SYMBOLS, hence it should be true that SKIPPED_FRAMES never
- indexes outside of the SKIPPED_SYMBOLS vector. */
+ hence FUNCTION_SYMBOLS will contain more than one entry (the last
+ entry is the "outer" containing function).
+
+ As we initialise SKIPPED_FRAMES at the same time as we build
+ FUNCTION_SYMBOLS it should be true that SKIPPED_FRAMES never indexes
+ outside of the FUNCTION_SYMBOLS vector. */
+ gdb_assert (state->function_symbols.size () > 1);
gdb_assert (state->skipped_frames > 0);
- gdb_assert (state->skipped_frames <= state->skipped_symbols.size ());
- return state->skipped_symbols[state->skipped_frames - 1];
+ gdb_assert (state->skipped_frames < state->function_symbols.size ());
+ return state->function_symbols[state->skipped_frames - 1];
}
/* Return the number of functions inlined into THIS_FRAME. Some of
@@ -460,3 +520,93 @@ frame_inlined_callees (const frame_info_ptr &this_frame)
return inline_count;
}
+
+/* The 'maint info inline-frames' command. Takes an optional address
+ expression and displays inline frames that start at the given address,
+ or at the address of the current thread if no address is given. */
+
+static void
+maintenance_info_inline_frames (const char *arg, int from_tty)
+{
+ std::optional<std::vector<const symbol *>> local_function_symbols;
+ std::vector<const symbol *> *function_symbols;
+ int skipped_frames;
+ CORE_ADDR addr;
+
+ if (arg == nullptr)
+ {
+ /* With no argument then the user wants to know about the current
+ inline frame information. This information is cached per-thread
+ and can be updated as the user steps between inline functions at
+ the current address. */
+
+ if (inferior_ptid == null_ptid)
+ error (_("no inferior thread"));
+
+ thread_info *thread = inferior_thread ();
+ auto it = std::find_if (inline_states.begin (), inline_states.end (),
+ [thread] (const inline_state &istate)
+ {
+ return thread == istate.thread;
+ });
+
+ /* Stopped threads always have cached inline_state information. */
+ gdb_assert (it != inline_states.end ());
+
+ gdb_printf (_("Cached inline state information for thread %s.\n"),
+ print_thread_id (thread));
+
+ function_symbols = &it->function_symbols;
+ skipped_frames = it->skipped_frames;
+ addr = it->saved_pc;
+ }
+ else
+ {
+ /* If there is an argument then parse it as an address, the user is
+ asking about inline functions that start at the given address. */
+
+ addr = parse_and_eval_address (arg);
+ local_function_symbols.emplace (gather_inline_frames (addr));
+
+ function_symbols = &(local_function_symbols.value ());
+ skipped_frames = function_symbols->size () - 1;
+ }
+
+ /* The address we're analysing. */
+ gdb_printf (_("program counter = %ps\n"),
+ styled_string (address_style.style (),
+ core_addr_to_string_nz (addr)));
+
+ gdb_printf (_("skipped frames = %d\n"), skipped_frames);
+
+ /* Print the full list of function symbols in STATE. Highlight the
+ current function as indicated by the skipped frames counter. */
+ for (size_t i = 0; i < function_symbols->size (); ++i)
+ gdb_printf (_("%c %ps\n"),
+ (i == skipped_frames ? '>' : ' '),
+ styled_string (function_name_style.style (),
+ (*function_symbols)[i]->print_name ()));
+}
+
+
+
+void _initialize_inline_frame ();
+void
+_initialize_inline_frame ()
+{
+ add_cmd ("inline-frames", class_maintenance, maintenance_info_inline_frames,
+ _("\
+Display inline frame information for current thread.\n\
+\n\
+Usage:\n\
+\n\
+ maintenance info inline-frames [ADDRESS]\n\
+\n\
+With no ADDRESS show all inline frames starting at the current program\n\
+counter address. When ADDRESS is given, list all inline frames starting\n\
+at ADDRESS.\n\
+\n\
+The last frame listed might not start at ADDRESS, this is the frame that\n\
+contains the other inline frames."),
+ &maintenanceinfolist);
+}
diff --git a/gdb/inline-frame.h b/gdb/inline-frame.h
index bbe617c..3ddc9cf 100644
--- a/gdb/inline-frame.h
+++ b/gdb/inline-frame.h
@@ -62,7 +62,7 @@ int inline_skipped_frames (thread_info *thread);
/* If one or more inlined functions are hidden, return the symbol for
the function inlined into the current frame. */
-struct symbol *inline_skipped_symbol (thread_info *thread);
+const symbol *inline_skipped_symbol (thread_info *thread);
/* Return the number of functions inlined into THIS_FRAME. Some of
the callees may not have associated frames (see
diff --git a/gdb/jit.c b/gdb/jit.c
index 797be95..78b3d98 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -613,6 +613,7 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
new_block = new (&objfile->objfile_obstack) global_block;
else
new_block = new (&objfile->objfile_obstack) block;
+
new_block->set_multidict
(mdict_create_linear (&objfile->objfile_obstack, NULL));
new_block->set_superblock (block_iter);
@@ -624,7 +625,7 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
bv->set_block (i, new_block);
if (i == GLOBAL_BLOCK)
- new_block->set_compunit_symtab (cust);
+ new_block->as_global_block ()->set_compunit (cust);
}
/* Fill up the superblock fields for the real blocks, using the
@@ -660,8 +661,8 @@ jit_object_close_impl (struct gdb_symbol_callbacks *cb,
paddress (priv_data->gdbarch,
priv_data->entry.symfile_addr));
- objfile *objfile = objfile::make (nullptr, objfile_name.c_str (),
- OBJF_NOT_FILENAME);
+ objfile *objfile = objfile::make (nullptr, current_program_space,
+ objfile_name.c_str (), OBJF_NOT_FILENAME);
objfile->per_bfd->gdbarch = priv_data->gdbarch;
for (gdb_symtab &symtab : obj->symtabs)
@@ -880,7 +881,7 @@ jit_breakpoint_re_set_internal (struct gdbarch *gdbarch, program_space *pspace)
/* Lookup the registration symbol. If it is missing, then we
assume we are not attached to a JIT. */
bound_minimal_symbol reg_symbol
- = lookup_minimal_symbol_text (jit_break_name, the_objfile);
+ = lookup_minimal_symbol_text (pspace, jit_break_name, the_objfile);
if (reg_symbol.minsym == NULL
|| reg_symbol.value_address () == 0)
{
@@ -1328,7 +1329,7 @@ Usage: jit-reader-load FILE\n\
Try to load file FILE as a debug info reader (and unwinder) for\n\
JIT compiled code. The file is loaded from " JIT_READER_DIR ",\n\
relocated relative to the GDB executable if required."));
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, deprecated_filename_completer);
c = add_com ("jit-reader-unload", no_class,
jit_reader_unload_command, _("\
diff --git a/gdb/language.c b/gdb/language.c
index be6a1e8..d697331 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -110,6 +110,13 @@ scoped_restore_current_language::scoped_restore_current_language ()
{
}
+scoped_restore_current_language::scoped_restore_current_language
+ (enum language lang)
+ : scoped_restore_current_language ()
+{
+ set_language (lang);
+}
+
scoped_restore_current_language::~scoped_restore_current_language ()
{
/* If both are NULL, then that means dont_restore was called. */
diff --git a/gdb/language.h b/gdb/language.h
index a2ce169..985e622 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -860,6 +860,10 @@ class scoped_restore_current_language
public:
scoped_restore_current_language ();
+
+ /* Set the current language as well. */
+ explicit scoped_restore_current_language (enum language lang);
+
~scoped_restore_current_language ();
scoped_restore_current_language (scoped_restore_current_language &&other)
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 7a1fbc2..d525626 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -23,7 +23,6 @@
#include "symfile.h"
#include "objfiles.h"
#include "source.h"
-#include "demangle.h"
#include "value.h"
#include "completer.h"
#include "cp-abi.h"
@@ -34,7 +33,6 @@
#include "linespec.h"
#include "language.h"
#include "interps.h"
-#include "mi/mi-cmds.h"
#include "target.h"
#include "arch-utils.h"
#include <ctype.h>
@@ -1156,7 +1154,7 @@ iterate_over_all_matching_symtabs
set_current_program_space (pspace);
- for (objfile *objfile : current_program_space->objfiles ())
+ for (objfile *objfile : pspace->objfiles ())
{
objfile->expand_symtabs_matching (NULL, &lookup_name, NULL, NULL,
(SEARCH_GLOBAL_BLOCK
@@ -1544,15 +1542,15 @@ decode_line_2 (struct linespec_state *self,
/* Throw an appropriate error when SYMBOL is not found (optionally in
FILENAME). */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
symbol_not_found_error (const char *symbol, const char *filename)
{
if (symbol == NULL)
symbol = "";
- if (!have_full_symbols ()
- && !have_partial_symbols ()
- && !have_minimal_symbols ())
+ if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space)
+ && !have_minimal_symbols (current_program_space))
throw_error (NOT_FOUND_ERROR,
_("No symbol table is loaded. Use the \"file\" command."));
@@ -1586,7 +1584,7 @@ symbol_not_found_error (const char *symbol, const char *filename)
/* Throw an appropriate error when an unexpected token is encountered
in the input. */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
unexpected_linespec_error (linespec_parser *parser)
{
linespec_token token;
@@ -1613,7 +1611,7 @@ unexpected_linespec_error (linespec_parser *parser)
/* Throw an undefined label error. */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
undefined_label_error (const char *function, const char *label)
{
if (function != NULL)
@@ -1628,7 +1626,7 @@ undefined_label_error (const char *function, const char *label)
/* Throw a source file not found error. */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
source_file_not_found_error (const char *name)
{
throw_error (NOT_FOUND_ERROR, _("No source file named %s."), name);
@@ -2069,12 +2067,19 @@ create_sals_line_offset (struct linespec_state *self,
const linetable_entry *best_entry = NULL;
int i, j;
+ /* True if the provided line gave an exact match. False if we had to
+ search for the next following line with code. */
+ bool was_exact = true;
+
std::vector<symtab_and_line> intermediate_results
= decode_digits_ordinary (self, ls, val.line, &best_entry);
if (intermediate_results.empty () && best_entry != NULL)
- intermediate_results = decode_digits_ordinary (self, ls,
- best_entry->line,
- &best_entry);
+ {
+ was_exact = false;
+ intermediate_results = decode_digits_ordinary (self, ls,
+ best_entry->line,
+ &best_entry);
+ }
/* For optimized code, the compiler can scatter one source line
across disjoint ranges of PC values, even when no duplicate
@@ -2117,11 +2122,45 @@ create_sals_line_offset (struct linespec_state *self,
struct symbol *sym = (blocks[i]
? blocks[i]->containing_function ()
: NULL);
+ symtab_and_line &sal = intermediate_results[i];
+
+ /* Don't consider a match if:
+
+ - the provided line did not give an exact match (so we
+ started looking for lines below until we found one with
+ code associated to it)
+ - the found location is exactly the start of a function
+ - the provided line is above the declaration line of the
+ function
+
+ Consider the following source:
+
+ 10 } // end of a previous function
+ 11
+ 12 int
+ 13 main (void)
+ 14 {
+ 15 int i = 1;
+ 16
+ 17 return 0;
+ 18 }
+
+ The intent of this heuristic is that a breakpoint requested on
+ line 11 and 12 will not result in a breakpoint on main, but a
+ breakpoint on line 13 will. A breakpoint requested on the empty
+ line 16 will also result in a breakpoint in main, at line 17. */
+ if (!was_exact
+ && sym != nullptr
+ && sym->aclass () == LOC_BLOCK
+ && sal.pc == sym->value_block ()->entry_pc ()
+ && val.line < sym->line ())
+ continue;
if (self->funfirstline)
- skip_prologue_sal (&intermediate_results[i]);
- intermediate_results[i].symbol = sym;
- add_sal_to_sals (self, &values, &intermediate_results[i],
+ skip_prologue_sal (&sal);
+
+ sal.symbol = sym;
+ add_sal_to_sals (self, &values, &sal,
sym ? sym->natural_name () : NULL, 0);
}
}
@@ -2129,10 +2168,12 @@ create_sals_line_offset (struct linespec_state *self,
if (values.empty ())
{
if (ls->explicit_loc.source_filename)
- throw_error (NOT_FOUND_ERROR, _("No line %d in file \"%s\"."),
+ throw_error (NOT_FOUND_ERROR,
+ _("No compiled code for line %d in file \"%s\"."),
val.line, ls->explicit_loc.source_filename.get ());
else
- throw_error (NOT_FOUND_ERROR, _("No line %d in the current file."),
+ throw_error (NOT_FOUND_ERROR,
+ _("No compiled code for line %d in the current file."),
val.line);
}
@@ -2172,7 +2213,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec *ls)
for (const auto &sym : ls->labels.label_symbols)
{
struct program_space *pspace
- = sym.symbol->symtab ()->compunit ()->objfile ()->pspace;
+ = sym.symbol->symtab ()->compunit ()->objfile ()->pspace ();
if (symbol_to_sal (&sal, state->funfirstline, sym.symbol)
&& maybe_add_address (state->addr_set, pspace, sal.pc))
@@ -2194,7 +2235,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec *ls)
for (const auto &sym : ls->function_symbols)
{
program_space *pspace
- = sym.symbol->symtab ()->compunit ()->objfile ()->pspace;
+ = sym.symbol->symtab ()->compunit ()->objfile ()->pspace ();
set_current_program_space (pspace);
/* Don't skip to the first line of the function if we
@@ -2256,7 +2297,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec *ls)
for (const auto &elem : ls->minimal_symbols)
{
- program_space *pspace = elem.objfile->pspace;
+ program_space *pspace = elem.objfile->pspace ();
set_current_program_space (pspace);
minsym_found (state, elem.objfile, elem.minsym, &sals);
}
@@ -3205,7 +3246,8 @@ decode_line_with_current_source (const char *string, int flags)
/* We use whatever is set as the current source line. We do not try
and get a default source symtab+line or it will recursively call us! */
- symtab_and_line cursal = get_current_source_symtab_and_line ();
+ symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
location_spec_up locspec = string_to_location_spec (&string,
current_language);
@@ -3255,9 +3297,9 @@ initialize_defaults (struct symtab **default_symtab, int *default_line)
/* Use whatever we have for the default source line. We don't use
get_current_or_default_symtab_and_line as it can recurse and call
us back! */
- struct symtab_and_line cursal =
- get_current_source_symtab_and_line ();
-
+ symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
+
*default_symtab = cursal.symtab;
*default_line = cursal.line;
}
@@ -3437,7 +3479,7 @@ lookup_prefix_sym (struct linespec_state *state,
{
/* Program spaces that are executing startup should have
been filtered out earlier. */
- program_space *pspace = elt->compunit ()->objfile ()->pspace;
+ program_space *pspace = elt->compunit ()->objfile ()->pspace ();
gdb_assert (!pspace->executing_startup);
set_current_program_space (pspace);
@@ -3459,8 +3501,8 @@ compare_symbols (const block_symbol &a, const block_symbol &b)
{
uintptr_t uia, uib;
- uia = (uintptr_t) a.symbol->symtab ()->compunit ()->objfile ()->pspace;
- uib = (uintptr_t) b.symbol->symtab ()->compunit ()->objfile ()->pspace;
+ uia = (uintptr_t) a.symbol->symtab ()->compunit ()->objfile ()->pspace ();
+ uib = (uintptr_t) b.symbol->symtab ()->compunit ()->objfile ()->pspace ();
if (uia < uib)
return true;
@@ -3483,8 +3525,8 @@ 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;
+ uia = (uintptr_t) a.objfile->pspace ();
+ uib = (uintptr_t) a.objfile->pspace ();
if (uia < uib)
return true;
@@ -3584,7 +3626,7 @@ find_method (struct linespec_state *self,
/* Program spaces that are executing startup should have
been filtered out earlier. */
- pspace = sym->symtab ()->compunit ()->objfile ()->pspace;
+ pspace = sym->symtab ()->compunit ()->objfile ()->pspace ();
gdb_assert (!pspace->executing_startup);
set_current_program_space (pspace);
t = check_typedef (sym->type ());
@@ -3596,7 +3638,7 @@ find_method (struct linespec_state *self,
if (ix == sym_classes->size () - 1
|| (pspace
!= (sym_classes->at (ix + 1).symbol->symtab ()
- ->compunit ()->objfile ()->pspace)))
+ ->compunit ()->objfile ()->pspace ())))
{
/* If we did not find a direct implementation anywhere in
this program space, consider superclasses. */
@@ -3691,15 +3733,11 @@ collect_symtabs_from_filename (const char *file,
if (pspace->executing_startup)
continue;
- set_current_program_space (pspace);
- iterate_over_symtabs (file, collector);
+ iterate_over_symtabs (pspace, file, collector);
}
}
else
- {
- set_current_program_space (search_pspace);
- iterate_over_symtabs (file, collector);
- }
+ iterate_over_symtabs (search_pspace, file, collector);
return collector.release_symtabs ();
}
@@ -3716,7 +3754,8 @@ symtabs_from_filename (const char *filename,
if (result.empty ())
{
- if (!have_full_symbols () && !have_partial_symbols ())
+ if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space))
throw_error (NOT_FOUND_ERROR,
_("No symbol table is loaded. "
"Use the \"file\" command."));
@@ -3963,7 +4002,7 @@ find_label_symbols (struct linespec_state *self,
{
fn_sym = elt.symbol;
set_current_program_space
- (fn_sym->symtab ()->compunit ()->objfile ()->pspace);
+ (fn_sym->symtab ()->compunit ()->objfile ()->pspace ());
block = fn_sym->value_block ();
find_label_symbols_in_block (block, name, fn_sym, completion_mode,
@@ -3992,7 +4031,7 @@ decode_digits_list_mode (struct linespec_state *self,
/* The logic above should ensure this. */
gdb_assert (elt != NULL);
- program_space *pspace = elt->compunit ()->objfile ()->pspace;
+ program_space *pspace = elt->compunit ()->objfile ()->pspace ();
set_current_program_space (pspace);
/* Simplistic search just for the list command. */
@@ -4027,7 +4066,7 @@ decode_digits_ordinary (struct linespec_state *self,
/* The logic above should ensure this. */
gdb_assert (elt != NULL);
- program_space *pspace = elt->compunit ()->objfile ()->pspace;
+ program_space *pspace = elt->compunit ()->objfile ()->pspace ();
set_current_program_space (pspace);
pcs = find_pcs_for_symtab_line (elt, line, best_entry);
@@ -4153,7 +4192,7 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
sal.section = msymbol->obj_section (objfile);
- if (maybe_add_address (self->addr_set, objfile->pspace, sal.pc))
+ if (maybe_add_address (self->addr_set, objfile->pspace (), sal.pc))
add_sal_to_sals (self, result, &sal, msymbol->natural_name (), 0);
}
@@ -4163,7 +4202,7 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
static void
add_minsym (struct minimal_symbol *minsym, struct objfile *objfile,
struct symtab *symtab, int list_mode,
- std::vector<struct bound_minimal_symbol> *msyms)
+ std::vector<bound_minimal_symbol> *msyms)
{
if (symtab != NULL)
{
@@ -4200,7 +4239,7 @@ search_minsyms_for_name (struct collect_info *info,
struct program_space *search_pspace,
struct symtab *symtab)
{
- std::vector<struct bound_minimal_symbol> minsyms;
+ std::vector<bound_minimal_symbol> minsyms;
if (symtab == NULL)
{
@@ -4213,7 +4252,7 @@ search_minsyms_for_name (struct collect_info *info,
set_current_program_space (pspace);
- for (objfile *objfile : current_program_space->objfiles ())
+ for (objfile *objfile : pspace->objfiles ())
{
iterate_over_minimal_symbols (objfile, name,
[&] (struct minimal_symbol *msym)
@@ -4228,7 +4267,7 @@ search_minsyms_for_name (struct collect_info *info,
}
else
{
- program_space *pspace = symtab->compunit ()->objfile ()->pspace;
+ program_space *pspace = symtab->compunit ()->objfile ()->pspace ();
if (search_pspace == NULL || pspace == search_pspace)
{
@@ -4322,13 +4361,13 @@ add_matching_symbols_to_info (const char *name,
{ return info->add_symbol (bsym); });
search_minsyms_for_name (info, lookup_name, pspace, NULL);
}
- else if (pspace == NULL || pspace == elt->compunit ()->objfile ()->pspace)
+ else if (pspace == NULL || pspace == elt->compunit ()->objfile ()->pspace ())
{
int prev_len = info->result.symbols->size ();
/* Program spaces that are executing startup should have
been filtered out earlier. */
- program_space *elt_pspace = elt->compunit ()->objfile ()->pspace;
+ program_space *elt_pspace = elt->compunit ()->objfile ()->pspace ();
gdb_assert (!elt_pspace->executing_startup);
set_current_program_space (elt_pspace);
iterate_over_file_blocks (elt, lookup_name, SEARCH_VFT,
@@ -4369,7 +4408,7 @@ symbol_to_sal (struct symtab_and_line *result,
result->symbol = sym;
result->line = sym->line ();
result->pc = sym->value_address ();
- result->pspace = result->symtab->compunit ()->objfile ()->pspace;
+ result->pspace = result->symtab->compunit ()->objfile ()->pspace ();
result->explicit_pc = 1;
return 1;
}
@@ -4385,7 +4424,7 @@ symbol_to_sal (struct symtab_and_line *result,
result->symbol = sym;
result->line = sym->line ();
result->pc = sym->value_address ();
- result->pspace = result->symtab->compunit ()->objfile ()->pspace;
+ result->pspace = result->symtab->compunit ()->objfile ()->pspace ();
return 1;
}
}
diff --git a/gdb/linux-fork.c b/gdb/linux-fork.c
index 319a13f..c457a90 100644
--- a/gdb/linux-fork.c
+++ b/gdb/linux-fork.c
@@ -484,10 +484,12 @@ inferior_call_waitpid (ptid_t pptid, int pid)
scoped_switch_fork_info switch_fork_info (pptid);
/* Get the waitpid_fn. */
- if (lookup_minimal_symbol ("waitpid", NULL, NULL).minsym != NULL)
+ if (lookup_minimal_symbol (current_program_space, "waitpid").minsym
+ != nullptr)
waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf);
if (!waitpid_fn
- && lookup_minimal_symbol ("_waitpid", NULL, NULL).minsym != NULL)
+ && (lookup_minimal_symbol (current_program_space, "_waitpid").minsym
+ != nullptr))
waitpid_fn = find_function_in_inferior ("_waitpid", &waitpid_objf);
if (waitpid_fn != nullptr)
{
@@ -638,9 +640,7 @@ info_checkpoints_command (const char *arg, int from_tty)
gdb_printf (_(", line %d"), sal.line);
if (!sal.symtab && !sal.line)
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (pc);
if (msym.minsym)
gdb_printf (", <%s>", msym.minsym->linkage_name ());
}
@@ -703,10 +703,11 @@ checkpoint_command (const char *args, int from_tty)
/* Make the inferior fork, record its (and gdb's) state. */
- if (lookup_minimal_symbol ("fork", NULL, NULL).minsym != NULL)
+ if (lookup_minimal_symbol (current_program_space, "fork").minsym != nullptr)
fork_fn = find_function_in_inferior ("fork", &fork_objf);
if (!fork_fn)
- if (lookup_minimal_symbol ("_fork", NULL, NULL).minsym != NULL)
+ if (lookup_minimal_symbol (current_program_space, "_fork").minsym
+ != nullptr)
fork_fn = find_function_in_inferior ("fork", &fork_objf);
if (!fork_fn)
error (_("checkpoint: can't find fork function in inferior."));
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index fe880b3..65ec221 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -43,6 +43,7 @@
#include "gcore-elf.h"
#include "solib-svr4.h"
#include "memtag.h"
+#include "cli/cli-style.h"
#include <ctype.h>
#include <unordered_map>
@@ -213,7 +214,7 @@ get_linux_gdbarch_data (struct gdbarch *gdbarch)
/* Linux-specific cached data. This is used by GDB for caching
purposes for each inferior. This helps reduce the overhead of
- transfering data from a remote target to the local host. */
+ transferring data from a remote target to the local host. */
struct linux_info
{
/* Cache of the inferior's vsyscall/vDSO mapping range. Only valid
@@ -457,7 +458,7 @@ struct mapping
{
ULONGEST addr;
ULONGEST endaddr;
- std::string_view permissions;
+ std::string permissions;
ULONGEST offset;
std::string_view device;
ULONGEST inode;
@@ -484,7 +485,8 @@ read_mapping (const char *line)
const char *permissions_start = p;
while (*p && !isspace (*p))
p++;
- mapping.permissions = {permissions_start, (size_t) (p - permissions_start)};
+ mapping.permissions = std::string (permissions_start,
+ (size_t) (p - permissions_start));
mapping.offset = strtoulst (p, &p, 16);
@@ -897,51 +899,39 @@ linux_info_proc (struct gdbarch *gdbarch, const char *args,
= target_fileio_read_stralloc (NULL, filename);
if (map != NULL)
{
- char *line;
-
gdb_printf (_("Mapped address spaces:\n\n"));
- if (gdbarch_addr_bit (gdbarch) == 32)
- {
- gdb_printf ("\t%10s %10s %10s %10s %s %s\n",
- "Start Addr", " End Addr", " Size",
- " Offset", "Perms ", "objfile");
- }
- else
- {
- gdb_printf (" %18s %18s %10s %10s %s %s\n",
- "Start Addr", " End Addr", " Size",
- " Offset", "Perms ", "objfile");
- }
+ ui_out_emit_table emitter (current_uiout, 6, -1, "ProcMappings");
+
+ int width = gdbarch_addr_bit (gdbarch) == 32 ? 10 : 18;
+ current_uiout->table_header (width, ui_left, "start", "Start Addr");
+ current_uiout->table_header (width, ui_left, "end", "End Addr");
+ current_uiout->table_header (width, ui_left, "size", "Size");
+ current_uiout->table_header (width, ui_left, "offset", "Offset");
+ current_uiout->table_header (5, ui_left, "perms", "Perms");
+ current_uiout->table_header (0, ui_left, "objfile", "File");
+ current_uiout->table_body ();
char *saveptr;
- for (line = strtok_r (map.get (), "\n", &saveptr);
- line;
- line = strtok_r (NULL, "\n", &saveptr))
+ for (const char *line = strtok_r (map.get (), "\n", &saveptr);
+ line != nullptr;
+ line = strtok_r (nullptr, "\n", &saveptr))
{
struct mapping m = read_mapping (line);
- if (gdbarch_addr_bit (gdbarch) == 32)
- {
- gdb_printf ("\t%10s %10s %10s %10s %-5.*s %s\n",
- paddress (gdbarch, m.addr),
- paddress (gdbarch, m.endaddr),
- hex_string (m.endaddr - m.addr),
- hex_string (m.offset),
- (int) m.permissions.size (),
- m.permissions.data (),
- m.filename);
- }
- else
- {
- gdb_printf (" %18s %18s %10s %10s %-5.*s %s\n",
- paddress (gdbarch, m.addr),
- paddress (gdbarch, m.endaddr),
- hex_string (m.endaddr - m.addr),
- hex_string (m.offset),
- (int) m.permissions.size (),
- m.permissions.data (),
- m.filename);
- }
+ ui_out_emit_tuple tuple_emitter (current_uiout, nullptr);
+ current_uiout->field_core_addr ("start", gdbarch, m.addr);
+ current_uiout->field_core_addr ("end", gdbarch, m.endaddr);
+ /* These next two aren't really addresses and so
+ shouldn't be styled as such. */
+ current_uiout->field_string ("size",
+ paddress (gdbarch,
+ m.endaddr - m.addr));
+ current_uiout->field_string ("offset",
+ paddress (gdbarch, m.offset));
+ current_uiout->field_string ("perms", m.permissions);
+ current_uiout->field_string ("objfile", m.filename,
+ file_name_style.style ());
+ current_uiout->text ("\n");
}
}
else
@@ -1242,42 +1232,34 @@ linux_read_core_file_mappings
static void
linux_core_info_proc_mappings (struct gdbarch *gdbarch, const char *args)
{
+ std::optional<ui_out_emit_table> emitter;
+
linux_read_core_file_mappings (gdbarch, current_program_space->core_bfd (),
- [=] (ULONGEST count)
+ [&] (ULONGEST count)
{
gdb_printf (_("Mapped address spaces:\n\n"));
- if (gdbarch_addr_bit (gdbarch) == 32)
- {
- gdb_printf ("\t%10s %10s %10s %10s %s\n",
- "Start Addr",
- " End Addr",
- " Size", " Offset", "objfile");
- }
- else
- {
- gdb_printf (" %18s %18s %10s %10s %s\n",
- "Start Addr",
- " End Addr",
- " Size", " Offset", "objfile");
- }
+ emitter.emplace (current_uiout, 5, -1, "ProcMappings");
+ int width = gdbarch_addr_bit (gdbarch) == 32 ? 10 : 18;
+ current_uiout->table_header (width, ui_left, "start", "Start Addr");
+ current_uiout->table_header (width, ui_left, "end", "End Addr");
+ current_uiout->table_header (width, ui_left, "size", "Size");
+ current_uiout->table_header (width, ui_left, "offset", "Offset");
+ current_uiout->table_header (0, ui_left, "objfile", "File");
+ current_uiout->table_body ();
},
[=] (int num, ULONGEST start, ULONGEST end, ULONGEST file_ofs,
const char *filename, const bfd_build_id *build_id)
{
- if (gdbarch_addr_bit (gdbarch) == 32)
- gdb_printf ("\t%10s %10s %10s %10s %s\n",
- paddress (gdbarch, start),
- paddress (gdbarch, end),
- hex_string (end - start),
- hex_string (file_ofs),
- filename);
- else
- gdb_printf (" %18s %18s %10s %10s %s\n",
- paddress (gdbarch, start),
- paddress (gdbarch, end),
- hex_string (end - start),
- hex_string (file_ofs),
- filename);
+ ui_out_emit_tuple tuple_emitter (current_uiout, nullptr);
+ current_uiout->field_core_addr ("start", gdbarch, start);
+ current_uiout->field_core_addr ("end", gdbarch, end);
+ /* These next two aren't really addresses and so shouldn't be
+ styled as such. */
+ current_uiout->field_string ("size", paddress (gdbarch, end - start));
+ current_uiout->field_string ("offset", paddress (gdbarch, file_ofs));
+ current_uiout->field_string ("objfile", filename,
+ file_name_style.style ());
+ current_uiout->text ("\n");
});
}
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index 018bd68..9d84187 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -467,11 +467,11 @@ verbose_dlsym (void *handle, const char *name)
static int
inferior_has_bug (const char *ver_symbol, int ver_major_min, int ver_minor_min)
{
- struct bound_minimal_symbol version_msym;
CORE_ADDR version_addr;
int got, retval = 0;
- version_msym = lookup_minimal_symbol (ver_symbol, NULL, NULL);
+ bound_minimal_symbol version_msym
+ = lookup_minimal_symbol (current_program_space, ver_symbol);
if (version_msym.minsym == NULL)
return 0;
@@ -810,9 +810,8 @@ static bool
libpthread_objfile_p (objfile *obj)
{
return (libpthread_name_p (objfile_name (obj))
- && lookup_minimal_symbol ("pthread_create",
- NULL,
- obj).minsym != NULL);
+ && lookup_minimal_symbol (current_program_space,
+ "pthread_create", obj).minsym != nullptr);
}
/* Attempt to initialize dlopen()ed libthread_db, described by INFO.
diff --git a/gdb/loongarch-linux-nat.c b/gdb/loongarch-linux-nat.c
index 8736287..bc9927d 100644
--- a/gdb/loongarch-linux-nat.c
+++ b/gdb/loongarch-linux-nat.c
@@ -18,6 +18,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 "cli/cli-cmds.h"
#include "elf/common.h"
#include "gregset.h"
#include "inferior.h"
@@ -765,4 +766,19 @@ _initialize_loongarch_linux_nat ()
{
linux_target = &the_loongarch_linux_nat_target;
add_inf_child_target (&the_loongarch_linux_nat_target);
+
+ /* Add a maintenance command to enable printing the LoongArch internal
+ debug registers mirror variables. */
+ add_setshow_boolean_cmd ("show-debug-regs", class_maintenance,
+ &show_debug_regs, _("\
+Set whether to show the LoongArch debug registers state."), _("\
+Show whether to show the LoongArch debug registers state."), _("\
+Use \"on\" to enable, \"off\" to disable.\n\
+If enabled, the debug registers values are shown when GDB inserts\n\
+or removes a hardware breakpoint or watchpoint, and when the inferior\n\
+triggers a breakpoint or watchpoint."),
+ NULL,
+ NULL,
+ &maintenance_set_cmdlist,
+ &maintenance_show_cmdlist);
}
diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c
index 757f4ac..c50dd7f 100644
--- a/gdb/loongarch-tdep.c
+++ b/gdb/loongarch-tdep.c
@@ -36,14 +36,14 @@ static insn_t
loongarch_fetch_instruction (CORE_ADDR pc)
{
size_t insn_len = loongarch_insn_length (0);
- gdb_byte buf[insn_len];
+ gdb::byte_vector buf (insn_len);
int err;
- err = target_read_memory (pc, buf, insn_len);
+ err = target_read_memory (pc, buf.data (), insn_len);
if (err)
memory_error (TARGET_XFER_E_IO, pc);
- return extract_unsigned_integer (buf, insn_len, BFD_ENDIAN_LITTLE);
+ return extract_unsigned_integer (buf.data (), insn_len, BFD_ENDIAN_LITTLE);
}
/* Return TRUE if INSN is a unconditional branch instruction, otherwise return FALSE. */
@@ -1306,18 +1306,24 @@ loongarch_return_value (struct gdbarch *gdbarch, struct value *function,
and the signed integer scalars are sign-extended. */
if (writebuf)
{
- gdb_byte buf[regsize];
+ gdb::byte_vector buf (regsize);
if (type->is_unsigned ())
{
- ULONGEST data = extract_unsigned_integer (writebuf, len, BFD_ENDIAN_LITTLE);
- store_unsigned_integer (buf, regsize, BFD_ENDIAN_LITTLE, data);
+ ULONGEST data = extract_unsigned_integer (writebuf, len,
+ BFD_ENDIAN_LITTLE);
+ store_unsigned_integer (buf.data (), regsize,
+ BFD_ENDIAN_LITTLE, data);
}
else
{
- LONGEST data = extract_signed_integer (writebuf, len, BFD_ENDIAN_LITTLE);
- store_signed_integer (buf, regsize, BFD_ENDIAN_LITTLE, data);
+ LONGEST data
+ = extract_signed_integer (writebuf, len, BFD_ENDIAN_LITTLE);
+ store_signed_integer (buf.data (), regsize, BFD_ENDIAN_LITTLE,
+ data);
}
- loongarch_xfer_reg (regcache, a0, regsize, nullptr, buf, 0);
+
+ loongarch_xfer_reg (regcache, a0, regsize, nullptr, buf.data (),
+ 0);
}
else
loongarch_xfer_reg (regcache, a0, len, readbuf, nullptr, 0);
diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y
index 28005e1..2887ad2 100644
--- a/gdb/m2-exp.y
+++ b/gdb/m2-exp.y
@@ -117,7 +117,7 @@ using namespace expr;
%token <sval> TYPENAME
%token SIZE CAP ORD HIGH ABS MIN_FUNC MAX_FUNC FLOAT_FUNC VAL CHR ODD TRUNC
-%token TSIZE
+%token TSIZE ADR
%token INC DEC INCL EXCL
/* The GDB scope operator */
@@ -191,6 +191,10 @@ exp : ABS '(' exp ')'
{ error (_("ABS function is not implemented")); }
;
+exp : ADR '(' exp ')'
+ { pstate->wrap<unop_addr_operation> (); }
+ ;
+
exp : HIGH '(' exp ')'
{ pstate->wrap<m2_unop_high_operation> (); }
;
@@ -699,6 +703,7 @@ static struct keyword keytab[] =
{"IN", IN },/* Note space after IN */
{"AND", LOGICAL_AND},
{"ABS", ABS },
+ {"ADR", ADR },
{"CHR", CHR },
{"DEC", DEC },
{"NOT", NOT },
@@ -918,8 +923,9 @@ yylex (void)
std::string tmp = copy_name (yylval.sval);
struct symbol *sym;
- if (lookup_symtab (tmp.c_str ()))
+ if (lookup_symtab (current_program_space, tmp.c_str ()) != nullptr)
return BLOCKNAME;
+
sym = lookup_symbol (tmp.c_str (), pstate->expression_context_block,
SEARCH_VFT, 0).symbol;
if (sym && sym->aclass () == LOC_BLOCK)
diff --git a/gdb/m2-typeprint.c b/gdb/m2-typeprint.c
index c0ae722..4ade1ce 100644
--- a/gdb/m2-typeprint.c
+++ b/gdb/m2-typeprint.c
@@ -27,7 +27,6 @@
#include "gdbcore.h"
#include "m2-lang.h"
#include "target.h"
-#include "language.h"
#include "demangle.h"
#include "c-lang.h"
#include "typeprint.h"
diff --git a/gdb/m32c-tdep.c b/gdb/m32c-tdep.c
index d9890d0..28dfb2f 100644
--- a/gdb/m32c-tdep.c
+++ b/gdb/m32c-tdep.c
@@ -2212,8 +2212,8 @@ m32c_return_value (struct gdbarch *gdbarch,
/* Everything else is passed in mem0, using as many bytes as
needed. This is not what the Renesas tools do, but it's
what GCC does at the moment. */
- struct bound_minimal_symbol mem0
- = lookup_minimal_symbol ("mem0", NULL, NULL);
+ bound_minimal_symbol mem0
+ = lookup_minimal_symbol (current_program_space, "mem0");
if (! mem0.minsym)
error (_("The return value is stored in memory at 'mem0', "
@@ -2244,8 +2244,8 @@ m32c_return_value (struct gdbarch *gdbarch,
/* Everything else is passed in mem0, using as many bytes as
needed. This is not what the Renesas tools do, but it's
what GCC does at the moment. */
- struct bound_minimal_symbol mem0
- = lookup_minimal_symbol ("mem0", NULL, NULL);
+ bound_minimal_symbol mem0
+ = lookup_minimal_symbol (current_program_space, "mem0");
if (! mem0.minsym)
error (_("The return value is stored in memory at 'mem0', "
@@ -2421,11 +2421,9 @@ m32c_m16c_address_to_pointer (struct gdbarch *gdbarch,
{
const char *func_name;
char *tramp_name;
- struct bound_minimal_symbol tramp_msym;
/* Try to find a linker symbol at this address. */
- struct bound_minimal_symbol func_msym
- = lookup_minimal_symbol_by_pc (addr);
+ bound_minimal_symbol func_msym = lookup_minimal_symbol_by_pc (addr);
if (! func_msym.minsym)
error (_("Cannot convert code address %s to function pointer:\n"
@@ -2438,7 +2436,8 @@ m32c_m16c_address_to_pointer (struct gdbarch *gdbarch,
strcat (tramp_name, ".plt");
/* Try to find a linker symbol for the trampoline. */
- tramp_msym = lookup_minimal_symbol (tramp_name, NULL, NULL);
+ bound_minimal_symbol tramp_msym
+ = lookup_minimal_symbol (current_program_space, tramp_name);
/* We've either got another copy of the name now, or don't need
the name any more. */
@@ -2502,7 +2501,7 @@ m32c_m16c_pointer_to_address (struct gdbarch *gdbarch,
{
/* See if there is a minimal symbol at that address whose name is
"NAME.plt". */
- struct bound_minimal_symbol ptr_msym = lookup_minimal_symbol_by_pc (ptr);
+ bound_minimal_symbol ptr_msym = lookup_minimal_symbol_by_pc (ptr);
if (ptr_msym.minsym)
{
@@ -2512,7 +2511,6 @@ m32c_m16c_pointer_to_address (struct gdbarch *gdbarch,
if (len > 4
&& strcmp (ptr_msym_name + len - 4, ".plt") == 0)
{
- struct bound_minimal_symbol func_msym;
/* We have a .plt symbol; try to find the symbol for the
corresponding function.
@@ -2522,8 +2520,8 @@ m32c_m16c_pointer_to_address (struct gdbarch *gdbarch,
char *func_name = (char *) xmalloc (len - 4 + 1);
memcpy (func_name, ptr_msym_name, len - 4);
func_name[len - 4] = '\0';
- func_msym
- = lookup_minimal_symbol (func_name, NULL, NULL);
+ bound_minimal_symbol func_msym
+ = lookup_minimal_symbol (current_program_space, func_name);
/* If we do have such a symbol, return its value as the
function's true address. */
diff --git a/gdb/m32r-tdep.c b/gdb/m32r-tdep.c
index f2f8602..c6428f6 100644
--- a/gdb/m32r-tdep.c
+++ b/gdb/m32r-tdep.c
@@ -800,14 +800,14 @@ m32r_frame_this_id (const frame_info_ptr &this_frame,
= m32r_frame_unwind_cache (this_frame, this_prologue_cache);
CORE_ADDR base;
CORE_ADDR func;
- struct bound_minimal_symbol msym_stack;
struct frame_id id;
/* The FUNC is easy. */
func = get_frame_func (this_frame);
/* Check if the stack is empty. */
- msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL);
+ bound_minimal_symbol msym_stack
+ = lookup_minimal_symbol (current_program_space, "_stack");
if (msym_stack.minsym && info->base == msym_stack.value_address ())
return;
diff --git a/gdb/m68hc11-tdep.c b/gdb/m68hc11-tdep.c
index e58e44b..12cd0ef 100644
--- a/gdb/m68hc11-tdep.c
+++ b/gdb/m68hc11-tdep.c
@@ -210,9 +210,8 @@ static int soft_reg_initialized = 0;
static void
m68hc11_get_register_info (struct m68hc11_soft_reg *reg, const char *name)
{
- struct bound_minimal_symbol msymbol;
-
- msymbol = lookup_minimal_symbol (name, NULL, NULL);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space, name);
if (msymbol.minsym)
{
reg->addr = msymbol.value_address ();
@@ -591,12 +590,10 @@ m68hc11_analyze_instruction (struct gdbarch *gdbarch,
static enum insn_return_kind
m68hc11_get_return_insn (CORE_ADDR pc)
{
- struct bound_minimal_symbol sym;
-
/* A flag indicating that this is a STO_M68HC12_FAR or STO_M68HC12_INTERRUPT
function is stored by elfread.c in the high bit of the info field.
Use this to decide which instruction the function uses to return. */
- sym = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol sym = lookup_minimal_symbol_by_pc (pc);
if (sym.minsym == 0)
return RETURN_RTS;
diff --git a/gdb/m68k-linux-nat.c b/gdb/m68k-linux-nat.c
index 7f33739..49cd491 100644
--- a/gdb/m68k-linux-nat.c
+++ b/gdb/m68k-linux-nat.c
@@ -350,7 +350,7 @@ fill_fpregset (const struct regcache *regcache,
#ifdef HAVE_PTRACE_GETREGS
/* Fetch all floating-point registers from process/thread TID and store
- thier values in GDB's register array. */
+ their values in GDB's register array. */
static void
fetch_fpregs (struct regcache *regcache, int tid)
diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c
index 1b8cc92..375d5e6 100644
--- a/gdb/m68k-tdep.c
+++ b/gdb/m68k-tdep.c
@@ -1350,11 +1350,19 @@ static enum gdb_osabi
m68k_osabi_sniffer (bfd *abfd)
{
unsigned int elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
+ enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
if (elfosabi == ELFOSABI_NONE)
- return GDB_OSABI_SVR4;
+ {
+ /* Check note sections. */
+ for (asection *sect : gdb_bfd_sections (abfd))
+ generic_elf_osabi_sniff_abi_tag_sections (abfd, sect, &osabi);
+
+ if (osabi == GDB_OSABI_UNKNOWN)
+ osabi = GDB_OSABI_SVR4;
+ }
- return GDB_OSABI_UNKNOWN;
+ return osabi;
}
void _initialize_m68k_tdep ();
diff --git a/gdb/machoread.c b/gdb/machoread.c
index be68e45..ef6cf66 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -390,13 +390,14 @@ static CORE_ADDR
macho_resolve_oso_sym_with_minsym (struct objfile *main_objfile, asymbol *sym)
{
/* For common symbol and global symbols, use the min symtab. */
- struct bound_minimal_symbol msym;
const char *name = sym->name;
if (*name != '\0'
&& *name == bfd_get_symbol_leading_char (main_objfile->obfd.get ()))
++name;
- msym = lookup_minimal_symbol (name, NULL, main_objfile);
+
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, name, main_objfile);
if (msym.minsym == NULL)
{
warning (_("can't find symbol '%s' in minsymtab"), name);
diff --git a/gdb/macrocmd.c b/gdb/macrocmd.c
index 6cf3a0d..2da5a5b 100644
--- a/gdb/macrocmd.c
+++ b/gdb/macrocmd.c
@@ -271,18 +271,17 @@ skip_ws (const char **expp)
}
/* Try to find the bounds of an identifier. If an identifier is
- found, returns a newly allocated string; otherwise returns NULL.
+ found, return it; otherwise return an empty string.
+
EXPP is a pointer to an input string; it is updated to point to the
text following the identifier. If IS_PARAMETER is true, this
function will also allow "..." forms as used in varargs macro
parameters. */
-static gdb::unique_xmalloc_ptr<char>
+static std::string
extract_identifier (const char **expp, int is_parameter)
{
- char *result;
const char *p = *expp;
- unsigned int len;
if (is_parameter && startswith (p, "..."))
{
@@ -291,67 +290,39 @@ extract_identifier (const char **expp, int is_parameter)
else
{
if (! *p || ! macro_is_identifier_nondigit (*p))
- return NULL;
+ return {};
+
for (++p;
*p && (macro_is_identifier_nondigit (*p) || macro_is_digit (*p));
++p)
;
}
- if (is_parameter && startswith (p, "..."))
+ if (is_parameter && startswith (p, "..."))
p += 3;
- len = p - *expp;
- result = (char *) xmalloc (len + 1);
- memcpy (result, *expp, len);
- result[len] = '\0';
- *expp += len;
- return gdb::unique_xmalloc_ptr<char> (result);
-}
+ std::string result (*expp, p);
+ *expp = p;
-struct temporary_macro_definition : public macro_definition
-{
- temporary_macro_definition ()
- {
- table = nullptr;
- kind = macro_object_like;
- argc = 0;
- argv = nullptr;
- replacement = nullptr;
- }
-
- ~temporary_macro_definition ()
- {
- int i;
-
- for (i = 0; i < argc; ++i)
- xfree ((char *) argv[i]);
- xfree ((char *) argv);
- /* Note that the 'replacement' field is not allocated. */
- }
-};
+ return result;
+}
static void
macro_define_command (const char *exp, int from_tty)
{
- temporary_macro_definition new_macro;
-
if (!exp)
error (_("usage: macro define NAME[(ARGUMENT-LIST)] [REPLACEMENT-LIST]"));
skip_ws (&exp);
- gdb::unique_xmalloc_ptr<char> name = extract_identifier (&exp, 0);
- if (name == NULL)
+
+ std::string name = extract_identifier (&exp, 0);
+ if (name.empty ())
error (_("Invalid macro name."));
+
if (*exp == '(')
{
/* Function-like macro. */
- int alloced = 5;
- char **argv = XNEWVEC (char *, alloced);
-
- new_macro.kind = macro_function_like;
- new_macro.argc = 0;
- new_macro.argv = (const char * const *) argv;
+ std::vector<std::string> argv;
/* Skip the '(' and whitespace. */
++exp;
@@ -359,23 +330,13 @@ macro_define_command (const char *exp, int from_tty)
while (*exp != ')')
{
- int i;
-
- if (new_macro.argc == alloced)
- {
- alloced *= 2;
- argv = (char **) xrealloc (argv, alloced * sizeof (char *));
- /* Must update new_macro as well... */
- new_macro.argv = (const char * const *) argv;
- }
- argv[new_macro.argc] = extract_identifier (&exp, 1).release ();
- if (! argv[new_macro.argc])
+ argv.emplace_back (extract_identifier (&exp, 1));
+ if (argv.back ().empty ())
error (_("Macro is missing an argument."));
- ++new_macro.argc;
- for (i = new_macro.argc - 2; i >= 0; --i)
+ for (const auto &other_arg : argv)
{
- if (! strcmp (argv[i], argv[new_macro.argc - 1]))
+ if (&other_arg != &argv.back () && other_arg == argv.back ())
error (_("Two macro arguments with identical names."));
}
@@ -388,18 +349,18 @@ macro_define_command (const char *exp, int from_tty)
else if (*exp != ')')
error (_("',' or ')' expected at end of macro arguments."));
}
+
/* Skip the closing paren. */
++exp;
skip_ws (&exp);
- macro_define_function (macro_main (macro_user_macros), -1, name.get (),
- new_macro.argc, (const char **) new_macro.argv,
- exp);
+ macro_define_function (macro_main (macro_user_macros), -1, name.c_str (),
+ argv, exp);
}
else
{
skip_ws (&exp);
- macro_define_object (macro_main (macro_user_macros), -1, name.get (),
+ macro_define_object (macro_main (macro_user_macros), -1, name.c_str (),
exp);
}
}
@@ -412,10 +373,12 @@ macro_undef_command (const char *exp, int from_tty)
error (_("usage: macro undef NAME"));
skip_ws (&exp);
- gdb::unique_xmalloc_ptr<char> name = extract_identifier (&exp, 0);
- if (name == nullptr)
+
+ std::string name = extract_identifier (&exp, 0);
+ if (name.empty ())
error (_("Invalid macro name."));
- macro_undef (macro_main (macro_user_macros), -1, name.get ());
+
+ macro_undef (macro_main (macro_user_macros), -1, name.c_str ());
}
diff --git a/gdb/macroscope.c b/gdb/macroscope.c
index 4c1304f..c1b2238 100644
--- a/gdb/macroscope.c
+++ b/gdb/macroscope.c
@@ -121,9 +121,9 @@ default_macro_scope (void)
symbol files loaded, then get_current_or_default would raise an
error. But `set width' shouldn't raise an error just because
it can't decide which scope to macro-expand its argument in. */
- struct symtab_and_line cursal
- = get_current_source_symtab_and_line ();
-
+ symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
+
sal.symtab = cursal.symtab;
sal.line = cursal.line;
}
diff --git a/gdb/macrotab.c b/gdb/macrotab.c
index 3a7f792..37ae0f2 100644
--- a/gdb/macrotab.c
+++ b/gdb/macrotab.c
@@ -545,10 +545,10 @@ macro_lookup_inclusion (struct macro_source_file *source, const char *name)
/* Construct a definition for a macro in table T. Cache all strings,
and the macro_definition structure itself, in T's bcache. */
-static struct macro_definition *
-new_macro_definition (struct macro_table *t,
- enum macro_kind kind,
- int argc, const char **argv,
+static macro_definition *
+new_macro_definition (macro_table *t, macro_kind kind,
+ macro_special_kind special_kind,
+ const std::vector<std::string> &argv,
const char *replacement)
{
struct macro_definition *d
@@ -558,22 +558,26 @@ new_macro_definition (struct macro_table *t,
d->table = t;
d->kind = kind;
d->replacement = macro_bcache_str (t, replacement);
- d->argc = argc;
if (kind == macro_function_like)
{
- int i;
- const char **cached_argv;
- int cached_argv_size = argc * sizeof (*cached_argv);
+ d->argc = argv.size ();
/* Bcache all the arguments. */
- cached_argv = (const char **) alloca (cached_argv_size);
- for (i = 0; i < argc; i++)
- cached_argv[i] = macro_bcache_str (t, argv[i]);
+ if (d->argc > 0)
+ {
+ std::vector<const char *> cached_argv;
- /* Now bcache the array of argument pointers itself. */
- d->argv = macro_bcache (t, cached_argv, cached_argv_size);
+ for (const auto &arg : argv)
+ cached_argv.push_back (macro_bcache_str (t, arg.c_str ()));
+
+ /* Now bcache the array of argument pointers itself. */
+ d->argv = macro_bcache (t, cached_argv.data (),
+ cached_argv.size () * sizeof (const char *));
+ }
}
+ else
+ d->argc = special_kind;
/* We don't bcache the entire definition structure because it's got
a pointer to the macro table in it; since each compilation unit
@@ -677,13 +681,12 @@ find_definition (const char *name,
/* If NAME already has a definition in scope at LINE in SOURCE, return
the key. If the old definition is different from the definition
- given by KIND, ARGC, ARGV, and REPLACEMENT, complain, too.
- Otherwise, return zero. (ARGC and ARGV are meaningless unless KIND
+ given by KIND, ARGV, and REPLACEMENT, complain, too.
+ Otherwise, return nullptr. (ARGV is meaningless unless KIND
is `macro_function_like'.) */
-static struct macro_key *
-check_for_redefinition (struct macro_source_file *source, int line,
- const char *name, enum macro_kind kind,
- int argc, const char **argv,
+static macro_key *
+check_for_redefinition (macro_source_file *source, int line, const char *name,
+ macro_kind kind, const std::vector<std::string> &argv,
const char *replacement)
{
splay_tree_node n = find_definition (name, source, line);
@@ -708,14 +711,14 @@ check_for_redefinition (struct macro_source_file *source, int line,
same = 0;
else if (kind == macro_function_like)
{
- if (argc != found_def->argc)
+ if (argv.size () != found_def->argc)
same = 0;
else
{
- int i;
+ int i = 0;
- for (i = 0; i < argc; i++)
- if (strcmp (argv[i], found_def->argv[i]))
+ for (const auto &arg : argv)
+ if (arg != found_def->argv[i++])
same = 0;
}
}
@@ -739,15 +742,18 @@ check_for_redefinition (struct macro_source_file *source, int line,
}
/* A helper function to define a new object-like or function-like macro
- according to KIND. When KIND is macro_object_like,
- the macro_special_kind must be provided as ARGC, and ARGV must be NULL.
- When KIND is macro_function_like, ARGC and ARGV are giving the function
- arguments. */
+ according to KIND.
+
+ When KIND is macro_object_like, the possible special kind is given by
+ SPECIAL_KIND, and ARGV is meaningless.
+
+ When KIND is macro_function_like, ARGV gives the macro argument names, and
+ SPECIAL_KIND is meaningless. */
static void
-macro_define_internal (struct macro_source_file *source, int line,
- const char *name, enum macro_kind kind,
- int argc, const char **argv,
+macro_define_internal (macro_source_file *source, int line, const char *name,
+ macro_kind kind, macro_special_kind special_kind,
+ const std::vector<std::string> &argv,
const char *replacement)
{
struct macro_table *t = source->table;
@@ -755,10 +761,7 @@ macro_define_internal (struct macro_source_file *source, int line,
struct macro_definition *d;
if (! t->redef_ok)
- k = check_for_redefinition (source, line,
- name, kind,
- argc, argv,
- replacement);
+ k = check_for_redefinition (source, line, name, kind, argv, replacement);
/* If we're redefining a symbol, and the existing key would be
identical to our new key, then the splay_tree_insert function
@@ -774,7 +777,7 @@ macro_define_internal (struct macro_source_file *source, int line,
return;
k = new_macro_key (t, name, source, line);
- d = new_macro_definition (t, kind, argc, argv, replacement);
+ d = new_macro_definition (t, kind, special_kind, argv, replacement);
splay_tree_insert (t->definitions, (splay_tree_key) k, (splay_tree_value) d);
}
@@ -785,10 +788,8 @@ macro_define_object_internal (struct macro_source_file *source, int line,
const char *name, const char *replacement,
enum macro_special_kind special_kind)
{
- macro_define_internal (source, line,
- name, macro_object_like,
- special_kind, NULL,
- replacement);
+ macro_define_internal (source, line, name, macro_object_like, special_kind,
+ {}, replacement);
}
void
@@ -811,14 +812,12 @@ macro_define_special (struct macro_table *table)
}
void
-macro_define_function (struct macro_source_file *source, int line,
- const char *name, int argc, const char **argv,
+macro_define_function (macro_source_file *source, int line, const char *name,
+ const std::vector<std::string> &argv,
const char *replacement)
{
- macro_define_internal (source, line,
- name, macro_function_like,
- argc, argv,
- replacement);
+ macro_define_internal (source, line, name, macro_function_like,
+ macro_ordinary, argv, replacement);
}
void
diff --git a/gdb/macrotab.h b/gdb/macrotab.h
index 789beed..d501595 100644
--- a/gdb/macrotab.h
+++ b/gdb/macrotab.h
@@ -242,26 +242,23 @@ struct macro_source_file *macro_lookup_inclusion
Record in SOURCE's macro table that, at line number LINE in SOURCE,
we #defined a preprocessor symbol named NAME, whose replacement
string is REPLACEMENT. This function makes copies of NAME and
- REPLACEMENT; the caller is responsible for freeing them. */
+ REPLACEMENT. */
void macro_define_object (struct macro_source_file *source, int line,
const char *name, const char *replacement);
-/* Record an function-like #definition (i.e., one with a parameter list).
+/* Record a function-like #definition (i.e., one with a parameter list).
Record in SOURCE's macro table that, at line number LINE in SOURCE,
- we #defined a preprocessor symbol named NAME, with ARGC arguments
- whose names are given in ARGV, whose replacement string is REPLACEMENT. If
- the macro takes a variable number of arguments, then ARGC should be
- one greater than the number of named arguments, and ARGV[ARGC-1]
- should be the string "...". This function makes its own copies of
- NAME, ARGV, and REPLACEMENT; the caller is responsible for freeing
- them. */
-void macro_define_function (struct macro_source_file *source, int line,
- const char *name, int argc, const char **argv,
+ we #defined a preprocessor symbol named NAME, with argument names given by
+ ARGV, whose replacement string is REPLACEMENT. If the macro takes a variable
+ number of arguments, then the last element of ARGV should be the string
+ "...". This function makes copies of NAME, ARGV, and REPLACEMENT. */
+void macro_define_function (macro_source_file *source, int line,
+ const char *name,
+ const std::vector<std::string> &argv,
const char *replacement);
-
/* Record an #undefinition.
Record in SOURCE's macro table that, at line number LINE in SOURCE,
we removed the definition for the preprocessor symbol named NAME. */
diff --git a/gdb/maint.c b/gdb/maint.c
index d091634..237c9d8 100644
--- a/gdb/maint.c
+++ b/gdb/maint.c
@@ -546,7 +546,6 @@ maintenance_translate_address (const char *arg, int from_tty)
CORE_ADDR address;
struct obj_section *sect;
const char *p;
- struct bound_minimal_symbol sym;
if (arg == NULL || *arg == 0)
error (_("requires argument (address or section + address)"));
@@ -577,6 +576,7 @@ maintenance_translate_address (const char *arg, int from_tty)
address = parse_and_eval_address (p);
+ bound_minimal_symbol sym;
if (sect)
sym = lookup_minimal_symbol_by_pc_section (address, sect);
else
diff --git a/gdb/make-target-delegates.py b/gdb/make-target-delegates.py
index bfcf7fa..fc69cb3 100755
--- a/gdb/make-target-delegates.py
+++ b/gdb/make-target-delegates.py
@@ -362,7 +362,7 @@ for current_line in scan_target_h():
delegators.append(name)
-with open("target-delegates.c", "w") as f:
+with open("target-delegates-gen.c", "w") as f:
print(
gdbcopyright.copyright(
"make-target-delegates.py", "Boilerplate target methods for GDB"
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index ab4d509..dae4e4d 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -413,7 +413,7 @@ static struct parse_stack
struct type *cur_type; /* Type we parse fields for. */
int cur_field; /* Field number in cur_type. */
- CORE_ADDR procadr; /* Start addres of this procedure. */
+ CORE_ADDR procadr; /* Start address of this procedure. */
int numargs; /* Its argument count. */
}
@@ -1319,7 +1319,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
consequence of GDB's type management; CC and GCC (at
least through version 2.4) both output variables of
either type char * or caddr_t with the type
- refering to the stTypedef symbol for caddr_t. If a future
+ referring to the stTypedef symbol for caddr_t. If a future
compiler cleans this up it GDB is not ready for it
yet, but if it becomes ready we somehow need to
disable this check (without breaking the PCC/GCC2.4
@@ -2522,14 +2522,14 @@ parse_partial_symbols (minimal_symbol_reader &reader,
/* On certain platforms, some extra label symbols can be
generated by the linker. One possible usage for this kind
- of symbols is to represent the address of the begining of a
+ of symbols is to represent the address of the beginning of a
given section. For instance, on Tru64 5.1, the address of
the _ftext label is the start address of the .text section.
The storage class of these symbols is usually directly
related to the section to which the symbol refers. For
instance, on Tru64 5.1, the storage class for the _fdata
- label is scData, refering to the .data section.
+ label is scData, referring to the .data section.
It is actually possible that the section associated to the
storage class of the label does not exist. On True64 5.1
@@ -2892,7 +2892,7 @@ parse_partial_symbols (minimal_symbol_reader &reader,
const char *basename;
/* A zero value is probably an indication for the
- SunPRO 3.0 compiler. dbx_end_psymtab explicitly tests
+ SunPRO 3.0 compiler. stabs_end_psymtab explicitly tests
for zero, so don't relocate it. */
if (sh.value == 0
@@ -3297,7 +3297,7 @@ parse_partial_symbols (minimal_symbol_reader &reader,
case N_ENDM:
/* Solaris 2 end of module, finish current partial
- symbol table. dbx_end_psymtab will set the
+ symbol table. stabs_end_psymtab will set the
high text address of PST to the proper value,
which is necessary if a module compiled without
debugging info follows this module. */
@@ -3368,7 +3368,7 @@ parse_partial_symbols (minimal_symbol_reader &reader,
char *sym_name;
enum address_class theclass;
unrelocated_addr minsym_value;
- short section = -1;
+ int section = -1;
(*swap_sym_in) (cur_bfd,
((char *) debug_info->external_sym
@@ -3616,7 +3616,7 @@ parse_partial_symbols (minimal_symbol_reader &reader,
enum address_class theclass;
SYMR *psh;
CORE_ADDR svalue;
- short section;
+ int section;
gdb_assert (ext_ptr->ifd == f_idx);
@@ -3686,14 +3686,14 @@ parse_partial_symbols (minimal_symbol_reader &reader,
}
}
- /* Link pst to FDR. dbx_end_psymtab returns NULL if the psymtab was
+ /* Link pst to FDR. stabs_end_psymtab returns NULL if the psymtab was
empty and put on the free list. */
fdr_to_pst[f_idx].pst
- = dbx_end_psymtab (objfile, partial_symtabs, save_pst,
- psymtab_include_list, includes_used,
- -1, save_pst->unrelocated_text_high (),
- dependency_list, dependencies_used,
- textlow_not_set);
+ = stabs_end_psymtab (objfile, partial_symtabs, save_pst,
+ psymtab_include_list, includes_used,
+ -1, save_pst->unrelocated_text_high (),
+ dependency_list, dependencies_used,
+ textlow_not_set);
includes_used = 0;
dependencies_used = 0;
}
diff --git a/gdb/memattr.c b/gdb/memattr.c
index 735068e..c92792e 100644
--- a/gdb/memattr.c
+++ b/gdb/memattr.c
@@ -134,7 +134,7 @@ create_user_mem_region (CORE_ADDR lo, CORE_ADDR hi,
int ix = std::distance (user_mem_region_list.begin (), it);
/* Check for an overlapping memory region. We only need to check
- in the vincinity - at most one before and one after the
+ in the vicinity - at most one before and one after the
insertion point. */
for (int i = ix - 1; i < ix + 1; i++)
{
diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c
index 913889e..a4ef343 100644
--- a/gdb/mep-tdep.c
+++ b/gdb/mep-tdep.c
@@ -60,7 +60,7 @@
/* A quick recap for GDB hackers not familiar with the whole Toshiba
Media Processor story:
- The MeP media engine is a configureable processor: users can design
+ The MeP media engine is a configurable processor: users can design
their own coprocessors, implement custom instructions, adjust cache
sizes, select optional standard facilities like add-and-saturate
instructions, and so on. Then, they can build custom versions of
diff --git a/gdb/mi/mi-cmd-disas.c b/gdb/mi/mi-cmd-disas.c
index 99b2ae4..a311e25 100644
--- a/gdb/mi/mi-cmd-disas.c
+++ b/gdb/mi/mi-cmd-disas.c
@@ -18,6 +18,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "arch-utils.h"
+#include "progspace.h"
#include "target.h"
#include "value.h"
#include "mi-cmds.h"
@@ -245,7 +246,7 @@ mi_cmd_disassemble (const char *command, const char *const *argv, int argc)
if (line_seen && file_seen)
{
- s = lookup_symtab (file_string);
+ s = lookup_symtab (current_program_space, file_string);
if (s == NULL)
error (_("-data-disassemble: Invalid filename."));
if (!find_line_pc (s, line_num, &start))
diff --git a/gdb/mi/mi-cmd-file.c b/gdb/mi/mi-cmd-file.c
index 3e2702e..f2fe435 100644
--- a/gdb/mi/mi-cmd-file.c
+++ b/gdb/mi/mi-cmd-file.c
@@ -35,7 +35,6 @@ void
mi_cmd_file_list_exec_source_file (const char *command,
const char *const *argv, int argc)
{
- struct symtab_and_line st;
struct ui_out *uiout = current_uiout;
if (!mi_valid_noargs ("-file-list-exec-source-file", argc, argv))
@@ -43,7 +42,8 @@ mi_cmd_file_list_exec_source_file (const char *command,
/* Set the default file and line, also get them. */
set_default_source_symtab_and_line ();
- st = get_current_source_symtab_and_line ();
+ symtab_and_line st
+ = get_current_source_symtab_and_line (current_program_space);
/* We should always get a symtab. Apparently, filename does not
need to be tested for NULL. The documentation in symtab.h
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 5bcb5f7..b72cd1b9 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -2130,10 +2130,7 @@ mi_cmd_execute (struct mi_parse *parse)
std::optional<scoped_restore_current_language> lang_saver;
if (parse->language != language_unknown)
- {
- lang_saver.emplace ();
- set_language (parse->language);
- }
+ lang_saver.emplace (parse->language);
current_context = parse;
diff --git a/gdb/mi/mi-out.c b/gdb/mi/mi-out.c
index ff93d2c..9ad26e7 100644
--- a/gdb/mi/mi-out.c
+++ b/gdb/mi/mi-out.c
@@ -35,8 +35,8 @@ mi_ui_out::do_table_begin (int nr_cols, int nr_rows,
const char *tblid)
{
open (tblid, ui_out_type_tuple);
- do_field_signed (-1, -1, ui_left, "nr_rows", nr_rows);
- do_field_signed (-1, -1, ui_left, "nr_cols", nr_cols);
+ do_field_signed (-1, -1, ui_left, "nr_rows", nr_rows, ui_file_style ());
+ do_field_signed (-1, -1, ui_left, "nr_cols", nr_cols, ui_file_style ());
open ("hdr", ui_out_type_list);
}
@@ -67,8 +67,8 @@ mi_ui_out::do_table_header (int width, ui_align alignment,
const std::string &col_hdr)
{
open (NULL, ui_out_type_tuple);
- do_field_signed (0, 0, ui_center, "width", width);
- do_field_signed (0, 0, ui_center, "alignment", alignment);
+ do_field_signed (0, 0, ui_center, "width", width, ui_file_style ());
+ do_field_signed (0, 0, ui_center, "alignment", alignment, ui_file_style ());
do_field_string (0, 0, ui_center, "col_name", col_name.c_str (),
ui_file_style ());
do_field_string (0, width, alignment, "colhdr", col_hdr.c_str (),
@@ -96,10 +96,11 @@ mi_ui_out::do_end (ui_out_type type)
void
mi_ui_out::do_field_signed (int fldno, int width, ui_align alignment,
- const char *fldname, LONGEST value)
+ const char *fldname, LONGEST value,
+ const ui_file_style &style)
{
do_field_string (fldno, width, alignment, fldname, plongest (value),
- ui_file_style ());
+ style);
}
/* Output an unsigned field. */
diff --git a/gdb/mi/mi-out.h b/gdb/mi/mi-out.h
index a21a34f..9ad419e 100644
--- a/gdb/mi/mi-out.h
+++ b/gdb/mi/mi-out.h
@@ -62,7 +62,8 @@ protected:
virtual void do_begin (ui_out_type type, const char *id) override;
virtual void do_end (ui_out_type type) override;
virtual void do_field_signed (int fldno, int width, ui_align align,
- const char *fldname, LONGEST value) override;
+ const char *fldname, LONGEST value,
+ const ui_file_style &style) override;
virtual void do_field_unsigned (int fldno, int width, ui_align align,
const char *fldname, ULONGEST value)
override;
diff --git a/gdb/mi/mi-symbol-cmds.c b/gdb/mi/mi-symbol-cmds.c
index 15c032b..e4d890f 100644
--- a/gdb/mi/mi-symbol-cmds.c
+++ b/gdb/mi/mi-symbol-cmds.c
@@ -41,7 +41,7 @@ mi_cmd_symbol_list_lines (const char *command, const char *const *argv,
error (_("-symbol-list-lines: Usage: SOURCE_FILENAME"));
filename = argv[0];
- s = lookup_symtab (filename);
+ s = lookup_symtab (current_program_space, filename);
if (s == NULL)
error (_("-symbol-list-lines: Unknown source file name."));
@@ -95,8 +95,7 @@ output_debug_symbol (ui_out *uiout, domain_search_flags kind,
and then outputs the fields for this msymbol. */
static void
-output_nondebug_symbol (ui_out *uiout,
- const struct bound_minimal_symbol &msymbol)
+output_nondebug_symbol (ui_out *uiout, const bound_minimal_symbol &msymbol)
{
struct gdbarch *gdbarch = msymbol.objfile->arch ();
ui_out_emit_tuple tuple_emitter (uiout, NULL);
diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c
index 3d768d7..609c665 100644
--- a/gdb/microblaze-tdep.c
+++ b/gdb/microblaze-tdep.c
@@ -160,7 +160,7 @@ microblaze_alloc_frame_cache (void)
/* The base of the current frame is in a frame pointer register.
This register is noted in frame_extra_info->fp_regnum.
- Note that the existance of an FP might also indicate that the
+ Note that the existence of an FP might also indicate that the
function has called alloca. */
#define MICROBLAZE_MY_FRAME_IN_FP 0x2
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index 38176c4..33eb907 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -358,9 +358,9 @@ lookup_minimal_symbol_demangled (const lookup_name_info &lookup_name,
Obviously, there must be distinct mangled names for each of these,
but the demangled names are all the same: S::S or S::~S. */
-struct bound_minimal_symbol
-lookup_minimal_symbol (const char *name, const char *sfile,
- struct objfile *objf)
+bound_minimal_symbol
+lookup_minimal_symbol (program_space *pspace, const char *name, objfile *objf,
+ const char *sfile)
{
found_minimal_symbols found;
@@ -376,7 +376,7 @@ lookup_minimal_symbol (const char *name, const char *sfile,
lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
- for (objfile *objfile : current_program_space->objfiles ())
+ for (objfile *objfile : pspace->objfiles ())
{
if (found.external_symbol.minsym != NULL)
break;
@@ -384,7 +384,8 @@ lookup_minimal_symbol (const char *name, const char *sfile,
if (objf == NULL || objf == objfile
|| objf == objfile->separate_debug_objfile_backlink)
{
- symbol_lookup_debug_printf ("lookup_minimal_symbol (%s, %s, %s)",
+ symbol_lookup_debug_printf ("lookup_minimal_symbol (%s, %s, %s, %s)",
+ host_address_to_string (pspace),
name, sfile != NULL ? sfile : "NULL",
objfile_debug_name (objfile));
@@ -474,23 +475,14 @@ lookup_minimal_symbol (const char *name, const char *sfile,
return {};
}
-/* See minsyms.h. */
-
-struct bound_minimal_symbol
-lookup_bound_minimal_symbol (const char *name)
-{
- return lookup_minimal_symbol (name, NULL, NULL);
-}
-
/* See gdbsupport/symbol.h. */
int
find_minimal_symbol_address (const char *name, CORE_ADDR *addr,
struct objfile *objfile)
{
- struct bound_minimal_symbol sym
- = lookup_minimal_symbol (name, NULL, objfile);
-
+ bound_minimal_symbol sym
+ = lookup_minimal_symbol (current_program_space, name, objfile);
if (sym.minsym != NULL)
*addr = sym.value_address ();
@@ -591,10 +583,11 @@ lookup_minimal_symbol_linkage (const char *name, struct objfile *objf)
/* See minsyms.h. */
-struct bound_minimal_symbol
-lookup_minimal_symbol_linkage (const char *name, bool only_main)
+bound_minimal_symbol
+lookup_minimal_symbol_linkage (program_space *pspace, const char *name,
+ bool only_main)
{
- for (objfile *objfile : current_program_space->objfiles ())
+ for (objfile *objfile : pspace->objfiles ())
{
if (objfile->separate_debug_objfile_backlink != nullptr)
continue;
@@ -613,12 +606,13 @@ lookup_minimal_symbol_linkage (const char *name, bool only_main)
/* See minsyms.h. */
-struct bound_minimal_symbol
-lookup_minimal_symbol_text (const char *name, struct objfile *objf)
+bound_minimal_symbol
+lookup_minimal_symbol_text (program_space *pspace, const char *name,
+ objfile *objf)
{
struct minimal_symbol *msymbol;
- struct bound_minimal_symbol found_symbol;
- struct bound_minimal_symbol found_file_symbol;
+ bound_minimal_symbol found_symbol;
+ bound_minimal_symbol found_file_symbol;
unsigned int hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE;
@@ -650,7 +644,7 @@ lookup_minimal_symbol_text (const char *name, struct objfile *objf)
if (objf == nullptr)
{
- for (objfile *objfile : current_program_space->objfiles ())
+ for (objfile *objfile : pspace->objfiles ())
{
if (found_symbol.minsym != NULL)
break;
@@ -765,7 +759,6 @@ lookup_minimal_symbol_by_pc_section (CORE_ADDR pc_in, struct obj_section *sectio
struct minimal_symbol *msymbol;
struct minimal_symbol *best_symbol = NULL;
struct objfile *best_objfile = NULL;
- struct bound_minimal_symbol result;
if (previous != nullptr)
{
@@ -997,6 +990,7 @@ lookup_minimal_symbol_by_pc_section (CORE_ADDR pc_in, struct obj_section *sectio
}
}
+ bound_minimal_symbol result;
result.minsym = best_symbol;
result.objfile = best_objfile;
return result;
@@ -1004,7 +998,7 @@ lookup_minimal_symbol_by_pc_section (CORE_ADDR pc_in, struct obj_section *sectio
/* See minsyms.h. */
-struct bound_minimal_symbol
+bound_minimal_symbol
lookup_minimal_symbol_by_pc (CORE_ADDR pc)
{
return lookup_minimal_symbol_by_pc_section (pc, NULL);
@@ -1074,20 +1068,19 @@ const struct gnu_ifunc_fns *gnu_ifunc_fns_p = &stub_gnu_ifunc_fns;
-/* Return leading symbol character for a BFD. If BFD is NULL,
- return the leading symbol character from the main objfile. */
+/* Return the leading symbol character for BFD ABFD. If ABFD is nullptr,
+ return the leading symbol character from the the main objfile of PSPACE.. */
static int
-get_symbol_leading_char (bfd *abfd)
+get_symbol_leading_char (program_space *pspace, bfd *abfd)
{
if (abfd != NULL)
return bfd_get_symbol_leading_char (abfd);
- if (current_program_space->symfile_object_file != NULL)
- {
- objfile *objf = current_program_space->symfile_object_file;
- if (objf->obfd != NULL)
- return bfd_get_symbol_leading_char (objf->obfd.get ());
- }
+
+ if (objfile *objf = pspace->symfile_object_file;
+ objf != nullptr && objf->obfd != nullptr)
+ return bfd_get_symbol_leading_char (objf->obfd.get ());
+
return 0;
}
@@ -1202,7 +1195,8 @@ minimal_symbol_reader::record_full (std::string_view name,
/* It's safe to strip the leading char here once, since the name
is also stored stripped in the minimal symbol table. */
- if (name[0] == get_symbol_leading_char (m_objfile->obfd.get ()))
+ if (name[0] == get_symbol_leading_char (m_objfile->pspace (),
+ m_objfile->obfd.get ()))
name = name.substr (1);
if (ms_type == mst_file_text && startswith (name, "__gnu_compiled"))
@@ -1598,9 +1592,8 @@ find_solib_trampoline_target (const frame_info_ptr &frame, CORE_ADDR pc)
/* See minsyms.h. */
CORE_ADDR
-minimal_symbol_upper_bound (struct bound_minimal_symbol minsym)
+minimal_symbol_upper_bound (bound_minimal_symbol minsym)
{
- short section;
struct obj_section *obj_section;
CORE_ADDR result;
struct minimal_symbol *iter, *msymbol;
@@ -1622,7 +1615,7 @@ minimal_symbol_upper_bound (struct bound_minimal_symbol minsym)
= (minsym.objfile->per_bfd->msymbols.get ()
+ minsym.objfile->per_bfd->minimal_symbol_count);
msymbol = minsym.minsym;
- section = msymbol->section_index ();
+ int section = msymbol->section_index ();
for (iter = msymbol + 1; iter != past_the_end; ++iter)
{
if ((iter->unrelocated_address ()
diff --git a/gdb/minsyms.h b/gdb/minsyms.h
index d44f281..9659f30 100644
--- a/gdb/minsyms.h
+++ b/gdb/minsyms.h
@@ -20,6 +20,7 @@
#ifndef MINSYMS_H
#define MINSYMS_H
+struct program_space;
struct type;
/* Several lookup functions return both a minimal symbol and the
@@ -205,16 +206,12 @@ unsigned int msymbol_hash_iw (const char *);
symbols are still preferred). Returns a bound minimal symbol that
matches, or an empty bound minimal symbol if no match is found. */
-struct bound_minimal_symbol lookup_minimal_symbol (const char *,
- const char *,
- struct objfile *);
+bound_minimal_symbol lookup_minimal_symbol (program_space *pspace,
+ const char *name,
+ objfile *obj = nullptr,
+ const char *sfile = nullptr);
-/* Like lookup_minimal_symbol, but searches all files and
- objfiles. */
-
-struct bound_minimal_symbol lookup_bound_minimal_symbol (const char *);
-
-/* Look through all the current minimal symbol tables and find the
+/* Look through all the minimal symbol tables in PSPACE and find the
first minimal symbol that matches NAME and has text type. If OBJF
is non-NULL, limit the search to that objfile. Returns a bound
minimal symbol that matches, or an "empty" bound minimal symbol
@@ -222,8 +219,9 @@ struct bound_minimal_symbol lookup_bound_minimal_symbol (const char *);
This function only searches the mangled (linkage) names. */
-struct bound_minimal_symbol lookup_minimal_symbol_text (const char *,
- struct objfile *);
+bound_minimal_symbol lookup_minimal_symbol_text (program_space *pspace,
+ const char *name,
+ objfile *objf);
/* Look through the minimal symbols in OBJF (and its separate debug
objfiles) for a global (not file-local) minsym whose linkage name
@@ -232,16 +230,16 @@ struct bound_minimal_symbol lookup_minimal_symbol_text (const char *,
objfile is not accepted. Returns a bound minimal symbol that
matches, or an "empty" bound minimal symbol otherwise. */
-extern struct bound_minimal_symbol lookup_minimal_symbol_linkage
- (const char *name, struct objfile *objf)
+extern bound_minimal_symbol lookup_minimal_symbol_linkage (const char *name,
+ struct objfile *objf)
ATTRIBUTE_NONNULL (1) ATTRIBUTE_NONNULL (2);
/* A variant of lookup_minimal_symbol_linkage that iterates over all
- objfiles. If ONLY_MAIN is true, then only an objfile with
+ objfiles of PSPACE. If ONLY_MAIN is true, then only an objfile with
OBJF_MAINLINE will be considered. */
-extern struct bound_minimal_symbol lookup_minimal_symbol_linkage
- (const char *name, bool only_main)
+extern bound_minimal_symbol lookup_minimal_symbol_linkage
+ (program_space *pspace, const char *name, bool only_main)
ATTRIBUTE_NONNULL (1);
/* Look through all the current minimal symbol tables and find the
@@ -287,7 +285,7 @@ enum class lookup_msym_prefer
then the contents will be set to reference the closest symbol before
PC_IN. */
-struct bound_minimal_symbol lookup_minimal_symbol_by_pc_section
+bound_minimal_symbol lookup_minimal_symbol_by_pc_section
(CORE_ADDR pc_in,
struct obj_section *section,
lookup_msym_prefer prefer = lookup_msym_prefer::TEXT,
@@ -299,7 +297,7 @@ struct bound_minimal_symbol lookup_minimal_symbol_by_pc_section
This is a wrapper that calls lookup_minimal_symbol_by_pc_section
with a NULL section argument. */
-struct bound_minimal_symbol lookup_minimal_symbol_by_pc (CORE_ADDR);
+bound_minimal_symbol lookup_minimal_symbol_by_pc (CORE_ADDR);
/* Iterate over all the minimal symbols in the objfile OBJF which
match NAME. Both the ordinary and demangled names of each symbol
@@ -318,7 +316,7 @@ void iterate_over_minimal_symbols
symbol in the same section, or the end of the section, as the end
of the function. */
-CORE_ADDR minimal_symbol_upper_bound (struct bound_minimal_symbol minsym);
+CORE_ADDR minimal_symbol_upper_bound (bound_minimal_symbol minsym);
/* Return the type of MSYMBOL, a minimal symbol of OBJFILE. If
ADDRESS_P is not NULL, set it to the MSYMBOL's resolved
diff --git a/gdb/mips-fbsd-tdep.c b/gdb/mips-fbsd-tdep.c
index 7452057..7736078 100644
--- a/gdb/mips-fbsd-tdep.c
+++ b/gdb/mips-fbsd-tdep.c
@@ -468,8 +468,8 @@ static const struct tramp_frame mips64_fbsd_sigframe =
static CORE_ADDR
mips_fbsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- struct bound_minimal_symbol msym
- = lookup_bound_minimal_symbol ("_mips_rtld_bind");
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, "_mips_rtld_bind");
if (msym.minsym != nullptr && msym.value_address () == pc)
return frame_unwind_caller_pc (get_current_frame ());
diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
index 7bd96a8..b076d24 100644
--- a/gdb/mips-linux-tdep.c
+++ b/gdb/mips-linux-tdep.c
@@ -99,16 +99,17 @@ mips_linux_get_longjmp_target (const frame_info_ptr &frame, CORE_ADDR *pc)
CORE_ADDR jb_addr;
struct gdbarch *gdbarch = get_frame_arch (frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- gdb_byte buf[gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT];
+ gdb::byte_vector buf (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT);
jb_addr = get_frame_register_unsigned (frame, MIPS_A0_REGNUM);
if (target_read_memory ((jb_addr
+ MIPS_LINUX_JB_PC * MIPS_LINUX_JB_ELEMENT_SIZE),
- buf, gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT))
+ buf.data (),
+ gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT))
return 0;
- *pc = extract_unsigned_integer (buf,
+ *pc = extract_unsigned_integer (buf.data (),
gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT,
byte_order);
@@ -698,9 +699,8 @@ mips_linux_in_dynsym_resolve_code (CORE_ADDR pc)
static CORE_ADDR
mips_linux_skip_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- struct bound_minimal_symbol resolver;
-
- resolver = lookup_minimal_symbol ("__dl_runtime_resolve", NULL, NULL);
+ bound_minimal_symbol resolver
+ = lookup_minimal_symbol (current_program_space, "__dl_runtime_resolve");
if (resolver.minsym && resolver.value_address () == pc)
return frame_unwind_caller_pc (get_current_frame ());
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index ae58d7c..c00efbd 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -490,10 +490,10 @@ mips_make_symbol_special (struct symbol *sym, struct objfile *objfile)
/* We are in symbol reading so it is OK to cast away constness. */
struct block *block = (struct block *) sym->value_block ();
CORE_ADDR compact_block_start;
- struct bound_minimal_symbol msym;
compact_block_start = block->start () | 1;
- msym = lookup_minimal_symbol_by_pc (compact_block_start);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol_by_pc (compact_block_start);
if (msym.minsym && !msymbol_is_mips (msym.minsym))
{
block->set_start (compact_block_start);
@@ -558,7 +558,7 @@ mips_xfer_register (struct gdbarch *gdbarch, struct regcache *regcache,
}
/* Determine if a MIPS3 or later cpu is operating in MIPS{1,2} FPU
- compatiblity mode. A return value of 1 means that we have
+ compatibility mode. A return value of 1 means that we have
physical 64-bit registers, but should treat them as 32-bit registers. */
static int
@@ -574,7 +574,7 @@ mips2_fp_compat (const frame_info_ptr &frame)
/* FIXME drow 2002-03-10: This is disabled until we can do it consistently,
in all the places we deal with FP registers. PR gdb/413. */
/* Otherwise check the FR bit in the status register - it controls
- the FP compatiblity mode. If it is clear we are in compatibility
+ the FP compatibility mode. If it is clear we are in compatibility
mode. */
if ((get_frame_register_unsigned (frame, MIPS_PS_REGNUM) & ST0_FR) == 0)
return 1;
@@ -592,7 +592,7 @@ static CORE_ADDR heuristic_proc_start (struct gdbarch *, CORE_ADDR);
static struct cmd_list_element *setmipscmdlist = NULL;
static struct cmd_list_element *showmipscmdlist = NULL;
-/* Integer registers 0 thru 31 are handled explicitly by
+/* Integer registers 0 through 31 are handled explicitly by
mips_register_name(). Processor specific registers 32 and above
are listed in the following tables. */
@@ -896,7 +896,7 @@ set_mips64_transfers_32bit_regs (const char *args, int from_tty,
/* FIXME: cagney/2003-11-15: Should be setting a field in "info"
instead of relying on globals. Doing that would let generic code
handle the search for this specific architecture. */
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
{
mips64_transfers_32bit_regs_p = 0;
error (_("32-bit compatibility mode not supported"));
@@ -920,7 +920,7 @@ mips_convert_register_float_case_p (struct gdbarch *gdbarch, int regnum,
}
/* This predicate tests for the case of a value of less than 8
- bytes in width that is being transfered to or from an 8 byte
+ bytes in width that is being transferred to or from an 8 byte
general purpose register. */
static int
mips_convert_register_gpreg_case_p (struct gdbarch *gdbarch, int regnum,
@@ -1076,7 +1076,7 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
return builtin_type (gdbarch)->builtin_int32;
else if (tdep->mips64_transfers_32bit_regs_p)
/* The target, while possibly using a 64-bit register buffer,
- is only transfering 32-bits of each integer register.
+ is only transferring 32-bits of each integer register.
Reflect this in the cooked/pseudo (ABI) register value. */
return builtin_type (gdbarch)->builtin_int32;
else if (mips_abi_regsize (gdbarch) == 4)
@@ -1212,13 +1212,12 @@ show_mask_address (struct ui_file *file, int from_tty,
int
mips_pc_is_mips (CORE_ADDR memaddr)
{
- struct bound_minimal_symbol sym;
-
/* Flags indicating that this is a MIPS16 or microMIPS function is
stored by elfread.c in the high bit of the info field. Use this
to decide if the function is standard MIPS. Otherwise if bit 0
of the address is clear, then this is a standard MIPS function. */
- sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
+ bound_minimal_symbol sym
+ = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_mips (sym.minsym);
else
@@ -1230,13 +1229,12 @@ mips_pc_is_mips (CORE_ADDR memaddr)
int
mips_pc_is_mips16 (struct gdbarch *gdbarch, CORE_ADDR memaddr)
{
- struct bound_minimal_symbol sym;
-
/* A flag indicating that this is a MIPS16 function is stored by
elfread.c in the high bit of the info field. Use this to decide
if the function is MIPS16. Otherwise if bit 0 of the address is
set, then ELF file flags will tell if this is a MIPS16 function. */
- sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
+ bound_minimal_symbol sym
+ = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_mips16 (sym.minsym);
else
@@ -1248,14 +1246,13 @@ mips_pc_is_mips16 (struct gdbarch *gdbarch, CORE_ADDR memaddr)
int
mips_pc_is_micromips (struct gdbarch *gdbarch, CORE_ADDR memaddr)
{
- struct bound_minimal_symbol sym;
-
/* A flag indicating that this is a microMIPS function is stored by
elfread.c in the high bit of the info field. Use this to decide
if the function is microMIPS. Otherwise if bit 0 of the address
is set, then ELF file flags will tell if this is a microMIPS
function. */
- sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
+ bound_minimal_symbol sym
+ = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_micromips (sym.minsym);
else
@@ -1268,14 +1265,13 @@ mips_pc_is_micromips (struct gdbarch *gdbarch, CORE_ADDR memaddr)
static enum mips_isa
mips_pc_isa (struct gdbarch *gdbarch, CORE_ADDR memaddr)
{
- struct bound_minimal_symbol sym;
-
/* A flag indicating that this is a MIPS16 or a microMIPS function
is stored by elfread.c in the high bit of the info field. Use
this to decide if the function is MIPS16 or microMIPS or normal
MIPS. Otherwise if bit 0 of the address is set, then ELF file
flags will tell if this is a MIPS16 or a microMIPS function. */
- sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
+ bound_minimal_symbol sym
+ = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
{
if (msymbol_is_micromips (sym.minsym))
@@ -2881,7 +2877,7 @@ mips_insn16_frame_cache (const frame_info_ptr &this_frame, void **this_cache)
find_pc_partial_function (pc, NULL, &start_addr, NULL);
if (start_addr == 0)
start_addr = heuristic_proc_start (gdbarch, pc);
- /* We can't analyze the prologue if we couldn't find the begining
+ /* We can't analyze the prologue if we couldn't find the beginning
of the function. */
if (start_addr == 0)
return cache;
@@ -3316,7 +3312,7 @@ mips_micro_frame_cache (const frame_info_ptr &this_frame, void **this_cache)
find_pc_partial_function (pc, NULL, &start_addr, NULL);
if (start_addr == 0)
start_addr = heuristic_proc_start (get_frame_arch (this_frame), pc);
- /* We can't analyze the prologue if we couldn't find the begining
+ /* We can't analyze the prologue if we couldn't find the beginning
of the function. */
if (start_addr == 0)
return cache;
@@ -3697,7 +3693,7 @@ mips_insn32_frame_cache (const frame_info_ptr &this_frame, void **this_cache)
find_pc_partial_function (pc, NULL, &start_addr, NULL);
if (start_addr == 0)
start_addr = heuristic_proc_start (gdbarch, pc);
- /* We can't analyze the prologue if we couldn't find the begining
+ /* We can't analyze the prologue if we couldn't find the beginning
of the function. */
if (start_addr == 0)
return cache;
@@ -3841,7 +3837,6 @@ mips_stub_frame_sniffer (const struct frame_unwind *self,
{
gdb_byte dummy[4];
CORE_ADDR pc = get_frame_address_in_block (this_frame);
- struct bound_minimal_symbol msym;
/* Use the stub unwinder for unreadable code. */
if (target_read_memory (get_frame_pc (this_frame), dummy, 4) != 0)
@@ -3852,7 +3847,7 @@ mips_stub_frame_sniffer (const struct frame_unwind *self,
/* Calling a PIC function from a non-PIC function passes through a
stub. The stub for foo is named ".pic.foo". */
- msym = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (pc);
if (msym.minsym != NULL
&& msym.minsym->linkage_name () != NULL
&& startswith (msym.minsym->linkage_name (), ".pic."))
@@ -4510,7 +4505,7 @@ mips_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
breakpoints inserted in a branch delay slot. With enough
bad luck, the 4 bytes located just before our breakpoint
instruction could look like a branch instruction, and thus
- trigger the adjustement, and break the function call entirely.
+ trigger the adjustment, and break the function call entirely.
So, we reserve those 4 bytes and write a nop instruction
to prevent that from happening. */
nop_addr = bp_slot - sizeof (nop_insn);
@@ -4586,7 +4581,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
}
/* Now load as many as possible of the first arguments into
- registers, and push the rest onto the stack. Loop thru args
+ registers, and push the rest onto the stack. Loop through args
from first to last. */
for (argnum = 0; argnum < nargs; argnum++)
{
@@ -4759,7 +4754,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
}
/* Note!!! This is NOT an else clause. Odd sized
- structs may go thru BOTH paths. Floating point
+ structs may go through BOTH paths. Floating point
arguments will not. */
/* Write this portion of the argument to a general
purpose register. */
@@ -4980,7 +4975,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
}
/* Now load as many as possible of the first arguments into
- registers, and push the rest onto the stack. Loop thru args
+ registers, and push the rest onto the stack. Loop through args
from first to last. */
for (argnum = 0; argnum < nargs; argnum++)
{
@@ -5111,7 +5106,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
}
/* Note!!! This is NOT an else clause. Odd sized
- structs may go thru BOTH paths. */
+ structs may go through BOTH paths. */
/* Write this portion of the argument to a general
purpose register. */
if (argreg <= mips_last_arg_regnum (gdbarch))
@@ -5460,7 +5455,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
}
/* Now load as many as possible of the first arguments into
- registers, and push the rest onto the stack. Loop thru args
+ registers, and push the rest onto the stack. Loop through args
from first to last. */
for (argnum = 0; argnum < nargs; argnum++)
{
@@ -5623,7 +5618,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
}
/* Note!!! This is NOT an else clause. Odd sized
- structs may go thru BOTH paths. */
+ structs may go through BOTH paths. */
/* Write this portion of the argument to a general
purpose register. */
if (argreg <= mips_last_arg_regnum (gdbarch))
@@ -5981,7 +5976,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
}
/* Now load as many as possible of the first arguments into
- registers, and push the rest onto the stack. Loop thru args
+ registers, and push the rest onto the stack. Loop through args
from first to last. */
for (argnum = 0; argnum < nargs; argnum++)
{
@@ -6085,7 +6080,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
}
/* Note!!! This is NOT an else clause. Odd sized
- structs may go thru BOTH paths. */
+ structs may go through BOTH paths. */
/* Write this portion of the argument to a general
purpose register. */
if (argreg <= mips_last_arg_regnum (gdbarch))
@@ -6973,7 +6968,7 @@ set_mipsfpu_single_command (const char *args, int from_tty)
/* FIXME: cagney/2003-11-15: Should be setting a field in "info"
instead of relying on globals. Doing that would let generic code
handle the search for this specific architecture. */
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("set mipsfpu failed"));
}
@@ -6986,7 +6981,7 @@ set_mipsfpu_double_command (const char *args, int from_tty)
/* FIXME: cagney/2003-11-15: Should be setting a field in "info"
instead of relying on globals. Doing that would let generic code
handle the search for this specific architecture. */
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("set mipsfpu failed"));
}
@@ -6999,7 +6994,7 @@ set_mipsfpu_none_command (const char *args, int from_tty)
/* FIXME: cagney/2003-11-15: Should be setting a field in "info"
instead of relying on globals. Doing that would let generic code
handle the search for this specific architecture. */
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("set mipsfpu failed"));
}
@@ -7824,7 +7819,6 @@ mips_skip_pic_trampoline_code (const frame_info_ptr &frame, CORE_ADDR pc)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct bound_minimal_symbol msym;
int i;
gdb_byte stub_code[16];
int32_t stub_words[4];
@@ -7832,7 +7826,7 @@ mips_skip_pic_trampoline_code (const frame_info_ptr &frame, CORE_ADDR pc)
/* The stub for foo is named ".pic.foo", and is either two
instructions inserted before foo or a three instruction sequence
which jumps to foo. */
- msym = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (pc);
if (msym.minsym == NULL
|| msym.value_address () != pc
|| msym.minsym->linkage_name () == NULL
@@ -8846,7 +8840,7 @@ mips_abi_update (const char *ignore_args,
/* Force the architecture to update, and (if it's a MIPS architecture)
mips_gdbarch_init will take care of the rest. */
- gdbarch_update_p (info);
+ gdbarch_update_p (current_inferior (), info);
}
/* Print out which MIPS ABI is in use. */
diff --git a/gdb/msp430-tdep.c b/gdb/msp430-tdep.c
index 017ebb4..41a8f99 100644
--- a/gdb/msp430-tdep.c
+++ b/gdb/msp430-tdep.c
@@ -807,11 +807,10 @@ msp430_in_return_stub (struct gdbarch *gdbarch, CORE_ADDR pc,
static CORE_ADDR
msp430_skip_trampoline_code (const frame_info_ptr &frame, CORE_ADDR pc)
{
- struct bound_minimal_symbol bms;
const char *stub_name;
struct gdbarch *gdbarch = get_frame_arch (frame);
- bms = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol bms = lookup_minimal_symbol_by_pc (pc);
if (!bms.minsym)
return pc;
diff --git a/gdb/nat/aarch64-mte-linux-ptrace.c b/gdb/nat/aarch64-mte-linux-ptrace.c
index ace3e18..f215588 100644
--- a/gdb/nat/aarch64-mte-linux-ptrace.c
+++ b/gdb/nat/aarch64-mte-linux-ptrace.c
@@ -22,6 +22,7 @@
#include "linux-ptrace.h"
#include "arch/aarch64.h"
+#include "arch/aarch64-mte.h"
#include "arch/aarch64-mte-linux.h"
#include "nat/aarch64-linux.h"
#include "nat/aarch64-mte-linux-ptrace.h"
@@ -31,7 +32,7 @@
/* Helper function to display various possible errors when reading
MTE tags. */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
aarch64_mte_linux_peek_error (int error)
{
switch (error)
@@ -53,7 +54,7 @@ aarch64_mte_linux_peek_error (int error)
/* Helper function to display various possible errors when writing
MTE tags. */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
aarch64_mte_linux_poke_error (int error)
{
switch (error)
@@ -118,10 +119,10 @@ aarch64_mte_fetch_memtags (int tid, CORE_ADDR address, size_t len,
if (ntags == 0)
return true;
- gdb_byte tagbuf[ntags];
+ gdb::byte_vector tagbuf (ntags);
struct iovec iovec;
- iovec.iov_base = tagbuf;
+ iovec.iov_base = tagbuf.data ();
iovec.iov_len = ntags;
tags.clear ();
diff --git a/gdb/nat/aarch64-scalable-linux-ptrace.c b/gdb/nat/aarch64-scalable-linux-ptrace.c
index 81bb8ea..0f1bedf 100644
--- a/gdb/nat/aarch64-scalable-linux-ptrace.c
+++ b/gdb/nat/aarch64-scalable-linux-ptrace.c
@@ -920,8 +920,7 @@ aarch64_za_regs_copy_to_reg_buf (int tid, struct reg_buffer_common *reg_buf,
else
{
size_t za_bytes = header->vl * header->vl;
- gdb_byte za_zeroed[za_bytes];
- memset (za_zeroed, 0, za_bytes);
+ gdb::byte_vector za_zeroed (za_bytes, 0);
reg_buf->raw_supply (za_regnum, za_zeroed);
}
@@ -994,8 +993,7 @@ aarch64_za_regs_copy_from_reg_buf (int tid,
bool has_za_state = aarch64_has_za_state (tid);
size_t za_bytes = sve_vl_from_vg (old_svg) * sve_vl_from_vg (old_svg);
- gdb_byte za_zeroed[za_bytes];
- memset (za_zeroed, 0, za_bytes);
+ gdb::byte_vector za_zeroed (za_bytes, 0);
/* If the streaming vector length changed, zero out the contents of ZA in
the register cache. Otherwise, we will need to update the ZA contents
@@ -1007,8 +1005,7 @@ aarch64_za_regs_copy_from_reg_buf (int tid,
/* When we update svg, we don't automatically initialize the ZA buffer. If
we have no ZA state and the ZA register contents in the register cache are
zero, just return and leave the ZA register cache contents as zero. */
- if (!has_za_state
- && reg_buf->raw_compare (za_regnum, za_zeroed, 0))
+ if (!has_za_state && reg_buf->raw_compare (za_regnum, za_zeroed.data (), 0))
{
/* No ZA state in the thread or in the register cache. This was likely
just an adjustment of the streaming vector length. Let this fall
@@ -1020,7 +1017,7 @@ aarch64_za_regs_copy_from_reg_buf (int tid,
need to initialize the ZA data through ptrace. First we initialize
all the bytes of ZA to zero. */
if (!has_za_state
- && !reg_buf->raw_compare (za_regnum, za_zeroed, 0))
+ && !reg_buf->raw_compare (za_regnum, za_zeroed.data (), 0))
aarch64_initialize_za_regset (tid);
/* From this point onwards, it is assumed we have a ZA payload in
diff --git a/gdb/nat/fork-inferior.h b/gdb/nat/fork-inferior.h
index f3e2f54..0fd4218 100644
--- a/gdb/nat/fork-inferior.h
+++ b/gdb/nat/fork-inferior.h
@@ -84,13 +84,12 @@ extern void gdb_flush_out_err ();
/* Report an error that happened when starting to trace the inferior
(i.e., when the "traceme_fun" callback is called on fork_inferior)
and bail out. This function does not return. */
-extern void trace_start_error (const char *fmt, ...)
- ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (1, 2);
+[[noreturn]] extern void trace_start_error (const char *fmt, ...)
+ ATTRIBUTE_PRINTF (1, 2);
/* Like "trace_start_error", but the error message is constructed by
combining STRING with the system error message for errno. This
function does not return. */
-extern void trace_start_error_with_name (const char *string)
- ATTRIBUTE_NORETURN;
+[[noreturn]] extern void trace_start_error_with_name (const char *string);
#endif /* NAT_FORK_INFERIOR_H */
diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c
index 5715168..7ff12d6 100644
--- a/gdb/nat/linux-btrace.c
+++ b/gdb/nat/linux-btrace.c
@@ -415,6 +415,59 @@ cpu_supports_bts (void)
}
}
+/* Return the Intel PT config bitmask from the linux sysfs for a FEATURE.
+ The bits can be used in the perf_event configuration when enabling PT.
+ Callers of this function are expected to check the availability of the
+ feature first via linux_supports_pt_feature. */
+
+static uint64_t
+linux_read_pt_config_bitmask (const char *feature)
+{
+ uint64_t config_bitmask = 0;
+ std::string filename
+ = std::string ("/sys/bus/event_source/devices/intel_pt/format/")
+ + feature;
+
+ gdb_file_up file = gdb_fopen_cloexec (filename.c_str (), "r");
+ if (file.get () == nullptr)
+ error (_("Failed to determine config from %s."), filename.c_str ());
+
+ uint8_t start, end;
+ int found = fscanf (file.get (), "config:%hhu-%hhu", &start, &end);
+ if (found == 1)
+ end = start;
+ else if (found != 2)
+ error (_("Failed to determine config from %s."), filename.c_str ());
+
+ for (uint8_t i = start; i <= end; ++i)
+ config_bitmask |= (1ULL << i);
+
+ return config_bitmask;
+}
+
+/* Check whether the linux target supports the Intel PT FEATURE. */
+
+static bool
+linux_supports_pt_feature (const char *feature)
+{
+ std::string filename
+ = std::string ("/sys/bus/event_source/devices/intel_pt/caps/") + feature;
+
+ gdb_file_up file = gdb_fopen_cloexec (filename.c_str (), "r");
+ if (file.get () == nullptr)
+ return false;
+
+ int status, found = fscanf (file.get (), "%d", &status);
+ if (found != 1)
+ {
+ warning (_("Failed to determine %s support from %s."), feature,
+ filename.c_str ());
+ return false;
+ }
+
+ return (status == 1);
+}
+
/* The perf_event_open syscall failed. Try to print a helpful error
message. */
@@ -627,6 +680,23 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf)
tinfo->attr.exclude_hv = 1;
tinfo->attr.exclude_idle = 1;
+ if (conf->ptwrite && linux_supports_pt_feature ("ptwrite"))
+ {
+ tinfo->attr.config |= linux_read_pt_config_bitmask ("ptw");
+ tinfo->conf.pt.ptwrite = true;
+ }
+
+ if (conf->event_tracing)
+ {
+ if (linux_supports_pt_feature ("event_trace"))
+ {
+ tinfo->attr.config |= linux_read_pt_config_bitmask ("event");
+ tinfo->conf.pt.event_tracing = true;
+ }
+ else
+ error (_("Event tracing for record btrace pt is not supported."));
+ }
+
errno = 0;
scoped_fd fd (syscall (SYS_perf_event_open, &tinfo->attr, pid, -1, -1, 0));
if (fd.get () < 0)
diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
index 36a245c..9abd3d6 100644
--- a/gdb/nat/linux-namespaces.c
+++ b/gdb/nat/linux-namespaces.c
@@ -548,7 +548,7 @@ mnsh_handle_readlink (int sock, const char *filename)
/* The helper process. Never returns. Must be async-signal-safe. */
-static void mnsh_main (int sock) ATTRIBUTE_NORETURN;
+[[noreturn]] static void mnsh_main (int sock);
static void
mnsh_main (int sock)
diff --git a/gdb/nat/x86-linux-tdesc.c b/gdb/nat/x86-linux-tdesc.c
index c15a600..1824f57 100644
--- a/gdb/nat/x86-linux-tdesc.c
+++ b/gdb/nat/x86-linux-tdesc.c
@@ -106,12 +106,6 @@ x86_linux_tdesc_for_tid (int tid, uint64_t *xcr0_storage,
*xcr0_storage = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
/ sizeof (uint64_t))];
-#ifdef __x86_64__
- /* No MPX on x32. */
- if (is_64bit && is_x32)
- *xcr0_storage &= ~X86_XSTATE_MPX;
-#endif /* __x86_64__ */
-
*xsave_layout_storage
= x86_fetch_xsave_layout (*xcr0_storage, x86_xsave_length ());
}
diff --git a/gdb/nat/x86-xstate.c b/gdb/nat/x86-xstate.c
index 970dda1..ca6fbbf 100644
--- a/gdb/nat/x86-xstate.c
+++ b/gdb/nat/x86-xstate.c
@@ -56,8 +56,6 @@ x86_fetch_xsave_layout (uint64_t xcr0, int len)
x86_xsave_layout layout;
layout.sizeof_xsave = len;
layout.avx_offset = xsave_feature_offset (xcr0, X86_XSTATE_AVX_ID);
- layout.bndregs_offset = xsave_feature_offset (xcr0, X86_XSTATE_BNDREGS_ID);
- layout.bndcfg_offset = xsave_feature_offset (xcr0, X86_XSTATE_BNDCFG_ID);
layout.k_offset = xsave_feature_offset (xcr0, X86_XSTATE_K_ID);
layout.zmm_h_offset = xsave_feature_offset (xcr0, X86_XSTATE_ZMM_H_ID);
layout.zmm_offset = xsave_feature_offset (xcr0, X86_XSTATE_ZMM_ID);
diff --git a/gdb/netbsd-tdep.c b/gdb/netbsd-tdep.c
index 953b329..415a743 100644
--- a/gdb/netbsd-tdep.c
+++ b/gdb/netbsd-tdep.c
@@ -348,9 +348,8 @@ nbsd_gdb_signal_to_target (struct gdbarch *gdbarch,
static CORE_ADDR
nbsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol ("_rtld_bind_start", NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, "_rtld_bind_start");
if (msym.minsym && msym.value_address () == pc)
return frame_unwind_caller_pc (get_current_frame ());
else
diff --git a/gdb/nto-procfs.c b/gdb/nto-procfs.c
deleted file mode 100644
index c310874..0000000
--- a/gdb/nto-procfs.c
+++ /dev/null
@@ -1,1583 +0,0 @@
-/* Machine independent support for QNX Neutrino /proc (process file system)
- for GDB. Written by Colin Burgess at QNX Software Systems Limited.
-
- Copyright (C) 2003-2024 Free Software Foundation, Inc.
-
- Contributed by QNX Software Systems Ltd.
-
- 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 <fcntl.h>
-#include <spawn.h>
-#include <sys/debug.h>
-#include <sys/procfs.h>
-#include <sys/neutrino.h>
-#include <sys/syspage.h>
-#include <dirent.h>
-#include <sys/netmgr.h>
-#include <sys/auxv.h>
-
-#include "gdbcore.h"
-#include "inferior.h"
-#include "target.h"
-#include "objfiles.h"
-#include "gdbthread.h"
-#include "nto-tdep.h"
-#include "command.h"
-#include "regcache.h"
-#include "solib.h"
-#include "inf-child.h"
-#include "gdbsupport/filestuff.h"
-#include "gdbsupport/scoped_fd.h"
-
-#define NULL_PID 0
-#define _DEBUG_FLAG_TRACE (_DEBUG_FLAG_TRACE_EXEC|_DEBUG_FLAG_TRACE_RD|\
- _DEBUG_FLAG_TRACE_WR|_DEBUG_FLAG_TRACE_MODIFY)
-
-int ctl_fd;
-
-static sighandler_t ofunc;
-
-static procfs_run run;
-
-/* Create the "native" and "procfs" targets. */
-
-struct nto_procfs_target : public inf_child_target
-{
- void open (const char *arg, int from_tty) override;
-
- void attach (const char *, int) override = 0;
-
- void post_attach (int);
-
- void detach (inferior *, int) override;
-
- void resume (ptid_t, int, enum gdb_signal) override;
-
- ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
-
- void fetch_registers (struct regcache *, int) override;
- void store_registers (struct regcache *, int) override;
-
- enum target_xfer_status xfer_partial (enum target_object object,
- const char *annex,
- gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len,
- ULONGEST *xfered_len) override;
-
- void files_info () override;
-
- int insert_breakpoint (struct gdbarch *, struct bp_target_info *) override;
-
- int remove_breakpoint (struct gdbarch *, struct bp_target_info *,
- enum remove_bp_reason) override;
-
- int can_use_hw_breakpoint (enum bptype, int, int) override;
-
- int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
-
- int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
-
- int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
- struct expression *) override;
-
- int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
- struct expression *) override;
-
- bool stopped_by_watchpoint () override;
-
- void kill () override;
-
- void create_inferior (const char *, const std::string &,
- char **, int) override;
-
- void mourn_inferior () override;
-
- void pass_signals (gdb::array_view<const unsigned char>) override;
-
- bool thread_alive (ptid_t ptid) override;
-
- void update_thread_list () override;
-
- std::string pid_to_str (ptid_t) override;
-
- void interrupt () override;
-
- const char *extra_thread_info (struct thread_info *) override;
-
- const char *pid_to_exec_file (int pid) override;
-};
-
-/* For "target native". */
-
-static const target_info nto_native_target_info = {
- "native",
- N_("QNX Neutrino local process"),
- N_("QNX Neutrino local process (started by the \"run\" command).")
-};
-
-class nto_procfs_target_native final : public nto_procfs_target
-{
- const target_info &info () const override
- { return nto_native_target_info; }
-};
-
-/* For "target procfs <node>". */
-
-static const target_info nto_procfs_target_info = {
- "procfs",
- N_("QNX Neutrino local or remote process"),
- N_("QNX Neutrino process. target procfs NODE")
-};
-
-struct nto_procfs_target_procfs final : public nto_procfs_target
-{
- const target_info &info () const override
- { return nto_procfs_target_info; }
-};
-
-static ptid_t do_attach (ptid_t ptid);
-
-/* These two globals are only ever set in procfs_open_1, but are
- referenced elsewhere. 'nto_procfs_node' is a flag used to say
- whether we are local, or we should get the current node descriptor
- for the remote QNX node. */
-static char *nodestr;
-static unsigned nto_procfs_node = ND_LOCAL_NODE;
-
-/* Return the current QNX Node, or error out. This is a simple
- wrapper for the netmgr_strtond() function. The reason this
- is required is because QNX node descriptors are transient so
- we have to re-acquire them every time. */
-static unsigned
-nto_node (void)
-{
- unsigned node;
-
- if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0
- || nodestr == NULL)
- return ND_LOCAL_NODE;
-
- node = netmgr_strtond (nodestr, 0);
- if (node == -1)
- error (_("Lost the QNX node. Debug session probably over."));
-
- return (node);
-}
-
-static enum gdb_osabi
-procfs_is_nto_target (bfd *abfd)
-{
- return GDB_OSABI_QNXNTO;
-}
-
-/* This is called when we call 'target native' or 'target procfs
- <arg>' from the (gdb) prompt. For QNX6 (nto), the only valid arg
- will be a QNX node string, eg: "/net/some_node". If arg is not a
- valid QNX node, we will default to local. */
-void
-nto_procfs_target::open (const char *arg, int from_tty)
-{
- char *endstr;
- char buffer[50];
- int total_size;
- procfs_sysinfo *sysinfo;
- char nto_procfs_path[PATH_MAX];
-
- /* Offer to kill previous inferiors before opening this target. */
- target_preopen (from_tty);
-
- nto_is_nto_target = procfs_is_nto_target;
-
- /* Set the default node used for spawning to this one,
- and only override it if there is a valid arg. */
-
- xfree (nodestr);
- nodestr = NULL;
-
- nto_procfs_node = ND_LOCAL_NODE;
- nodestr = (arg != NULL) ? xstrdup (arg) : NULL;
-
- if (nodestr)
- {
- nto_procfs_node = netmgr_strtond (nodestr, &endstr);
- if (nto_procfs_node == -1)
- {
- if (errno == ENOTSUP)
- gdb_printf ("QNX Net Manager not found.\n");
- gdb_printf ("Invalid QNX node %s: error %d (%s).\n", nodestr,
- errno, safe_strerror (errno));
- xfree (nodestr);
- nodestr = NULL;
- nto_procfs_node = ND_LOCAL_NODE;
- }
- else if (*endstr)
- {
- if (*(endstr - 1) == '/')
- *(endstr - 1) = 0;
- else
- *endstr = 0;
- }
- }
- snprintf (nto_procfs_path, PATH_MAX - 1, "%s%s",
- (nodestr != NULL) ? nodestr : "", "/proc");
-
- scoped_fd fd (open (nto_procfs_path, O_RDONLY));
- if (fd.get () == -1)
- {
- gdb_printf ("Error opening %s : %d (%s)\n", nto_procfs_path, errno,
- safe_strerror (errno));
- error (_("Invalid procfs arg"));
- }
-
- sysinfo = (void *) buffer;
- if (devctl (fd.get (), DCMD_PROC_SYSINFO, sysinfo, sizeof buffer, 0) != EOK)
- {
- gdb_printf ("Error getting size: %d (%s)\n", errno,
- safe_strerror (errno));
- error (_("Devctl failed."));
- }
- else
- {
- total_size = sysinfo->total_size;
- sysinfo = alloca (total_size);
- if (sysinfo == NULL)
- {
- gdb_printf ("Memory error: %d (%s)\n", errno,
- safe_strerror (errno));
- error (_("alloca failed."));
- }
- else
- {
- if (devctl (fd.get (), DCMD_PROC_SYSINFO, sysinfo, total_size, 0)
- != EOK)
- {
- gdb_printf ("Error getting sysinfo: %d (%s)\n", errno,
- safe_strerror (errno));
- error (_("Devctl failed."));
- }
- else
- {
- if (sysinfo->type !=
- nto_map_arch_to_cputype
- (gdbarch_bfd_arch_info
- (current_inferior ()->arch ())->arch_name))
- error (_("Invalid target CPU."));
- }
- }
- }
-
- inf_child_target::open (arg, from_tty);
- gdb_printf ("Debugging using %s\n", nto_procfs_path);
-}
-
-static void
-procfs_set_thread (ptid_t ptid)
-{
- pid_t tid;
-
- tid = ptid.tid ();
- devctl (ctl_fd, DCMD_PROC_CURTHREAD, &tid, sizeof (tid), 0);
-}
-
-/* Return true if the thread TH is still alive. */
-
-bool
-nto_procfs_target::thread_alive (ptid_t ptid)
-{
- pid_t tid;
- pid_t pid;
- procfs_status status;
- int err;
-
- tid = ptid.tid ();
- pid = ptid.pid ();
-
- if (kill (pid, 0) == -1)
- return false;
-
- status.tid = tid;
- if ((err = devctl (ctl_fd, DCMD_PROC_TIDSTATUS,
- &status, sizeof (status), 0)) != EOK)
- return false;
-
- /* Thread is alive or dead but not yet joined,
- or dead and there is an alive (or dead unjoined) thread with
- higher tid.
-
- If the tid is not the same as requested, requested tid is dead. */
- return (status.tid == tid) && (status.state != STATE_DEAD);
-}
-
-static void
-update_thread_private_data_name (struct thread_info *new_thread,
- const char *newname)
-{
- nto_thread_info *pti = get_nto_thread_info (new_thread);
-
- gdb_assert (newname != NULL);
- gdb_assert (new_thread != NULL);
-
- if (pti)
- {
- pti = new nto_thread_info;
- new_thread->priv.reset (pti);
- }
-
- pti->name = newname;
-}
-
-static void
-update_thread_private_data (struct thread_info *new_thread,
- pthread_t tid, int state, int flags)
-{
- procfs_info pidinfo;
- struct _thread_name *tn;
- procfs_threadctl tctl;
-
-#if _NTO_VERSION > 630
- gdb_assert (new_thread != NULL);
-
- if (devctl (ctl_fd, DCMD_PROC_INFO, &pidinfo,
- sizeof(pidinfo), 0) != EOK)
- return;
-
- memset (&tctl, 0, sizeof (tctl));
- tctl.cmd = _NTO_TCTL_NAME;
- tn = (struct _thread_name *) (&tctl.data);
-
- /* Fetch name for the given thread. */
- tctl.tid = tid;
- tn->name_buf_len = sizeof (tctl.data) - sizeof (*tn);
- tn->new_name_len = -1; /* Getting, not setting. */
- if (devctl (ctl_fd, DCMD_PROC_THREADCTL, &tctl, sizeof (tctl), NULL) != EOK)
- tn->name_buf[0] = '\0';
-
- tn->name_buf[_NTO_THREAD_NAME_MAX] = '\0';
-
- update_thread_private_data_name (new_thread, tn->name_buf);
-
- nto_thread_info *pti = get_nto_thread_info (new_thread);
- pti->tid = tid;
- pti->state = state;
- pti->flags = flags;
-#endif /* _NTO_VERSION */
-}
-
-void
-nto_procfs_target::update_thread_list ()
-{
- procfs_status status;
- pid_t pid;
- ptid_t ptid;
- pthread_t tid;
- struct thread_info *new_thread;
-
- if (ctl_fd == -1)
- return;
-
- prune_threads ();
-
- pid = current_inferior ()->pid;
-
- status.tid = 1;
-
- for (tid = 1;; ++tid)
- {
- if (status.tid == tid
- && (devctl (ctl_fd, DCMD_PROC_TIDSTATUS, &status, sizeof (status), 0)
- != EOK))
- break;
- if (status.tid != tid)
- /* The reason why this would not be equal is that devctl might have
- returned different tid, meaning the requested tid no longer exists
- (e.g. thread exited). */
- continue;
- ptid = ptid_t (pid, 0, tid);
- new_thread = this->find_thread (ptid);
- if (!new_thread)
- new_thread = add_thread (ptid);
- update_thread_private_data (new_thread, tid, status.state, 0);
- status.tid++;
- }
- return;
-}
-
-static void
-procfs_pidlist (const char *args, int from_tty)
-{
- struct dirent *dirp = NULL;
- char buf[PATH_MAX];
- procfs_info *pidinfo = NULL;
- procfs_debuginfo *info = NULL;
- procfs_status *status = NULL;
- pid_t num_threads = 0;
- pid_t pid;
- char name[512];
- char procfs_dir[PATH_MAX];
-
- snprintf (procfs_dir, sizeof (procfs_dir), "%s%s",
- (nodestr != NULL) ? nodestr : "", "/proc");
-
- gdb_dir_up dp (opendir (procfs_dir));
- if (dp == NULL)
- {
- gdb_printf (gdb_stderr, "failed to opendir \"%s\" - %d (%s)",
- procfs_dir, errno, safe_strerror (errno));
- return;
- }
-
- /* Start scan at first pid. */
- rewinddir (dp.get ());
-
- do
- {
- /* Get the right pid and procfs path for the pid. */
- do
- {
- dirp = readdir (dp.get ());
- if (dirp == NULL)
- return;
- snprintf (buf, sizeof (buf), "%s%s/%s/as",
- (nodestr != NULL) ? nodestr : "",
- "/proc", dirp->d_name);
- pid = atoi (dirp->d_name);
- }
- while (pid == 0);
-
- /* Open the procfs path. */
- scoped_fd fd (open (buf, O_RDONLY));
- if (fd.get () == -1)
- {
- gdb_printf (gdb_stderr, "failed to open %s - %d (%s)\n",
- buf, errno, safe_strerror (errno));
- continue;
- }
-
- pidinfo = (procfs_info *) buf;
- if (devctl (fd.get (), DCMD_PROC_INFO, pidinfo, sizeof (buf), 0) != EOK)
- {
- gdb_printf (gdb_stderr,
- "devctl DCMD_PROC_INFO failed - %d (%s)\n",
- errno, safe_strerror (errno));
- break;
- }
- num_threads = pidinfo->num_threads;
-
- info = (procfs_debuginfo *) buf;
- if (devctl (fd.get (), DCMD_PROC_MAPDEBUG_BASE, info, sizeof (buf), 0)
- != EOK)
- strcpy (name, "unavailable");
- else
- strcpy (name, info->path);
-
- /* Collect state info on all the threads. */
- status = (procfs_status *) buf;
- for (status->tid = 1; status->tid <= num_threads; status->tid++)
- {
- const int err
- = devctl (fd.get (), DCMD_PROC_TIDSTATUS, status, sizeof (buf), 0);
- gdb_printf ("%s - %d", name, pid);
- if (err == EOK && status->tid != 0)
- gdb_printf ("/%d\n", status->tid);
- else
- {
- gdb_printf ("\n");
- break;
- }
- }
- }
- while (dirp != NULL);
-}
-
-static void
-procfs_meminfo (const char *args, int from_tty)
-{
- procfs_mapinfo *mapinfos = NULL;
- static int num_mapinfos = 0;
- procfs_mapinfo *mapinfo_p, *mapinfo_p2;
- int flags = ~0, err, num, i, j;
-
- struct
- {
- procfs_debuginfo info;
- char buff[_POSIX_PATH_MAX];
- } map;
-
- struct info
- {
- unsigned addr;
- unsigned size;
- unsigned flags;
- unsigned debug_vaddr;
- unsigned long long offset;
- };
-
- struct printinfo
- {
- unsigned long long ino;
- unsigned dev;
- struct info text;
- struct info data;
- char name[256];
- } printme;
-
- /* Get the number of map entrys. */
- err = devctl (ctl_fd, DCMD_PROC_MAPINFO, NULL, 0, &num);
- if (err != EOK)
- {
- printf ("failed devctl num mapinfos - %d (%s)\n", err,
- safe_strerror (err));
- return;
- }
-
- mapinfos = XNEWVEC (procfs_mapinfo, num);
-
- num_mapinfos = num;
- mapinfo_p = mapinfos;
-
- /* Fill the map entrys. */
- err = devctl (ctl_fd, DCMD_PROC_MAPINFO, mapinfo_p, num
- * sizeof (procfs_mapinfo), &num);
- if (err != EOK)
- {
- printf ("failed devctl mapinfos - %d (%s)\n", err, safe_strerror (err));
- xfree (mapinfos);
- return;
- }
-
- num = std::min (num, num_mapinfos);
-
- /* Run through the list of mapinfos, and store the data and text info
- so we can print it at the bottom of the loop. */
- for (mapinfo_p = mapinfos, i = 0; i < num; i++, mapinfo_p++)
- {
- if (!(mapinfo_p->flags & flags))
- mapinfo_p->ino = 0;
-
- if (mapinfo_p->ino == 0) /* Already visited. */
- continue;
-
- map.info.vaddr = mapinfo_p->vaddr;
-
- err = devctl (ctl_fd, DCMD_PROC_MAPDEBUG, &map, sizeof (map), 0);
- if (err != EOK)
- continue;
-
- memset (&printme, 0, sizeof printme);
- printme.dev = mapinfo_p->dev;
- printme.ino = mapinfo_p->ino;
- printme.text.addr = mapinfo_p->vaddr;
- printme.text.size = mapinfo_p->size;
- printme.text.flags = mapinfo_p->flags;
- printme.text.offset = mapinfo_p->offset;
- printme.text.debug_vaddr = map.info.vaddr;
- strcpy (printme.name, map.info.path);
-
- /* Check for matching data. */
- for (mapinfo_p2 = mapinfos, j = 0; j < num; j++, mapinfo_p2++)
- {
- if (mapinfo_p2->vaddr != mapinfo_p->vaddr
- && mapinfo_p2->ino == mapinfo_p->ino
- && mapinfo_p2->dev == mapinfo_p->dev)
- {
- map.info.vaddr = mapinfo_p2->vaddr;
- err =
- devctl (ctl_fd, DCMD_PROC_MAPDEBUG, &map, sizeof (map), 0);
- if (err != EOK)
- continue;
-
- if (strcmp (map.info.path, printme.name))
- continue;
-
- /* Lower debug_vaddr is always text, if necessary, swap. */
- if ((int) map.info.vaddr < (int) printme.text.debug_vaddr)
- {
- memcpy (&(printme.data), &(printme.text),
- sizeof (printme.data));
- printme.text.addr = mapinfo_p2->vaddr;
- printme.text.size = mapinfo_p2->size;
- printme.text.flags = mapinfo_p2->flags;
- printme.text.offset = mapinfo_p2->offset;
- printme.text.debug_vaddr = map.info.vaddr;
- }
- else
- {
- printme.data.addr = mapinfo_p2->vaddr;
- printme.data.size = mapinfo_p2->size;
- printme.data.flags = mapinfo_p2->flags;
- printme.data.offset = mapinfo_p2->offset;
- printme.data.debug_vaddr = map.info.vaddr;
- }
- mapinfo_p2->ino = 0;
- }
- }
- mapinfo_p->ino = 0;
-
- gdb_printf ("%s\n", printme.name);
- gdb_printf ("\ttext=%08x bytes @ 0x%08x\n", printme.text.size,
- printme.text.addr);
- gdb_printf ("\t\tflags=%08x\n", printme.text.flags);
- gdb_printf ("\t\tdebug=%08x\n", printme.text.debug_vaddr);
- gdb_printf ("\t\toffset=%s\n", phex (printme.text.offset, 8));
- if (printme.data.size)
- {
- gdb_printf ("\tdata=%08x bytes @ 0x%08x\n", printme.data.size,
- printme.data.addr);
- gdb_printf ("\t\tflags=%08x\n", printme.data.flags);
- gdb_printf ("\t\tdebug=%08x\n", printme.data.debug_vaddr);
- gdb_printf ("\t\toffset=%s\n", phex (printme.data.offset, 8));
- }
- gdb_printf ("\tdev=0x%x\n", printme.dev);
- gdb_printf ("\tino=0x%x\n", (unsigned int) printme.ino);
- }
- xfree (mapinfos);
- return;
-}
-
-/* Print status information about what we're accessing. */
-void
-nto_procfs_target::files_info ()
-{
- struct inferior *inf = current_inferior ();
-
- gdb_printf ("\tUsing the running image of %s %s via %s.\n",
- inf->attach_flag ? "attached" : "child",
- target_pid_to_str (ptid_t (inf->pid)).c_str (),
- (nodestr != NULL) ? nodestr : "local node");
-}
-
-/* Target to_pid_to_exec_file implementation. */
-
-const char *
-nto_procfs_target::pid_to_exec_file (const int pid)
-{
- int proc_fd;
- static char proc_path[PATH_MAX];
- ssize_t rd;
-
- /* Read exe file name. */
- snprintf (proc_path, sizeof (proc_path), "%s/proc/%d/exefile",
- (nodestr != NULL) ? nodestr : "", pid);
- proc_fd = open (proc_path, O_RDONLY);
- if (proc_fd == -1)
- return NULL;
-
- rd = read (proc_fd, proc_path, sizeof (proc_path) - 1);
- close (proc_fd);
- if (rd <= 0)
- {
- proc_path[0] = '\0';
- return NULL;
- }
- proc_path[rd] = '\0';
- return proc_path;
-}
-
-/* Attach to process PID, then initialize for debugging it. */
-void
-nto_procfs_target::attach (const char *args, int from_tty)
-{
- int pid;
- struct inferior *inf;
-
- pid = parse_pid_to_attach (args);
-
- if (pid == getpid ())
- error (_("Attaching GDB to itself is not a good idea..."));
-
- target_announce_attach (from_tty, pid);
-
- ptid_t ptid = do_attach (ptid_t (pid));
- inf = current_inferior ();
- inferior_appeared (inf, pid);
- inf->attach_flag = true;
-
- if (!inf->target_is_pushed (ops))
- inf->push_target (ops);
-
- update_thread_list ();
-
- switch_to_thread (this->find_thread (ptid));
-}
-
-void
-nto_procfs_target::post_attach (pid_t pid)
-{
- if (current_program_space->exec_bfd ())
- solib_create_inferior_hook (0);
-}
-
-static ptid_t
-do_attach (ptid_t ptid)
-{
- procfs_status status;
- struct sigevent event;
- char path[PATH_MAX];
-
- snprintf (path, PATH_MAX - 1, "%s%s/%d/as",
- (nodestr != NULL) ? nodestr : "", "/proc", ptid.pid ());
- ctl_fd = open (path, O_RDWR);
- if (ctl_fd == -1)
- error (_("Couldn't open proc file %s, error %d (%s)"), path, errno,
- safe_strerror (errno));
- if (devctl (ctl_fd, DCMD_PROC_STOP, &status, sizeof (status), 0) != EOK)
- error (_("Couldn't stop process"));
-
- /* Define a sigevent for process stopped notification. */
- event.sigev_notify = SIGEV_SIGNAL_THREAD;
- event.sigev_signo = SIGUSR1;
- event.sigev_code = 0;
- event.sigev_value.sival_ptr = NULL;
- event.sigev_priority = -1;
- devctl (ctl_fd, DCMD_PROC_EVENT, &event, sizeof (event), 0);
-
- if (devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0) == EOK
- && status.flags & _DEBUG_FLAG_STOPPED)
- SignalKill (nto_node (), ptid.pid (), 0, SIGCONT, 0, 0);
- nto_init_solib_absolute_prefix ();
- return ptid_t (ptid.pid (), 0, status.tid);
-}
-
-/* Ask the user what to do when an interrupt is received. */
-static void
-interrupt_query (void)
-{
- if (query (_("Interrupted while waiting for the program.\n\
-Give up (and stop debugging it)? ")))
- {
- target_mourn_inferior (inferior_ptid);
- quit ();
- }
-}
-
-/* The user typed ^C twice. */
-static void
-nto_handle_sigint_twice (int signo)
-{
- signal (signo, ofunc);
- interrupt_query ();
- signal (signo, nto_handle_sigint_twice);
-}
-
-static void
-nto_handle_sigint (int signo)
-{
- /* If this doesn't work, try more severe steps. */
- signal (signo, nto_handle_sigint_twice);
-
- target_interrupt ();
-}
-
-sptid_t
-nto_procfs_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
- target_wait_flags options)
-{
- sigset_t set;
- siginfo_t info;
- procfs_status status;
- static int exit_signo = 0; /* To track signals that cause termination. */
-
- ourstatus->set_spurious ();
-
- if (inferior_ptid == null_ptid)
- {
- ourstatus->set_stopped (GDB_SIGNAL_0);
- exit_signo = 0;
- return null_ptid;
- }
-
- sigemptyset (&set);
- sigaddset (&set, SIGUSR1);
-
- devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
- while (!(status.flags & _DEBUG_FLAG_ISTOP))
- {
- ofunc = signal (SIGINT, nto_handle_sigint);
- sigwaitinfo (&set, &info);
- signal (SIGINT, ofunc);
- devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
- }
-
- nto_inferior_data (NULL)->stopped_flags = status.flags;
- nto_inferior_data (NULL)->stopped_pc = status.ip;
-
- if (status.flags & _DEBUG_FLAG_SSTEP)
- ourstatus->set_stopped (GDB_SIGNAL_TRAP);
- /* Was it a breakpoint? */
- else if (status.flags & _DEBUG_FLAG_TRACE)
- ourstatus->set_stopped (GDB_SIGNAL_TRAP);
- else if (status.flags & _DEBUG_FLAG_ISTOP)
- {
- switch (status.why)
- {
- case _DEBUG_WHY_SIGNALLED:
- ourstatus->set_stopped (gdb_signal_from_host (status.info.si_signo));
- exit_signo = 0;
- break;
- case _DEBUG_WHY_FAULTED:
- if (status.info.si_signo == SIGTRAP)
- {
- ourstatus->set_stopped (0);
- exit_signo = 0;
- }
- else
- {
- ourstatus->set_stopped
- (gdb_signal_from_host (status.info.si_signo));
- exit_signo = ourstatus->sig ();
- }
- break;
-
- case _DEBUG_WHY_TERMINATED:
- {
- int waitval = 0;
-
- waitpid (inferior_ptid.pid (), &waitval, WNOHANG);
- if (exit_signo)
- {
- /* Abnormal death. */
- ourstatus->set_signalled (exit_signo);
- }
- else
- {
- /* Normal death. */
- ourstatus->set_exited (WEXITSTATUS (waitval));
- }
- exit_signo = 0;
- break;
- }
-
- case _DEBUG_WHY_REQUESTED:
- /* We are assuming a requested stop is due to a SIGINT. */
- ourstatus->set_stopped (GDB_SIGNAL_INT);
- exit_signo = 0;
- break;
- }
- }
-
- return ptid_t (status.pid, 0, status.tid);
-}
-
-/* Read the current values of the inferior's registers, both the
- general register set and floating point registers (if supported)
- and update gdb's idea of their current values. */
-void
-nto_procfs_target::fetch_registers (struct regcache *regcache, int regno)
-{
- union
- {
- procfs_greg greg;
- procfs_fpreg fpreg;
- procfs_altreg altreg;
- }
- reg;
- int regsize;
-
- procfs_set_thread (regcache->ptid ());
- if (devctl (ctl_fd, DCMD_PROC_GETGREG, &reg, sizeof (reg), &regsize) == EOK)
- nto_supply_gregset (regcache, (char *) &reg.greg);
- if (devctl (ctl_fd, DCMD_PROC_GETFPREG, &reg, sizeof (reg), &regsize)
- == EOK)
- nto_supply_fpregset (regcache, (char *) &reg.fpreg);
- if (devctl (ctl_fd, DCMD_PROC_GETALTREG, &reg, sizeof (reg), &regsize)
- == EOK)
- nto_supply_altregset (regcache, (char *) &reg.altreg);
-}
-
-/* Helper for procfs_xfer_partial that handles memory transfers.
- Arguments are like target_xfer_partial. */
-
-static enum target_xfer_status
-procfs_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST memaddr, ULONGEST len, ULONGEST *xfered_len)
-{
- int nbytes;
-
- if (lseek (ctl_fd, (off_t) memaddr, SEEK_SET) != (off_t) memaddr)
- return TARGET_XFER_E_IO;
-
- if (writebuf != NULL)
- nbytes = write (ctl_fd, writebuf, len);
- else
- nbytes = read (ctl_fd, readbuf, len);
- if (nbytes <= 0)
- return TARGET_XFER_E_IO;
- *xfered_len = nbytes;
- return TARGET_XFER_OK;
-}
-
-/* Target to_xfer_partial implementation. */
-
-enum target_xfer_status
-nto_procfs_target::xfer_partial (enum target_object object,
- const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset,
- ULONGEST len, ULONGEST *xfered_len)
-{
- switch (object)
- {
- case TARGET_OBJECT_MEMORY:
- return procfs_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
- case TARGET_OBJECT_AUXV:
- if (readbuf != NULL)
- {
- int err;
- CORE_ADDR initial_stack;
- debug_process_t procinfo;
- /* For 32-bit architecture, size of auxv_t is 8 bytes. */
- const unsigned int sizeof_auxv_t = sizeof (auxv_t);
- const unsigned int sizeof_tempbuf = 20 * sizeof_auxv_t;
- int tempread;
- gdb_byte *const tempbuf = alloca (sizeof_tempbuf);
-
- if (tempbuf == NULL)
- return TARGET_XFER_E_IO;
-
- err = devctl (ctl_fd, DCMD_PROC_INFO, &procinfo,
- sizeof procinfo, 0);
- if (err != EOK)
- return TARGET_XFER_E_IO;
-
- initial_stack = procinfo.initial_stack;
-
- /* procfs is always 'self-hosted', no byte-order manipulation. */
- tempread = nto_read_auxv_from_initial_stack (initial_stack, tempbuf,
- sizeof_tempbuf,
- sizeof (auxv_t));
- tempread = std::min (tempread, len) - offset;
- memcpy (readbuf, tempbuf + offset, tempread);
- *xfered_len = tempread;
- return tempread ? TARGET_XFER_OK : TARGET_XFER_EOF;
- }
- /* Fallthru */
- default:
- return this->beneath ()->xfer_partial (object, annex,
- readbuf, writebuf, offset, len,
- xfered_len);
- }
-}
-
-/* Take a program previously attached to and detaches it.
- The program resumes execution and will no longer stop
- on signals, etc. We'd better not have left any breakpoints
- in the program or it'll die when it hits one. */
-void
-nto_procfs_target::detach (inferior *inf, int from_tty)
-{
- target_announce_detach ();
-
- if (siggnal)
- SignalKill (nto_node (), inf->pid, 0, 0, 0, 0);
-
- close (ctl_fd);
- ctl_fd = -1;
-
- switch_to_no_thread ();
- detach_inferior (inf->pid);
- init_thread_list ();
- inf_child_maybe_unpush_target (ops);
-}
-
-static int
-procfs_breakpoint (CORE_ADDR addr, int type, int size)
-{
- procfs_break brk;
-
- brk.type = type;
- brk.addr = addr;
- brk.size = size;
- errno = devctl (ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0);
- if (errno != EOK)
- return 1;
- return 0;
-}
-
-int
-nto_procfs_target::insert_breakpoint (struct gdbarch *gdbarch,
- struct bp_target_info *bp_tgt)
-{
- bp_tgt->placed_address = bp_tgt->reqstd_address;
- return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, 0);
-}
-
-int
-nto_procfs_target::remove_breakpoint (struct gdbarch *gdbarch,
- struct bp_target_info *bp_tgt,
- enum remove_bp_reason reason)
-{
- return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, -1);
-}
-
-int
-nto_procfs_target::insert_hw_breakpoint (struct gdbarch *gdbarch,
- struct bp_target_info *bp_tgt)
-{
- bp_tgt->placed_address = bp_tgt->reqstd_address;
- return procfs_breakpoint (bp_tgt->placed_address,
- _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, 0);
-}
-
-int
-nto_procfs_target::remove_hw_breakpoint (struct gdbarch *gdbarch,
- struct bp_target_info *bp_tgt)
-{
- return procfs_breakpoint (bp_tgt->placed_address,
- _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, -1);
-}
-
-void
-nto_procfs_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
-{
- int signal_to_pass;
- procfs_status status;
- sigset_t *run_fault = (sigset_t *) (void *) &run.fault;
-
- if (inferior_ptid == null_ptid)
- return;
-
- procfs_set_thread (ptid == minus_one_ptid ? inferior_ptid :
- ptid);
-
- run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE;
- if (step)
- run.flags |= _DEBUG_RUN_STEP;
-
- sigemptyset (run_fault);
- sigaddset (run_fault, FLTBPT);
- sigaddset (run_fault, FLTTRACE);
- sigaddset (run_fault, FLTILL);
- sigaddset (run_fault, FLTPRIV);
- sigaddset (run_fault, FLTBOUNDS);
- sigaddset (run_fault, FLTIOVF);
- sigaddset (run_fault, FLTIZDIV);
- sigaddset (run_fault, FLTFPE);
- /* Peter V will be changing this at some point. */
- sigaddset (run_fault, FLTPAGE);
-
- run.flags |= _DEBUG_RUN_ARM;
-
- signal_to_pass = gdb_signal_to_host (signo);
-
- if (signal_to_pass)
- {
- devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
- signal_to_pass = gdb_signal_to_host (signo);
- if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
- {
- if (signal_to_pass != status.info.si_signo)
- {
- SignalKill (nto_node (), inferior_ptid.pid (), 0,
- signal_to_pass, 0, 0);
- run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
- }
- else /* Let it kill the program without telling us. */
- sigdelset (&run.trace, signal_to_pass);
- }
- }
- else
- run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT;
-
- errno = devctl (ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0);
- if (errno != EOK)
- {
- perror (_("run error!\n"));
- return;
- }
-}
-
-void
-nto_procfs_target::mourn_inferior ()
-{
- if (inferior_ptid != null_ptid)
- {
- SignalKill (nto_node (), inferior_ptid.pid (), 0, SIGKILL, 0, 0);
- close (ctl_fd);
- }
- switch_to_no_thread ();
- init_thread_list ();
- inf_child_mourn_inferior (ops);
-}
-
-/* This function breaks up an argument string into an argument
- vector suitable for passing to execvp().
- E.g., on "run a b c d" this routine would get as input
- the string "a b c d", and as output it would fill in argv with
- the four arguments "a", "b", "c", "d". The only additional
- functionality is simple quoting. The gdb command:
- run a "b c d" f
- will fill in argv with the three args "a", "b c d", "e". */
-static void
-breakup_args (char *scratch, char **argv)
-{
- char *pp, *cp = scratch;
- char quoting = 0;
-
- for (;;)
- {
- /* Scan past leading separators. */
- quoting = 0;
- while (*cp == ' ' || *cp == '\t' || *cp == '\n')
- cp++;
-
- /* Break if at end of string. */
- if (*cp == '\0')
- break;
-
- /* Take an arg. */
- if (*cp == '"')
- {
- cp++;
- quoting = strchr (cp, '"') ? 1 : 0;
- }
-
- *argv++ = cp;
-
- /* Scan for next arg separator. */
- pp = cp;
- if (quoting)
- cp = strchr (pp, '"');
- if ((cp == NULL) || (!quoting))
- cp = strchr (pp, ' ');
- if (cp == NULL)
- cp = strchr (pp, '\t');
- if (cp == NULL)
- cp = strchr (pp, '\n');
-
- /* No separators => end of string => break. */
- if (cp == NULL)
- {
- pp = cp;
- break;
- }
-
- /* Replace the separator with a terminator. */
- *cp++ = '\0';
- }
-
- /* Execv requires a null-terminated arg vector. */
- *argv = NULL;
-}
-
-void
-nto_procfs_target::create_inferior (const char *exec_file,
- const std::string &allargs,
- char **env, int from_tty)
-{
- if (exec_file == nullptr)
- no_executable_specified_error ();
-
- struct inheritance inherit;
- pid_t pid;
- int flags, errn;
- char **argv, *args;
- const char *in = "", *out = "", *err = "";
- int fd, fds[3];
- sigset_t set;
- struct inferior *inf;
-
- argv = xmalloc ((allargs.size () / (unsigned) 2 + 2) *
- sizeof (*argv));
- argv[0] = exec_file;
- args = xstrdup (allargs.c_str ());
- breakup_args (args, &argv[1]);
-
- argv = nto_parse_redirection (argv, &in, &out, &err);
-
- fds[0] = STDIN_FILENO;
- fds[1] = STDOUT_FILENO;
- fds[2] = STDERR_FILENO;
-
- /* If the user specified I/O via gdb's --tty= arg, use it, but only
- if the i/o is not also being specified via redirection. */
- const char *inferior_tty = current_inferior ()->tty ();
- if (inferior_tty != nullptr)
- {
- if (!in[0])
- in = inferior_tty;
- if (!out[0])
- out = inferior_tty;
- if (!err[0])
- err = inferior_tty;
- }
-
- if (in[0])
- {
- fd = open (in, O_RDONLY);
- if (fd == -1)
- perror (in);
- else
- fds[0] = fd;
- }
- if (out[0])
- {
- fd = open (out, O_WRONLY);
- if (fd == -1)
- perror (out);
- else
- fds[1] = fd;
- }
- if (err[0])
- {
- fd = open (err, O_WRONLY);
- if (fd == -1)
- perror (err);
- else
- fds[2] = fd;
- }
-
- /* Clear any pending SIGUSR1's but keep the behavior the same. */
- signal (SIGUSR1, signal (SIGUSR1, SIG_IGN));
-
- sigemptyset (&set);
- sigaddset (&set, SIGUSR1);
- sigprocmask (SIG_UNBLOCK, &set, NULL);
-
- memset (&inherit, 0, sizeof (inherit));
-
- if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) != 0)
- {
- inherit.nd = nto_node ();
- inherit.flags |= SPAWN_SETND;
- inherit.flags &= ~SPAWN_EXEC;
- }
- inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD;
- inherit.pgroup = SPAWN_NEWPGROUP;
- pid = spawnp (argv[0], 3, fds, &inherit, argv,
- ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0 ? env : 0);
- xfree (args);
-
- sigprocmask (SIG_BLOCK, &set, NULL);
-
- if (pid == -1)
- error (_("Error spawning %s: %d (%s)"), argv[0], errno,
- safe_strerror (errno));
-
- if (fds[0] != STDIN_FILENO)
- close (fds[0]);
- if (fds[1] != STDOUT_FILENO)
- close (fds[1]);
- if (fds[2] != STDERR_FILENO)
- close (fds[2]);
-
- ptid_t ptid = do_attach (ptid_t (pid));
- update_thread_list ();
- switch_to_thread (this->find_thread (ptid));
-
- inf = current_inferior ();
- inferior_appeared (inf, pid);
- inf->attach_flag = false;
-
- flags = _DEBUG_FLAG_KLC; /* Kill-on-Last-Close flag. */
- errn = devctl (ctl_fd, DCMD_PROC_SET_FLAG, &flags, sizeof (flags), 0);
- if (errn != EOK)
- {
- /* FIXME: expected warning? */
- /* warning( "Failed to set Kill-on-Last-Close flag: errno = %d(%s)\n",
- errn, safe_strerror(errn) ); */
- }
- if (!inf->target_is_pushed (ops))
- inf->push_target (ops);
- target_terminal::init ();
-
- if (current_program_space->exec_bfd () != NULL
- || (current_program_space->symfile_object_file != NULL
- && current_program_space->symfile_object_file->obfd != NULL))
- solib_create_inferior_hook (0);
-}
-
-void
-nto_procfs_target::interrupt ()
-{
- devctl (ctl_fd, DCMD_PROC_STOP, NULL, 0, 0);
-}
-
-void
-nto_procfs_target::kill ()
-{
- target_mourn_inferior (inferior_ptid);
-}
-
-/* Fill buf with regset and return devctl cmd to do the setting. Return
- -1 if we fail to get the regset. Store size of regset in regsize. */
-static int
-get_regset (int regset, char *buf, int bufsize, int *regsize)
-{
- int dev_get, dev_set;
- switch (regset)
- {
- case NTO_REG_GENERAL:
- dev_get = DCMD_PROC_GETGREG;
- dev_set = DCMD_PROC_SETGREG;
- break;
-
- case NTO_REG_FLOAT:
- dev_get = DCMD_PROC_GETFPREG;
- dev_set = DCMD_PROC_SETFPREG;
- break;
-
- case NTO_REG_ALT:
- dev_get = DCMD_PROC_GETALTREG;
- dev_set = DCMD_PROC_SETALTREG;
- break;
-
- case NTO_REG_SYSTEM:
- default:
- return -1;
- }
- if (devctl (ctl_fd, dev_get, buf, bufsize, regsize) != EOK)
- return -1;
-
- return dev_set;
-}
-
-void
-nto_procfs_target::store_registers (struct regcache *regcache, int regno)
-{
- union
- {
- procfs_greg greg;
- procfs_fpreg fpreg;
- procfs_altreg altreg;
- }
- reg;
- unsigned off;
- int len, regset, regsize, dev_set, err;
- char *data;
- ptid_t ptid = regcache->ptid ();
-
- if (ptid == null_ptid)
- return;
- procfs_set_thread (ptid);
-
- if (regno == -1)
- {
- for (regset = NTO_REG_GENERAL; regset < NTO_REG_END; regset++)
- {
- dev_set = get_regset (regset, (char *) &reg,
- sizeof (reg), &regsize);
- if (dev_set == -1)
- continue;
-
- if (nto_regset_fill (regcache, regset, (char *) &reg) == -1)
- continue;
-
- err = devctl (ctl_fd, dev_set, &reg, regsize, 0);
- if (err != EOK)
- gdb_printf (gdb_stderr,
- "Warning unable to write regset %d: %s\n",
- regno, safe_strerror (err));
- }
- }
- else
- {
- regset = nto_regset_id (regno);
- if (regset == -1)
- return;
-
- dev_set = get_regset (regset, (char *) &reg, sizeof (reg), &regsize);
- if (dev_set == -1)
- return;
-
- len = nto_register_area (regcache->arch (),
- regno, regset, &off);
-
- if (len < 1)
- return;
-
- regcache->raw_collect (regno, (char *) &reg + off);
-
- err = devctl (ctl_fd, dev_set, &reg, regsize, 0);
- if (err != EOK)
- gdb_printf (gdb_stderr,
- "Warning unable to write regset %d: %s\n", regno,
- safe_strerror (err));
- }
-}
-
-/* Set list of signals to be handled in the target. */
-
-void
-nto_procfs_target::pass_signals
- (gdb::array_view<const unsigned char> pass_signals)
-{
- int signo;
-
- sigfillset (&run.trace);
-
- for (signo = 1; signo < NSIG; signo++)
- {
- int target_signo = gdb_signal_from_host (signo);
- if (target_signo < pass_signals.size () && pass_signals[target_signo])
- sigdelset (&run.trace, signo);
- }
-}
-
-std::string
-nto_procfs_target::pid_to_str (ptid_t ptid)
-{
- int pid, tid;
- struct tidinfo *tip;
-
- pid = ptid.pid ();
- tid = ptid.tid ();
-
-#if 0 /* NYI */
- tip = procfs_thread_info (pid, tid);
- if (tip != NULL)
- snprintf (&buf[n], 1023, " (state = 0x%02x)", tip->state);
-#endif
-
- return string_printf ("process %d", pid);
-}
-
-/* to_can_run implementation for "target procfs". Note this really
- means "can this target be the default run target", which there can
- be only one, and we make it be "target native" like other ports.
- "target procfs <node>" wouldn't make sense as default run target, as
- it needs <node>. */
-
-int
-nto_procfs_target::can_run ()
-{
- return 0;
-}
-
-/* "target procfs". */
-static nto_procfs_target_procfs nto_procfs_ops;
-
-/* "target native". */
-static nto_procfs_target_native nto_native_ops;
-
-/* Create the "native" and "procfs" targets. */
-
-static void
-init_procfs_targets (void)
-{
- /* Register "target native". This is the default run target. */
- add_target (nto_native_target_info, inf_child_open_target);
- set_native_target (&nto_native_ops);
-
- /* Register "target procfs <node>". */
- add_target (nto_procfs_target_info, inf_child_open_target);
-}
-
-#define OSTYPE_NTO 1
-
-void _initialize_procfs ();
-void
-_initialize_procfs ()
-{
- sigset_t set;
-
- init_procfs_targets ();
-
- /* We use SIGUSR1 to gain control after we block waiting for a process.
- We use sigwaitevent to wait. */
- sigemptyset (&set);
- sigaddset (&set, SIGUSR1);
- sigprocmask (SIG_BLOCK, &set, NULL);
-
- /* Initially, make sure all signals are reported. */
- sigfillset (&run.trace);
-
- /* Stuff some information. */
- nto_cpuinfo_flags = SYSPAGE_ENTRY (cpuinfo)->flags;
- nto_cpuinfo_valid = 1;
-
- add_info ("pidlist", procfs_pidlist, _("pidlist"));
- add_info ("meminfo", procfs_meminfo, _("memory information"));
-
- nto_is_nto_target = procfs_is_nto_target;
-}
-
-
-static int
-procfs_hw_watchpoint (int addr, int len, enum target_hw_bp_type type)
-{
- procfs_break brk;
-
- switch (type)
- {
- case hw_read:
- brk.type = _DEBUG_BREAK_RD;
- break;
- case hw_access:
- brk.type = _DEBUG_BREAK_RW;
- break;
- default: /* Modify. */
-/* FIXME: brk.type = _DEBUG_BREAK_RWM gives EINVAL for some reason. */
- brk.type = _DEBUG_BREAK_RW;
- }
- brk.type |= _DEBUG_BREAK_HW; /* Always ask for HW. */
- brk.addr = addr;
- brk.size = len;
-
- errno = devctl (ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0);
- if (errno != EOK)
- {
- perror (_("Failed to set hardware watchpoint"));
- return -1;
- }
- return 0;
-}
-
-bool
-nto_procfs_target::can_use_hw_breakpoint (enum bptype type,
- int cnt, int othertype)
-{
- return 1;
-}
-
-int
-nto_procfs_target::remove_hw_watchpoint (CORE_ADDR addr, int len,
- enum target_hw_bp_type type,
- struct expression *cond)
-{
- return procfs_hw_watchpoint (addr, -1, type);
-}
-
-int
-nto_procfs_target::insert_hw_watchpoint (CORE_ADDR addr, int len,
- enum target_hw_bp_type type,
- struct expression *cond)
-{
- return procfs_hw_watchpoint (addr, len, type);
-}
-
-bool
-nto_procfs_target::stopped_by_watchpoint ()
-{
- /* NOTE: nto_stopped_by_watchpoint will be called ONLY while we are
- stopped due to a SIGTRAP. This assumes gdb works in 'all-stop' mode;
- future gdb versions will likely run in 'non-stop' mode in which case
- we will have to store/examine statuses per thread in question.
- Until then, this will work fine. */
-
- struct inferior *inf = current_inferior ();
- struct nto_inferior_data *inf_data;
-
- gdb_assert (inf != NULL);
-
- inf_data = nto_inferior_data (inf);
-
- return inf_data->stopped_flags
- & (_DEBUG_FLAG_TRACE_RD
- | _DEBUG_FLAG_TRACE_WR
- | _DEBUG_FLAG_TRACE_MODIFY);
-}
diff --git a/gdb/nto-tdep.c b/gdb/nto-tdep.c
deleted file mode 100644
index eeef52db..0000000
--- a/gdb/nto-tdep.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/* nto-tdep.c - general QNX Neutrino target functionality.
-
- Copyright (C) 2003-2024 Free Software Foundation, Inc.
-
- Contributed by QNX Software Systems Ltd.
-
- 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 <sys/stat.h>
-#include "nto-tdep.h"
-#include "extract-store-integer.h"
-#include "top.h"
-#include "inferior.h"
-#include "infrun.h"
-#include "gdbarch.h"
-#include "bfd.h"
-#include "elf-bfd.h"
-#include "solib-svr4.h"
-#include "gdbcore.h"
-#include "objfiles.h"
-#include "source.h"
-#include "gdbsupport/pathstuff.h"
-
-#define QNX_NOTE_NAME "QNX"
-#define QNX_INFO_SECT_NAME "QNX_info"
-
-#ifdef __CYGWIN__
-#include <sys/cygwin.h>
-#endif
-
-#ifdef __CYGWIN__
-static char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6";
-#elif defined(__sun__) || defined(linux)
-static char default_nto_target[] = "/opt/QNXsdk/target/qnx6";
-#else
-static char default_nto_target[] = "";
-#endif
-
-struct nto_target_ops current_nto_target;
-
-static const registry<inferior>::key<struct nto_inferior_data>
- nto_inferior_data_reg;
-
-static char *
-nto_target (void)
-{
- char *p = getenv ("QNX_TARGET");
-
-#ifdef __CYGWIN__
- static char buf[PATH_MAX];
- if (p)
- cygwin_conv_path (CCP_WIN_A_TO_POSIX, p, buf, PATH_MAX);
- else
- cygwin_conv_path (CCP_WIN_A_TO_POSIX, default_nto_target, buf, PATH_MAX);
- return buf;
-#else
- return p ? p : default_nto_target;
-#endif
-}
-
-/* Take a string such as i386, rs6000, etc. and map it onto CPUTYPE_X86,
- CPUTYPE_PPC, etc. as defined in nto-share/dsmsgs.h. */
-int
-nto_map_arch_to_cputype (const char *arch)
-{
- if (!strcmp (arch, "i386") || !strcmp (arch, "x86"))
- return CPUTYPE_X86;
- if (!strcmp (arch, "rs6000") || !strcmp (arch, "powerpc"))
- return CPUTYPE_PPC;
- if (!strcmp (arch, "mips"))
- return CPUTYPE_MIPS;
- if (!strcmp (arch, "arm"))
- return CPUTYPE_ARM;
- if (!strcmp (arch, "sh"))
- return CPUTYPE_SH;
- return CPUTYPE_UNKNOWN;
-}
-
-int
-nto_find_and_open_solib (const char *solib, unsigned o_flags,
- gdb::unique_xmalloc_ptr<char> *temp_pathname)
-{
- char *buf, *arch_path, *nto_root;
- const char *endian;
- const char *base;
- const char *arch;
- int arch_len, len, ret;
-#define PATH_FMT \
- "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
-
- nto_root = nto_target ();
- gdbarch *gdbarch = current_inferior ()->arch ();
- if (strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name, "i386") == 0)
- {
- arch = "x86";
- endian = "";
- }
- else if (strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name,
- "rs6000") == 0
- || strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name,
- "powerpc") == 0)
- {
- arch = "ppc";
- endian = "be";
- }
- else
- {
- arch = gdbarch_bfd_arch_info (gdbarch)->arch_name;
- endian = gdbarch_byte_order (gdbarch)
- == BFD_ENDIAN_BIG ? "be" : "le";
- }
-
- /* In case nto_root is short, add strlen(solib)
- so we can reuse arch_path below. */
-
- arch_len = (strlen (nto_root) + strlen (arch) + strlen (endian) + 2
- + strlen (solib));
- arch_path = (char *) alloca (arch_len);
- xsnprintf (arch_path, arch_len, "%s/%s%s", nto_root, arch, endian);
-
- len = strlen (PATH_FMT) + strlen (arch_path) * 5 + 1;
- buf = (char *) alloca (len);
- xsnprintf (buf, len, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
- arch_path);
-
- base = lbasename (solib);
- ret = openp (buf, OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, base, o_flags,
- temp_pathname);
- if (ret < 0 && base != solib)
- {
- xsnprintf (arch_path, arch_len, "/%s", solib);
- ret = open (arch_path, o_flags, 0);
- if (temp_pathname)
- {
- if (ret >= 0)
- *temp_pathname = gdb_realpath (arch_path);
- else
- temp_pathname->reset (NULL);
- }
- }
- return ret;
-}
-
-void
-nto_init_solib_absolute_prefix (void)
-{
- char buf[PATH_MAX * 2], arch_path[PATH_MAX];
- char *nto_root;
- const char *endian;
- const char *arch;
-
- nto_root = nto_target ();
- gdbarch *gdbarch = current_inferior ()->arch ();
- if (strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name, "i386") == 0)
- {
- arch = "x86";
- endian = "";
- }
- else if (strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name,
- "rs6000") == 0
- || strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name,
- "powerpc") == 0)
- {
- arch = "ppc";
- endian = "be";
- }
- else
- {
- arch = gdbarch_bfd_arch_info (gdbarch)->arch_name;
- endian = gdbarch_byte_order (gdbarch)
- == BFD_ENDIAN_BIG ? "be" : "le";
- }
-
- xsnprintf (arch_path, sizeof (arch_path), "%s/%s%s", nto_root, arch, endian);
-
- xsnprintf (buf, sizeof (buf), "set solib-absolute-prefix %s", arch_path);
- execute_command (buf, 0);
-}
-
-char **
-nto_parse_redirection (char *pargv[], const char **pin, const char **pout,
- const char **perr)
-{
- char **argv;
- const char *in, *out, *err, *p;
- int argc, i, n;
-
- for (n = 0; pargv[n]; n++);
- if (n == 0)
- return NULL;
- in = "";
- out = "";
- err = "";
-
- argv = XCNEWVEC (char *, n + 1);
- argc = n;
- for (i = 0, n = 0; n < argc; n++)
- {
- p = pargv[n];
- if (*p == '>')
- {
- p++;
- if (*p)
- out = p;
- else
- out = pargv[++n];
- }
- else if (*p == '<')
- {
- p++;
- if (*p)
- in = p;
- else
- in = pargv[++n];
- }
- else if (*p++ == '2' && *p++ == '>')
- {
- if (*p == '&' && *(p + 1) == '1')
- err = out;
- else if (*p)
- err = p;
- else
- err = pargv[++n];
- }
- else
- argv[i++] = pargv[n];
- }
- *pin = in;
- *pout = out;
- *perr = err;
- return argv;
-}
-
-static CORE_ADDR
-lm_addr (const solib &so)
-{
- auto *li = gdb::checked_static_cast<const lm_info_svr4 *> (so.lm_info.get ());
-
- return li->l_addr;
-}
-
-static CORE_ADDR
-nto_truncate_ptr (CORE_ADDR addr)
-{
- gdbarch *gdbarch = current_inferior ()->arch ();
- if (gdbarch_ptr_bit (gdbarch) == sizeof (CORE_ADDR) * 8)
- /* We don't need to truncate anything, and the bit twiddling below
- will fail due to overflow problems. */
- return addr;
- else
- return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (gdbarch)) - 1);
-}
-
-static Elf_Internal_Phdr *
-find_load_phdr (bfd *abfd)
-{
- Elf_Internal_Phdr *phdr;
- unsigned int i;
-
- if (!elf_tdata (abfd))
- return NULL;
-
- phdr = elf_tdata (abfd)->phdr;
- for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
- {
- if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
- return phdr;
- }
- return NULL;
-}
-
-void
-nto_relocate_section_addresses (solib &so, target_section *sec)
-{
- /* Neutrino treats the l_addr base address field in link.h as different than
- the base address in the System V ABI and so the offset needs to be
- calculated and applied to relocations. */
- Elf_Internal_Phdr *phdr = find_load_phdr (sec->the_bfd_section->owner);
- unsigned vaddr = phdr ? phdr->p_vaddr : 0;
-
- sec->addr = nto_truncate_ptr (sec->addr + lm_addr (so) - vaddr);
- sec->endaddr = nto_truncate_ptr (sec->endaddr + lm_addr (so) - vaddr);
-}
-
-/* This is cheating a bit because our linker code is in libc.so. If we
- ever implement lazy linking, this may need to be re-examined. */
-int
-nto_in_dynsym_resolve_code (CORE_ADDR pc)
-{
- if (in_plt_section (pc))
- return 1;
- return 0;
-}
-
-void
-nto_dummy_supply_regset (struct regcache *regcache, char *regs)
-{
- /* Do nothing. */
-}
-
-static void
-nto_sniff_abi_note_section (bfd *abfd, asection *sect, void *obj)
-{
- const char *sectname;
- unsigned int sectsize;
- /* Buffer holding the section contents. */
- char *note;
- unsigned int namelen;
- const char *name;
- const unsigned sizeof_Elf_Nhdr = 12;
-
- sectname = bfd_section_name (sect);
- sectsize = bfd_section_size (sect);
-
- if (sectsize > 128)
- sectsize = 128;
-
- if (sectname != NULL && strstr (sectname, QNX_INFO_SECT_NAME) != NULL)
- *(enum gdb_osabi *) obj = GDB_OSABI_QNXNTO;
- else if (sectname != NULL && strstr (sectname, "note") != NULL
- && sectsize > sizeof_Elf_Nhdr)
- {
- note = XNEWVEC (char, sectsize);
- bfd_get_section_contents (abfd, sect, note, 0, sectsize);
- namelen = (unsigned int) bfd_h_get_32 (abfd, note);
- name = note + sizeof_Elf_Nhdr;
- if (sectsize >= namelen + sizeof_Elf_Nhdr
- && namelen == sizeof (QNX_NOTE_NAME)
- && 0 == strcmp (name, QNX_NOTE_NAME))
- *(enum gdb_osabi *) obj = GDB_OSABI_QNXNTO;
-
- XDELETEVEC (note);
- }
-}
-
-enum gdb_osabi
-nto_elf_osabi_sniffer (bfd *abfd)
-{
- enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
-
- bfd_map_over_sections (abfd,
- nto_sniff_abi_note_section,
- &osabi);
-
- return osabi;
-}
-
-static const char * const nto_thread_state_str[] =
-{
- "DEAD", /* 0 0x00 */
- "RUNNING", /* 1 0x01 */
- "READY", /* 2 0x02 */
- "STOPPED", /* 3 0x03 */
- "SEND", /* 4 0x04 */
- "RECEIVE", /* 5 0x05 */
- "REPLY", /* 6 0x06 */
- "STACK", /* 7 0x07 */
- "WAITTHREAD", /* 8 0x08 */
- "WAITPAGE", /* 9 0x09 */
- "SIGSUSPEND", /* 10 0x0a */
- "SIGWAITINFO", /* 11 0x0b */
- "NANOSLEEP", /* 12 0x0c */
- "MUTEX", /* 13 0x0d */
- "CONDVAR", /* 14 0x0e */
- "JOIN", /* 15 0x0f */
- "INTR", /* 16 0x10 */
- "SEM", /* 17 0x11 */
- "WAITCTX", /* 18 0x12 */
- "NET_SEND", /* 19 0x13 */
- "NET_REPLY" /* 20 0x14 */
-};
-
-const char *
-nto_extra_thread_info (struct target_ops *self, struct thread_info *ti)
-{
- if (ti != NULL && ti->priv != NULL)
- {
- nto_thread_info *priv = get_nto_thread_info (ti);
-
- if (priv->state < ARRAY_SIZE (nto_thread_state_str))
- return nto_thread_state_str [priv->state];
- }
- return "";
-}
-
-void
-nto_initialize_signals (void)
-{
- /* We use SIG45 for pulses, or something, so nostop, noprint
- and pass them. */
- signal_stop_update (gdb_signal_from_name ("SIG45"), 0);
- signal_print_update (gdb_signal_from_name ("SIG45"), 0);
- signal_pass_update (gdb_signal_from_name ("SIG45"), 1);
-
- /* By default we don't want to stop on these two, but we do want to pass. */
-#if defined(SIGSELECT)
- signal_stop_update (SIGSELECT, 0);
- signal_print_update (SIGSELECT, 0);
- signal_pass_update (SIGSELECT, 1);
-#endif
-
-#if defined(SIGPHOTON)
- signal_stop_update (SIGPHOTON, 0);
- signal_print_update (SIGPHOTON, 0);
- signal_pass_update (SIGPHOTON, 1);
-#endif
-}
-
-/* Read AUXV from initial_stack. */
-LONGEST
-nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack, gdb_byte *readbuf,
- LONGEST len, size_t sizeof_auxv_t)
-{
- gdb_byte targ32[4]; /* For 32 bit target values. */
- gdb_byte targ64[8]; /* For 64 bit target values. */
- CORE_ADDR data_ofs = 0;
- ULONGEST anint;
- LONGEST len_read = 0;
- gdb_byte *buff;
- enum bfd_endian byte_order;
- int ptr_size;
-
- if (sizeof_auxv_t == 16)
- ptr_size = 8;
- else
- ptr_size = 4;
-
- /* Skip over argc, argv and envp... Comment from ldd.c:
-
- The startup frame is set-up so that we have:
- auxv
- NULL
- ...
- envp2
- envp1 <----- void *frame + (argc + 2) * sizeof(char *)
- NULL
- ...
- argv2
- argv1
- argc <------ void * frame
-
- On entry to ldd, frame gives the address of argc on the stack. */
- /* Read argc. 4 bytes on both 64 and 32 bit arches and luckily little
- * endian. So we just read first 4 bytes. */
- if (target_read_memory (initial_stack + data_ofs, targ32, 4) != 0)
- return 0;
-
- byte_order = gdbarch_byte_order (current_inferior ()->arch ());
-
- anint = extract_unsigned_integer (targ32, sizeof (targ32), byte_order);
-
- /* Size of pointer is assumed to be 4 bytes (32 bit arch.) */
- data_ofs += (anint + 2) * ptr_size; /* + 2 comes from argc itself and
- NULL terminating pointer in
- argv. */
-
- /* Now loop over env table: */
- anint = 0;
- while (target_read_memory (initial_stack + data_ofs, targ64, ptr_size)
- == 0)
- {
- if (extract_unsigned_integer (targ64, ptr_size, byte_order) == 0)
- anint = 1; /* Keep looping until non-null entry is found. */
- else if (anint)
- break;
- data_ofs += ptr_size;
- }
- initial_stack += data_ofs;
-
- memset (readbuf, 0, len);
- buff = readbuf;
- while (len_read <= len-sizeof_auxv_t)
- {
- if (target_read_memory (initial_stack + len_read, buff, sizeof_auxv_t)
- == 0)
- {
- /* Both 32 and 64 bit structures have int as the first field. */
- const ULONGEST a_type
- = extract_unsigned_integer (buff, sizeof (targ32), byte_order);
-
- if (a_type == AT_NULL)
- break;
- buff += sizeof_auxv_t;
- len_read += sizeof_auxv_t;
- }
- else
- break;
- }
- return len_read;
-}
-
-/* Return nto_inferior_data for the given INFERIOR. If not yet created,
- construct it. */
-
-struct nto_inferior_data *
-nto_inferior_data (struct inferior *const inferior)
-{
- struct inferior *const inf = inferior ? inferior : current_inferior ();
- struct nto_inferior_data *inf_data;
-
- gdb_assert (inf != NULL);
-
- inf_data = nto_inferior_data_reg.get (inf);
- if (inf_data == NULL)
- inf_data = nto_inferior_data_reg.emplace (inf);
-
- return inf_data;
-}
diff --git a/gdb/nto-tdep.h b/gdb/nto-tdep.h
deleted file mode 100644
index 249a4f6..0000000
--- a/gdb/nto-tdep.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/* nto-tdep.h - QNX Neutrino target header.
-
- Copyright (C) 2003-2024 Free Software Foundation, Inc.
-
- Contributed by QNX Software Systems Ltd.
-
- 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 NTO_TDEP_H
-#define NTO_TDEP_H
-
-#include "solist.h"
-#include "osabi.h"
-#include "regset.h"
-#include "gdbthread.h"
-#include "gdbsupport/gdb-checked-static-cast.h"
-
-/* Target operations defined for Neutrino targets (<target>-nto-tdep.c). */
-
-struct nto_target_ops
-{
-/* The CPUINFO flags from the remote. Currently used by
- i386 for fxsave but future proofing other hosts.
- This is initialized in procfs_attach or nto_start_remote
- depending on our host/target. It would only be invalid
- if we were talking to an older pdebug which didn't support
- the cpuinfo message. */
- unsigned cpuinfo_flags;
-
-/* True if successfully retrieved cpuinfo from remote. */
- int cpuinfo_valid;
-
-/* Given a register, return an id that represents the Neutrino
- regset it came from. If reg == -1 update all regsets. */
- int (*regset_id) (int);
-
- void (*supply_gregset) (struct regcache *, char *);
-
- void (*supply_fpregset) (struct regcache *, char *);
-
- void (*supply_altregset) (struct regcache *, char *);
-
-/* Given a regset, tell gdb about registers stored in data. */
- void (*supply_regset) (struct regcache *, int, char *);
-
-/* Given a register and regset, calculate the offset into the regset
- and stuff it into the last argument. If regno is -1, calculate the
- size of the entire regset. Returns length of data, -1 if unknown
- regset, 0 if unknown register. */
- int (*register_area) (struct gdbarch *, int, int, unsigned *);
-
-/* Build the Neutrino register set info into the data buffer.
- Return -1 if unknown regset, 0 otherwise. */
- int (*regset_fill) (const struct regcache *, int, char *);
-
-/* Gives the fetch_link_map_offsets function exposure outside of
- solib-svr4.c so that we can override relocate_section_addresses(). */
- struct link_map_offsets *(*fetch_link_map_offsets) (void);
-
-/* Used by nto_elf_osabi_sniffer to determine if we're connected to an
- Neutrino target. */
- enum gdb_osabi (*is_nto_target) (bfd *abfd);
-};
-
-extern struct nto_target_ops current_nto_target;
-
-#define nto_cpuinfo_flags (current_nto_target.cpuinfo_flags)
-
-#define nto_cpuinfo_valid (current_nto_target.cpuinfo_valid)
-
-#define nto_regset_id (current_nto_target.regset_id)
-
-#define nto_supply_gregset (current_nto_target.supply_gregset)
-
-#define nto_supply_fpregset (current_nto_target.supply_fpregset)
-
-#define nto_supply_altregset (current_nto_target.supply_altregset)
-
-#define nto_supply_regset (current_nto_target.supply_regset)
-
-#define nto_register_area (current_nto_target.register_area)
-
-#define nto_regset_fill (current_nto_target.regset_fill)
-
-#define nto_fetch_link_map_offsets \
-(current_nto_target.fetch_link_map_offsets)
-
-#define nto_is_nto_target (current_nto_target.is_nto_target)
-
-/* Keep this consistant with neutrino syspage.h. */
-enum
-{
- CPUTYPE_X86,
- CPUTYPE_PPC,
- CPUTYPE_MIPS,
- CPUTYPE_SPARE,
- CPUTYPE_ARM,
- CPUTYPE_SH,
- CPUTYPE_UNKNOWN
-};
-
-enum
-{
- OSTYPE_QNX4,
- OSTYPE_NTO
-};
-
-/* These correspond to the DSMSG_* versions in dsmsgs.h. */
-enum
-{
- NTO_REG_GENERAL,
- NTO_REG_FLOAT,
- NTO_REG_SYSTEM,
- NTO_REG_ALT,
- NTO_REG_END
-};
-
-typedef char qnx_reg64[8];
-
-typedef struct _debug_regs
-{
- qnx_reg64 padding[1024];
-} nto_regset_t;
-
-struct nto_thread_info : public private_thread_info
-{
- short tid = 0;
- unsigned char state = 0;
- unsigned char flags = 0;
- std::string name;
-};
-
-static inline nto_thread_info *
-get_nto_thread_info (thread_info *thread)
-{
- return gdb::checked_static_cast<nto_thread_info *> (thread->priv.get ());
-}
-
-/* Per-inferior data, common for both procfs and remote. */
-struct nto_inferior_data
-{
- /* Last stopped flags result from wait function */
- unsigned int stopped_flags = 0;
-
- /* Last known stopped PC */
- CORE_ADDR stopped_pc = 0;
-};
-
-/* Generic functions in nto-tdep.c. */
-
-void nto_init_solib_absolute_prefix (void);
-
-char **nto_parse_redirection (char *start_argv[], const char **in,
- const char **out, const char **err);
-
-void nto_relocate_section_addresses (solib &, target_section *);
-
-int nto_map_arch_to_cputype (const char *);
-
-int nto_find_and_open_solib (const char *, unsigned,
- gdb::unique_xmalloc_ptr<char> *);
-
-enum gdb_osabi nto_elf_osabi_sniffer (bfd *abfd);
-
-void nto_initialize_signals (void);
-
-/* Dummy function for initializing nto_target_ops on targets which do
- not define a particular regset. */
-void nto_dummy_supply_regset (struct regcache *regcache, char *regs);
-
-int nto_in_dynsym_resolve_code (CORE_ADDR pc);
-
-const char *nto_extra_thread_info (struct target_ops *self, struct thread_info *);
-
-LONGEST nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack,
- gdb_byte *readbuf,
- LONGEST len, size_t sizeof_auxv_t);
-
-struct nto_inferior_data *nto_inferior_data (struct inferior *inf);
-
-#endif /* NTO_TDEP_H */
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index 3655445..fa2befd 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -120,9 +120,11 @@ lookup_objc_class (struct gdbarch *gdbarch, const char *classname)
return 0;
}
- if (lookup_minimal_symbol("objc_lookUpClass", 0, 0).minsym)
+ if (lookup_minimal_symbol (current_program_space,
+ "objc_lookUpClass").minsym != nullptr)
function = find_function_in_inferior("objc_lookUpClass", NULL);
- else if (lookup_minimal_symbol ("objc_lookup_class", 0, 0).minsym)
+ else if (lookup_minimal_symbol (current_program_space,
+ "objc_lookup_class").minsym != nullptr)
function = find_function_in_inferior("objc_lookup_class", NULL);
else
{
@@ -149,9 +151,11 @@ lookup_child_selector (struct gdbarch *gdbarch, const char *selname)
return 0;
}
- if (lookup_minimal_symbol("sel_getUid", 0, 0).minsym)
+ if (lookup_minimal_symbol (current_program_space, "sel_getUid").minsym
+ != nullptr)
function = find_function_in_inferior("sel_getUid", NULL);
- else if (lookup_minimal_symbol ("sel_get_any_uid", 0, 0).minsym)
+ else if (lookup_minimal_symbol (current_program_space,
+ "sel_get_any_uid").minsym != nullptr)
function = find_function_in_inferior("sel_get_any_uid", NULL);
else
{
@@ -180,17 +184,21 @@ value_nsstring (struct gdbarch *gdbarch, const char *ptr, int len)
stringValue[2] = value_string(ptr, len, char_type);
stringValue[2] = value_coerce_array(stringValue[2]);
/* _NSNewStringFromCString replaces "istr" after Lantern2A. */
- if (lookup_minimal_symbol("_NSNewStringFromCString", 0, 0).minsym)
+ if (lookup_minimal_symbol (current_program_space,
+ "_NSNewStringFromCString").minsym != nullptr)
{
function = find_function_in_inferior("_NSNewStringFromCString", NULL);
nsstringValue = call_function_by_hand(function, NULL, stringValue[2]);
}
- else if (lookup_minimal_symbol("istr", 0, 0).minsym)
+ else if (lookup_minimal_symbol (current_program_space,
+ "istr").minsym != nullptr)
{
function = find_function_in_inferior("istr", NULL);
nsstringValue = call_function_by_hand(function, NULL, stringValue[2]);
}
- else if (lookup_minimal_symbol("+[NSString stringWithCString:]", 0, 0).minsym)
+ else if (lookup_minimal_symbol (current_program_space,
+ "+[NSString stringWithCString:]").minsym
+ != nullptr)
{
function
= find_function_in_inferior("+[NSString stringWithCString:]", NULL);
@@ -544,7 +552,7 @@ compare_selectors (const void *a, const void *b)
*
* Implements the "Info selectors" command. Takes an optional regexp
* arg. Lists all objective c selectors that match the regexp. Works
- * by grepping thru all symbols for objective c methods. Output list
+ * by grepping through all symbols for objective c methods. Output list
* is sorted and uniqued.
*/
@@ -593,7 +601,7 @@ info_selectors_command (const char *regexp, int from_tty)
error (_("Invalid regexp (%s): %s"), val, regexp);
}
- /* First time thru is JUST to get max length and count. */
+ /* First time through is JUST to get max length and count. */
for (objfile *objfile : current_program_space->objfiles ())
{
for (minimal_symbol *msymbol : objfile->msymbols ())
@@ -708,7 +716,7 @@ compare_classes (const void *a, const void *b)
*
* Implements the "info classes" command for objective c classes.
* Lists all objective c classes that match the optional regexp.
- * Works by grepping thru the list of objective c methods. List will
+ * Works by grepping through the list of objective c methods. List will
* be sorted and uniqued (since one class may have many methods).
* BUGS: will not list a class that has no methods.
*/
@@ -747,7 +755,7 @@ info_classes_command (const char *regexp, int from_tty)
error (_("Invalid regexp (%s): %s"), val, regexp);
}
- /* First time thru is JUST to get max length and count. */
+ /* First time through is JUST to get max length and count. */
for (objfile *objfile : current_program_space->objfiles ())
{
for (minimal_symbol *msymbol : objfile->msymbols ())
@@ -1137,8 +1145,8 @@ find_imps (const char *method, std::vector<const char *> *symbol_names)
symbol_names->push_back (sym->natural_name ());
else
{
- struct bound_minimal_symbol msym
- = lookup_minimal_symbol (selector, 0, 0);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, selector);
if (msym.minsym != NULL)
symbol_names->push_back (msym.minsym->natural_name ());
@@ -1240,13 +1248,13 @@ find_objc_msgsend (void)
for (i = 0; i < nmethcalls; i++)
{
- struct bound_minimal_symbol func;
-
/* Try both with and without underscore. */
- func = lookup_bound_minimal_symbol (methcalls[i].name);
+ bound_minimal_symbol func
+ = lookup_minimal_symbol (current_program_space, methcalls[i].name);
if ((func.minsym == NULL) && (methcalls[i].name[0] == '_'))
{
- func = lookup_bound_minimal_symbol (methcalls[i].name + 1);
+ func = lookup_minimal_symbol (current_program_space,
+ methcalls[i].name + 1);
}
if (func.minsym == NULL)
{
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index 368e129..0e076fe 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -306,9 +306,10 @@ build_objfile_section_table (struct objfile *objfile)
requests for specific operations. Other bits like OBJF_SHARED are
simply copied through to the new objfile flags member. */
-objfile::objfile (gdb_bfd_ref_ptr bfd_, const char *name, objfile_flags flags_)
+objfile::objfile (gdb_bfd_ref_ptr bfd_, program_space *pspace,
+ const char *name, objfile_flags flags_)
: flags (flags_),
- pspace (current_program_space),
+ m_pspace (pspace),
obfd (std::move (bfd_))
{
const char *expanded_name;
@@ -345,13 +346,12 @@ objfile::objfile (gdb_bfd_ref_ptr bfd_, const char *name, objfile_flags flags_)
set_objfile_per_bfd (this);
}
-/* If there is a valid and known entry point, function fills *ENTRY_P with it
- and returns non-zero; otherwise it returns zero. */
+/* See objfiles.h. */
int
-entry_point_address_query (CORE_ADDR *entry_p)
+entry_point_address_query (program_space *pspace, CORE_ADDR *entry_p)
{
- objfile *objf = current_program_space->symfile_object_file;
+ objfile *objf = pspace->symfile_object_file;
if (objf == NULL || !objf->per_bfd->ei.entry_point_p)
return 0;
@@ -361,14 +361,14 @@ entry_point_address_query (CORE_ADDR *entry_p)
return 1;
}
-/* Get current entry point address. Call error if it is not known. */
+/* See objfiles.h. */
CORE_ADDR
-entry_point_address (void)
+entry_point_address (program_space *pspace)
{
CORE_ADDR retval;
- if (!entry_point_address_query (&retval))
+ if (!entry_point_address_query (pspace, &retval))
error (_("Entry point address is not known."));
return retval;
@@ -442,10 +442,11 @@ add_separate_debug_objfile (struct objfile *objfile, struct objfile *parent)
/* See objfiles.h. */
objfile *
-objfile::make (gdb_bfd_ref_ptr bfd_, const char *name_, objfile_flags flags_,
- objfile *parent)
+objfile::make (gdb_bfd_ref_ptr bfd_, program_space *pspace, const char *name_,
+ objfile_flags flags_, objfile *parent)
{
- objfile *result = new objfile (std::move (bfd_), name_, flags_);
+ objfile *result
+ = new objfile (std::move (bfd_), current_program_space, name_, flags_);
if (parent != nullptr)
add_separate_debug_objfile (result, parent);
@@ -463,7 +464,7 @@ objfile::make (gdb_bfd_ref_ptr bfd_, const char *name_, objfile_flags flags_,
void
objfile::unlink ()
{
- current_program_space->remove_objfile (this);
+ this->pspace ()->remove_objfile (this);
}
/* Free all separate debug objfile of OBJFILE, but don't free OBJFILE
@@ -561,14 +562,15 @@ objfile::~objfile ()
and if so, call clear_current_source_symtab_and_line. */
{
- struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+ symtab_and_line cursal
+ = get_current_source_symtab_and_line (this->pspace ());
if (cursal.symtab && cursal.symtab->compunit ()->objfile () == this)
- clear_current_source_symtab_and_line ();
+ clear_current_source_symtab_and_line (this->pspace ());
}
/* Rebuild section map next time we need it. */
- get_objfile_pspace_data (pspace)->section_map_dirty = 1;
+ get_objfile_pspace_data (m_pspace)->section_map_dirty = 1;
}
@@ -646,7 +648,7 @@ objfile_relocate1 (struct objfile *objfile,
objfile->section_offsets[i] = new_offsets[i];
/* Rebuild section map next time we need it. */
- get_objfile_pspace_data (objfile->pspace)->section_map_dirty = 1;
+ 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 ())
@@ -731,67 +733,58 @@ objfile_rebase (struct objfile *objfile, CORE_ADDR slide)
if (changed)
breakpoint_re_set ();
}
-
-/* Return non-zero if OBJFILE has full symbols. */
-int
-objfile_has_full_symbols (struct objfile *objfile)
+/* See objfiles.h. */
+
+bool
+objfile_has_full_symbols (objfile *objfile)
{
- return objfile->compunit_symtabs != NULL;
+ return objfile->compunit_symtabs != nullptr;
}
-/* Return non-zero if OBJFILE has full or partial symbols, either directly
- or through a separate debug file. */
+/* See objfiles.h. */
-int
-objfile_has_symbols (struct objfile *objfile)
+bool
+objfile_has_symbols (objfile *objfile)
{
for (::objfile *o : objfile->separate_debug_objfiles ())
if (o->has_partial_symbols () || objfile_has_full_symbols (o))
- return 1;
- return 0;
-}
+ return true;
+ return false;
+}
-/* Many places in gdb want to test just to see if we have any partial
- symbols available. This function returns zero if none are currently
- available, nonzero otherwise. */
+/* See objfiles.h. */
-int
-have_partial_symbols (void)
+bool
+have_partial_symbols (program_space *pspace)
{
- for (objfile *ofp : current_program_space->objfiles ())
- {
- if (ofp->has_partial_symbols ())
- return 1;
- }
- return 0;
+ for (objfile *ofp : pspace->objfiles ())
+ if (ofp->has_partial_symbols ())
+ return true;
+
+ return false;
}
-/* Many places in gdb want to test just to see if we have any full
- symbols available. This function returns zero if none are currently
- available, nonzero otherwise. */
+/* See objfiles.h. */
-int
-have_full_symbols (void)
+bool
+have_full_symbols (program_space *pspace)
{
- for (objfile *ofp : current_program_space->objfiles ())
- {
- if (objfile_has_full_symbols (ofp))
- return 1;
- }
- return 0;
+ for (objfile *ofp : pspace->objfiles ())
+ if (objfile_has_full_symbols (ofp))
+ return true;
+
+ return false;
}
-/* This operations deletes all objfile entries that represent solibs that
- weren't explicitly loaded by the user, via e.g., the add-symbol-file
- command. */
+/* See objfiles.h. */
void
-objfile_purge_solibs (void)
+objfile_purge_solibs (program_space *pspace)
{
- for (objfile *objf : current_program_space->objfiles_safe ())
+ for (objfile *objf : pspace->objfiles_safe ())
{
/* We assume that the solib package has been purged already, or will
be soon. */
@@ -801,22 +794,16 @@ objfile_purge_solibs (void)
}
}
+/* See objfiles.h. */
-/* Many places in gdb want to test just to see if we have any minimal
- symbols available. This function returns zero if none are currently
- available, nonzero otherwise. */
-
-int
-have_minimal_symbols (void)
+bool
+have_minimal_symbols (program_space *pspace)
{
- for (objfile *ofp : current_program_space->objfiles ())
- {
- if (ofp->per_bfd->minimal_symbol_count > 0)
- {
- return 1;
- }
- }
- return 0;
+ for (objfile *ofp : pspace->objfiles ())
+ if (ofp->per_bfd->minimal_symbol_count > 0)
+ return true;
+
+ return false;
}
/* Qsort comparison function. */
@@ -1177,16 +1164,14 @@ pc_in_section (CORE_ADDR pc, const char *name)
&& s->the_bfd_section->name != nullptr
&& strcmp (s->the_bfd_section->name, name) == 0);
}
-
-/* Set section_map_dirty so section map will be rebuilt next time it
- is used. Called by reread_symbols. */
+/* See objfiles.h. */
void
-objfiles_changed (void)
+objfiles_changed (program_space *pspace)
{
/* Rebuild section map next time we need it. */
- get_objfile_pspace_data (current_program_space)->section_map_dirty = 1;
+ get_objfile_pspace_data (pspace)->section_map_dirty = 1;
}
/* See comments in objfiles.h. */
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index 88dfb33..d92570a 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -423,7 +423,8 @@ struct objfile
private:
/* The only way to create an objfile is to call objfile::make. */
- objfile (gdb_bfd_ref_ptr, const char *, objfile_flags);
+ objfile (gdb_bfd_ref_ptr, program_space *pspace, const char *,
+ objfile_flags);
public:
@@ -436,15 +437,19 @@ public:
~objfile ();
/* Create an objfile. */
- static objfile *make (gdb_bfd_ref_ptr bfd_, const char *name_,
- objfile_flags flags_, objfile *parent = nullptr);
+ static objfile *make (gdb_bfd_ref_ptr bfd_, program_space *pspace,
+ const char *name_, objfile_flags flags_,
+ objfile *parent = nullptr);
- /* Remove an objfile from the current program space, and free
+ /* Remove this objfile from its program space's objfile list, and frees
it. */
void unlink ();
DISABLE_COPY_AND_ASSIGN (objfile);
+ /* Return the program space associated with this objfile. */
+ program_space *pspace () { return m_pspace; }
+
/* A range adapter that makes it possible to iterate over all
compunits in one objfile. */
@@ -592,14 +597,15 @@ public:
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
block_search_flags search_flags,
- domain_search_flags domain);
+ domain_search_flags domain,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher
+ = nullptr);
/* See quick_symbol_functions. */
- struct compunit_symtab *find_pc_sect_compunit_symtab
- (struct bound_minimal_symbol msymbol,
- CORE_ADDR pc,
- struct obj_section *section,
- int warn_if_readin);
+ struct compunit_symtab *
+ find_pc_sect_compunit_symtab (bound_minimal_symbol msymbol, CORE_ADDR pc,
+ struct obj_section *section,
+ int warn_if_readin);
/* See quick_symbol_functions. */
void map_symbol_filenames (gdb::function_view<symbol_filename_ftype> fun,
@@ -716,10 +722,12 @@ public:
objfile_flags flags;
+private:
/* The program space associated with this objfile. */
- struct program_space *pspace;
+ program_space *m_pspace;
+public:
/* List of compunits.
These are used to do symbol lookups and file/line-number lookups. */
@@ -907,9 +915,15 @@ obj_section::set_offset (CORE_ADDR offset)
/* Declarations for functions defined in objfiles.c */
-extern int entry_point_address_query (CORE_ADDR *entry_p);
+/* If there is a valid and known entry point in PSPACE, fill *ENTRY_P with it
+ and return non-zero. */
-extern CORE_ADDR entry_point_address (void);
+extern int entry_point_address_query (program_space *pspace,
+ CORE_ADDR *entry_p);
+
+/* Get the entry point address in PSPACE. Call error if it is not known. */
+
+extern CORE_ADDR entry_point_address (program_space *pspace);
extern void build_objfile_section_table (struct objfile *);
@@ -918,18 +932,30 @@ 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);
-extern int objfile_has_full_symbols (struct objfile *objfile);
+/* Return true if OBJFILE has full symbols. */
+
+extern bool objfile_has_full_symbols (objfile *objfile);
-extern int objfile_has_symbols (struct objfile *objfile);
+/* Return true if OBJFILE has full or partial symbols, either directly
+ or through a separate debug file. */
-extern int have_partial_symbols (void);
+extern bool objfile_has_symbols (objfile *objfile);
-extern int have_full_symbols (void);
+/* Return true if any objfile of PSPACE has partial symbols. */
+
+extern bool have_partial_symbols (program_space *pspace);
+
+/* Return true if any objfile of PSPACE has full symbols. */
+
+extern bool have_full_symbols (program_space *pspace);
extern void objfile_set_sym_fns (struct objfile *objfile,
const struct sym_fns *sf);
-extern void objfiles_changed (void);
+/* Set section_map_dirty for PSPACE so the section map will be rebuilt next time
+ it is used. */
+
+extern void objfiles_changed (program_space *pspace);
/* Return true if ADDR maps into one of the sections of OBJFILE and false
otherwise. */
@@ -942,16 +968,18 @@ extern bool is_addr_in_objfile (CORE_ADDR addr, const struct objfile *objfile);
extern bool shared_objfile_contains_address_p (struct program_space *pspace,
CORE_ADDR address);
-/* This operation deletes all objfile entries that represent solibs that
- weren't explicitly loaded by the user, via e.g., the add-symbol-file
+/* This operation deletes all objfile entries in PSPACE that represent solibs
+ that weren't explicitly loaded by the user, via e.g., the add-symbol-file
command. */
-extern void objfile_purge_solibs (void);
+extern void objfile_purge_solibs (program_space *pspace);
/* Functions for dealing with the minimal symbol table, really a misc
address<->symbol mapping for things we don't have debug symbols for. */
-extern int have_minimal_symbols (void);
+/* Return true if any objfile of PSPACE has minimal symbols. */
+
+extern bool have_minimal_symbols (program_space *pspace);
extern struct obj_section *find_pc_section (CORE_ADDR pc);
diff --git a/gdb/obsd-tdep.c b/gdb/obsd-tdep.c
index 5142984..00de5c0 100644
--- a/gdb/obsd-tdep.c
+++ b/gdb/obsd-tdep.c
@@ -27,9 +27,8 @@
CORE_ADDR
obsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol("_dl_bind", NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, "_dl_bind");
if (msym.minsym && msym.value_address () == pc)
return frame_unwind_caller_pc (get_current_frame ());
else
diff --git a/gdb/osabi.c b/gdb/osabi.c
index d494d89..236d425 100644
--- a/gdb/osabi.c
+++ b/gdb/osabi.c
@@ -25,6 +25,7 @@
#include "gdb_bfd.h"
#include "elf-bfd.h"
+#include "inferior.h"
#ifndef GDB_OSABI_DEFAULT
#define GDB_OSABI_DEFAULT GDB_OSABI_UNKNOWN
@@ -41,94 +42,6 @@ static const char *gdb_osabi_available_names[GDB_OSABI_INVALID + 3] = {
};
static const char *set_osabi_string;
-/* Names associated with each osabi. */
-
-struct osabi_names
-{
- /* The "pretty" name. */
-
- const char *pretty;
-
- /* The triplet regexp, or NULL if not known. */
-
- const char *regexp;
-};
-
-/* This table matches the indices assigned to enum gdb_osabi. Keep
- them in sync. */
-static const struct osabi_names gdb_osabi_names[] =
-{
- { "unknown", NULL },
- { "none", NULL },
-
- { "SVR4", NULL },
- { "GNU/Hurd", NULL },
- { "Solaris", NULL },
- { "GNU/Linux", "linux(-gnu[^-]*)?" },
- { "FreeBSD", NULL },
- { "NetBSD", NULL },
- { "OpenBSD", NULL },
- { "WindowsCE", NULL },
- { "DJGPP", NULL },
- { "QNX-Neutrino", NULL },
- { "Cygwin", NULL },
- { "Windows", NULL },
- { "AIX", NULL },
- { "DICOS", NULL },
- { "Darwin", NULL },
- { "OpenVMS", NULL },
- { "LynxOS178", NULL },
- { "Newlib", NULL },
- { "SDE", NULL },
- { "PikeOS", NULL },
-
- { "<invalid>", NULL }
-};
-
-const char *
-gdbarch_osabi_name (enum gdb_osabi osabi)
-{
- if (osabi >= GDB_OSABI_UNKNOWN && osabi < GDB_OSABI_INVALID)
- return gdb_osabi_names[osabi].pretty;
-
- return gdb_osabi_names[GDB_OSABI_INVALID].pretty;
-}
-
-/* See osabi.h. */
-
-const char *
-osabi_triplet_regexp (enum gdb_osabi osabi)
-{
- if (osabi >= GDB_OSABI_UNKNOWN && osabi < GDB_OSABI_INVALID)
- return gdb_osabi_names[osabi].regexp;
-
- return gdb_osabi_names[GDB_OSABI_INVALID].regexp;
-}
-
-/* Lookup the OS ABI corresponding to the specified target description
- string. */
-
-enum gdb_osabi
-osabi_from_tdesc_string (const char *name)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE (gdb_osabi_names); i++)
- if (strcmp (name, gdb_osabi_names[i].pretty) == 0)
- {
- /* See note above: the name table matches the indices assigned
- to enum gdb_osabi. */
- enum gdb_osabi osabi = (enum gdb_osabi) i;
-
- if (osabi == GDB_OSABI_INVALID)
- return GDB_OSABI_UNKNOWN;
- else
- return osabi;
- }
-
- return GDB_OSABI_UNKNOWN;
-}
-
/* Handler for a given architecture/OS ABI pair. There should be only
one handler for a given OS ABI each architecture family. */
struct gdb_osabi_handler
@@ -611,6 +524,35 @@ generic_elf_osabi_sniffer (bfd *abfd)
return osabi;
}
+
+/* See osabi.h. */
+
+const char *
+gdbarch_osabi_enum_name (enum gdb_osabi osabi)
+{
+ switch (osabi)
+ {
+#define GDB_OSABI_DEF_FIRST(Enum, Name, Regex) \
+ case GDB_OSABI_ ## Enum: \
+ return "GDB_OSABI_" #Enum;
+
+#define GDB_OSABI_DEF(Enum, Name, Regex) \
+ case GDB_OSABI_ ## Enum: \
+ return "GDB_OSABI_" #Enum;
+
+#define GDB_OSABI_DEF_LAST(Enum, Name, Regex) \
+ case GDB_OSABI_ ## Enum: \
+ return "GDB_OSABI_" #Enum;
+
+#include "gdbsupport/osabi.def"
+
+#undef GDB_OSABI_DEF_LAST
+#undef GDB_OSABI_DEF
+#undef GDB_OSABI_DEF_FIRST
+ }
+
+ gdb_assert_not_reached ();
+}
static void
set_osabi (const char *args, int from_tty, struct cmd_list_element *c)
@@ -645,7 +587,7 @@ set_osabi (const char *args, int from_tty, struct cmd_list_element *c)
/* NOTE: At some point (true multiple architectures) we'll need to be more
graceful here. */
gdbarch_info info;
- if (! gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("Updating OS ABI failed."));
}
@@ -671,10 +613,6 @@ void _initialize_gdb_osabi ();
void
_initialize_gdb_osabi ()
{
- if (strcmp (gdb_osabi_names[GDB_OSABI_INVALID].pretty, "<invalid>") != 0)
- internal_error
- (_("_initialize_gdb_osabi: gdb_osabi_names[] is inconsistent"));
-
/* Register a generic sniffer for ELF flavoured files. */
gdbarch_register_osabi_sniffer (bfd_arch_unknown,
bfd_target_elf_flavour,
diff --git a/gdb/osabi.h b/gdb/osabi.h
index c1a85d1..2d828d5 100644
--- a/gdb/osabi.h
+++ b/gdb/osabi.h
@@ -19,36 +19,7 @@
#ifndef OSABI_H
#define OSABI_H
-/* * List of known OS ABIs. If you change this, make sure to update the
- table in osabi.c. */
-enum gdb_osabi
-{
- GDB_OSABI_UNKNOWN = 0, /* keep this zero */
- GDB_OSABI_NONE,
-
- GDB_OSABI_SVR4,
- GDB_OSABI_HURD,
- GDB_OSABI_SOLARIS,
- GDB_OSABI_LINUX,
- GDB_OSABI_FREEBSD,
- GDB_OSABI_NETBSD,
- GDB_OSABI_OPENBSD,
- GDB_OSABI_WINCE,
- GDB_OSABI_GO32,
- GDB_OSABI_QNXNTO,
- GDB_OSABI_CYGWIN,
- GDB_OSABI_WINDOWS,
- GDB_OSABI_AIX,
- GDB_OSABI_DICOS,
- GDB_OSABI_DARWIN,
- GDB_OSABI_OPENVMS,
- GDB_OSABI_LYNXOS178,
- GDB_OSABI_NEWLIB,
- GDB_OSABI_SDE,
- GDB_OSABI_PIKEOS,
-
- GDB_OSABI_INVALID /* keep this last */
-};
+#include "gdbsupport/osabi.h"
/* Register an OS ABI sniffer. Each arch/flavour may have more than
one sniffer. This is used to e.g. differentiate one OS's a.out from
@@ -70,26 +41,19 @@ void gdbarch_register_osabi (enum bfd_architecture, unsigned long,
/* Lookup the OS ABI corresponding to the specified BFD. */
enum gdb_osabi gdbarch_lookup_osabi (bfd *);
-/* Lookup the OS ABI corresponding to the specified target description
- string. */
-enum gdb_osabi osabi_from_tdesc_string (const char *text);
-
/* Return true if there's an OS ABI handler for INFO. */
bool has_gdb_osabi_handler (struct gdbarch_info info);
/* Initialize the gdbarch for the specified OS ABI variant. */
void gdbarch_init_osabi (struct gdbarch_info, struct gdbarch *);
-/* Return the name of the specified OS ABI. */
-const char *gdbarch_osabi_name (enum gdb_osabi);
-
-/* Return a regular expression that matches the OS part of a GNU
- configury triplet for the given OSABI. */
-const char *osabi_triplet_regexp (enum gdb_osabi osabi);
-
/* Helper routine for ELF file sniffers. This looks at ABI tag note
sections to determine the OS ABI from the note. */
void generic_elf_osabi_sniff_abi_tag_sections (bfd *, asection *,
enum gdb_osabi *);
+/* Return a string version of OSABI. This is used when generating code
+ which calls set_tdesc_osabi and an 'enum gdb_osabi' value is needed. */
+const char *gdbarch_osabi_enum_name (enum gdb_osabi osabi);
+
#endif /* OSABI_H */
diff --git a/gdb/p-exp.y b/gdb/p-exp.y
index f334db6..938d3cf 100644
--- a/gdb/p-exp.y
+++ b/gdb/p-exp.y
@@ -614,7 +614,7 @@ block : BLOCKNAME
{
std::string copy = copy_name ($1.stoken);
struct symtab *tem =
- lookup_symtab (copy.c_str ());
+ lookup_symtab (current_program_space, copy.c_str ());
if (tem)
$$ = (tem->compunit ()->blockvector ()
->static_block ());
@@ -717,16 +717,15 @@ variable: name_not_typename
}
else
{
- struct bound_minimal_symbol msymbol;
std::string arg = copy_name ($1.stoken);
- msymbol =
- lookup_bound_minimal_symbol (arg.c_str ());
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space, arg.c_str ());
if (msymbol.minsym != NULL)
pstate->push_new<var_msym_value_operation>
(msymbol);
- else if (!have_full_symbols ()
- && !have_partial_symbols ())
+ else if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space))
error (_("No symbol table is loaded. "
"Use the \"file\" command."));
else
@@ -1521,7 +1520,7 @@ yylex (void)
no psymtabs (coff, xcoff, or some future change to blow away the
psymtabs once once symbols are read). */
if ((sym && sym->aclass () == LOC_BLOCK)
- || lookup_symtab (tmp.c_str ()))
+ || lookup_symtab (current_program_space, tmp.c_str ()))
{
yylval.ssym.sym.symbol = sym;
yylval.ssym.sym.block = NULL;
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index d3d491c..4c5d4dd 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -59,22 +59,23 @@ static const char GPC_MAIN_PROGRAM_NAME_2[] = "pascal_main_program";
const char *
pascal_main_name (void)
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol (GPC_P_INITIALIZE, NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, GPC_P_INITIALIZE);
/* If '_p_initialize' was not found, the main program is likely not
written in Pascal. */
if (msym.minsym == NULL)
return NULL;
- msym = lookup_minimal_symbol (GPC_MAIN_PROGRAM_NAME_1, NULL, NULL);
+ msym
+ = lookup_minimal_symbol (current_program_space, GPC_MAIN_PROGRAM_NAME_1);
if (msym.minsym != NULL)
{
return GPC_MAIN_PROGRAM_NAME_1;
}
- msym = lookup_minimal_symbol (GPC_MAIN_PROGRAM_NAME_2, NULL, NULL);
+ msym
+ = lookup_minimal_symbol (current_program_space, GPC_MAIN_PROGRAM_NAME_2);
if (msym.minsym != NULL)
{
return GPC_MAIN_PROGRAM_NAME_2;
diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c
index bdb9524..aa7f1a9 100644
--- a/gdb/p-valprint.c
+++ b/gdb/p-valprint.c
@@ -225,8 +225,8 @@ pascal_language::value_print_inner (struct value *val,
{
/* Print vtbl's nicely. */
CORE_ADDR vt_address = unpack_pointer (type, valaddr);
- struct bound_minimal_symbol msymbol =
- lookup_minimal_symbol_by_pc (vt_address);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol_by_pc (vt_address);
/* If 'symbol_print' is set, we did the work above. */
if (!options->symbol_print
diff --git a/gdb/parse.c b/gdb/parse.c
index 0a2b2a5..e0837de 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -145,10 +145,12 @@ parser_state::push_symbol (const char *name, block_symbol sym)
}
else
{
- struct bound_minimal_symbol msymbol = lookup_bound_minimal_symbol (name);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space, name);
if (msymbol.minsym != NULL)
push_new<expr::var_msym_value_operation> (msymbol);
- else if (!have_full_symbols () && !have_partial_symbols ())
+ else if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space))
error (_("No symbol table is loaded. Use the \"file\" command."));
else
error (_("No symbol \"%s\" in current context."), name);
@@ -161,7 +163,6 @@ void
parser_state::push_dollar (struct stoken str)
{
struct block_symbol sym;
- struct bound_minimal_symbol msym;
struct internalvar *isym = NULL;
std::string copy;
@@ -231,7 +232,8 @@ parser_state::push_dollar (struct stoken str)
push_new<expr::var_value_operation> (sym);
return;
}
- msym = lookup_bound_minimal_symbol (copy.c_str ());
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, copy.c_str ());
if (msym.minsym)
{
push_new<expr::var_msym_value_operation> (msym);
@@ -374,8 +376,8 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
if (!expression_context_block)
{
- struct symtab_and_line cursal
- = get_current_source_symtab_and_line ();
+ symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
if (cursal.symtab)
expression_context_block
@@ -421,8 +423,7 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
expression_context_pc, flags, *stringptr,
completer != nullptr, tracker);
- scoped_restore_current_language lang_saver;
- set_language (lang->la_language);
+ scoped_restore_current_language lang_saver (lang->la_language);
try
{
@@ -488,10 +489,7 @@ parse_expression_with_language (const char *string, enum language lang)
{
std::optional<scoped_restore_current_language> lang_saver;
if (current_language->la_language != lang)
- {
- lang_saver.emplace ();
- set_language (lang);
- }
+ lang_saver.emplace (lang);
return parse_expression (string);
}
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index e100045..8a5eea7 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -133,7 +133,7 @@ static solib_ops powerpc_so_ops;
(gdb) b main
Breakpoint 2 at 0x100006a0: file gdb.base/shmain.c, line 44.
- Examine the instruction (and the immediatly following instruction)
+ Examine the instruction (and the immediately following instruction)
upon which the breakpoint was placed. Note that the PLT entry
for shr1 contains zeros.
@@ -313,15 +313,13 @@ static const struct ppc_insn_pattern powerpc32_plt_stub_so_2[] =
static int
powerpc_linux_in_dynsym_resolve_code (CORE_ADDR pc)
{
- struct bound_minimal_symbol sym;
-
/* 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;
/* Check if we are in the resolver. */
- sym = lookup_minimal_symbol_by_pc (pc);
+ 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))
@@ -1670,10 +1668,9 @@ ppc_elfv2_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym)
static CORE_ADDR
ppc_elfv2_skip_entrypoint (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- struct bound_minimal_symbol fun;
int local_entry_offset = 0;
- fun = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol fun = lookup_minimal_symbol_by_pc (pc);
if (fun.minsym == NULL)
return pc;
diff --git a/gdb/ppc-netbsd-tdep.c b/gdb/ppc-netbsd-tdep.c
index d8e4c42..b412030 100644
--- a/gdb/ppc-netbsd-tdep.c
+++ b/gdb/ppc-netbsd-tdep.c
@@ -28,7 +28,6 @@
#include "ppc-tdep.h"
#include "netbsd-tdep.h"
-#include "ppc-tdep.h"
#include "solib-svr4.h"
/* Register offsets from <machine/reg.h>. */
diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c
index 47e6292..f317c94 100644
--- a/gdb/ppc-sysv-tdep.c
+++ b/gdb/ppc-sysv-tdep.c
@@ -1044,12 +1044,10 @@ static int
convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
{
struct obj_section *dot_fn_section;
- struct bound_minimal_symbol dot_fn;
- struct bound_minimal_symbol fn;
/* Find the minimal symbol that corresponds to CODE_ADDR (should
have a name of the form ".FN"). */
- dot_fn = lookup_minimal_symbol_by_pc (code_addr);
+ bound_minimal_symbol dot_fn = lookup_minimal_symbol_by_pc (code_addr);
if (dot_fn.minsym == NULL || dot_fn.minsym->linkage_name ()[0] != '.')
return 0;
/* Get the section that contains CODE_ADDR. Need this for the
@@ -1061,8 +1059,10 @@ convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
address. Only look for the minimal symbol in ".FN"'s object file
- avoids problems when two object files (i.e., shared libraries)
contain a minimal symbol with the same name. */
- fn = lookup_minimal_symbol (dot_fn.minsym->linkage_name () + 1, NULL,
- dot_fn_section->objfile);
+ bound_minimal_symbol fn
+ = lookup_minimal_symbol (current_program_space,
+ dot_fn.minsym->linkage_name () + 1,
+ dot_fn_section->objfile);
if (fn.minsym == NULL)
return 0;
/* Found a descriptor. */
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 1d6a492..f1aaa64 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -606,7 +606,6 @@ build_address_symbolic (struct gdbarch *gdbarch,
int *line, /* OUT */
int *unmapped) /* OUT */
{
- struct bound_minimal_symbol msymbol;
struct symbol *symbol;
CORE_ADDR name_location = 0;
struct obj_section *section = NULL;
@@ -638,7 +637,8 @@ build_address_symbolic (struct gdbarch *gdbarch,
save some memory, but for many debug format--ELF/DWARF or
anything/stabs--it would be inconvenient to eliminate those minimal
symbols anyway). */
- msymbol = lookup_minimal_symbol_by_pc_section (addr, section);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol_by_pc_section (addr, section);
symbol = find_pc_sect_function (addr, section);
if (symbol)
@@ -1575,7 +1575,6 @@ info_address_command (const char *exp, int from_tty)
struct gdbarch *gdbarch;
int regno;
struct symbol *sym;
- struct bound_minimal_symbol msymbol;
long val;
struct obj_section *section;
CORE_ADDR load_addr, context_pc = 0;
@@ -1601,7 +1600,8 @@ info_address_command (const char *exp, int from_tty)
return;
}
- msymbol = lookup_bound_minimal_symbol (exp);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space, exp);
if (msymbol.minsym != NULL)
{
@@ -1753,9 +1753,9 @@ info_address_command (const char *exp, int from_tty)
case LOC_UNRESOLVED:
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_bound_minimal_symbol (sym->linkage_name ());
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space,
+ sym->linkage_name ());
if (msym.minsym == NULL)
gdb_printf ("unresolved");
else
@@ -2294,11 +2294,11 @@ disable_display_command (const char *args, int from_tty)
static void
clear_dangling_display_expressions (struct objfile *objfile)
{
- program_space *pspace = objfile->pspace;
+ program_space *pspace = objfile->pspace ();
if (objfile->separate_debug_objfile_backlink)
{
objfile = objfile->separate_debug_objfile_backlink;
- gdb_assert (objfile->pspace == pspace);
+ gdb_assert (objfile->pspace () == pspace);
}
for (auto &d : all_displays)
diff --git a/gdb/proc-service.c b/gdb/proc-service.c
index 1889a00..ce2d69a 100644
--- a/gdb/proc-service.c
+++ b/gdb/proc-service.c
@@ -99,7 +99,8 @@ ps_pglobal_lookup (struct ps_prochandle *ph, const char *obj,
set_current_program_space (inf->pspace);
/* FIXME: kettenis/2000-09-03: What should we do with OBJ? */
- bound_minimal_symbol ms = lookup_minimal_symbol (name, NULL, NULL);
+ bound_minimal_symbol ms
+ = lookup_minimal_symbol (current_program_space, name);
if (ms.minsym == NULL)
return PS_NOSYM;
diff --git a/gdb/procfs.c b/gdb/procfs.c
index a9a26c6..c6abe3e 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -205,7 +205,7 @@ procfs_target::auxv_parse (const gdb_byte **readptr,
concerning a /proc process. There should be exactly one procinfo
for each process, and since GDB currently can debug only one
process at a time, that means there should be only one procinfo.
- All of the LWP's of a process can be accessed indirectly thru the
+ All of the LWP's of a process can be accessed indirectly through the
single process procinfo.
However, against the day when GDB may debug more than one process,
diff --git a/gdb/progspace.c b/gdb/progspace.c
index d5b5ef2..28198c1 100644
--- a/gdb/progspace.c
+++ b/gdb/progspace.c
@@ -115,7 +115,7 @@ program_space::~program_space ()
set_current_program_space (this);
breakpoint_program_space_exit (this);
- no_shared_libraries (NULL, 0);
+ no_shared_libraries (this);
free_all_objfiles ();
/* Defer breakpoint re-set because we don't want to create new
locations for this pspace which we're tearing down. */
@@ -128,7 +128,7 @@ void
program_space::free_all_objfiles ()
{
/* Any objfile reference would become stale. */
- for (const solib &so : current_program_space->solibs ())
+ for (const solib &so : this->solibs ())
gdb_assert (so.objfile == NULL);
while (!objfiles_list.empty ())
diff --git a/gdb/progspace.h b/gdb/progspace.h
index 82c0a74..999e7a3 100644
--- a/gdb/progspace.h
+++ b/gdb/progspace.h
@@ -289,7 +289,7 @@ struct program_space
struct objfile *objfile_for_address (CORE_ADDR address);
/* Return the list of all the solibs in this program space. */
- intrusive_list<solib> &solibs ()
+ owning_intrusive_list<solib> &solibs ()
{ return so_list; }
/* Similar to `bfd_get_filename (exec_bfd ())` but in original form given
@@ -399,7 +399,7 @@ struct program_space
/* List of shared objects mapped into this space. Managed by
solib.c. */
- intrusive_list<solib> so_list;
+ owning_intrusive_list<solib> so_list;
/* Number of calls to solib_add. */
unsigned int solib_add_generation = 0;
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index 7d6648c..f8c83d9 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -87,7 +87,7 @@ static struct partial_symtab *
find_pc_sect_psymtab_closer (struct objfile *objfile,
CORE_ADDR pc, struct obj_section *section,
struct partial_symtab *pst,
- struct bound_minimal_symbol msymbol)
+ bound_minimal_symbol msymbol)
{
struct partial_symtab *tpst;
struct partial_symtab *best_pst = pst;
@@ -161,7 +161,7 @@ struct partial_symtab *
psymbol_functions::find_pc_sect_psymtab (struct objfile *objfile,
CORE_ADDR pc,
struct obj_section *section,
- struct bound_minimal_symbol msymbol)
+ bound_minimal_symbol msymbol)
{
for (partial_symtab *pst : partial_symbols (objfile))
if (pc >= pst->text_low (objfile) && pc < pst->text_high (objfile))
@@ -181,12 +181,11 @@ psymbol_functions::find_pc_sect_psymtab (struct objfile *objfile,
the definition of quick_symbol_functions in symfile.h. */
struct compunit_symtab *
-psymbol_functions::find_pc_sect_compunit_symtab
- (struct objfile *objfile,
- struct bound_minimal_symbol msymbol,
- CORE_ADDR pc,
- struct obj_section *section,
- int warn_if_readin)
+psymbol_functions::find_pc_sect_compunit_symtab (struct objfile *objfile,
+ bound_minimal_symbol msymbol,
+ CORE_ADDR pc,
+ struct obj_section *section,
+ int warn_if_readin)
{
struct partial_symtab *ps = find_pc_sect_psymtab (objfile,
pc, section,
@@ -894,7 +893,9 @@ psymbol_functions::expand_symtabs_matching
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
block_search_flags search_flags,
- domain_search_flags domain)
+ domain_search_flags domain,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype>
+ lang_matcher ATTRIBUTE_UNUSED)
{
/* Clear the search flags. */
for (partial_symtab *ps : partial_symbols (objfile))
@@ -1083,7 +1084,7 @@ void
partial_symtab::add_psymbol (std::string_view name, bool copy_name,
domain_enum domain,
enum address_class theclass,
- short section,
+ int section,
psymbol_placement where,
unrelocated_addr coreaddr,
enum language language,
@@ -1281,7 +1282,7 @@ maintenance_print_psymbols (const char *args, int from_tty)
if (address_arg != NULL)
{
- struct bound_minimal_symbol msymbol;
+ bound_minimal_symbol msymbol;
/* We don't assume each pc has a unique objfile (this is for
debugging). */
diff --git a/gdb/psymtab.h b/gdb/psymtab.h
index f41f241..b23aadb 100644
--- a/gdb/psymtab.h
+++ b/gdb/psymtab.h
@@ -349,7 +349,7 @@ struct partial_symtab
void add_psymbol (std::string_view name,
bool copy_name, domain_enum domain,
enum address_class theclass,
- short section,
+ int section,
psymbol_placement where,
unrelocated_addr coreaddr,
enum language language,
@@ -633,11 +633,13 @@ struct psymbol_functions : public quick_symbol_functions
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
block_search_flags search_flags,
- domain_search_flags kind) override;
+ domain_search_flags kind,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher)
+ override;
struct compunit_symtab *find_pc_sect_compunit_symtab
- (struct objfile *objfile, struct bound_minimal_symbol msymbol,
- CORE_ADDR pc, struct obj_section *section, int warn_if_readin) override;
+ (struct objfile *objfile, bound_minimal_symbol msymbol, CORE_ADDR pc,
+ struct obj_section *section, int warn_if_readin) override;
struct compunit_symtab *find_compunit_symtab_by_address
(struct objfile *objfile, CORE_ADDR address) override
@@ -672,11 +674,10 @@ struct psymbol_functions : public quick_symbol_functions
exactly matches PC, or, if we cannot find an exact match, the
psymtab that contains a symbol whose address is closest to PC. */
- struct partial_symtab *find_pc_sect_psymtab
- (struct objfile *objfile,
- CORE_ADDR pc,
- struct obj_section *section,
- struct bound_minimal_symbol msymbol);
+ struct partial_symtab *find_pc_sect_psymtab (struct objfile *objfile,
+ CORE_ADDR pc,
+ struct obj_section *section,
+ bound_minimal_symbol msymbol);
private:
diff --git a/gdb/python/lib/gdb/dap/__init__.py b/gdb/python/lib/gdb/dap/__init__.py
index 51b9546..145aeb6 100644
--- a/gdb/python/lib/gdb/dap/__init__.py
+++ b/gdb/python/lib/gdb/dap/__init__.py
@@ -92,5 +92,8 @@ def pre_command_loop():
# session.
session_started = True
startup.thread_log("starting DAP server")
+ # These are handy for bug reports.
+ startup.exec_and_log("show version")
+ startup.exec_and_log("show configuration")
global server
startup.start_dap(server.main_loop)
diff --git a/gdb/python/lib/gdb/dap/breakpoint.py b/gdb/python/lib/gdb/dap/breakpoint.py
index e60265b..15055f2 100644
--- a/gdb/python/lib/gdb/dap/breakpoint.py
+++ b/gdb/python/lib/gdb/dap/breakpoint.py
@@ -23,7 +23,14 @@ import gdb
from .server import capability, request, send_event
from .sources import make_source
-from .startup import DAPException, LogLevel, in_gdb_thread, log_stack, parse_and_eval
+from .startup import (
+ DAPException,
+ LogLevel,
+ exec_mi_and_log,
+ in_gdb_thread,
+ log_stack,
+ parse_and_eval,
+)
from .typecheck import type_check
# True when suppressing new breakpoint events.
@@ -97,11 +104,16 @@ breakpoint_map = {}
@in_gdb_thread
def _breakpoint_descriptor(bp):
"Return the Breakpoint object descriptor given a gdb Breakpoint."
+ # If there are no objfiles (that is, before the launch request),
+ # we consider all breakpoints to be pending. This is done to work
+ # around the gdb oddity that setting a breakpoint by address will
+ # always succeed.
+ pending = bp.pending or len(gdb.objfiles()) == 0
result = {
"id": bp.number,
- "verified": not bp.pending,
+ "verified": not pending,
}
- if bp.pending:
+ if pending:
result["reason"] = "pending"
if bp.locations:
# Just choose the first location, because DAP doesn't allow
@@ -196,9 +208,9 @@ def _set_breakpoints_callback(kind, specs, creator):
}
)
- # Delete any breakpoints that were not reused.
- for entry in saved_map.values():
- entry.delete()
+ # Delete any breakpoints that were not reused.
+ for entry in saved_map.values():
+ entry.delete()
return result
@@ -368,10 +380,13 @@ def _catch_exception(filterId, **args):
cmd = "-catch-" + filterId
else:
raise DAPException("Invalid exception filterID: " + str(filterId))
- result = gdb.execute_mi(cmd)
+ result = exec_mi_and_log(cmd)
+ # While the Ada catchpoints emit a "bkptno" field here, the C++
+ # ones do not. So, instead we look at the "number" field.
+ num = result["bkpt"]["number"]
# A little lame that there's no more direct way.
for bp in gdb.breakpoints():
- if bp.number == result["bkptno"]:
+ if bp.number == num:
return bp
# Not a DAPException because this is definitely unexpected.
raise Exception("Could not find catchpoint after creating")
diff --git a/gdb/python/lib/gdb/dap/globalvars.py b/gdb/python/lib/gdb/dap/globalvars.py
index 149c9a8..38bdc5c 100644
--- a/gdb/python/lib/gdb/dap/globalvars.py
+++ b/gdb/python/lib/gdb/dap/globalvars.py
@@ -60,7 +60,8 @@ class _Globals(BaseReference):
@in_gdb_thread
def fetch_one_child(self, idx):
- return self.var_list[idx].value()
+ sym = self.var_list[idx]
+ return (sym.name, sym.value())
@in_gdb_thread
diff --git a/gdb/python/lib/gdb/dap/launch.py b/gdb/python/lib/gdb/dap/launch.py
index 2674e02..65444bf 100644
--- a/gdb/python/lib/gdb/dap/launch.py
+++ b/gdb/python/lib/gdb/dap/launch.py
@@ -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/>.
+import re
+
# These are deprecated in 3.9, but required in older versions.
from typing import Mapping, Optional, Sequence
@@ -20,7 +22,16 @@ import gdb
from .events import exec_and_expect_stop, expect_process, expect_stop
from .server import capability, request
-from .startup import DAPException, exec_and_log
+from .startup import DAPException, exec_and_log, in_gdb_thread
+
+
+# A wrapper for the 'file' command that correctly quotes its argument.
+@in_gdb_thread
+def file_command(program):
+ # Handle whitespace, quotes, and backslashes here. Exactly what
+ # to quote depends on libiberty's buildargv and safe-ctype.
+ program = re.sub("[ \t\n\r\f\v\\\\'\"]", "\\\\\\g<0>", program)
+ exec_and_log("file " + program)
# Any parameters here are necessarily extensions -- DAP requires this
@@ -34,12 +45,13 @@ def launch(
args: Sequence[str] = (),
env: Optional[Mapping[str, str]] = None,
stopAtBeginningOfMainSubprogram: bool = False,
+ stopOnEntry: bool = False,
**extra,
):
if cwd is not None:
exec_and_log("cd " + cwd)
if program is not None:
- exec_and_log("file " + program)
+ file_command(program)
inf = gdb.selected_inferior()
if stopAtBeginningOfMainSubprogram:
main = inf.main_name
@@ -51,7 +63,7 @@ def launch(
for name, value in env.items():
inf.set_env(name, value)
expect_process("process")
- exec_and_expect_stop("run")
+ exec_and_expect_stop("starti" if stopOnEntry else "run")
@request("attach")
@@ -63,7 +75,7 @@ def attach(
**args,
):
if program is not None:
- exec_and_log("file " + program)
+ file_command(program)
if pid is not None:
cmd = "attach " + str(pid)
elif target is not None:
diff --git a/gdb/python/lib/gdb/dap/locations.py b/gdb/python/lib/gdb/dap/locations.py
index 92e68f5..967322f 100644
--- a/gdb/python/lib/gdb/dap/locations.py
+++ b/gdb/python/lib/gdb/dap/locations.py
@@ -16,10 +16,9 @@
# This is deprecated in 3.9, but required in older versions.
from typing import Optional
-import gdb
-
from .server import capability, request
from .sources import decode_source
+from .startup import exec_mi_and_log
# Note that the spec says that the arguments to this are optional.
@@ -36,7 +35,7 @@ def breakpoint_locations(*, source, line: int, endLine: Optional[int] = None, **
endLine = line
filename = decode_source(source)
lines = set()
- for entry in gdb.execute_mi("-symbol-list-lines", filename)["lines"]:
+ for entry in exec_mi_and_log("-symbol-list-lines", filename)["lines"]:
this_line = entry["line"]
if this_line >= line and this_line <= endLine:
lines.add(this_line)
diff --git a/gdb/python/lib/gdb/dap/scopes.py b/gdb/python/lib/gdb/dap/scopes.py
index d0e9115..fb90f64 100644
--- a/gdb/python/lib/gdb/dap/scopes.py
+++ b/gdb/python/lib/gdb/dap/scopes.py
@@ -111,20 +111,19 @@ class _ScopeReference(BaseReference):
return symbol_value(self.var_list[idx], self.frame)
-# A _ScopeReference that prepends the most recent return value. Note
-# that this object is only created if such a value actually exists.
+# A _ScopeReference that wraps the 'finish' value. Note that this
+# object is only created if such a value actually exists.
class _FinishScopeReference(_ScopeReference):
- def __init__(self, *args):
- super().__init__(*args)
+ def __init__(self, frame):
+ super().__init__("Return", "returnValue", frame, ())
def child_count(self):
- return super().child_count() + 1
+ return 1
def fetch_one_child(self, idx):
- if idx == 0:
- global _last_return_value
- return ("(return)", _last_return_value)
- return super().fetch_one_child(idx - 1)
+ assert idx == 0
+ global _last_return_value
+ return ("(return)", _last_return_value)
class _RegisterReference(_ScopeReference):
@@ -159,11 +158,11 @@ def scopes(*, frameId: int, **extra):
# Make sure to handle the None case as well as the empty
# iterator case.
locs = tuple(frame.frame_locals() or ())
- if has_return_value:
- scopes.append(_FinishScopeReference("Locals", "locals", frame, locs))
- elif locs:
+ if locs:
scopes.append(_ScopeReference("Locals", "locals", frame, locs))
scopes.append(_RegisterReference("Registers", frame))
+ if has_return_value:
+ scopes.append(_FinishScopeReference(frame))
frame_to_scope[frameId] = scopes
global_scope = get_global_scope(frame)
if global_scope is not None:
diff --git a/gdb/python/lib/gdb/dap/sources.py b/gdb/python/lib/gdb/dap/sources.py
index ad0c913..a9f4ea6 100644
--- a/gdb/python/lib/gdb/dap/sources.py
+++ b/gdb/python/lib/gdb/dap/sources.py
@@ -15,10 +15,8 @@
import os
-import gdb
-
from .server import capability, request
-from .startup import DAPException, in_gdb_thread
+from .startup import DAPException, exec_mi_and_log, in_gdb_thread
# The next available source reference ID. Must be greater than 0.
_next_source = 1
@@ -83,7 +81,7 @@ def decode_source(source):
@capability("supportsLoadedSourcesRequest")
def loaded_sources(**extra):
result = []
- for elt in gdb.execute_mi("-file-list-exec-source-files")["files"]:
+ for elt in exec_mi_and_log("-file-list-exec-source-files")["files"]:
result.append(make_source(elt["fullname"], elt["file"]))
return {
"sources": result,
diff --git a/gdb/python/lib/gdb/dap/startup.py b/gdb/python/lib/gdb/dap/startup.py
index 3952447..a3f048b 100644
--- a/gdb/python/lib/gdb/dap/startup.py
+++ b/gdb/python/lib/gdb/dap/startup.py
@@ -217,3 +217,10 @@ def exec_and_log(cmd, propagate_exception=False):
raise DAPException(str(e)) from e
else:
log_stack()
+
+
+@in_gdb_thread
+def exec_mi_and_log(*args):
+ """Wrap gdb.execute_mi, logging the command."""
+ log("+++ " + str(args))
+ return gdb.execute_mi(*args)
diff --git a/gdb/python/lib/gdb/dap/varref.py b/gdb/python/lib/gdb/dap/varref.py
index 57e84a1..0dd9879 100644
--- a/gdb/python/lib/gdb/dap/varref.py
+++ b/gdb/python/lib/gdb/dap/varref.py
@@ -18,6 +18,7 @@ from collections import defaultdict
from contextlib import contextmanager
import gdb
+import gdb.printing
from .server import client_bool_capability
from .startup import DAPException, in_gdb_thread
diff --git a/gdb/python/lib/gdb/disassembler.py b/gdb/python/lib/gdb/disassembler.py
index 72d311b..7d0e781 100644
--- a/gdb/python/lib/gdb/disassembler.py
+++ b/gdb/python/lib/gdb/disassembler.py
@@ -147,7 +147,7 @@ class maint_info_py_disassemblers_cmd(gdb.Command):
# Figure out the name of the current architecture. There
# should always be a current inferior, but if, somehow, there
# isn't, then leave curr_arch as the empty string, which will
- # not then match agaisnt any architecture in the dictionary.
+ # not then match against any architecture in the dictionary.
curr_arch = ""
if gdb.selected_inferior() is not None:
curr_arch = gdb.selected_inferior().architecture().name()
diff --git a/gdb/python/lib/gdb/missing_debug.py b/gdb/python/lib/gdb/missing_debug.py
index 6d57462..7ccc4fe 100644
--- a/gdb/python/lib/gdb/missing_debug.py
+++ b/gdb/python/lib/gdb/missing_debug.py
@@ -31,9 +31,33 @@ if sys.version_info >= (3, 7):
return ch.isalnum()
else:
- # Fall back to curses.ascii.isascii() and curses.ascii.isalnum() for
- # earlier versions.
- from curses.ascii import isalnum, isascii
+ # Older version of Python doesn't have str.isascii() and
+ # str.isalnum() so provide our own.
+ #
+ # We could import isalnum() and isascii() from the curses library,
+ # but that adds an extra dependency. Given these functions are
+ # both small and trivial lets implement them here.
+ #
+ # These definitions are based on those in the curses library, but
+ # simplified as we know C will always be a single character 'str'.
+
+ def isdigit(c):
+ return 48 <= ord(c) <= 57
+
+ def islower(c):
+ return 97 <= ord(c) <= 122
+
+ def isupper(c):
+ return 65 <= ord(c) <= 90
+
+ def isalpha(c):
+ return isupper(c) or islower(c)
+
+ def isalnum(c):
+ return isalpha(c) or isdigit(c)
+
+ def isascii(c):
+ return 0 <= ord(c) <= 127
def _validate_name(name):
diff --git a/gdb/python/lib/gdb/printer/bound_registers.py b/gdb/python/lib/gdb/printer/bound_registers.py
deleted file mode 100644
index d00b455..0000000
--- a/gdb/python/lib/gdb/printer/bound_registers.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Pretty-printers for bounds registers.
-# Copyright (C) 2013-2024 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import gdb
-import gdb.printing
-
-
-class MpxBound128Printer(gdb.ValuePrinter):
- """Adds size field to a mpx __gdb_builtin_type_bound128 type."""
-
- def __init__(self, val):
- self.__val = val
-
- def to_string(self):
- upper = self.__val["ubound"]
- lower = self.__val["lbound"]
- size = upper - lower
- if size > -1:
- size = size + 1
- result = "{lbound = %s, ubound = %s} : size %s" % (lower, upper, size)
- return result
-
-
-gdb.printing.add_builtin_pretty_printer(
- "mpx_bound128", "^builtin_type_bound128", MpxBound128Printer
-)
diff --git a/gdb/python/lib/gdb/ptwrite.py b/gdb/python/lib/gdb/ptwrite.py
new file mode 100644
index 0000000..3be65fe
--- /dev/null
+++ b/gdb/python/lib/gdb/ptwrite.py
@@ -0,0 +1,77 @@
+# Ptwrite utilities.
+# Copyright (C) 2023 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/>.
+
+"""Utilities for working with ptwrite filters."""
+
+import gdb
+
+# _ptwrite_filter contains the per thread copies of the filter function.
+# The keys are tuples of inferior id and thread id.
+# The filter functions are created for each thread by calling the
+# _ptwrite_filter_factory.
+_ptwrite_filter = {}
+_ptwrite_filter_factory = None
+
+
+def _ptwrite_exit_handler(event):
+ """Exit handler to prune _ptwrite_filter on thread exit."""
+ _ptwrite_filter.pop(event.inferior_thread.ptid, None)
+
+
+gdb.events.thread_exited.connect(_ptwrite_exit_handler)
+
+
+def _clear_traces():
+ """Helper function to clear the trace of all threads."""
+ current_thread = gdb.selected_thread()
+
+ for inferior in gdb.inferiors():
+ for thread in inferior.threads():
+ thread.switch()
+ recording = gdb.current_recording()
+ if recording is not None:
+ recording.clear()
+
+ current_thread.switch()
+
+
+def register_filter_factory(filter_factory_):
+ """Register the ptwrite filter factory."""
+ if filter_factory_ is not None and not callable(filter_factory_):
+ raise TypeError("The filter factory must be callable or 'None'.")
+
+ # Clear the traces of all threads of all inferiors to force
+ # re-decoding with the new filter.
+ _clear_traces()
+
+ _ptwrite_filter.clear()
+ global _ptwrite_filter_factory
+ _ptwrite_filter_factory = filter_factory_
+
+
+def get_filter():
+ """Returns the filter of the current thread."""
+ thread = gdb.selected_thread()
+ key = thread.ptid
+
+ # Create a new filter for new threads.
+ if key not in _ptwrite_filter:
+ if _ptwrite_filter_factory is not None:
+ _ptwrite_filter[key] = _ptwrite_filter_factory(thread)
+ else:
+ return None
+
+ return _ptwrite_filter[key]
diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c
index c6f5662..d73d7fc 100644
--- a/gdb/python/py-arch.c
+++ b/gdb/python/py-arch.c
@@ -199,8 +199,7 @@ archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
- return NULL;
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
gdbpy_ref<> pc_obj = gdb_py_object_from_ulongest (pc);
@@ -362,11 +361,7 @@ static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_arch (void)
{
arch_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&arch_object_type) < 0)
- return -1;
-
- return gdb_pymodule_addobject (gdb_module, "Architecture",
- (PyObject *) &arch_object_type);
+ return gdbpy_type_ready (&arch_object_type);
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_arch);
diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c
index 62e93d5..aeb9acb 100644
--- a/gdb/python/py-block.c
+++ b/gdb/python/py-block.c
@@ -493,19 +493,14 @@ static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_blocks (void)
{
block_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&block_object_type) < 0)
+ if (gdbpy_type_ready (&block_object_type) < 0)
return -1;
block_syms_iterator_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&block_syms_iterator_object_type) < 0)
+ if (gdbpy_type_ready (&block_syms_iterator_object_type) < 0)
return -1;
- if (gdb_pymodule_addobject (gdb_module, "Block",
- (PyObject *) &block_object_type) < 0)
- return -1;
-
- return gdb_pymodule_addobject (gdb_module, "BlockIterator",
- (PyObject *) &block_syms_iterator_object_type);
+ return 0;
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_blocks);
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index e7dd470..1edd556 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -207,7 +207,7 @@ bppy_set_enabled (PyObject *self, PyObject *newvalue, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_SET_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (-1, except);
}
return 0;
@@ -394,7 +394,7 @@ bppy_set_task (PyObject *self, PyObject *newvalue, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_SET_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (-1, except);
}
if (! valid_id)
@@ -443,7 +443,7 @@ bppy_delete_breakpoint (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -484,7 +484,7 @@ bppy_set_ignore_count (PyObject *self, PyObject *newvalue, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_SET_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (-1, except);
}
return 0;
@@ -611,9 +611,9 @@ bppy_set_condition (PyObject *self, PyObject *newvalue, void *closure)
{
set_breakpoint_condition (self_bp->bp, exp, 0, false);
}
- catch (gdb_exception &ex)
+ catch (const gdb_exception &ex)
{
- GDB_PY_SET_HANDLE_EXCEPTION (ex);
+ return gdbpy_handle_gdb_exception (-1, ex);
}
return 0;
@@ -640,8 +640,7 @@ bppy_get_commands (PyObject *self, void *closure)
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
- return NULL;
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return host_string_to_python_string (stb.c_str ()).release ();
@@ -677,9 +676,9 @@ bppy_set_commands (PyObject *self, PyObject *newvalue, void *closure)
counted_command_line lines = read_command_lines_1 (reader, 1, nullptr);
breakpoint_set_commands (self_bp->bp, std::move (lines));
}
- catch (gdb_exception &ex)
+ catch (const gdb_exception &ex)
{
- GDB_PY_SET_HANDLE_EXCEPTION (ex);
+ return gdbpy_handle_gdb_exception (-1, ex);
}
return 0;
@@ -1055,8 +1054,7 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
catch (const gdb_exception &except)
{
bppy_pending_object = NULL;
- gdbpy_convert_exception (except);
- return -1;
+ return gdbpy_handle_gdb_exception (-1, except);
}
BPPY_SET_REQUIRE_VALID ((gdbpy_breakpoint_object *) self);
@@ -1116,7 +1114,7 @@ gdbpy_breakpoint_init_breakpoint_type ()
if (breakpoint_object_type.tp_new == nullptr)
{
breakpoint_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&breakpoint_object_type) < 0)
+ if (gdbpy_type_ready (&breakpoint_object_type) < 0)
{
/* Reset tp_new back to nullptr so future calls to this function
will try calling PyType_Ready again. */
@@ -1361,10 +1359,6 @@ gdbpy_initialize_breakpoints (void)
if (!gdbpy_breakpoint_init_breakpoint_type ())
return -1;
- if (gdb_pymodule_addobject (gdb_module, "Breakpoint",
- (PyObject *) &breakpoint_object_type) < 0)
- return -1;
-
gdb::observers::breakpoint_created.attach (gdbpy_breakpoint_created,
"py-breakpoint");
gdb::observers::breakpoint_deleted.attach (gdbpy_breakpoint_deleted,
@@ -1396,14 +1390,7 @@ gdbpy_initialize_breakpoints (void)
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_breakpoint_locations ()
{
- if (PyType_Ready (&breakpoint_location_object_type) < 0)
- return -1;
-
- if (gdb_pymodule_addobject (gdb_module, "BreakpointLocation",
- (PyObject *) &breakpoint_location_object_type)
- < 0)
- return -1;
- return 0;
+ return gdbpy_type_ready (&breakpoint_location_object_type);
}
@@ -1597,7 +1584,7 @@ bplocpy_set_enabled (PyObject *py_self, PyObject *newvalue, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_SET_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (-1, except);
}
return 0;
}
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index f83b45d..2bb9b82 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -39,7 +39,7 @@ struct cmdpy_completer
static const struct cmdpy_completer completers[] =
{
{ "COMPLETE_NONE", noop_completer },
- { "COMPLETE_FILENAME", filename_completer },
+ { "COMPLETE_FILENAME", filename_maybe_quoted_completer },
{ "COMPLETE_LOCATION", location_completer },
{ "COMPLETE_COMMAND", command_completer },
{ "COMPLETE_SYMBOL", symbol_completer },
@@ -541,8 +541,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
- return -1;
+ return gdbpy_handle_gdb_exception (-1, except);
}
return 0;
@@ -558,7 +557,7 @@ gdbpy_initialize_commands (void)
int i;
cmdpy_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&cmdpy_object_type) < 0)
+ if (gdbpy_type_ready (&cmdpy_object_type) < 0)
return -1;
/* Note: alias and user are special. */
@@ -588,10 +587,6 @@ gdbpy_initialize_commands (void)
return -1;
}
- if (gdb_pymodule_addobject (gdb_module, "Command",
- (PyObject *) &cmdpy_object_type) < 0)
- return -1;
-
invoke_cst = PyUnicode_FromString ("invoke");
if (invoke_cst == NULL)
return -1;
diff --git a/gdb/python/py-connection.c b/gdb/python/py-connection.c
index dcca76b..1fdcd73 100644
--- a/gdb/python/py-connection.c
+++ b/gdb/python/py-connection.c
@@ -287,18 +287,10 @@ connpy_get_connection_details (PyObject *self, void *closure)
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_connection (void)
{
- if (PyType_Ready (&connection_object_type) < 0)
+ if (gdbpy_type_ready (&connection_object_type) < 0)
return -1;
- if (gdb_pymodule_addobject (gdb_module, "TargetConnection",
- (PyObject *) &connection_object_type) < 0)
- return -1;
-
- if (PyType_Ready (&remote_connection_object_type) < 0)
- return -1;
-
- if (gdb_pymodule_addobject (gdb_module, "RemoteTargetConnection",
- (PyObject *) &remote_connection_object_type) < 0)
+ if (gdbpy_type_ready (&remote_connection_object_type) < 0)
return -1;
return 0;
@@ -431,8 +423,7 @@ connpy_send_packet (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
- return nullptr;
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
}
diff --git a/gdb/python/py-disasm.c b/gdb/python/py-disasm.c
index 87fea26..7b64436 100644
--- a/gdb/python/py-disasm.c
+++ b/gdb/python/py-disasm.c
@@ -595,7 +595,7 @@ disasmpy_builtin_disassemble (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (!str.empty ())
PyErr_SetString (gdbpy_gdberror_exc, str.c_str ());
@@ -933,7 +933,7 @@ disasmpy_result_str (PyObject *self)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return PyUnicode_Decode (str.c_str (), str.size (),
@@ -1306,7 +1306,7 @@ gdbpy_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
}
else
{
- gdbpy_print_stack ();
+ gdbpy_print_stack_or_quit ();
return std::optional<int> (-1);
}
@@ -1512,7 +1512,7 @@ disasmpy_addr_part_str (PyObject *self)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return PyUnicode_Decode (str.c_str (), str.size (),
@@ -1665,45 +1665,23 @@ gdbpy_initialize_disasm ()
}
disasm_info_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&disasm_info_object_type) < 0)
- return -1;
-
- if (gdb_pymodule_addobject (gdb_disassembler_module, "DisassembleInfo",
- (PyObject *) &disasm_info_object_type) < 0)
+ if (gdbpy_type_ready (&disasm_info_object_type, gdb_disassembler_module) < 0)
return -1;
disasm_result_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&disasm_result_object_type) < 0)
- return -1;
-
- if (gdb_pymodule_addobject (gdb_disassembler_module, "DisassemblerResult",
- (PyObject *) &disasm_result_object_type) < 0)
+ if (gdbpy_type_ready (&disasm_result_object_type, gdb_disassembler_module) < 0)
return -1;
disasm_part_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&disasm_part_object_type) < 0)
- return -1;
-
- if (gdb_pymodule_addobject (gdb_disassembler_module, "DisassemblerPart",
- (PyObject *) &disasm_part_object_type) < 0)
+ if (gdbpy_type_ready (&disasm_part_object_type, gdb_disassembler_module) < 0)
return -1;
disasm_addr_part_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&disasm_addr_part_object_type) < 0)
- return -1;
-
- if (gdb_pymodule_addobject (gdb_disassembler_module,
- "DisassemblerAddressPart",
- (PyObject *) &disasm_addr_part_object_type) < 0)
+ if (gdbpy_type_ready (&disasm_addr_part_object_type, gdb_disassembler_module) < 0)
return -1;
disasm_text_part_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&disasm_text_part_object_type) < 0)
- return -1;
-
- if (gdb_pymodule_addobject (gdb_disassembler_module,
- "DisassemblerTextPart",
- (PyObject *) &disasm_text_part_object_type) < 0)
+ if (gdbpy_type_ready (&disasm_text_part_object_type, gdb_disassembler_module) < 0)
return -1;
return 0;
diff --git a/gdb/python/py-event.c b/gdb/python/py-event.c
index 47a2997..a918136 100644
--- a/gdb/python/py-event.c
+++ b/gdb/python/py-event.c
@@ -56,25 +56,9 @@ evpy_add_attribute (PyObject *event, const char *name, PyObject *attr)
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_event (void)
{
- return gdbpy_initialize_event_generic (&event_object_type,
- "Event");
+ return gdbpy_type_ready (&event_object_type);
}
-/* Initialize the given event type. If BASE is not NULL it will
- be set as the types base.
- Returns 0 if initialization was successful -1 otherwise. */
-
-int
-gdbpy_initialize_event_generic (PyTypeObject *type,
- const char *name)
-{
- if (PyType_Ready (type) < 0)
- return -1;
-
- return gdb_pymodule_addobject (gdb_module, name, (PyObject *) type);
-}
-
-
/* Notify the list of listens that the given EVENT has occurred.
returns 0 if emit is successful -1 otherwise. */
diff --git a/gdb/python/py-event.h b/gdb/python/py-event.h
index 388c513..a723824 100644
--- a/gdb/python/py-event.h
+++ b/gdb/python/py-event.h
@@ -84,7 +84,5 @@ extern void evpy_dealloc (PyObject *self);
extern int evpy_add_attribute (PyObject *event,
const char *name, PyObject *attr)
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_event_generic (PyTypeObject *type, const char *name)
- CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
#endif /* PYTHON_PY_EVENT_H */
diff --git a/gdb/python/py-evtregistry.c b/gdb/python/py-evtregistry.c
index 1f486e2..7ae3997 100644
--- a/gdb/python/py-evtregistry.c
+++ b/gdb/python/py-evtregistry.c
@@ -104,11 +104,7 @@ evregpy_dealloc (PyObject *self)
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_eventregistry (void)
{
- if (PyType_Ready (&eventregistry_object_type) < 0)
- return -1;
-
- return gdb_pymodule_addobject (gdb_module, "EventRegistry",
- (PyObject *) &eventregistry_object_type);
+ return gdbpy_type_ready (&eventregistry_object_type);
}
/* Return the number of listeners currently connected to this
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index 78030be..bc53d4e 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -217,8 +217,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
- return -1;
+ return gdbpy_handle_gdb_exception (-1, except);
}
if (PyErr_Occurred ())
@@ -318,7 +317,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
}
catch (const gdb_exception &except)
{
- GDB_PY_SET_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (-1, except);
}
self_bpfinish->py_bp.bp->frame_id = frame_id;
@@ -440,11 +439,7 @@ gdbpy_initialize_finishbreakpoints (void)
if (!gdbpy_breakpoint_init_breakpoint_type ())
return -1;
- if (PyType_Ready (&finish_breakpoint_object_type) < 0)
- return -1;
-
- if (gdb_pymodule_addobject (gdb_module, "FinishBreakpoint",
- (PyObject *) &finish_breakpoint_object_type) < 0)
+ if (gdbpy_type_ready (&finish_breakpoint_object_type) < 0)
return -1;
gdb::observers::normal_stop.attach (bpfinishpy_handle_stop,
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index bbb42af..88646ee 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -115,7 +115,7 @@ frapy_is_valid (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (frame == NULL)
@@ -143,7 +143,7 @@ frapy_name (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (name)
@@ -177,7 +177,7 @@ frapy_type (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return gdb_py_object_from_longest (type).release ();
@@ -198,7 +198,7 @@ frapy_arch (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return gdbarch_to_arch_object (obj->gdbarch);
@@ -219,7 +219,7 @@ frapy_unwind_stop_reason (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
stop_reason = get_frame_unwind_stop_reason (frame);
@@ -244,7 +244,7 @@ frapy_pc (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return gdb_py_object_from_ulongest (pc).release ();
@@ -286,7 +286,7 @@ frapy_read_register (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -308,7 +308,7 @@ frapy_block (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
for (fn_block = block;
@@ -347,7 +347,7 @@ frapy_function (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (sym)
@@ -389,8 +389,7 @@ frame_info_to_frame_object (const frame_info_ptr &frame)
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
- return NULL;
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return (PyObject *) frame_obj.release ();
@@ -414,7 +413,7 @@ frapy_older (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (prev)
@@ -446,7 +445,7 @@ frapy_newer (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (next)
@@ -478,7 +477,7 @@ frapy_find_sal (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return sal_obj;
@@ -538,8 +537,7 @@ frapy_read_var (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
- return NULL;
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (!var)
@@ -569,7 +567,7 @@ frapy_read_var (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -590,7 +588,7 @@ frapy_select (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -611,7 +609,7 @@ frapy_level (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -634,7 +632,7 @@ frapy_language (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -655,7 +653,7 @@ frapy_static_link (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (link == nullptr)
@@ -678,7 +676,7 @@ gdbpy_newest_frame (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return frame_info_to_frame_object (frame);
@@ -698,7 +696,7 @@ gdbpy_selected_frame (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return frame_info_to_frame_object (frame);
@@ -763,7 +761,7 @@ static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_frames (void)
{
frame_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&frame_object_type) < 0)
+ if (gdbpy_type_ready (&frame_object_type) < 0)
return -1;
/* Note: These would probably be best exposed as class attributes of
@@ -787,8 +785,7 @@ gdbpy_initialize_frames (void)
#include "unwind_stop_reasons.def"
#undef SET
- return gdb_pymodule_addobject (gdb_module, "Frame",
- (PyObject *) &frame_object_type);
+ return 0;
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_frames);
diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
index 89695ff..daec6dd 100644
--- a/gdb/python/py-framefilter.c
+++ b/gdb/python/py-framefilter.c
@@ -923,12 +923,12 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
else if (PyLong_Check (py_func.get ()))
{
CORE_ADDR addr;
- struct bound_minimal_symbol msymbol;
if (get_addr_from_python (py_func.get (), &addr) < 0)
return EXT_LANG_BT_ERROR;
- msymbol = lookup_minimal_symbol_by_pc (addr);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol_by_pc (addr);
if (msymbol.minsym != NULL)
function = msymbol.minsym->print_name ();
}
@@ -1007,7 +1007,7 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
out->text (":");
annotate_frame_source_line ();
- out->field_signed ("line", line);
+ out->field_signed ("line", line, line_number_style.style ());
}
}
if (out->is_mi_like_p ())
diff --git a/gdb/python/py-function.c b/gdb/python/py-function.c
index 2bbfb9d..58ae0d0 100644
--- a/gdb/python/py-function.c
+++ b/gdb/python/py-function.c
@@ -137,11 +137,7 @@ static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_functions (void)
{
fnpy_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&fnpy_object_type) < 0)
- return -1;
-
- return gdb_pymodule_addobject (gdb_module, "Function",
- (PyObject *) &fnpy_object_type);
+ return gdbpy_type_ready (&fnpy_object_type);
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_functions);
diff --git a/gdb/python/py-gdb-readline.c b/gdb/python/py-gdb-readline.c
index 92287ee..dd0ee45 100644
--- a/gdb/python/py-gdb-readline.c
+++ b/gdb/python/py-gdb-readline.c
@@ -59,8 +59,7 @@ gdbpy_readline_wrapper (FILE *sys_stdin, FILE *sys_stdout,
/* This readline callback is called without the GIL held. */
gdbpy_gil gil;
- gdbpy_convert_exception (except);
- return NULL;
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
/* Detect EOF (Ctrl-D). */
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index a1042ee..60bf56d 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -412,7 +412,7 @@ infpy_threads (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
tuple = PyTuple_New (inf_obj->threads->size ());
@@ -578,7 +578,7 @@ infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
@@ -631,9 +631,9 @@ infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
write_memory_with_notification (addr, buffer, length);
}
- catch (gdb_exception &ex)
+ catch (const gdb_exception &ex)
{
- GDB_PY_HANDLE_EXCEPTION (ex);
+ return gdbpy_handle_gdb_exception (nullptr, ex);
}
Py_RETURN_NONE;
@@ -705,9 +705,9 @@ infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
buffer, pattern_size,
&found_addr);
}
- catch (gdb_exception &ex)
+ catch (const gdb_exception &ex)
{
- GDB_PY_HANDLE_EXCEPTION (ex);
+ return gdbpy_handle_gdb_exception (nullptr, ex);
}
if (found)
@@ -783,7 +783,7 @@ infpy_thread_from_thread_handle (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -1009,11 +1009,7 @@ gdbpy_selected_inferior (PyObject *self, PyObject *args)
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_inferior (void)
{
- if (PyType_Ready (&inferior_object_type) < 0)
- return -1;
-
- if (gdb_pymodule_addobject (gdb_module, "Inferior",
- (PyObject *) &inferior_object_type) < 0)
+ if (gdbpy_type_ready (&inferior_object_type) < 0)
return -1;
gdb::observers::new_thread.attach (add_thread_object, "py-inferior");
diff --git a/gdb/python/py-infthread.c b/gdb/python/py-infthread.c
index a17f25e..4340666 100644
--- a/gdb/python/py-infthread.c
+++ b/gdb/python/py-infthread.c
@@ -104,7 +104,7 @@ thpy_get_details (PyObject *self, void *ignore)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (extra_info == nullptr)
Py_RETURN_NONE;
@@ -212,7 +212,7 @@ thpy_get_ptid_string (PyObject *self, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
}
@@ -245,7 +245,7 @@ thpy_switch (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -330,7 +330,7 @@ thpy_thread_handle (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (hv.size () == 0)
@@ -412,11 +412,7 @@ gdbpy_selected_thread (PyObject *self, PyObject *args)
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_thread (void)
{
- if (PyType_Ready (&thread_object_type) < 0)
- return -1;
-
- return gdb_pymodule_addobject (gdb_module, "InferiorThread",
- (PyObject *) &thread_object_type);
+ return gdbpy_type_ready (&thread_object_type);
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_thread);
diff --git a/gdb/python/py-instruction.c b/gdb/python/py-instruction.c
index bc3945a..7d77572 100644
--- a/gdb/python/py-instruction.c
+++ b/gdb/python/py-instruction.c
@@ -66,7 +66,7 @@ py_insn_get_insn_type ()
py_insn_type.tp_doc = "GDB instruction object";
py_insn_type.tp_getset = py_insn_getset;
- if (PyType_Ready (&py_insn_type) < 0)
+ if (gdbpy_type_ready (&py_insn_type) < 0)
{
/* Reset the tp_new field so any subsequent calls to this
function will retry to make the type ready. */
diff --git a/gdb/python/py-lazy-string.c b/gdb/python/py-lazy-string.c
index 8779716..4898a1f 100644
--- a/gdb/python/py-lazy-string.c
+++ b/gdb/python/py-lazy-string.c
@@ -148,7 +148,7 @@ stpy_convert_to_value (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -236,11 +236,7 @@ gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_lazy_string (void)
{
- if (PyType_Ready (&lazy_string_object_type) < 0)
- return -1;
-
- Py_INCREF (&lazy_string_object_type);
- return 0;
+ return gdbpy_type_ready (&lazy_string_object_type);
}
/* Determine whether the printer object pointed to by OBJ is a
@@ -315,7 +311,7 @@ stpy_str (PyObject *self)
}
catch (const gdb_exception &exc)
{
- GDB_PY_HANDLE_EXCEPTION (exc);
+ return gdbpy_handle_gdb_exception (nullptr, exc);
}
return host_string_to_python_string (stream.c_str ()).release ();
diff --git a/gdb/python/py-linetable.c b/gdb/python/py-linetable.c
index e3e71f9..fc57f36 100644
--- a/gdb/python/py-linetable.c
+++ b/gdb/python/py-linetable.c
@@ -169,7 +169,7 @@ ltpy_get_pcs_for_line (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return build_line_table_tuple_from_pcs (py_line, pcs);
@@ -287,27 +287,11 @@ ltpy_dealloc (PyObject *self)
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_linetable (void)
{
- if (PyType_Ready (&linetable_object_type) < 0)
+ if (gdbpy_type_ready (&linetable_object_type) < 0)
return -1;
- if (PyType_Ready (&linetable_entry_object_type) < 0)
+ if (gdbpy_type_ready (&linetable_entry_object_type) < 0)
return -1;
- if (PyType_Ready (&ltpy_iterator_object_type) < 0)
- return -1;
-
- Py_INCREF (&linetable_object_type);
- Py_INCREF (&linetable_entry_object_type);
- Py_INCREF (&ltpy_iterator_object_type);
-
- if (gdb_pymodule_addobject (gdb_module, "LineTable",
- (PyObject *) &linetable_object_type) < 0)
- return -1;
-
- if (gdb_pymodule_addobject (gdb_module, "LineTableEntry",
- (PyObject *) &linetable_entry_object_type) < 0)
- return -1;
-
- if (gdb_pymodule_addobject (gdb_module, "LineTableIterator",
- (PyObject *) &ltpy_iterator_object_type) < 0)
+ if (gdbpy_type_ready (&ltpy_iterator_object_type) < 0)
return -1;
return 0;
diff --git a/gdb/python/py-membuf.c b/gdb/python/py-membuf.c
index af48d01..25ebc99 100644
--- a/gdb/python/py-membuf.c
+++ b/gdb/python/py-membuf.c
@@ -102,11 +102,7 @@ static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_membuf (void)
{
membuf_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&membuf_object_type) < 0)
- return -1;
-
- return gdb_pymodule_addobject (gdb_module, "Membuf",
- (PyObject *) &membuf_object_type);
+ return gdbpy_type_ready (&membuf_object_type);
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_membuf);
diff --git a/gdb/python/py-mi.c b/gdb/python/py-mi.c
index bc95e86..f0e28d9 100644
--- a/gdb/python/py-mi.c
+++ b/gdb/python/py-mi.c
@@ -86,7 +86,8 @@ py_ui_out::do_end (ui_out_type type)
void
py_ui_out::do_field_signed (int fldno, int width, ui_align align,
- const char *fldname, LONGEST value)
+ const char *fldname, LONGEST value,
+ const ui_file_style &style)
{
if (m_error.has_value ())
return;
@@ -168,8 +169,7 @@ gdbpy_execute_mi_command (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
- return nullptr;
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return uiout.result ().release ();
diff --git a/gdb/python/py-micmd.c b/gdb/python/py-micmd.c
index 54427d4..f4abf2b 100644
--- a/gdb/python/py-micmd.c
+++ b/gdb/python/py-micmd.c
@@ -447,12 +447,7 @@ static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_micommands ()
{
micmdpy_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&micmdpy_object_type) < 0)
- return -1;
-
- if (gdb_pymodule_addobject (gdb_module, "MICommand",
- (PyObject *) &micmdpy_object_type)
- < 0)
+ if (gdbpy_type_ready (&micmdpy_object_type) < 0)
return -1;
invoke_cst = PyUnicode_FromString ("invoke");
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index 60a1483..6ce58a1 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -162,7 +162,7 @@ objfpy_get_build_id (PyObject *self, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (build_id != NULL)
@@ -183,7 +183,7 @@ objfpy_get_progspace (PyObject *self, void *closure)
objfile_object *obj = (objfile_object *) self;
if (obj->objfile)
- return pspace_to_pspace_object (obj->objfile->pspace).release ();
+ return pspace_to_pspace_object (obj->objfile->pspace ()).release ();
Py_RETURN_NONE;
}
@@ -453,7 +453,7 @@ objfpy_add_separate_debug_file (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -488,7 +488,7 @@ objfpy_lookup_global_symbol (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -523,7 +523,7 @@ objfpy_lookup_static_symbol (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -709,11 +709,7 @@ objfile_to_objfile_object (struct objfile *objfile)
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_objfile (void)
{
- if (PyType_Ready (&objfile_object_type) < 0)
- return -1;
-
- return gdb_pymodule_addobject (gdb_module, "Objfile",
- (PyObject *) &objfile_object_type);
+ return gdbpy_type_ready (&objfile_object_type);
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_objfile);
diff --git a/gdb/python/py-param.c b/gdb/python/py-param.c
index 621f85d..9741782 100644
--- a/gdb/python/py-param.c
+++ b/gdb/python/py-param.c
@@ -885,8 +885,7 @@ parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
catch (const gdb_exception &except)
{
Py_DECREF (self);
- gdbpy_convert_exception (except);
- return -1;
+ return gdbpy_handle_gdb_exception (-1, except);
}
return 0;
@@ -910,7 +909,7 @@ gdbpy_initialize_parameters (void)
int i;
parmpy_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&parmpy_object_type) < 0)
+ if (gdbpy_type_ready (&parmpy_object_type) < 0)
return -1;
set_doc_cst = PyUnicode_FromString ("set_doc");
@@ -928,8 +927,7 @@ gdbpy_initialize_parameters (void)
return -1;
}
- return gdb_pymodule_addobject (gdb_module, "Parameter",
- (PyObject *) &parmpy_object_type);
+ return 0;
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_parameters);
diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c
index 368b3a3..e061ea1 100644
--- a/gdb/python/py-prettyprint.c
+++ b/gdb/python/py-prettyprint.c
@@ -836,10 +836,7 @@ PyTypeObject printer_object_type =
static int
gdbpy_initialize_prettyprint ()
{
- if (PyType_Ready (&printer_object_type) < 0)
- return -1;
- return gdb_pymodule_addobject (gdb_module, "ValuePrinter",
- (PyObject *) &printer_object_type);
+ return gdbpy_type_ready (&printer_object_type);
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_prettyprint);
diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c
index 5bc0015..aa1e713 100644
--- a/gdb/python/py-progspace.c
+++ b/gdb/python/py-progspace.c
@@ -522,7 +522,7 @@ pspy_block_for_pc (PyObject *o, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (cust == NULL || cust->objfile () == NULL)
@@ -564,7 +564,7 @@ pspy_find_pc_line (PyObject *o, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -747,11 +747,10 @@ gdbpy_initialize_pspace (void)
gdb::observers::free_program_space.attach (gdbpy_free_program_space_event,
"py-progspace");
- if (PyType_Ready (&pspace_object_type) < 0)
+ if (gdbpy_type_ready (&pspace_object_type) < 0)
return -1;
- return gdb_pymodule_addobject (gdb_module, "Progspace",
- (PyObject *) &pspace_object_type);
+ return 0;
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_pspace);
diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c
index 36454fc..bdfebf1 100644
--- a/gdb/python/py-record-btrace.c
+++ b/gdb/python/py-record-btrace.c
@@ -44,7 +44,8 @@ struct btpy_list_object {
/* Stride size. */
Py_ssize_t step;
- /* Either &BTPY_CALL_TYPE or &RECPY_INSN_TYPE. */
+ /* Either &recpy_func_type, &recpy_insn_type, &recpy_aux_type or
+ &recpy_gap_type. */
PyTypeObject* element_type;
};
@@ -140,15 +141,21 @@ btrace_func_from_recpy_func (const PyObject * const pyobject)
}
/* Looks at the recorded item with the number NUMBER and create a
- gdb.RecordInstruction or gdb.RecordGap object for it accordingly. */
+ gdb.RecordInstruction, gdb.RecordGap or gdb.RecordAuxiliary object
+ for it accordingly. */
static PyObject *
-btpy_insn_or_gap_new (thread_info *tinfo, Py_ssize_t number)
+btpy_item_new (thread_info *tinfo, Py_ssize_t number)
{
btrace_insn_iterator iter;
int err_code;
- btrace_find_insn_by_number (&iter, &tinfo->btrace, number);
+ if (btrace_find_insn_by_number (&iter, &tinfo->btrace, number) == 0)
+ {
+ PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
+ return nullptr;
+ }
+
err_code = btrace_insn_get_error (&iter);
if (err_code != 0)
@@ -162,6 +169,12 @@ btpy_insn_or_gap_new (thread_info *tinfo, Py_ssize_t number)
return recpy_gap_new (err_code, err_string, number);
}
+ const struct btrace_insn *insn = btrace_insn_get (&iter);
+ gdb_assert (insn != nullptr);
+
+ if (insn->iclass == BTRACE_INSN_AUX)
+ return recpy_aux_new (tinfo, RECORD_METHOD_BTRACE, number);
+
return recpy_insn_new (tinfo, RECORD_METHOD_BTRACE, number);
}
@@ -204,7 +217,7 @@ recpy_bt_insn_sal (PyObject *self, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -275,7 +288,7 @@ recpy_bt_insn_data (PyObject *self, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
object = PyBytes_FromStringAndSize ((const char *) buffer.data (),
@@ -305,8 +318,7 @@ recpy_bt_insn_decoded (PyObject *self, void *closure)
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
- return NULL;
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return PyBytes_FromString (strfile.string ().c_str ());
@@ -423,6 +435,48 @@ recpy_bt_func_next (PyObject *self, void *closure)
RECORD_METHOD_BTRACE, func->next);
}
+/* Implementation of Auxiliary.data [str] for btrace. */
+
+PyObject *
+recpy_bt_aux_data (PyObject *self, void *closure)
+{
+ const btrace_insn *insn;
+ const recpy_element_object *obj;
+ thread_info *tinfo;
+ btrace_insn_iterator iter;
+
+ if (Py_TYPE (self) != &recpy_aux_type)
+ {
+ PyErr_Format (gdbpy_gdb_error, _("Must be a gdb.Auxiliary."));
+ return nullptr;
+ }
+
+ obj = (const recpy_element_object *) self;
+ tinfo = obj->thread;
+
+ if (tinfo == nullptr || btrace_is_empty (tinfo))
+ {
+ PyErr_Format (gdbpy_gdb_error, _("No such auxiliary object."));
+ return nullptr;
+ }
+
+ if (btrace_find_insn_by_number (&iter, &tinfo->btrace, obj->number) == 0)
+ {
+ PyErr_Format (gdbpy_gdb_error, _("No such auxiliary object."));
+ return nullptr;
+ }
+
+ insn = btrace_insn_get (&iter);
+ if (insn == nullptr || insn->iclass != BTRACE_INSN_AUX)
+ {
+ PyErr_Format (gdbpy_gdb_error, _("Not a valid auxiliary object."));
+ return nullptr;
+ }
+
+ return PyUnicode_FromString
+ (iter.btinfo->aux_data.at (insn->aux_data_index).c_str ());
+}
+
/* Implementation of BtraceList.__len__ (self) -> int. */
static Py_ssize_t
@@ -439,8 +493,9 @@ btpy_list_length (PyObject *self)
}
/* Implementation of
- BtraceList.__getitem__ (self, key) -> BtraceInstruction and
- BtraceList.__getitem__ (self, key) -> BtraceFunctionCall. */
+ BtraceList.__getitem__ (self, key) -> BtraceInstruction,
+ BtraceList.__getitem__ (self, key) -> BtraceFunctionCall,
+ BtraceList.__getitem__ (self, key) -> BtraceAuxiliary. */
static PyObject *
btpy_list_item (PyObject *self, Py_ssize_t index)
@@ -454,10 +509,13 @@ btpy_list_item (PyObject *self, Py_ssize_t index)
number = obj->first + (obj->step * index);
- if (obj->element_type == &recpy_insn_type)
- return recpy_insn_new (obj->thread, RECORD_METHOD_BTRACE, number);
- else
+ if (obj->element_type == &recpy_func_type)
return recpy_func_new (obj->thread, RECORD_METHOD_BTRACE, number);
+ else if (obj->element_type == &recpy_insn_type
+ || obj->element_type == &recpy_aux_type)
+ return btpy_item_new (obj->thread, number);
+ else
+ return PyErr_Format (gdbpy_gdb_error, _("Not a valid BtraceList object."));
}
/* Implementation of BtraceList.__getitem__ (self, slice) -> BtraceList. */
@@ -644,8 +702,7 @@ recpy_bt_replay_position (PyObject *self, void *closure)
if (tinfo->btrace.replay == NULL)
Py_RETURN_NONE;
- return btpy_insn_or_gap_new (tinfo,
- btrace_insn_number (tinfo->btrace.replay));
+ return btpy_item_new (tinfo, btrace_insn_number (tinfo->btrace.replay));
}
/* Implementation of
@@ -667,7 +724,7 @@ recpy_bt_begin (PyObject *self, void *closure)
Py_RETURN_NONE;
btrace_insn_begin (&iterator, &tinfo->btrace);
- return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator));
+ return btpy_item_new (tinfo, btrace_insn_number (&iterator));
}
/* Implementation of
@@ -689,7 +746,7 @@ recpy_bt_end (PyObject *self, void *closure)
Py_RETURN_NONE;
btrace_insn_end (&iterator, &tinfo->btrace);
- return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator));
+ return btpy_item_new (tinfo, btrace_insn_number (&iterator));
}
/* Implementation of
@@ -750,6 +807,109 @@ recpy_bt_function_call_history (PyObject *self, void *closure)
return btpy_list_new (tinfo, first, last, 1, &recpy_func_type);
}
+/* Helper function that calls PTW_FILTER with PAYLOAD and IP as arguments.
+ Returns the string that will be printed, if there is a filter to call. */
+static std::optional<std::string>
+recpy_call_filter (const uint64_t payload, std::optional<uint64_t> ip,
+ const void *ptw_filter)
+{
+ std::optional<std::string> result;
+
+ gdb_assert (ptw_filter != nullptr);
+ if ((PyObject *) ptw_filter == Py_None)
+ return result;
+
+ gdbpy_enter enter_py;
+
+ gdbpy_ref<> py_payload = gdb_py_object_from_ulongest (payload);
+
+ gdbpy_ref<> py_ip;
+ if (!ip.has_value ())
+ py_ip = gdbpy_ref<>::new_reference (Py_None);
+ else
+ py_ip = gdb_py_object_from_ulongest (*ip);
+
+ gdbpy_ref<> py_result (PyObject_CallFunctionObjArgs ((PyObject *) ptw_filter,
+ py_payload.get (),
+ py_ip.get (),
+ nullptr));
+
+ if (py_result == nullptr)
+ {
+ gdbpy_print_stack ();
+ gdbpy_error (_("Couldn't call the ptwrite filter."));
+ }
+
+ /* Py_None is valid and results in no output. */
+ if (py_result == Py_None)
+ {
+ result = "";
+ return result;
+ }
+
+ gdb::unique_xmalloc_ptr<char> user_string
+ = gdbpy_obj_to_string (py_result.get ());
+
+ if (user_string == nullptr)
+ {
+ gdbpy_print_stack ();
+ gdbpy_error (_("The ptwrite filter didn't return a string."));
+ }
+ else
+ result = user_string.get ();
+
+ return result;
+}
+
+/* Helper function returning the current ptwrite filter. */
+
+static PyObject *
+get_ptwrite_filter ()
+{
+ gdbpy_ref<> module (PyImport_ImportModule ("gdb.ptwrite"));
+
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ gdbpy_error (_("Couldn't import gdb.ptwrite."));
+ }
+
+ /* We need to keep the reference count. */
+ gdbpy_ref<> ptw_filter (gdbpy_call_method (module.get (), "get_filter"));
+
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ gdbpy_error (_("Couldn't get the ptwrite filter."));
+ }
+
+ return ptw_filter.get();
+}
+
+/* Used for registering any python ptwrite filter to the current thread. A
+ pointer to this function is stored in the python extension interface. */
+
+void
+gdbpy_load_ptwrite_filter (const struct extension_language_defn *extlang,
+ struct btrace_thread_info *btinfo)
+{
+ gdb_assert (btinfo != nullptr);
+
+ gdbpy_enter enter_py;
+
+ btinfo->ptw_context = get_ptwrite_filter ();
+
+#if defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE)
+ if (!btinfo->target->conf.pt.ptwrite && btinfo->ptw_context != Py_None)
+ warning (_("The target doesn't support decoding ptwrite events."));
+#else
+ if (btinfo->ptw_context != Py_None)
+ warning (_("Libipt doesn't support decoding ptwrite events."));
+#endif /* defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) */
+
+ btinfo->ptw_callback_fun = &recpy_call_filter;
+}
+
/* Implementation of BtraceRecord.goto (self, BtraceInstruction) -> None. */
PyObject *
@@ -783,12 +943,25 @@ recpy_bt_goto (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
}
+/* Implementation of BtraceRecord.clear (self) -> None. */
+
+PyObject *
+recpy_bt_clear (PyObject *self, PyObject *args)
+{
+ const recpy_record_object * const record = (recpy_record_object *) self;
+ thread_info *const tinfo = record->thread;
+
+ btrace_clear (tinfo);
+
+ Py_RETURN_NONE;
+}
+
/* BtraceList methods. */
static PyMethodDef btpy_list_methods[] =
@@ -833,7 +1006,7 @@ gdbpy_initialize_btrace (void)
btpy_list_mapping_methods.mp_subscript = btpy_list_slice;
- return PyType_Ready (&btpy_list_type);
+ return gdbpy_type_ready (&btpy_list_type);
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_btrace);
diff --git a/gdb/python/py-record-btrace.h b/gdb/python/py-record-btrace.h
index 8678e77..3be5860 100644
--- a/gdb/python/py-record-btrace.h
+++ b/gdb/python/py-record-btrace.h
@@ -31,6 +31,9 @@ extern PyObject *recpy_bt_format (PyObject *self, void *closure);
/* Implementation of record.goto (instruction) -> None. */
extern PyObject *recpy_bt_goto (PyObject *self, PyObject *value);
+/* Implementation of BtraceRecord.clear (self) -> None. */
+extern PyObject *recpy_bt_clear (PyObject *self, PyObject *args);
+
/* Implementation of record.instruction_history [list]. */
extern PyObject *recpy_bt_instruction_history (PyObject *self, void *closure);
@@ -88,4 +91,7 @@ extern PyObject *recpy_bt_func_prev (PyObject *self, void *closure);
/* Implementation of RecordFunctionSegment.next [RecordFunctionSegment]. */
extern PyObject *recpy_bt_func_next (PyObject *self, void *closure);
+/* Implementation of RecordAuxiliary.decoded [str]. */
+extern PyObject *recpy_bt_aux_data (PyObject *self, void *closure);
+
#endif /* PYTHON_PY_RECORD_BTRACE_H */
diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c
index d489126..2995dc1 100644
--- a/gdb/python/py-record.c
+++ b/gdb/python/py-record.c
@@ -48,6 +48,12 @@ static PyTypeObject recpy_gap_type = {
PyVarObject_HEAD_INIT (NULL, 0)
};
+/* Python RecordAuxiliary type. */
+
+PyTypeObject recpy_aux_type = {
+ PyVarObject_HEAD_INIT (nullptr, 0)
+};
+
/* Python RecordGap object. */
struct recpy_gap_object
{
@@ -108,6 +114,19 @@ recpy_goto (PyObject *self, PyObject *value)
return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
}
+/* Implementation of record.clear () -> None. */
+
+static PyObject *
+recpy_clear (PyObject *self, PyObject *value)
+{
+ const recpy_record_object * const obj = (recpy_record_object *) self;
+
+ if (obj->method == RECORD_METHOD_BTRACE)
+ return recpy_bt_clear (self, value);
+
+ return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
/* Implementation of record.replay_position [instruction] */
static PyObject *
@@ -389,8 +408,8 @@ recpy_element_hash (PyObject *self)
return obj->number;
}
-/* Implementation of operator == and != of RecordInstruction and
- RecordFunctionSegment. */
+/* Implementation of operator == and != of RecordInstruction,
+ RecordFunctionSegment and RecordAuxiliary. */
static PyObject *
recpy_element_richcompare (PyObject *self, PyObject *other, int op)
@@ -478,12 +497,47 @@ recpy_gap_reason_string (PyObject *self, void *closure)
return PyUnicode_FromString (obj->reason_string);
}
+/* Create a new gdb.Auxiliary object. */
+
+PyObject *
+recpy_aux_new (thread_info *thread, enum record_method method,
+ Py_ssize_t number)
+{
+ recpy_element_object * const obj = PyObject_New (recpy_element_object,
+ &recpy_aux_type);
+
+ if (obj == NULL)
+ return NULL;
+
+ obj->thread = thread;
+ obj->method = method;
+ obj->number = number;
+
+ return (PyObject *) obj;
+}
+
+/* Implementation of Auxiliary.data [buffer]. */
+
+static PyObject *
+recpy_aux_data (PyObject *self, void *closure)
+{
+ const recpy_element_object * const obj = (recpy_element_object *) self;
+
+ if (obj->method == RECORD_METHOD_BTRACE)
+ return recpy_bt_aux_data (self, closure);
+
+ return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
/* Record method list. */
static PyMethodDef recpy_record_methods[] = {
{ "goto", recpy_goto, METH_VARARGS,
"goto (instruction|function_call) -> None.\n\
Rewind to given location."},
+ { "clear", recpy_clear, METH_VARARGS,
+ "clear () -> None.\n\
+Clears the trace."},
{ NULL }
};
@@ -543,6 +597,14 @@ static gdb_PyGetSetDef recpy_gap_getset[] = {
{ NULL }
};
+/* RecordAuxiliary member list. */
+
+static gdb_PyGetSetDef recpy_aux_getset[] = {
+ { "number", recpy_element_number, nullptr, "element number", nullptr},
+ { "data", recpy_aux_data, nullptr, "data", nullptr},
+ { nullptr }
+};
+
/* Sets up the record API in the gdb module. */
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
@@ -582,10 +644,20 @@ gdbpy_initialize_record (void)
recpy_gap_type.tp_doc = "GDB recorded gap object";
recpy_gap_type.tp_getset = recpy_gap_getset;
- if (PyType_Ready (&recpy_record_type) < 0
- || PyType_Ready (&recpy_insn_type) < 0
- || PyType_Ready (&recpy_func_type) < 0
- || PyType_Ready (&recpy_gap_type) < 0)
+ recpy_aux_type.tp_new = PyType_GenericNew;
+ recpy_aux_type.tp_flags = Py_TPFLAGS_DEFAULT;
+ recpy_aux_type.tp_basicsize = sizeof (recpy_element_object);
+ recpy_aux_type.tp_name = "gdb.RecordAuxiliary";
+ recpy_aux_type.tp_doc = "GDB recorded auxiliary object";
+ recpy_aux_type.tp_getset = recpy_aux_getset;
+ recpy_aux_type.tp_richcompare = recpy_element_richcompare;
+ recpy_aux_type.tp_hash = recpy_element_hash;
+
+ if (gdbpy_type_ready (&recpy_record_type) < 0
+ || gdbpy_type_ready (&recpy_insn_type) < 0
+ || gdbpy_type_ready (&recpy_func_type) < 0
+ || gdbpy_type_ready (&recpy_gap_type) < 0
+ || gdbpy_type_ready (&recpy_aux_type) < 0)
return -1;
else
return 0;
@@ -598,7 +670,6 @@ gdbpy_start_recording (PyObject *self, PyObject *args)
{
const char *method = NULL;
const char *format = NULL;
- PyObject *ret = NULL;
if (!PyArg_ParseTuple (args, "|ss", &method, &format))
return NULL;
@@ -606,14 +677,12 @@ gdbpy_start_recording (PyObject *self, PyObject *args)
try
{
record_start (method, format, 0);
- ret = gdbpy_current_recording (self, args);
+ return gdbpy_current_recording (self, args);
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
-
- return ret;
}
/* Implementation of gdb.current_recording (self) -> gdb.Record. */
@@ -644,7 +713,7 @@ gdbpy_stop_recording (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
diff --git a/gdb/python/py-record.h b/gdb/python/py-record.h
index 7e11610..0988584 100644
--- a/gdb/python/py-record.h
+++ b/gdb/python/py-record.h
@@ -59,6 +59,9 @@ extern PyTypeObject recpy_insn_type;
/* Python RecordFunctionSegment type. */
extern PyTypeObject recpy_func_type;
+/* Python RecordAuxiliary type. */
+extern PyTypeObject recpy_aux_type;
+
/* Create a new gdb.RecordInstruction object. */
extern PyObject *recpy_insn_new (thread_info *thread, enum record_method method,
Py_ssize_t number);
@@ -71,4 +74,8 @@ extern PyObject *recpy_func_new (thread_info *thread, enum record_method method,
extern PyObject *recpy_gap_new (int reason_code, const char *reason_string,
Py_ssize_t number);
+/* Create a new gdb.RecordGap object. */
+extern PyObject *recpy_aux_new (thread_info *thread, enum record_method method,
+ Py_ssize_t number);
+
#endif /* PYTHON_PY_RECORD_H */
diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c
index f03274c..229dd62 100644
--- a/gdb/python/py-registers.c
+++ b/gdb/python/py-registers.c
@@ -430,35 +430,22 @@ static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_registers ()
{
register_descriptor_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&register_descriptor_object_type) < 0)
- return -1;
- if (gdb_pymodule_addobject
- (gdb_module, "RegisterDescriptor",
- (PyObject *) &register_descriptor_object_type) < 0)
+ if (gdbpy_type_ready (&register_descriptor_object_type) < 0)
return -1;
reggroup_iterator_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&reggroup_iterator_object_type) < 0)
- return -1;
- if (gdb_pymodule_addobject
- (gdb_module, "RegisterGroupsIterator",
- (PyObject *) &reggroup_iterator_object_type) < 0)
+ if (gdbpy_type_ready (&reggroup_iterator_object_type) < 0)
return -1;
reggroup_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&reggroup_object_type) < 0)
- return -1;
- if (gdb_pymodule_addobject
- (gdb_module, "RegisterGroup",
- (PyObject *) &reggroup_object_type) < 0)
+ if (gdbpy_type_ready (&reggroup_object_type) < 0)
return -1;
register_descriptor_iterator_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&register_descriptor_iterator_object_type) < 0)
+ if (gdbpy_type_ready (&register_descriptor_iterator_object_type) < 0)
return -1;
- return (gdb_pymodule_addobject
- (gdb_module, "RegisterDescriptorIterator",
- (PyObject *) &register_descriptor_iterator_object_type));
+
+ return 0;
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_registers);
diff --git a/gdb/python/py-stopevent.c b/gdb/python/py-stopevent.c
index be26bc1..485bbb1 100644
--- a/gdb/python/py-stopevent.c
+++ b/gdb/python/py-stopevent.c
@@ -74,8 +74,7 @@ py_print_bpstat (bpstat *bs, enum gdb_signal stop_signal)
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
- return nullptr;
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
gdbpy_ref<> dict = uiout.result ();
diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c
index 754420f..24b53bb 100644
--- a/gdb/python/py-symbol.c
+++ b/gdb/python/py-symbol.c
@@ -222,7 +222,7 @@ sympy_needs_frame (PyObject *self, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (result)
@@ -307,7 +307,7 @@ sympy_value (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -425,7 +425,7 @@ gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
}
@@ -436,7 +436,7 @@ gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
gdbpy_ref<> ret_tuple (PyTuple_New (2));
@@ -485,7 +485,7 @@ gdbpy_lookup_global_symbol (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (symbol)
@@ -553,7 +553,7 @@ gdbpy_lookup_static_symbol (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (symbol)
@@ -631,7 +631,7 @@ gdbpy_lookup_static_symbols (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return return_list.release ();
@@ -640,7 +640,7 @@ gdbpy_lookup_static_symbols (PyObject *self, PyObject *args, PyObject *kw)
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_symbols (void)
{
- if (PyType_Ready (&symbol_object_type) < 0)
+ if (gdbpy_type_ready (&symbol_object_type) < 0)
return -1;
if (PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_UNDEF", LOC_UNDEF) < 0
@@ -685,8 +685,7 @@ gdbpy_initialize_symbols (void)
#include "sym-domains.def"
#undef SYM_DOMAIN
- return gdb_pymodule_addobject (gdb_module, "Symbol",
- (PyObject *) &symbol_object_type);
+ return 0;
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_symbols);
diff --git a/gdb/python/py-symtab.c b/gdb/python/py-symtab.c
index 7290b85..99a5094 100644
--- a/gdb/python/py-symtab.c
+++ b/gdb/python/py-symtab.c
@@ -512,19 +512,14 @@ static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_symtabs (void)
{
symtab_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&symtab_object_type) < 0)
+ if (gdbpy_type_ready (&symtab_object_type) < 0)
return -1;
sal_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&sal_object_type) < 0)
+ if (gdbpy_type_ready (&sal_object_type) < 0)
return -1;
- if (gdb_pymodule_addobject (gdb_module, "Symtab",
- (PyObject *) &symtab_object_type) < 0)
- return -1;
-
- return gdb_pymodule_addobject (gdb_module, "Symtab_and_line",
- (PyObject *) &sal_object_type);
+ return 0;
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_symtabs);
diff --git a/gdb/python/py-tui.c b/gdb/python/py-tui.c
index 984fa9b..afa6f36 100644
--- a/gdb/python/py-tui.c
+++ b/gdb/python/py-tui.c
@@ -95,7 +95,7 @@ public:
{
wnoutrefresh (handle.get ());
touchwin (m_inner_window.get ());
- tui_wrefresh (m_inner_window.get ());
+ wnoutrefresh (m_inner_window.get ());
}
else
tui_win_info::refresh_window ();
@@ -180,6 +180,8 @@ tui_py_window::~tui_py_window ()
void
tui_py_window::rerender ()
{
+ tui_batch_rendering batch;
+
tui_win_info::rerender ();
gdbpy_enter enter_py;
@@ -206,6 +208,8 @@ tui_py_window::rerender ()
void
tui_py_window::do_scroll_horizontal (int num_to_scroll)
{
+ tui_batch_rendering batch;
+
gdbpy_enter enter_py;
if (PyObject_HasAttrString (m_window.get (), "hscroll"))
@@ -220,6 +224,8 @@ tui_py_window::do_scroll_horizontal (int num_to_scroll)
void
tui_py_window::do_scroll_vertical (int num_to_scroll)
{
+ tui_batch_rendering batch;
+
gdbpy_enter enter_py;
if (PyObject_HasAttrString (m_window.get (), "vscroll"))
@@ -242,6 +248,8 @@ tui_py_window::resize (int height_, int width_, int origin_x_, int origin_y_)
void
tui_py_window::click (int mouse_x, int mouse_y, int mouse_button)
{
+ tui_batch_rendering batch;
+
gdbpy_enter enter_py;
if (PyObject_HasAttrString (m_window.get (), "click"))
@@ -258,6 +266,8 @@ tui_py_window::output (const char *text, bool full_window)
{
if (m_inner_window != nullptr)
{
+ tui_batch_rendering batch;
+
if (full_window)
werase (m_inner_window.get ());
@@ -265,7 +275,7 @@ tui_py_window::output (const char *text, bool full_window)
if (full_window)
check_and_display_highlight_if_needed ();
else
- tui_wrefresh (m_inner_window.get ());
+ wnoutrefresh (m_inner_window.get ());
}
}
@@ -415,8 +425,7 @@ gdbpy_register_tui_window (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
- return nullptr;
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -616,7 +625,7 @@ gdbpy_initialize_tui ()
{
#ifdef TUI
gdbpy_tui_window_object_type.tp_new = PyType_GenericNew;
- if (PyType_Ready (&gdbpy_tui_window_object_type) < 0)
+ if (gdbpy_type_ready (&gdbpy_tui_window_object_type) < 0)
return -1;
#endif /* TUI */
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 863e6f6..284960a 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -292,7 +292,7 @@ typy_fields_items (PyObject *self, enum gdbpy_iter_kind kind)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
gdbpy_ref<> type_holder;
@@ -456,7 +456,7 @@ typy_is_array_like (PyObject *self, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (result)
@@ -480,7 +480,7 @@ typy_is_string_like (PyObject *self, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (result)
@@ -501,7 +501,7 @@ typy_strip_typedefs (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return type_to_type_object (type);
@@ -522,7 +522,7 @@ typy_get_composite (struct type *type)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (!type->is_pointer_or_reference ())
@@ -592,7 +592,7 @@ typy_array_1 (PyObject *self, PyObject *args, int is_vector)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return type_to_type_object (array);
@@ -626,7 +626,7 @@ typy_pointer (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return type_to_type_object (type);
@@ -698,7 +698,7 @@ typy_reference (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return type_to_type_object (type);
@@ -732,7 +732,7 @@ typy_const (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return type_to_type_object (type);
@@ -750,7 +750,7 @@ typy_volatile (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return type_to_type_object (type);
@@ -768,7 +768,7 @@ typy_unqualified (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return type_to_type_object (type);
@@ -859,7 +859,7 @@ typy_lookup_typename (const char *type_name, const struct block *block)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return type;
@@ -913,7 +913,7 @@ typy_lookup_type (struct demangle_component *demangled,
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
}
@@ -955,7 +955,7 @@ typy_legacy_template_argument (struct type *type, const struct block *block,
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (! info)
@@ -1034,7 +1034,7 @@ typy_template_argument (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
/* We might not have DW_TAG_template_*, so try to parse the type's
@@ -1069,7 +1069,7 @@ typy_template_argument (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -1093,7 +1093,7 @@ typy_repr (PyObject *self)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
auto py_typename = PyUnicode_Decode (type_name.c_str (), type_name.size (),
host_charset (), NULL);
@@ -1115,7 +1115,7 @@ typy_str (PyObject *self)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return PyUnicode_Decode (thetype.c_str (), thetype.size (),
@@ -1151,7 +1151,7 @@ typy_richcompare (PyObject *self, PyObject *other, int op)
{
/* If there is a GDB exception, a comparison is not capable
(or trusted), so exit. */
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
}
@@ -1465,10 +1465,14 @@ type_to_type_object (struct type *type)
if (type->is_stub ())
type = check_typedef (type);
}
- catch (...)
+ catch (const gdb_exception_error &)
{
/* Just ignore failures in check_typedef. */
}
+ catch (const gdb_exception &except)
+ {
+ return gdbpy_handle_gdb_exception (nullptr, except);
+ }
type_obj = PyObject_New (type_object, &type_object_type);
if (type_obj)
@@ -1522,11 +1526,11 @@ gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw)
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_types (void)
{
- if (PyType_Ready (&type_object_type) < 0)
+ if (gdbpy_type_ready (&type_object_type) < 0)
return -1;
- if (PyType_Ready (&field_object_type) < 0)
+ if (gdbpy_type_ready (&field_object_type) < 0)
return -1;
- if (PyType_Ready (&type_iterator_object_type) < 0)
+ if (gdbpy_type_ready (&type_iterator_object_type) < 0)
return -1;
for (const auto &item : pyty_codes)
@@ -1535,16 +1539,7 @@ gdbpy_initialize_types (void)
return -1;
}
- if (gdb_pymodule_addobject (gdb_module, "Type",
- (PyObject *) &type_object_type) < 0)
- return -1;
-
- if (gdb_pymodule_addobject (gdb_module, "TypeIterator",
- (PyObject *) &type_iterator_object_type) < 0)
- return -1;
-
- return gdb_pymodule_addobject (gdb_module, "Field",
- (PyObject *) &field_object_type);
+ return 0;
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_types);
diff --git a/gdb/python/py-uiout.h b/gdb/python/py-uiout.h
index a2fc90e..5f8c530 100644
--- a/gdb/python/py-uiout.h
+++ b/gdb/python/py-uiout.h
@@ -86,7 +86,8 @@ protected:
void do_end (ui_out_type type) override;
void do_field_signed (int fldno, int width, ui_align align,
- const char *fldname, LONGEST value) override;
+ const char *fldname, LONGEST value,
+ const ui_file_style &style) override;
void do_field_unsigned (int fldno, int width, ui_align align,
const char *fldname, ULONGEST value) override;
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index e36768e..68deaf9 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -228,7 +228,7 @@ unwind_infopy_str (PyObject *self)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
}
else
@@ -378,7 +378,7 @@ unwind_infopy_add_saved_register (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
gdbpy_ref<> new_value = gdbpy_ref<>::new_reference (pyo_reg_value);
@@ -429,7 +429,7 @@ pending_framepy_str (PyObject *self)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return PyUnicode_FromFormat ("SP=%s,PC=%s", sp_str, pc_str);
@@ -456,7 +456,7 @@ pending_framepy_repr (PyObject *self)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return PyUnicode_FromFormat ("<%s level=%d, sp=%s, pc=%s>",
@@ -505,7 +505,7 @@ pending_framepy_read_register (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -546,7 +546,7 @@ pending_framepy_name (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (name != nullptr)
@@ -574,7 +574,7 @@ pending_framepy_pc (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return gdb_py_object_from_ulongest (pc).release ();
@@ -601,7 +601,7 @@ pending_framepy_language (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -628,7 +628,7 @@ pending_framepy_find_sal (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return sal_obj;
@@ -653,7 +653,7 @@ pending_framepy_block (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
for (fn_block = block;
@@ -696,7 +696,7 @@ pending_framepy_function (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (sym != nullptr)
@@ -1002,17 +1002,13 @@ gdbpy_initialize_unwind (void)
{
gdb::observers::new_architecture.attach (pyuw_on_new_gdbarch, "py-unwind");
- if (PyType_Ready (&pending_frame_object_type) < 0)
+ if (gdbpy_type_ready (&pending_frame_object_type) < 0)
return -1;
- int rc = gdb_pymodule_addobject (gdb_module, "PendingFrame",
- (PyObject *) &pending_frame_object_type);
- if (rc != 0)
- return rc;
- if (PyType_Ready (&unwind_info_object_type) < 0)
+ if (gdbpy_type_ready (&unwind_info_object_type) < 0)
return -1;
- return gdb_pymodule_addobject (gdb_module, "UnwindInfo",
- (PyObject *) &unwind_info_object_type);
+
+ return 0;
}
void _initialize_py_unwind ();
diff --git a/gdb/python/py-utils.c b/gdb/python/py-utils.c
index 47f65f4..0bc18a6 100644
--- a/gdb/python/py-utils.c
+++ b/gdb/python/py-utils.c
@@ -247,7 +247,7 @@ get_addr_from_python (PyObject *obj, CORE_ADDR *addr)
}
catch (const gdb_exception &except)
{
- GDB_PY_SET_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (-1, except);
}
}
else
@@ -390,6 +390,35 @@ gdbpy_handle_exception ()
if (fetched_error.type_matches (PyExc_KeyboardInterrupt))
throw_quit ("Quit");
+ else if (fetched_error.type_matches (PyExc_SystemExit))
+ {
+ gdbpy_ref<> value = fetched_error.value ();
+ gdbpy_ref<> code (PyObject_GetAttrString (value.get (), "code"));
+ int exit_arg;
+
+ if (code.get () == Py_None)
+ {
+ /* CODE == None: exit status is 0. */
+ exit_arg = 0;
+ }
+ else if (code.get () != nullptr && PyLong_Check (code.get ()))
+ {
+ /* CODE == integer: exit status is aforementioned integer. */
+ exit_arg = PyLong_AsLong (code.get ());
+ }
+ else
+ {
+ if (code.get () == nullptr)
+ gdbpy_print_stack ();
+
+ /* Otherwise: exit status is 1, print code to stderr. */
+ if (msg != nullptr)
+ gdb_printf (gdb_stderr, "%s\n", msg.get ());
+ exit_arg = 1;
+ }
+
+ quit_force (&exit_arg, 0);
+ }
else if (! fetched_error.type_matches (gdbpy_gdberror_exc)
|| msg == NULL || *msg == '\0')
{
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index dada8bf..119bf9f 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -257,7 +257,7 @@ valpy_dereference (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -300,7 +300,7 @@ valpy_referenced_value (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -323,7 +323,7 @@ valpy_reference_value (PyObject *self, PyObject *args, enum type_code refcode)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -369,7 +369,7 @@ valpy_to_array (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -393,7 +393,7 @@ valpy_const_value (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -499,7 +499,7 @@ valpy_get_dynamic_type (PyObject *self, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (type == NULL)
@@ -605,7 +605,7 @@ valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return str_obj;
@@ -640,7 +640,7 @@ valpy_string (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
encoding = (user_encoding && *user_encoding) ? user_encoding : la_encoding;
@@ -824,7 +824,7 @@ valpy_format_string (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return PyUnicode_Decode (stb.c_str (), stb.size (), host_charset (), NULL);
@@ -869,7 +869,7 @@ valpy_do_cast (PyObject *self, PyObject *args, enum exp_opcode op)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -921,8 +921,7 @@ valpy_assign_core (value_object *self, struct value *new_value)
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
- return false;
+ return gdbpy_handle_gdb_exception (false, except);
}
return true;
@@ -997,7 +996,7 @@ value_has_field (struct value *v, PyObject *field)
}
catch (const gdb_exception &except)
{
- GDB_PY_SET_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (-1, except);
}
return has_field;
@@ -1178,9 +1177,9 @@ valpy_getitem (PyObject *self, PyObject *key)
if (res_val)
result = value_to_value_object (res_val);
}
- catch (gdb_exception &ex)
+ catch (const gdb_exception &ex)
{
- GDB_PY_HANDLE_EXCEPTION (ex);
+ return gdbpy_handle_gdb_exception (nullptr, ex);
}
return result;
@@ -1211,7 +1210,7 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (ftype->code () != TYPE_CODE_FUNC && ftype->code () != TYPE_CODE_METHOD
@@ -1258,7 +1257,8 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
if (ftype->code () == TYPE_CODE_INTERNAL_FUNCTION)
return_value = call_internal_function (gdbpy_enter::get_gdbarch (),
current_language,
- function, args_count, vargs);
+ function, args_count, vargs,
+ EVAL_NORMAL);
else
return_value
= call_function_by_hand (function, NULL,
@@ -1267,7 +1267,7 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -1292,7 +1292,7 @@ valpy_str (PyObject *self)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return PyUnicode_Decode (stb.c_str (), stb.size (), host_charset (), NULL);
@@ -1311,7 +1311,7 @@ valpy_get_is_optimized_out (PyObject *self, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (opt)
@@ -1333,7 +1333,7 @@ valpy_get_is_lazy (PyObject *self, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (opt)
@@ -1363,7 +1363,7 @@ valpy_get_bytes (PyObject *self, void *closure)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
value_obj->content_bytes
@@ -1407,7 +1407,7 @@ valpy_fetch_lazy (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -1578,7 +1578,7 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -1646,7 +1646,7 @@ valpy_negative (PyObject *self)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -1673,7 +1673,7 @@ valpy_absolute (PyObject *self)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (isabs)
@@ -1703,12 +1703,12 @@ valpy_nonzero (PyObject *self)
/* All other values are True. */
nonzero = 1;
}
- catch (gdb_exception &ex)
+ catch (const gdb_exception &ex)
{
/* This is not documented in the Python documentation, but if
this function fails, return -1 as slot_nb_nonzero does (the
default Python nonzero function). */
- GDB_PY_SET_HANDLE_EXCEPTION (ex);
+ return gdbpy_handle_gdb_exception (-1, ex);
}
return nonzero;
@@ -1728,7 +1728,7 @@ valpy_invert (PyObject *self)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -1855,7 +1855,7 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
/* In this case, the Python exception has already been set. */
@@ -1894,7 +1894,7 @@ valpy_long (PyObject *self)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (type->is_unsigned ())
@@ -1929,7 +1929,7 @@ valpy_float (PyObject *self)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return PyFloat_FromDouble (d);
@@ -2055,8 +2055,7 @@ convert_value_from_python (PyObject *obj)
}
catch (const gdb_exception &except)
{
- gdbpy_convert_exception (except);
- return NULL;
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return value;
@@ -2080,7 +2079,7 @@ gdbpy_history (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -2107,7 +2106,7 @@ gdbpy_add_history (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return nullptr;
@@ -2152,7 +2151,7 @@ gdbpy_convenience_variable (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (result == nullptr && !found)
@@ -2198,7 +2197,7 @@ gdbpy_set_convenience_variable (PyObject *self, PyObject *args)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -2215,11 +2214,7 @@ gdbpy_is_value_object (PyObject *obj)
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_values (void)
{
- if (PyType_Ready (&value_object_type) < 0)
- return -1;
-
- return gdb_pymodule_addobject (gdb_module, "Value",
- (PyObject *) &value_object_type);
+ return gdbpy_type_ready (&value_object_type);
}
GDBPY_INITIALIZE_FILE (gdbpy_initialize_values);
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index f25cd3b..d723c4d 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -464,6 +464,9 @@ extern enum ext_lang_rc gdbpy_apply_val_pretty_printer
struct ui_file *stream, int recurse,
const struct value_print_options *options,
const struct language_defn *language);
+extern void gdbpy_load_ptwrite_filter
+ (const struct extension_language_defn *extlang,
+ struct btrace_thread_info *btinfo);
extern enum ext_lang_bt_status gdbpy_apply_frame_filter
(const struct extension_language_defn *,
const frame_info_ptr &frame, frame_filter_flags flags,
@@ -929,26 +932,10 @@ private:
PyGILState_STATE m_state;
};
-/* Use this in a 'catch' block to convert the exception to a Python
- exception and return nullptr. */
-#define GDB_PY_HANDLE_EXCEPTION(Exception) \
- do { \
- gdbpy_convert_exception (Exception); \
- return nullptr; \
- } while (0)
-
-/* Use this in a 'catch' block to convert the exception to a Python
- exception and return -1. */
-#define GDB_PY_SET_HANDLE_EXCEPTION(Exception) \
- do { \
- gdbpy_convert_exception (Exception); \
- return -1; \
- } while (0)
-
int gdbpy_print_python_errors_p (void);
void gdbpy_print_stack (void);
void gdbpy_print_stack_or_quit ();
-void gdbpy_handle_exception () ATTRIBUTE_NORETURN;
+[[noreturn]] void gdbpy_handle_exception ();
/* A wrapper around calling 'error'. Prefixes the error message with an
'Error occurred in Python' string. Use this in C++ code if we spot
@@ -958,8 +945,7 @@ void gdbpy_handle_exception () ATTRIBUTE_NORETURN;
This always calls error, and never returns. */
-void gdbpy_error (const char *fmt, ...)
- ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (1, 2);
+[[noreturn]] void gdbpy_error (const char *fmt, ...) ATTRIBUTE_PRINTF (1, 2);
gdbpy_ref<> python_string_to_unicode (PyObject *obj);
gdb::unique_xmalloc_ptr<char> unicode_to_target_string (PyObject *unicode_str);
@@ -1011,6 +997,18 @@ extern PyObject *gdbpy_gdberror_exc;
extern void gdbpy_convert_exception (const struct gdb_exception &)
CPYCHECKER_SETS_EXCEPTION;
+ /* Use this in a 'catch' block to convert the exception E to a Python
+ exception and return value VAL to signal that an exception occurred.
+ Typically at the use site, that value will be returned immediately. */
+
+template<typename T>
+[[nodiscard]] T
+gdbpy_handle_gdb_exception (T val, const gdb_exception &e)
+{
+ gdbpy_convert_exception (e);
+ return val;
+}
+
int get_addr_from_python (PyObject *obj, CORE_ADDR *addr)
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
@@ -1117,4 +1115,34 @@ extern std::optional<int> gdbpy_print_insn (struct gdbarch *gdbarch,
CORE_ADDR address,
disassemble_info *info);
+/* A wrapper for PyType_Ready that also automatically registers the
+ type in the appropriate module. Returns 0 on success, -1 on error.
+ If MOD is supplied, then the type is added to that module. If MOD
+ is not supplied, the type name (tp_name field) must be of the form
+ "gdb.Mumble", and the type will be added to the gdb module. */
+
+static inline int
+gdbpy_type_ready (PyTypeObject *type, PyObject *mod = nullptr)
+{
+ if (PyType_Ready (type) < 0)
+ return -1;
+ if (mod == nullptr)
+ {
+ gdb_assert (startswith (type->tp_name, "gdb."));
+ mod = gdb_module;
+ }
+ const char *dot = strrchr (type->tp_name, '.');
+ gdb_assert (dot != nullptr);
+ return gdb_pymodule_addobject (mod, dot + 1, (PyObject *) type);
+}
+
+/* Poison PyType_Ready. Only gdbpy_type_ready should be used, to
+ avoid forgetting to register the type. See PR python/32163. */
+#undef PyType_Ready
+#ifdef __GNUC__
+# pragma GCC poison PyType_Ready
+#else
+# define PyType_Ready POISONED_PyType_Ready
+#endif
+
#endif /* PYTHON_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index e9092b4..cc06526 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -159,6 +159,8 @@ static const struct extension_language_ops python_extension_ops =
gdbpy_apply_frame_filter,
+ gdbpy_load_ptwrite_filter,
+
gdbpy_preserve_values,
gdbpy_breakpoint_has_cond,
@@ -591,7 +593,7 @@ gdbpy_parameter (PyObject *self, PyObject *args)
}
catch (const gdb_exception &ex)
{
- GDB_PY_HANDLE_EXCEPTION (ex);
+ return gdbpy_handle_gdb_exception (nullptr, ex);
}
if (cmd == CMD_LIST_AMBIGUOUS)
@@ -754,7 +756,7 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
convert the exception and continue back in Python, we should
re-enable stdin here. */
async_enable_stdin ();
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
if (to_string)
@@ -963,15 +965,14 @@ gdbpy_decode_line (PyObject *self, PyObject *args)
else
{
set_default_source_symtab_and_line ();
- def_sal = get_current_source_symtab_and_line ();
+ def_sal = get_current_source_symtab_and_line (current_program_space);
sals = def_sal;
}
}
catch (const gdb_exception &ex)
{
/* We know this will always throw. */
- gdbpy_convert_exception (ex);
- return NULL;
+ return gdbpy_handle_gdb_exception (nullptr, ex);
}
if (!sals.empty ())
@@ -1052,7 +1053,7 @@ gdbpy_parse_and_eval (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
return result;
@@ -1537,7 +1538,7 @@ gdbpy_write (PyObject *self, PyObject *args, PyObject *kw)
}
catch (const gdb_exception &except)
{
- GDB_PY_HANDLE_EXCEPTION (except);
+ return gdbpy_handle_gdb_exception (nullptr, except);
}
Py_RETURN_NONE;
@@ -2315,7 +2316,7 @@ init_done:
return false;
#define GDB_PY_DEFINE_EVENT_TYPE(name, py_name, doc, base) \
- if (gdbpy_initialize_event_generic (&name##_event_object_type, py_name) < 0) \
+ if (gdbpy_type_ready (&name##_event_object_type) < 0) \
return false;
#include "py-event-types.def"
#undef GDB_PY_DEFINE_EVENT_TYPE
diff --git a/gdb/quick-symbol.h b/gdb/quick-symbol.h
index 676c3ed..0d76e18 100644
--- a/gdb/quick-symbol.h
+++ b/gdb/quick-symbol.h
@@ -47,6 +47,11 @@ typedef bool (expand_symtabs_file_matcher_ftype) (const char *filename,
typedef bool (expand_symtabs_symbol_matcher_ftype) (const char *name);
/* Callback for quick_symbol_functions->expand_symtabs_matching
+ to match a language. */
+
+typedef bool (expand_symtabs_lang_matcher_ftype) (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. */
@@ -122,6 +127,10 @@ struct quick_symbol_functions
/* Expand 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.
+
FILE_MATCHER is called for each file in OBJFILE. The file name
is passed to it. If the matcher returns false, the file is
skipped. If FILE_MATCHER is NULL the file is not skipped. If
@@ -154,7 +163,9 @@ struct quick_symbol_functions
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
block_search_flags search_flags,
- domain_search_flags domain) = 0;
+ domain_search_flags domain,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher
+ = nullptr) = 0;
/* Return the comp unit from OBJFILE that contains PC and
SECTION. Return NULL if there is no such compunit. This
@@ -163,8 +174,8 @@ struct quick_symbol_functions
compunit that contains a symbol whose address is closest to
PC. */
virtual struct compunit_symtab *find_pc_sect_compunit_symtab
- (struct objfile *objfile, struct bound_minimal_symbol msymbol,
- CORE_ADDR pc, struct obj_section *section, int warn_if_readin) = 0;
+ (struct objfile *objfile, bound_minimal_symbol msymbol, CORE_ADDR pc,
+ struct obj_section *section, int warn_if_readin) = 0;
/* Return the comp unit from OBJFILE that contains a symbol at
ADDRESS. Return NULL if there is no such comp unit. Unlike
diff --git a/gdb/ravenscar-thread.c b/gdb/ravenscar-thread.c
index 1957f3c..47db72b 100644
--- a/gdb/ravenscar-thread.c
+++ b/gdb/ravenscar-thread.c
@@ -326,18 +326,17 @@ ravenscar_thread_target::add_active_thread ()
and return its associated minimal symbol.
Return NULL if not found. */
-static struct bound_minimal_symbol
+static bound_minimal_symbol
get_running_thread_msymbol ()
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, running_thread_name);
if (!msym.minsym)
/* Older versions of the GNAT runtime were using a different
(less ideal) name for the symbol where the active thread ID
is stored. If we couldn't find the symbol using the latest
name, then try the old one. */
- msym = lookup_minimal_symbol ("running_thread", NULL, NULL);
+ msym = lookup_minimal_symbol (current_program_space, "running_thread");
return msym;
}
@@ -348,14 +347,14 @@ get_running_thread_msymbol ()
static bool
has_ravenscar_runtime ()
{
- struct bound_minimal_symbol msym_ravenscar_runtime_initializer
- = lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
- struct bound_minimal_symbol msym_known_tasks
- = lookup_minimal_symbol (known_tasks_name, NULL, NULL);
- struct bound_minimal_symbol msym_first_task
- = lookup_minimal_symbol (first_task_name, NULL, NULL);
- struct bound_minimal_symbol msym_running_thread
- = get_running_thread_msymbol ();
+ bound_minimal_symbol msym_ravenscar_runtime_initializer
+ = lookup_minimal_symbol (current_program_space,
+ ravenscar_runtime_initializer);
+ bound_minimal_symbol msym_known_tasks
+ = lookup_minimal_symbol (current_program_space, known_tasks_name);
+ bound_minimal_symbol msym_first_task
+ = lookup_minimal_symbol (current_program_space, first_task_name);
+ bound_minimal_symbol msym_running_thread = get_running_thread_msymbol ();
return (msym_ravenscar_runtime_initializer.minsym
&& (msym_known_tasks.minsym || msym_first_task.minsym)
@@ -377,7 +376,7 @@ ravenscar_thread_target::runtime_initialized ()
static CORE_ADDR
get_running_thread_id (int cpu)
{
- struct bound_minimal_symbol object_msym = get_running_thread_msymbol ();
+ bound_minimal_symbol object_msym = get_running_thread_msymbol ();
int object_size;
int buf_size;
gdb_byte *buf;
@@ -642,7 +641,8 @@ ravenscar_thread_target::get_fpu_state (struct regcache *regcache,
return NOTHING_SPECIAL;
bound_minimal_symbol fpu_context
- = lookup_minimal_symbol ("system__bb__cpu_primitives__current_fpu_context",
+ = lookup_minimal_symbol (current_program_space,
+ "system__bb__cpu_primitives__current_fpu_context",
nullptr, nullptr);
/* If the symbol can't be found, just fall back. */
if (fpu_context.minsym == nullptr)
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 9fec611..8fcf638 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -827,6 +827,22 @@ btrace_insn_history (struct ui_out *uiout,
btrace_ui_out_decode_error (uiout, btrace_insn_get_error (&it),
conf->format);
}
+ else if (insn->iclass == BTRACE_INSN_AUX)
+ {
+ if ((flags & DISASSEMBLY_OMIT_AUX_INSN) != 0)
+ continue;
+
+ uiout->field_fmt ("insn-number", "%u", btrace_insn_number (&it));
+ uiout->text ("\t");
+ /* Add 3 spaces to match the instructions and 2 to indent the aux
+ string to make it more visible. */
+ uiout->spaces (5);
+ uiout->text ("[");
+ uiout->field_fmt ("aux-data", "%s",
+ it.btinfo->aux_data.at
+ (insn->aux_data_index).c_str ());
+ uiout->text ("]\n");
+ }
else
{
struct disasm_insn dinsn;
@@ -1145,6 +1161,31 @@ btrace_get_bfun_name (const struct btrace_function *bfun)
return "??";
}
+static void
+btrace_print_aux_insn (struct ui_out *uiout,
+ const struct btrace_function *bfun,
+ const struct btrace_thread_info *btinfo,
+ int level)
+{
+ for (const btrace_insn &insn : bfun->insn)
+ {
+ if (insn.iclass == BTRACE_INSN_AUX)
+ {
+ /* Indent to the function level. */
+ uiout->text ("\t");
+ /* Adjust for RECORD_PRINT_INDENT_CALLS and indent one
+ additional level. */
+ for (int i = 0; i <= level; ++i)
+ uiout->text (" ");
+
+ uiout->text ("[");
+ uiout->field_fmt ("aux-data", "%s",
+ btinfo->aux_data.at (insn.aux_data_index).c_str ());
+ uiout->text ("]\n");
+ }
+ }
+}
+
/* Disassemble a section of the recorded function trace. */
static void
@@ -1165,6 +1206,7 @@ btrace_call_history (struct ui_out *uiout,
const struct btrace_function *bfun;
struct minimal_symbol *msym;
struct symbol *sym;
+ int level = 0;
bfun = btrace_call_get (&it);
sym = bfun->sym;
@@ -1191,9 +1233,9 @@ btrace_call_history (struct ui_out *uiout,
if ((flags & RECORD_PRINT_INDENT_CALLS) != 0)
{
- int level = bfun->level + btinfo->level, i;
+ level = bfun->level + btinfo->level;
- for (i = 0; i < level; ++i)
+ for (int i = 0; i < level; ++i)
uiout->text (" ");
}
@@ -1220,6 +1262,10 @@ btrace_call_history (struct ui_out *uiout,
}
uiout->text ("\n");
+
+ if (((flags & RECORD_DONT_PRINT_AUX) == 0)
+ && ((bfun->flags & BFUN_CONTAINS_AUX) != 0))
+ btrace_print_aux_insn (uiout, bfun, btinfo, level);
}
}
@@ -2345,9 +2391,13 @@ record_btrace_single_step_forward (struct thread_info *tp)
return btrace_step_stopped ();
/* Skip gaps during replay. If we end up at a gap (at the end of the trace),
- jump back to the instruction at which we started. */
+ jump back to the instruction at which we started. If we're stepping a
+ BTRACE_INSN_AUX instruction, print the auxiliary data and skip the
+ instruction. */
+
start = *replay;
- do
+
+ for (;;)
{
unsigned int steps;
@@ -2359,8 +2409,23 @@ record_btrace_single_step_forward (struct thread_info *tp)
*replay = start;
return btrace_step_no_history ();
}
+
+ const struct btrace_insn *insn = btrace_insn_get (replay);
+ if (insn == nullptr)
+ continue;
+
+ /* If we're stepping a BTRACE_INSN_AUX instruction, print the auxiliary
+ data and skip the instruction. */
+ if (insn->iclass == BTRACE_INSN_AUX)
+ {
+ gdb_printf ("[%s]\n",
+ btinfo->aux_data.at (insn->aux_data_index).c_str ());
+ continue;
+ }
+
+ /* We have an instruction, we are done. */
+ break;
}
- while (btrace_insn_get (replay) == NULL);
/* Determine the end of the instruction trace. */
btrace_insn_end (&end, btinfo);
@@ -2391,9 +2456,12 @@ record_btrace_single_step_backward (struct thread_info *tp)
/* If we can't step any further, we reached the end of the history.
Skip gaps during replay. If we end up at a gap (at the beginning of
- the trace), jump back to the instruction at which we started. */
+ the trace), jump back to the instruction at which we started.
+ If we're stepping a BTRACE_INSN_AUX instruction, print the auxiliary
+ data and skip the instruction. */
start = *replay;
- do
+
+ for (;;)
{
unsigned int steps;
@@ -2403,8 +2471,22 @@ record_btrace_single_step_backward (struct thread_info *tp)
*replay = start;
return btrace_step_no_history ();
}
+
+ const struct btrace_insn *insn = btrace_insn_get (replay);
+ if (insn == nullptr)
+ continue;
+
+ /* Check if we're stepping a BTRACE_INSN_AUX instruction and skip it. */
+ if (insn->iclass == BTRACE_INSN_AUX)
+ {
+ gdb_printf ("[%s]\n",
+ btinfo->aux_data.at (insn->aux_data_index).c_str ());
+ continue;
+ }
+
+ /* We have an instruction, we are done. */
+ break;
}
- while (btrace_insn_get (replay) == NULL);
/* Check if we're stepping a breakpoint.
@@ -2826,26 +2908,33 @@ record_btrace_target::goto_record_end ()
/* The goto_record method of target record-btrace. */
void
-record_btrace_target::goto_record (ULONGEST insn)
+record_btrace_target::goto_record (ULONGEST insn_number)
{
struct thread_info *tp;
struct btrace_insn_iterator it;
unsigned int number;
int found;
- number = insn;
+ number = insn_number;
/* Check for wrap-arounds. */
- if (number != insn)
+ if (number != insn_number)
error (_("Instruction number out of range."));
tp = require_btrace_thread ();
found = btrace_find_insn_by_number (&it, &tp->btrace, number);
- /* Check if the instruction could not be found or is a gap. */
- if (found == 0 || btrace_insn_get (&it) == NULL)
+ /* Check if the instruction could not be found or is a gap or an
+ auxiliary instruction. */
+ if (found == 0)
+ error (_("No such instruction."));
+
+ const struct btrace_insn *insn = btrace_insn_get (&it);
+ if (insn == NULL)
error (_("No such instruction."));
+ if (insn->iclass == BTRACE_INSN_AUX)
+ error (_("Can't go to an auxiliary instruction."));
record_btrace_set_replay (tp, &it);
}
@@ -3091,6 +3180,36 @@ show_record_pt_buffer_size_value (struct ui_file *file, int from_tty,
value);
}
+
+static bool event_tracing = false;
+
+/* The "record pt event-tracing" show value function. */
+
+static void
+show_record_pt_event_tracing_value (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+#if (LIBIPT_VERSION >= 0x201)
+ gdb_printf (file, _("record pt event-tracing is %s.\n"), value);
+#else
+ gdb_printf (_("Event-tracing is not supported by GDB.\n"));
+#endif /* defined (LIBIPT_VERSION >= 0x201) */
+}
+
+/* The "record pt event-tracing" set value function. */
+
+static void
+set_record_pt_event_tracing_value (const char *args, int from_tty,
+ cmd_list_element *c)
+{
+#if (LIBIPT_VERSION >= 0x201)
+ record_btrace_conf.pt.event_tracing = event_tracing;
+#else
+ gdb_printf (_("Event-tracing is not supported by GDB.\n"));
+#endif /* defined (LIBIPT_VERSION >= 0x201) */
+}
+
/* Initialize btrace commands. */
void _initialize_record_btrace ();
@@ -3210,6 +3329,19 @@ to see the actual buffer size."), NULL, show_record_pt_buffer_size_value,
&set_record_btrace_pt_cmdlist,
&show_record_btrace_pt_cmdlist);
+ add_setshow_boolean_cmd ("event-tracing", no_class, &event_tracing,
+ _("Set event-tracing for record pt."),
+ _("Show event-tracing for record pt."),
+ _("\
+Use \"on\" to enable event tracing for recordings with Intel Processor Trace, \
+and \"off\" to disable it.\n\
+Without an argument, event tracing is enabled. Changing this setting has no\
+effect on an active recording."),
+ set_record_pt_event_tracing_value,
+ show_record_pt_event_tracing_value,
+ &set_record_btrace_pt_cmdlist,
+ &show_record_btrace_pt_cmdlist);
+
add_target (record_btrace_target_info, record_btrace_target_open);
bfcache = htab_create_alloc (50, bfcache_hash, bfcache_eq, NULL,
@@ -3217,4 +3349,10 @@ to see the actual buffer size."), NULL, show_record_pt_buffer_size_value,
record_btrace_conf.bts.size = 64 * 1024;
record_btrace_conf.pt.size = 16 * 1024;
+#if (LIBIPT_VERSION >= 0x200)
+ record_btrace_conf.pt.ptwrite = true;
+#else
+ record_btrace_conf.pt.ptwrite = false;
+#endif
+ record_btrace_conf.pt.event_tracing = false;
}
diff --git a/gdb/record-full.c b/gdb/record-full.c
index eb62d18..a681ef9 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -2073,6 +2073,7 @@ record_full_core_target::resume (ptid_t ptid, int step,
enum gdb_signal signal)
{
record_full_resume_step = step;
+ record_full_resume_ptid = ptid;
record_full_resumed = 1;
record_full_execution_dir = ::execution_direction;
}
@@ -2891,12 +2892,12 @@ _initialize_record_full ()
_("Restore the execution log from a file.\n\
Argument is filename. File must be created with 'record save'."),
&record_full_cmdlist);
- set_cmd_completer (record_full_restore_cmd, filename_completer);
+ set_cmd_completer (record_full_restore_cmd, deprecated_filename_completer);
/* Deprecate the old version without "full" prefix. */
c = add_alias_cmd ("restore", record_full_restore_cmd, class_obscure, 1,
&record_cmdlist);
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, deprecated_filename_completer);
deprecate_cmd (c, "record full restore");
add_setshow_prefix_cmd ("full", class_support,
diff --git a/gdb/record.c b/gdb/record.c
index b254457..8bf8a69 100644
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -491,6 +491,9 @@ get_insn_history_modifiers (const char **arg)
switch (*args)
{
+ case 'a':
+ modifiers |= DISASSEMBLY_OMIT_AUX_INSN;
+ break;
case 'm':
case 's':
modifiers |= DISASSEMBLY_SOURCE;
@@ -641,6 +644,9 @@ get_call_history_modifiers (const char **arg)
case 'c':
modifiers |= RECORD_PRINT_INDENT_CALLS;
break;
+ case 'a':
+ modifiers |= RECORD_DONT_PRINT_AUX;
+ break;
default:
error (_("Invalid modifier: %c."), *args);
}
@@ -821,7 +827,7 @@ A size of \"unlimited\" means unlimited lines. The default is 10."),
Usage: record save [FILENAME]\n\
Default filename is 'gdb_record.PROCESS_ID'."),
&record_cmdlist);
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, deprecated_filename_completer);
cmd_list_element *record_delete_cmd
= add_cmd ("delete", class_obscure, cmd_record_delete,
@@ -859,6 +865,8 @@ With a /m or /s modifier, source lines are included (if available).\n\
With a /r modifier, raw instructions in hex are included.\n\
With a /f modifier, function names are omitted.\n\
With a /p modifier, current position markers are omitted.\n\
+With a /a modifier, omits output of auxiliary data, which is enabled \
+by default.\n\
With no argument, disassembles ten more instructions after the previous \
disassembly.\n\
\"record instruction-history -\" disassembles ten instructions before a \
@@ -881,6 +889,8 @@ Without modifiers, it prints the function name.\n\
With a /l modifier, the source file and line number range is included.\n\
With a /i modifier, the instruction number range is included.\n\
With a /c modifier, the output is indented based on the call stack depth.\n\
+With a /a modifier, omits output of auxiliary data, which is enabled \
+by default.\n\
With no argument, prints ten more lines after the previous ten-line print.\n\
\"record function-call-history -\" prints ten lines before a previous ten-line \
print.\n\
diff --git a/gdb/record.h b/gdb/record.h
index f44b395..aea6507 100644
--- a/gdb/record.h
+++ b/gdb/record.h
@@ -62,7 +62,10 @@ enum record_print_flag
RECORD_PRINT_INSN_RANGE = (1 << 1),
/* Indent based on call stack depth (if applicable). */
- RECORD_PRINT_INDENT_CALLS = (1 << 2)
+ RECORD_PRINT_INDENT_CALLS = (1 << 2),
+
+ /* Deactivate printing auxiliary data (if applicable). */
+ RECORD_DONT_PRINT_AUX = (1 << 3)
};
DEF_ENUM_FLAGS_TYPE (enum record_print_flag, record_print_flags);
diff --git a/gdb/regcache-dump.c b/gdb/regcache-dump.c
index bc665dc..6b711bf 100644
--- a/gdb/regcache-dump.c
+++ b/gdb/regcache-dump.c
@@ -162,7 +162,7 @@ protected:
{
if (regnum < 0)
{
- gdb_printf (file, "Rmt Nr g/G Offset");
+ gdb_printf (file, "Rmt Nr g/G Offset Expedited");
}
else if (regnum < gdbarch_num_regs (m_gdbarch))
{
@@ -170,7 +170,12 @@ protected:
if (remote_register_number_and_offset (m_gdbarch, regnum,
&pnum, &poffset))
- gdb_printf (file, "%7d %11d", pnum, poffset);
+ {
+ if (remote_register_is_expedited (regnum))
+ gdb_printf (file, "%7d %11d yes", pnum, poffset);
+ else
+ gdb_printf (file, "%7d %11d", pnum, poffset);
+ }
}
}
};
@@ -324,9 +329,11 @@ _initialize_regcache_dump ()
"Takes an optional file parameter."),
&maintenanceprintlist);
add_cmd ("remote-registers", class_maintenance,
- maintenance_print_remote_registers, _("\
-Print the internal register configuration including remote register number "
-"and g/G packets offset.\n\
-Takes an optional file parameter."),
+ maintenance_print_remote_registers,
+ _("Print the internal register configuration including remote "
+ "register number and g/G packets offset.\n"
+ "Also prints which registers were sent in the last stop reply "
+ "packet (i.e. expedited).\n"
+ "Takes an optional file parameter."),
&maintenanceprintlist);
}
diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
index f92de61..67d3f4c 100644
--- a/gdb/remote-sim.c
+++ b/gdb/remote-sim.c
@@ -69,8 +69,7 @@ static void gdb_os_vprintf_filtered (host_callback *, const char *, va_list);
static void gdb_os_evprintf_filtered (host_callback *, const char *, va_list);
-static void gdb_os_error (host_callback *, const char *, ...)
- ATTRIBUTE_NORETURN;
+[[noreturn]] static void gdb_os_error (host_callback *, const char *, ...);
/* Naming convention:
diff --git a/gdb/remote.c b/gdb/remote.c
index 90a4bd5..5323491 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -248,6 +248,7 @@ enum {
PACKET_vFile_unlink,
PACKET_vFile_readlink,
PACKET_vFile_fstat,
+ PACKET_vFile_stat,
PACKET_qXfer_auxv,
PACKET_qXfer_features,
PACKET_qXfer_exec_file,
@@ -360,6 +361,12 @@ enum {
/* Support for the Qbtrace-conf:pt:size packet. */
PACKET_Qbtrace_conf_pt_size,
+ /* Support for the Qbtrace-conf:pt:ptwrite packet. */
+ PACKET_Qbtrace_conf_pt_ptwrite,
+
+ /* Support for the Qbtrace-conf:pt:event-tracing packet. */
+ PACKET_Qbtrace_conf_pt_event_tracing,
+
/* Support for exec events. */
PACKET_exec_event_feature,
@@ -678,7 +685,7 @@ public: /* data */
/* FIXME: cagney/1999-09-23: Even though getpkt was called with
``forever'' still use the normal timeout mechanism. This is
- currently used by the ASYNC code to guarentee that target reads
+ currently used by the ASYNC code to guarantee that target reads
during the initial connect always time-out. Once getpkt has been
modified to return a timeout indication and, in turn
remote_wait()/wait_for_inferior() have gained a timeout parameter
@@ -689,6 +696,10 @@ public: /* data */
qSupported. */
gdb_thread_options supported_thread_options = 0;
+ /* Contains the regnums of the expedited registers in the last stop
+ reply packet. */
+ std::set<int> last_seen_expedited_registers;
+
private:
/* Asynchronous signal handle registered as event loop source for
when we have pending events ready to be passed to the core. */
@@ -1010,6 +1021,9 @@ 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_close (int fd, fileio_error *target_errno) override;
int fileio_unlink (struct inferior *inf,
@@ -1483,6 +1497,20 @@ is_remote_target (process_stratum_target *target)
return as_remote_target (target) != nullptr;
}
+/* See remote.h. */
+
+bool
+remote_register_is_expedited (int regnum)
+{
+ remote_target *rt = as_remote_target (current_inferior ()->process_target ());
+
+ if (rt == nullptr)
+ return false;
+
+ remote_state *rs = rt->get_remote_state ();
+ return rs->last_seen_expedited_registers.count (regnum) > 0;
+}
+
/* Per-program-space data key. */
static const registry<program_space>::key<char, gdb::xfree_deleter<char>>
remote_pspace_data;
@@ -1539,7 +1567,7 @@ static void remote_console_output (const char *msg, ui_file *stream);
static void remote_btrace_reset (remote_state *rs);
-static void remote_unpush_and_throw (remote_target *target);
+[[noreturn]] static void remote_unpush_and_throw (remote_target *target);
/* For "remote". */
@@ -2528,9 +2556,6 @@ packet_check_result (const char *buf)
/* "Enn" - definitely an error. */
return packet_result::make_numeric_error (buf + 1);
- /* Not every request accepts an error in a E.msg form.
- Some packets accepts only Enn, in this case E. is not
- defined and E. is treated as PACKET_OK. */
/* Always treat "E." as an error. This will be used for
more verbose error messages, such as E.memtypes. */
if (buf[0] == 'E' && buf[1] == '.')
@@ -3377,17 +3402,6 @@ struct gdb_ext_thread_info
whatever. */
};
-/* The volume of remote transfers can be limited by submitting
- a mask containing bits specifying the desired information.
- Use a union of these values as the 'selection' parameter to
- get_thread_info. FIXME: Make these TAG names more thread specific. */
-
-#define TAG_THREADID 1
-#define TAG_EXISTS 2
-#define TAG_DISPLAY 4
-#define TAG_THREADNAME 8
-#define TAG_MOREDISPLAY 16
-
#define BUF_THREAD_ID_SIZE (OPAQUETHREADBYTES * 2)
static const char *unpack_nibble (const char *buf, int *val);
@@ -3918,7 +3932,7 @@ remote_target::remote_get_threadlist (int startflag, threadref *nextthread,
/* FIXME: This is a good reason to drop the packet. */
/* Possibly, there is a duplicate response. */
/* Possibilities :
- retransmit immediatly - race conditions
+ retransmit immediately - race conditions
retransmit after timeout - yes
exit
wait for packet, then exit
@@ -5514,13 +5528,12 @@ remote_target::remote_check_symbols ()
while (startswith (reply.data (), "qSymbol:"))
{
- struct bound_minimal_symbol sym;
-
tmp = &reply[8];
end = hex2bin (tmp, reinterpret_cast <gdb_byte *> (msg.data ()),
strlen (tmp) / 2);
msg[end] = '\0';
- sym = lookup_minimal_symbol (msg.data (), NULL, NULL);
+ bound_minimal_symbol sym
+ = lookup_minimal_symbol (current_program_space, msg.data ());
if (sym.minsym == NULL)
xsnprintf (msg.data (), get_remote_packet_size (), "qSymbol::%s",
&reply[8]);
@@ -5821,6 +5834,10 @@ static const struct protocol_feature remote_protocol_features[] = {
PACKET_exec_event_feature },
{ "Qbtrace-conf:pt:size", PACKET_DISABLE, remote_supported_packet,
PACKET_Qbtrace_conf_pt_size },
+ { "Qbtrace-conf:pt:ptwrite", PACKET_DISABLE, remote_supported_packet,
+ PACKET_Qbtrace_conf_pt_ptwrite },
+ { "Qbtrace-conf:pt:event-tracing", PACKET_DISABLE, remote_supported_packet,
+ PACKET_Qbtrace_conf_pt_event_tracing },
{ "vContSupported", PACKET_DISABLE, remote_supported_packet, PACKET_vContSupported },
{ "QThreadEvents", PACKET_DISABLE, remote_supported_packet, PACKET_QThreadEvents },
{ "QThreadOptions", PACKET_DISABLE, remote_supported_thread_options,
@@ -5950,7 +5967,7 @@ remote_target::remote_query_supported ()
if (m_features.packet_set_cmd_state (PACKET_accept_error_message)
!= AUTO_BOOLEAN_FALSE)
- remote_query_supported_append (&q, "error-message+");
+ remote_query_supported_append (&q, "error-message+");
q = "qSupported:" + q;
putpkt (q.c_str ());
@@ -6150,7 +6167,7 @@ remote_unpush_target (remote_target *target)
fileio_handles_invalidate_target (target);
}
-static void
+[[noreturn]] static void
remote_unpush_and_throw (remote_target *target)
{
remote_unpush_target (target);
@@ -6271,11 +6288,11 @@ remote_target::open_1 (const char *name, int from_tty, int extended_p)
}
/* First delete any symbols previously loaded from shared libraries. */
- no_shared_libraries (NULL, 0);
+ no_shared_libraries (current_program_space);
/* Start the remote connection. If error() or QUIT, discard this
target (we'd otherwise be in an inconsistent state) and then
- propogate the error on up the exception chain. This ensures that
+ propagate the error on up the exception chain. This ensures that
the caller doesn't stumble along blindly assuming that the
function succeeded. The CLI doesn't have this problem but other
UI's, such as MI do.
@@ -8524,6 +8541,10 @@ remote_target::process_stop_reply (stop_reply_up stop_reply,
{
*status = stop_reply->ws;
ptid_t ptid = stop_reply->ptid;
+ struct remote_state *rs = get_remote_state ();
+
+ /* Forget about last reply's expedited registers. */
+ rs->last_seen_expedited_registers.clear ();
/* If no thread/process was reported by the stub then select a suitable
thread/process. */
@@ -8550,7 +8571,10 @@ remote_target::process_stop_reply (stop_reply_up stop_reply,
stop_reply->arch);
for (cached_reg_t &reg : stop_reply->regcache)
- regcache->raw_supply (reg.num, reg.data.get ());
+ {
+ regcache->raw_supply (reg.num, reg.data.get ());
+ rs->last_seen_expedited_registers.insert (reg.num);
+ }
}
remote_thread_info *remote_thr = get_remote_thread_info (this, ptid);
@@ -13048,6 +13072,41 @@ remote_target::fileio_readlink (struct inferior *inf, const char *filename,
return ret;
}
+/* Helper function to handle ::fileio_fstat and ::fileio_stat result
+ processing. When this function is called the remote syscall has been
+ performed and we know we didn't get an error back.
+
+ ATTACHMENT and ATTACHMENT_LEN are the attachment data extracted from the
+ remote syscall reply. EXPECTED_LEN is the length returned from the
+ fstat or stat call, this the length of the returned data (in ATTACHMENT)
+ once it has been decoded. The fstat/stat result (from the ATTACHMENT
+ 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)
+{
+ struct fio_stat fst;
+
+ int read_len
+ = remote_unescape_input ((gdb_byte *) attachment, attachment_len,
+ (gdb_byte *) &fst, sizeof (fst));
+
+ if (read_len != expected_len)
+ error (_("vFile:fstat returned %d, but %d bytes."),
+ expected_len, read_len);
+
+ if (read_len != sizeof (fst))
+ error (_("vFile:fstat returned %d bytes, but expecting %d."),
+ read_len, (int) sizeof (fst));
+
+ remote_fileio_to_host_stat (&fst, st);
+
+ return 0;
+}
+
/* Implementation of to_fileio_fstat. */
int
@@ -13058,8 +13117,6 @@ remote_target::fileio_fstat (int fd, struct stat *st, fileio_error *remote_errno
int left = get_remote_packet_size ();
int attachment_len, ret;
const char *attachment;
- struct fio_stat fst;
- int read_len;
remote_buffer_add_string (&p, &left, "vFile:fstat:");
@@ -13091,19 +13148,41 @@ remote_target::fileio_fstat (int fd, struct stat *st, fileio_error *remote_errno
return 0;
}
- read_len = remote_unescape_input ((gdb_byte *) attachment, attachment_len,
- (gdb_byte *) &fst, sizeof (fst));
+ return fileio_process_fstat_and_stat_reply (attachment, attachment_len,
+ ret, st);
+}
- if (read_len != ret)
- error (_("vFile:fstat returned %d, but %d bytes."), ret, read_len);
+/* Implementation of to_fileio_stat. */
- if (read_len != sizeof (fst))
- error (_("vFile:fstat returned %d bytes, but expecting %d."),
- read_len, (int) sizeof (fst));
+int
+remote_target::fileio_stat (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 ();
+ int left = get_remote_packet_size () - 1;
- remote_fileio_to_host_stat (&fst, st);
+ if (remote_hostio_set_filesystem (inf, remote_errno) != 0)
+ return {};
- return 0;
+ remote_buffer_add_string (&p, &left, "vFile:stat:");
+
+ 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,
+ remote_errno, &attachment,
+ &attachment_len);
+
+ /* Unlike ::fileio_fstat, the stat fileio call was added later on, and
+ has none of the legacy bfd issues, so we can just return the error. */
+ if (ret < 0)
+ return ret;
+
+ return fileio_process_fstat_and_stat_reply (attachment, attachment_len,
+ ret, st);
}
/* Implementation of to_filesystem_is_local. */
@@ -13188,6 +13267,18 @@ public:
fileio_error remote_errno;
m_remote->remote_hostio_close (m_fd, &remote_errno);
}
+ catch (const gdb_exception_quit &ex)
+ {
+ /* We can't throw from a destructor, so re-set the quit flag
+ for later QUIT checking. */
+ set_quit_flag ();
+ }
+ catch (const gdb_exception_forced_quit &ex)
+ {
+ /* Like above, but (eventually) cause GDB to terminate by
+ setting sync_quit_force_run. */
+ set_force_quit_flag ();
+ }
catch (...)
{
/* Swallow exception before it escapes the dtor. If
@@ -14692,7 +14783,7 @@ parse_xml_btrace_conf_pt (struct gdb_xml_parser *parser,
std::vector<gdb_xml_value> &attributes)
{
struct btrace_config *conf;
- struct gdb_xml_value *size;
+ struct gdb_xml_value *size, *ptwrite, *event_tracing;
conf = (struct btrace_config *) user_data;
conf->format = BTRACE_FORMAT_PT;
@@ -14701,10 +14792,22 @@ parse_xml_btrace_conf_pt (struct gdb_xml_parser *parser,
size = xml_find_attribute (attributes, "size");
if (size != NULL)
conf->pt.size = (unsigned int) *(ULONGEST *) size->value.get ();
+
+ ptwrite = xml_find_attribute (attributes, "ptwrite");
+ if (ptwrite != nullptr)
+ conf->pt.ptwrite = (bool) *(ULONGEST *) ptwrite->value.get ();
+
+ event_tracing = xml_find_attribute (attributes, "event-tracing");
+ if (event_tracing != nullptr)
+ conf->pt.event_tracing = (bool) *(ULONGEST *) event_tracing->value.get ();
}
static const struct gdb_xml_attribute btrace_conf_pt_attributes[] = {
{ "size", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
+ { "ptwrite", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_enum,
+ gdb_xml_enums_boolean },
+ { "event-tracing", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_enum,
+ gdb_xml_enums_boolean },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
@@ -14810,6 +14913,65 @@ remote_target::btrace_sync_conf (const btrace_config *conf)
rs->btrace_config.pt.size = conf->pt.size;
}
+
+ if ((m_features.packet_support (PACKET_Qbtrace_conf_pt_ptwrite)
+ == PACKET_ENABLE)
+ && conf->pt.ptwrite != rs->btrace_config.pt.ptwrite)
+ {
+ pos = buf;
+ const char *ptw = conf->pt.ptwrite ? "yes" : "no";
+ const char *name
+ = packets_descriptions[PACKET_Qbtrace_conf_pt_ptwrite].name;
+ pos += xsnprintf (pos, endbuf - pos, "%s=\"%s\"", name, ptw);
+
+ putpkt (buf);
+ getpkt (&rs->buf, 0);
+
+ packet_result result
+ = m_features.packet_ok (buf, PACKET_Qbtrace_conf_pt_ptwrite);
+ if (result.status () == PACKET_ERROR)
+ {
+ if (buf[0] == 'E' && buf[1] == '.')
+ error (_("Failed to sync ptwrite config: %s"), buf + 2);
+ else
+ error (_("Failed to sync ptwrite config."));
+ }
+
+ rs->btrace_config.pt.ptwrite = conf->pt.ptwrite;
+ }
+
+ /* Event tracing is a user setting, warn if it is set but the target
+ doesn't support it. */
+ if ((m_features.packet_support (PACKET_Qbtrace_conf_pt_event_tracing)
+ != PACKET_ENABLE)
+ && conf->pt.event_tracing)
+ warning (_("Target does not support event-tracing."));
+
+ if ((m_features.packet_support (PACKET_Qbtrace_conf_pt_event_tracing)
+ == PACKET_ENABLE)
+ && conf->pt.event_tracing != rs->btrace_config.pt.event_tracing)
+ {
+ pos = buf;
+ const char *event_tracing = conf->pt.event_tracing ? "yes" : "no";
+ const char *name
+ = packets_descriptions[PACKET_Qbtrace_conf_pt_event_tracing].name;
+ pos += xsnprintf (pos, endbuf - pos, "%s=\"%s\"", name, event_tracing);
+
+ putpkt (buf);
+ getpkt (&rs->buf, 0);
+
+ packet_result result
+ = m_features.packet_ok (buf, PACKET_Qbtrace_conf_pt_event_tracing);
+ if (result.status () == PACKET_ERROR)
+ {
+ if (buf[0] == 'E' && buf[1] == '.')
+ error (_("Failed to sync event-tracing config: %s"), buf + 2);
+ else
+ error (_("Failed to sync event-tracing config."));
+ }
+
+ rs->btrace_config.pt.event_tracing = conf->pt.event_tracing;
+ }
}
/* Read TP's btrace configuration from the target and store it into CONF. */
@@ -15165,7 +15327,7 @@ static serial_event_ftype remote_async_serial_handler;
static void
remote_async_serial_handler (struct serial *scb, void *context)
{
- /* Don't propogate error information up to the client. Instead let
+ /* Don't propagate error information up to the client. Instead let
the client find out about the error by querying the target. */
inferior_event_handler (INF_REG_EVENT);
}
@@ -15444,7 +15606,7 @@ remote_objfile_changed_check_symbols (program_space *pspace)
static void
remote_new_objfile (struct objfile *objfile)
{
- remote_objfile_changed_check_symbols (objfile->pspace);
+ remote_objfile_changed_check_symbols (objfile->pspace ());
}
/* Pull all the tracepoints defined on the target and create local
@@ -16178,6 +16340,8 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
add_packet_config_cmd (PACKET_vFile_fstat, "vFile:fstat", "hostio-fstat", 0);
+ add_packet_config_cmd (PACKET_vFile_stat, "vFile:stat", "hostio-stat", 0);
+
add_packet_config_cmd (PACKET_vAttach, "vAttach", "attach", 0);
add_packet_config_cmd (PACKET_vRun, "vRun", "run", 0);
@@ -16262,6 +16426,13 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
add_packet_config_cmd (PACKET_Qbtrace_conf_pt_size, "Qbtrace-conf:pt:size",
"btrace-conf-pt-size", 0);
+ add_packet_config_cmd (PACKET_Qbtrace_conf_pt_ptwrite, "Qbtrace-conf:pt:ptwrite",
+ "btrace-conf-pt-ptwrite", 0);
+
+ add_packet_config_cmd (PACKET_Qbtrace_conf_pt_event_tracing,
+ "Qbtrace-conf:pt:event-tracing",
+ "btrace-conf-pt-event-tracing", 0);
+
add_packet_config_cmd (PACKET_vContSupported, "vContSupported",
"verbose-resume-supported", 0);
diff --git a/gdb/remote.h b/gdb/remote.h
index cb0a66d..bfe3c65 100644
--- a/gdb/remote.h
+++ b/gdb/remote.h
@@ -121,4 +121,9 @@ extern void send_remote_packet (gdb::array_view<const char> &buf,
extern bool is_remote_target (process_stratum_target *target);
+/* Return true if REGNUM was returned as an expedited register in the last
+ stop reply we received. */
+
+extern bool remote_register_is_expedited (int regnum);
+
#endif
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index d592d2d..932708c 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -1015,7 +1015,7 @@ riscv_pseudo_register_write (struct gdbarch *gdbarch,
if (regnum == tdep->fflags_regnum || regnum == tdep->frm_regnum)
{
int fcsr_regnum = RISCV_CSR_FCSR_REGNUM;
- gdb_byte raw_buf[register_size (gdbarch, fcsr_regnum)];
+ gdb::byte_vector raw_buf (register_size (gdbarch, fcsr_regnum));
regcache->raw_read (fcsr_regnum, raw_buf);
diff --git a/gdb/rs6000-aix-nat.c b/gdb/rs6000-aix-nat.c
index 908671a..6a20f61 100644
--- a/gdb/rs6000-aix-nat.c
+++ b/gdb/rs6000-aix-nat.c
@@ -993,7 +993,7 @@ rs6000_nat_target::create_inferior (const char *exec_file,
info.bfd_arch_info = bfd_get_arch_info (&abfd);
info.abfd = current_program_space->exec_bfd ();
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("rs6000_create_inferior: failed "
"to select architecture"));
}
diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c
index 3faefe5..3cc0232 100644
--- a/gdb/rs6000-aix-tdep.c
+++ b/gdb/rs6000-aix-tdep.c
@@ -524,7 +524,7 @@ rs6000_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
on PPC variants that lack them. */
gdb_assert (ppc_floating_point_unit_p (gdbarch));
- /* The first eight words of ther arguments are passed in registers.
+ /* The first eight words of the arguments are passed in registers.
Copy them appropriately. */
ii = 0;
diff --git a/gdb/rs6000-lynx178-tdep.c b/gdb/rs6000-lynx178-tdep.c
index 17244b3..a5a6bb9 100644
--- a/gdb/rs6000-lynx178-tdep.c
+++ b/gdb/rs6000-lynx178-tdep.c
@@ -56,7 +56,7 @@ rs6000_lynx178_push_dummy_call (struct gdbarch *gdbarch,
on PPC variants that lack them. */
gdb_assert (ppc_floating_point_unit_p (gdbarch));
- /* The first eight words of ther arguments are passed in registers.
+ /* The first eight words of the arguments are passed in registers.
Copy them appropriately. */
ii = 0;
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 2edb823..d7f9698 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -1389,7 +1389,7 @@ rs6000_fetch_instruction (struct gdbarch *gdbarch, const CORE_ADDR pc)
return op;
}
-/* GCC generates several well-known sequences of instructions at the begining
+/* GCC generates several well-known sequences of instructions at the beginning
of each function prologue when compiling with -fstack-check. If one of
such sequences starts at START_PC, then return the address of the
instruction immediately past this sequence. Otherwise, return START_PC. */
@@ -2250,7 +2250,7 @@ rs6000_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
CORE_ADDR displ = op & BL_DISPLACEMENT_MASK;
CORE_ADDR call_dest = pc + 4 + displ;
- struct bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest);
+ bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest);
/* We check for ___eabi (three leading underscores) in addition
to __eabi in case the GCC option "-fleading-underscore" was
@@ -2324,7 +2324,6 @@ rs6000_skip_trampoline_code (const frame_info_ptr &frame, CORE_ADDR pc)
unsigned int ii, op;
int rel;
CORE_ADDR solib_target_pc;
- struct bound_minimal_symbol msymbol;
static unsigned trampoline_code[] =
{
@@ -2339,7 +2338,7 @@ rs6000_skip_trampoline_code (const frame_info_ptr &frame, CORE_ADDR pc)
};
/* Check for bigtoc fixup code. */
- msymbol = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (pc);
if (msymbol.minsym
&& rs6000_in_solib_return_trampoline (gdbarch, pc,
msymbol.minsym->linkage_name ()))
@@ -4299,7 +4298,7 @@ ppc_record_ACC_fpscr (struct regcache *regcache, ppc_gdbarch_tdep *tdep,
ACC[7][3] -> VSR[31]
NOTE:
- In ISA 3.1 the ACC is mapped on top of VSR[0] thru VSR[31].
+ In ISA 3.1 the ACC is mapped on top of VSR[0] through VSR[31].
In the future, the ACC may be implemented as an independent register file
rather than mapping on top of the VSRs. This will then require the ACC to
@@ -8604,7 +8603,7 @@ powerpc_set_soft_float (const char *args, int from_tty,
struct gdbarch_info info;
/* Update the architecture. */
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("could not update architecture"));
}
@@ -8630,7 +8629,7 @@ powerpc_set_vector_abi (const char *args, int from_tty,
/* Update the architecture. */
gdbarch_info info;
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("could not update architecture"));
}
diff --git a/gdb/run-on-main-thread.c b/gdb/run-on-main-thread.c
index e30daba..746ea35 100644
--- a/gdb/run-on-main-thread.c
+++ b/gdb/run-on-main-thread.c
@@ -74,7 +74,20 @@ run_events (int error, gdb_client_data client_data)
{
item ();
}
- catch (...)
+ catch (const gdb_exception_forced_quit &e)
+ {
+ /* GDB is terminating, so:
+ - make sure this is propagated, and
+ - no need to keep running things, so propagate immediately. */
+ throw;
+ }
+ catch (const gdb_exception_quit &e)
+ {
+ /* Should cancelation of a runnable event cancel the execution of
+ the following one? The answer is not clear, so keep doing what
+ we've done so far: ignore this exception. */
+ }
+ catch (const gdb_exception &)
{
/* Ignore exceptions in the callback. */
}
diff --git a/gdb/rust-lang.h b/gdb/rust-lang.h
index 9ae5961..866d1ac 100644
--- a/gdb/rust-lang.h
+++ b/gdb/rust-lang.h
@@ -45,7 +45,7 @@ extern const char *rust_last_path_segment (const char *path);
/* Create a new slice type. NAME is the name of the type. ELT_TYPE
is the type of the elements of the slice. USIZE_TYPE is the Rust
- "usize" type to use. The new type is allocated whereever ELT_TYPE
+ "usize" type to use. The new type is allocated wherever ELT_TYPE
is allocated. */
extern struct type *rust_slice_type (const char *name, struct type *elt_type,
struct type *usize_type);
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
index 6687127..064cf68 100644
--- a/gdb/s390-tdep.c
+++ b/gdb/s390-tdep.c
@@ -1897,7 +1897,7 @@ s390_handle_arg (struct s390_arg_state *as, struct value *arg,
for S/390 ELF Application Binary Interface Supplement".
SP is the current stack pointer. We must put arguments, links,
- padding, etc. whereever they belong, and return the new stack
+ padding, etc. wherever they belong, and return the new stack
pointer value.
If STRUCT_RETURN is non-zero, then the function we're calling is
diff --git a/gdb/ser-base.c b/gdb/ser-base.c
index 81ef942..838560e 100644
--- a/gdb/ser-base.c
+++ b/gdb/ser-base.c
@@ -148,7 +148,7 @@ run_async_handler_and_reschedule (struct serial *scb)
/* FD_EVENT: This is scheduled when the input FIFO is empty (and there
is no pending error). As soon as data arrives, it is read into the
input FIFO and the client notified. The client should then drain
- the FIFO using readchar(). If the FIFO isn't immediatly emptied,
+ the FIFO using readchar(). If the FIFO isn't immediately emptied,
push_event() is used to nag the client until it is. */
static void
@@ -419,7 +419,7 @@ do_ser_base_readchar (struct serial *scb, int timeout)
pre-reads the input into that FIFO. Once that has been emptied,
further data is obtained by polling the input FD using the device
specific readchar() function. Note: reschedule() is called after
- every read. This is because there is no guarentee that the lower
+ every read. This is because there is no guarantee that the lower
level fd_event() poll_event() code (which also calls reschedule())
will be called. */
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
index 0dbb905..d211265 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -1057,7 +1057,7 @@ sh_push_dummy_call_fpu (struct gdbarch *gdbarch,
/* Now load as many as possible of the first arguments into
registers, and push the rest onto the stack. There are 16 bytes
- in four registers available. Loop thru args from first to last. */
+ in four registers available. Loop through args from first to last. */
for (argnum = 0; argnum < nargs; argnum++)
{
type = args[argnum]->type ();
@@ -1195,7 +1195,7 @@ sh_push_dummy_call_nofpu (struct gdbarch *gdbarch,
/* Now load as many as possible of the first arguments into
registers, and push the rest onto the stack. There are 16 bytes
- in four registers available. Loop thru args from first to last. */
+ in four registers available. Loop through args from first to last. */
for (argnum = 0; argnum < nargs; argnum++)
{
type = args[argnum]->type ();
@@ -2171,7 +2171,7 @@ sh_corefile_collect_regset (const struct regset *regset,
}
/* The following two regsets have the same contents, so it is tempting to
- unify them, but they are distiguished by their address, so don't. */
+ unify them, but they are distinguished by their address, so don't. */
const struct regset sh_corefile_gregset =
{
diff --git a/gdb/skip.c b/gdb/skip.c
index 72f4efd..3791c29 100644
--- a/gdb/skip.c
+++ b/gdb/skip.c
@@ -684,7 +684,7 @@ Ignore a file while stepping.\n\
Usage: skip file [FILE-NAME]\n\
If no filename is given, ignore the current file."),
&skiplist);
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, deprecated_filename_completer);
c = add_cmd ("function", class_breakpoint, skip_function_command, _("\
Ignore a function while stepping.\n\
diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c
index 77740fe..db86079 100644
--- a/gdb/sol-thread.c
+++ b/gdb/sol-thread.c
@@ -759,9 +759,8 @@ ps_err_e
ps_pglobal_lookup (struct ps_prochandle *ph, const char *ld_object_name,
const char *ld_symbol_name, psaddr_t *ld_symbol_addr)
{
- struct bound_minimal_symbol ms;
-
- ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL);
+ bound_minimal_symbol ms
+ = lookup_minimal_symbol (current_program_space, ld_symbol_name);
if (!ms.minsym)
return PS_NOSYM;
@@ -1068,7 +1067,7 @@ info_cb (const td_thrhandle_t *th, void *s)
/* Print thr_create start function. */
if (ti.ti_startfunc != 0)
{
- const struct bound_minimal_symbol msym
+ const bound_minimal_symbol msym
= lookup_minimal_symbol_by_pc (ti.ti_startfunc);
gdb_printf (" startfunc=%s",
@@ -1081,7 +1080,7 @@ info_cb (const td_thrhandle_t *th, void *s)
/* If thread is asleep, print function that went to sleep. */
if (ti.ti_state == TD_THR_SLEEP)
{
- const struct bound_minimal_symbol msym
+ const bound_minimal_symbol msym
= lookup_minimal_symbol_by_pc (ti.ti_pc);
gdb_printf (" sleepfunc=%s",
diff --git a/gdb/sol2-tdep.c b/gdb/sol2-tdep.c
index 468b132..0beab74 100644
--- a/gdb/sol2-tdep.c
+++ b/gdb/sol2-tdep.c
@@ -63,9 +63,8 @@ sol2_sigtramp_p (const frame_info_ptr &this_frame)
static CORE_ADDR
sol2_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol("elf_bndr", NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, "elf_bndr");
if (msym.minsym && msym.value_address () == pc)
return frame_unwind_caller_pc (get_current_frame ());
diff --git a/gdb/solib-aix.c b/gdb/solib-aix.c
index a50bb16..926f1ed 100644
--- a/gdb/solib-aix.c
+++ b/gdb/solib-aix.c
@@ -444,7 +444,7 @@ solib_aix_solib_create_inferior_hook (int from_tty)
/* Implement the "current_sos" solib_ops method. */
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
solib_aix_current_sos ()
{
std::optional<std::vector<lm_info_aix>> &library_list
@@ -452,14 +452,13 @@ solib_aix_current_sos ()
if (!library_list.has_value ())
return {};
- intrusive_list<solib> sos;
+ owning_intrusive_list<solib> sos;
/* Build a struct solib for each entry on the list.
We skip the first entry, since this is the entry corresponding
to the main executable, not a shared library. */
for (int ix = 1; ix < library_list->size (); ix++)
{
- solib *new_solib = new solib;
std::string so_name;
lm_info_aix &info = (*library_list)[ix];
@@ -481,12 +480,11 @@ solib_aix_current_sos ()
info.member_name.c_str ());
}
- new_solib->so_original_name = so_name;
- new_solib->so_name = so_name;
- new_solib->lm_info = std::make_unique<lm_info_aix> (info);
-
/* Add it to the list. */
- sos.push_back (*new_solib);
+ auto &new_solib = sos.emplace_back ();
+ new_solib.so_original_name = so_name;
+ new_solib.so_name = so_name;
+ new_solib.lm_info = std::make_unique<lm_info_aix> (info);
}
return sos;
@@ -689,6 +687,11 @@ const solib_ops solib_aix_so_ops =
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 ();
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index f0828fd..6c7d906 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -212,7 +212,7 @@ open_symbol_file_object (int from_tty)
/* Build a list of currently loaded shared objects. See solib-svr4.c. */
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
darwin_current_sos ()
{
type *ptr_type
@@ -230,7 +230,7 @@ darwin_current_sos ()
image_info_size = ptr_len * 3;
- intrusive_list<solib> sos;
+ owning_intrusive_list<solib> sos;
/* Read infos for each solib.
The first entry was rumored to be the executable itself, but this is not
@@ -239,18 +239,18 @@ darwin_current_sos ()
for (int i = 0; i < info->all_image.count; i++)
{
CORE_ADDR iinfo = info->all_image.info + i * image_info_size;
- gdb_byte buf[image_info_size];
+ gdb::byte_vector buf (image_info_size);
CORE_ADDR load_addr;
CORE_ADDR path_addr;
struct mach_o_header_external hdr;
unsigned long hdr_val;
/* Read image info from inferior. */
- if (target_read_memory (iinfo, buf, image_info_size))
+ if (target_read_memory (iinfo, buf.data (), image_info_size))
break;
- load_addr = extract_typed_address (buf, ptr_type);
- path_addr = extract_typed_address (buf + ptr_len, ptr_type);
+ load_addr = extract_typed_address (buf.data (), ptr_type);
+ path_addr = extract_typed_address (buf.data () + ptr_len, ptr_type);
/* Read Mach-O header from memory. */
if (target_read_memory (load_addr, (gdb_byte *) &hdr, sizeof (hdr) - 4))
@@ -272,16 +272,15 @@ darwin_current_sos ()
break;
/* Create and fill the new struct solib element. */
- solib *newobj = new solib;
+ auto &newobj = sos.emplace_back ();
auto li = std::make_unique<lm_info_darwin> ();
- newobj->so_name = file_path.get ();
- newobj->so_original_name = newobj->so_name;
+ newobj.so_name = file_path.get ();
+ newobj.so_original_name = newobj.so_name;
li->lm_addr = load_addr;
- newobj->lm_info = std::move (li);
- sos.push_back (*newobj);
+ newobj.lm_info = std::move (li);
}
return sos;
@@ -333,14 +332,14 @@ darwin_read_exec_load_addr_from_dyld (struct darwin_info *info)
for (i = 0; i < info->all_image.count; i++)
{
CORE_ADDR iinfo = info->all_image.info + i * image_info_size;
- gdb_byte buf[image_info_size];
+ gdb::byte_vector buf (image_info_size);
CORE_ADDR load_addr;
/* Read image info from inferior. */
- if (target_read_memory (iinfo, buf, image_info_size))
+ if (target_read_memory (iinfo, buf.data (), image_info_size))
break;
- load_addr = extract_typed_address (buf, ptr_type);
+ load_addr = extract_typed_address (buf.data (), ptr_type);
if (darwin_validate_exec_header (load_addr) == load_addr)
return load_addr;
}
@@ -665,4 +664,9 @@ const solib_ops darwin_so_ops =
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-dsbt.c b/gdb/solib-dsbt.c
index 908c78a..360aede 100644
--- a/gdb/solib-dsbt.c
+++ b/gdb/solib-dsbt.c
@@ -434,7 +434,6 @@ static CORE_ADDR
lm_base (void)
{
bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
- struct bound_minimal_symbol got_sym;
CORE_ADDR addr;
gdb_byte buf[TIC6X_PTR_SIZE];
dsbt_info *info = get_dsbt_info (current_program_space);
@@ -451,8 +450,9 @@ lm_base (void)
if (info->lm_base_cache)
return info->lm_base_cache;
- got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_", NULL,
- current_program_space->symfile_object_file);
+ bound_minimal_symbol got_sym
+ = lookup_minimal_symbol (current_program_space, "_GLOBAL_OFFSET_TABLE_",
+ current_program_space->symfile_object_file);
if (got_sym.minsym != 0)
{
@@ -512,13 +512,13 @@ lm_base (void)
themselves. The declaration of `struct solib' says which fields
we provide values for. */
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
dsbt_current_sos (void)
{
bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
CORE_ADDR lm_addr;
dsbt_info *info = get_dsbt_info (current_program_space);
- intrusive_list<solib> sos;
+ owning_intrusive_list<solib> sos;
/* Make sure that the main executable has been relocated. This is
required in order to find the address of the global offset table,
@@ -594,7 +594,7 @@ dsbt_current_sos (void)
break;
}
- solib *sop = new solib;
+ auto &sop = sos.emplace_back ();
auto li = std::make_unique<lm_info_dsbt> ();
li->map = loadmap;
/* Fetch the name. */
@@ -612,12 +612,11 @@ 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.so_name = name_buf.get ();
+ sop.so_original_name = sop.so_name;
}
- sop->lm_info = std::move (li);
- sos.push_back (*sop);
+ sop.lm_info = std::move (li);
}
else
{
@@ -914,6 +913,11 @@ const solib_ops dsbt_so_ops =
open_symbol_file_object,
dsbt_in_dynsym_resolve_code,
solib_bfd_open,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ default_find_solib_addr,
};
void _initialize_dsbt_solib ();
diff --git a/gdb/solib-frv.c b/gdb/solib-frv.c
index 39508fa..25873e6 100644
--- a/gdb/solib-frv.c
+++ b/gdb/solib-frv.c
@@ -264,7 +264,6 @@ static CORE_ADDR
lm_base (void)
{
bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
- struct bound_minimal_symbol got_sym;
CORE_ADDR addr;
gdb_byte buf[FRV_PTR_SIZE];
@@ -280,8 +279,9 @@ lm_base (void)
if (lm_base_cache)
return lm_base_cache;
- got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_", NULL,
- current_program_space->symfile_object_file);
+ bound_minimal_symbol got_sym
+ = lookup_minimal_symbol (current_program_space, "_GLOBAL_OFFSET_TABLE_",
+ current_program_space->symfile_object_file);
if (got_sym.minsym == 0)
{
solib_debug_printf ("_GLOBAL_OFFSET_TABLE_ not found.");
@@ -306,12 +306,12 @@ lm_base (void)
/* Implement the "current_sos" solib_ops method. */
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
frv_current_sos ()
{
bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
CORE_ADDR lm_addr, mgot;
- intrusive_list<solib> sos;
+ owning_intrusive_list<solib> sos;
/* Make sure that the main executable has been relocated. This is
required in order to find the address of the global offset table,
@@ -377,11 +377,13 @@ frv_current_sos ()
break;
}
- solib *sop = new solib;
+ auto &sop = sos.emplace_back ();
auto li = std::make_unique<lm_info_frv> ();
li->map = loadmap;
li->got_value = got_addr;
li->lm_addr = lm_addr;
+ sop.lm_info = std::move (li);
+
/* Fetch the name. */
addr = extract_unsigned_integer (lm_buf.l_name,
sizeof (lm_buf.l_name),
@@ -395,11 +397,9 @@ 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.so_name = name_buf.get ();
+ sop.so_original_name = sop.so_name;
}
-
- sos.push_back (*sop);
}
else
{
@@ -687,7 +687,7 @@ enable_break (void)
return 0;
}
- if (!entry_point_address_query (&entry_point))
+ if (!entry_point_address_query (current_program_space, &entry_point))
{
solib_debug_printf ("Symbol file has no entry point.");
return 0;
@@ -838,10 +838,10 @@ frv_relocate_section_addresses (solib &so, target_section *sec)
static CORE_ADDR
main_got (void)
{
- struct bound_minimal_symbol got_sym;
-
objfile *objf = current_program_space->symfile_object_file;
- got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_", NULL, objf);
+ bound_minimal_symbol got_sym
+ = lookup_minimal_symbol (current_program_space, "_GLOBAL_OFFSET_TABLE_",
+ objf);
if (got_sym.minsym == 0)
return 0;
@@ -1084,4 +1084,9 @@ const solib_ops frv_so_ops =
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-rocm.c b/gdb/solib-rocm.c
index 9b995c7..156b36a 100644
--- a/gdb/solib-rocm.c
+++ b/gdb/solib-rocm.c
@@ -204,20 +204,18 @@ rocm_solib_handle_event ()
/* Create so_list objects from rocm_so objects in SOS. */
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
so_list_from_rocm_sos (const std::vector<rocm_so> &sos)
{
- intrusive_list<solib> dst;
+ owning_intrusive_list<solib> dst;
for (const rocm_so &so : sos)
{
- solib *newobj = new solib;
- newobj->lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
+ auto &newobj = dst.emplace_back ();
- newobj->so_name = so.name;
- newobj->so_original_name = so.unique_name;
-
- dst.push_back (*newobj);
+ newobj.lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
+ newobj.so_name = so.name;
+ newobj.so_original_name = so.unique_name;
}
return dst;
@@ -226,11 +224,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 intrusive_list<solib>
+static owning_intrusive_list<solib>
rocm_solib_current_sos ()
{
/* First, retrieve the host-side shared library list. */
- intrusive_list<solib> sos = svr4_so_ops.current_sos ();
+ owning_intrusive_list<solib> sos = svr4_so_ops.current_sos ();
/* Then, the device-side shared library list. */
std::vector<rocm_so> &dev_sos = get_solib_info (current_inferior ())->solib_list;
@@ -238,7 +236,7 @@ rocm_solib_current_sos ()
if (dev_sos.empty ())
return sos;
- intrusive_list<solib> dev_so_list = so_list_from_rocm_sos (dev_sos);
+ owning_intrusive_list<solib> dev_so_list = so_list_from_rocm_sos (dev_sos);
if (sos.empty ())
return dev_so_list;
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 5c8557e..7999a8e 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -619,7 +619,7 @@ find_program_interpreter (void)
/* Scan for DESIRED_DYNTAG in .dynamic section of the target's main executable,
- found by consulting the OS auxillary vector. If DESIRED_DYNTAG is found, 1
+ found by consulting the OS auxiliary vector. If DESIRED_DYNTAG is found, 1
is returned and the corresponding PTR is set. */
static int
@@ -695,7 +695,6 @@ scan_dyntag_auxv (const int desired_dyntag, CORE_ADDR *ptr,
static CORE_ADDR
elf_locate_base (void)
{
- struct bound_minimal_symbol msymbol;
CORE_ADDR dyn_ptr, dyn_ptr_addr;
if (!svr4_have_link_map_offsets ())
@@ -751,8 +750,9 @@ elf_locate_base (void)
/* This may be a static executable. Look for the symbol
conventionally named _r_debug, as a last resort. */
- msymbol = lookup_minimal_symbol ("_r_debug", NULL,
- current_program_space->symfile_object_file);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space, "_r_debug",
+ current_program_space->symfile_object_file);
if (msymbol.minsym != NULL)
return msymbol.value_address ();
@@ -991,20 +991,18 @@ svr4_clear_so (const solib &so)
/* Create the so_list objects equivalent to the svr4_sos in SOS. */
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
so_list_from_svr4_sos (const std::vector<svr4_so> &sos)
{
- intrusive_list<solib> dst;
+ owning_intrusive_list<solib> dst;
for (const svr4_so &so : sos)
{
- struct solib *newobj = new struct solib;
+ auto &newobj = dst.emplace_back ();
- newobj->so_name = so.name;
- newobj->so_original_name = so.name;
- newobj->lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
-
- dst.push_back (*newobj);
+ newobj.so_name = so.name;
+ newobj.so_original_name = so.name;
+ newobj.lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
}
return dst;
@@ -1184,25 +1182,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 intrusive_list<solib>
+static owning_intrusive_list<solib>
svr4_default_sos (svr4_info *info)
{
if (!info->debug_loader_offset_p)
return {};
- solib *newobj = new solib;
auto li = std::make_unique<lm_info_svr4> ();
/* 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;
- newobj->lm_info = std::move (li);
- newobj->so_name = info->debug_loader_name;
- newobj->so_original_name = newobj->so_name;
+ owning_intrusive_list<solib> sos;
+ auto &newobj = sos.emplace_back ();
- intrusive_list<solib> sos;
- sos.push_back (*newobj);
+ newobj.lm_info = std::move (li);
+ newobj.so_name = info->debug_loader_name;
+ newobj.so_original_name = newobj.so_name;
return sos;
}
@@ -1373,10 +1370,10 @@ svr4_current_sos_direct (struct svr4_info *info)
/* Collect sos read and stored by the probes interface. */
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
svr4_collect_probes_sos (svr4_info *info)
{
- intrusive_list<solib> res;
+ owning_intrusive_list<solib> res;
for (const auto &tuple : info->solib_lists)
{
@@ -1390,10 +1387,10 @@ svr4_collect_probes_sos (svr4_info *info)
/* Implement the main part of the "current_sos" solib_ops
method. */
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
svr4_current_sos_1 (svr4_info *info)
{
- intrusive_list<solib> sos;
+ 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. */
@@ -1417,11 +1414,11 @@ svr4_current_sos_1 (svr4_info *info)
/* Implement the "current_sos" solib_ops method. */
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
svr4_current_sos ()
{
svr4_info *info = get_svr4_info (current_program_space);
- intrusive_list<solib> sos = svr4_current_sos_1 (info);
+ owning_intrusive_list<solib> sos = svr4_current_sos_1 (info);
struct mem_range vsyscall_range;
/* Filter out the vDSO module, if present. Its symbol file would
@@ -1478,9 +1475,7 @@ svr4_current_sos ()
if (vsyscall_range.contains (li->l_ld))
{
- auto next = sos.erase (so);
- delete &*so;
- so = next;
+ so = sos.erase (so);
break;
}
@@ -1496,7 +1491,7 @@ svr4_current_sos ()
CORE_ADDR
svr4_fetch_objfile_link_map (struct objfile *objfile)
{
- struct svr4_info *info = get_svr4_info (objfile->pspace);
+ struct svr4_info *info = get_svr4_info (objfile->pspace ());
/* Cause svr4_current_sos() to be run if it hasn't been already. */
if (info->main_lm_addr == 0)
@@ -1625,7 +1620,7 @@ probes_table_htab_remove_objfile_probes (void **slot, void *info)
struct objfile *objfile = (struct objfile *) info;
if (pa->objfile == objfile)
- htab_clear_slot (get_svr4_info (objfile->pspace)->probes_table.get (),
+ htab_clear_slot (get_svr4_info (objfile->pspace ())->probes_table.get (),
slot);
return 1;
@@ -1636,7 +1631,7 @@ probes_table_htab_remove_objfile_probes (void **slot, void *info)
static void
probes_table_remove_objfile_probes (struct objfile *objfile)
{
- svr4_info *info = get_svr4_info (objfile->pspace);
+ svr4_info *info = get_svr4_info (objfile->pspace ());
if (info->probes_table != nullptr)
htab_traverse_noresize (info->probes_table.get (),
probes_table_htab_remove_objfile_probes, objfile);
@@ -1948,7 +1943,7 @@ svr4_handle_solib_event (void)
{
link_map_id_val = pa->prob->evaluate_argument (0, frame);
}
- catch (const gdb_exception_error)
+ catch (const gdb_exception_error &)
{
link_map_id_val = NULL;
}
@@ -2227,7 +2222,6 @@ svr4_create_solib_event_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
static int
enable_break (struct svr4_info *info, int from_tty)
{
- struct bound_minimal_symbol msymbol;
const char * const *bkpt_namep;
asection *interp_sect;
CORE_ADDR sym_addr;
@@ -2361,7 +2355,7 @@ enable_break (struct svr4_info *info, int from_tty)
}
/* If we were not able to find the base address of the loader
- from our so_list, then try using the AT_BASE auxilliary entry. */
+ from our so_list, then try using the AT_BASE auxiliary entry. */
if (!load_addr_found)
if (target_auxv_search (AT_BASE, &load_addr) > 0)
{
@@ -2482,7 +2476,8 @@ enable_break (struct svr4_info *info, int from_tty)
objfile *objf = current_program_space->symfile_object_file;
for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
{
- msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, objf);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space, *bkpt_namep, objf);
if ((msymbol.minsym != NULL)
&& (msymbol.value_address () != 0))
{
@@ -2501,7 +2496,8 @@ enable_break (struct svr4_info *info, int from_tty)
{
for (bkpt_namep = bkpt_names; *bkpt_namep != NULL; bkpt_namep++)
{
- msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, objf);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space, *bkpt_namep, objf);
if ((msymbol.minsym != NULL)
&& (msymbol.value_address () != 0))
{
@@ -2620,8 +2616,8 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
return 0;
}
- /* Verify that the auxilliary vector describes the same file as exec_bfd, by
- comparing their program headers. If the program headers in the auxilliary
+ /* Verify that the auxiliary vector describes the same file as exec_bfd, by
+ comparing their program headers. If the program headers in the auxiliary
vector do not match the program headers in the executable, then we are
looking at a different file than the one used by the kernel - for
instance, "gdb program" connected to "gdbserver :PORT ld.so program". */
@@ -3354,6 +3350,15 @@ 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)
+{
+ auto *li = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
+ return li->l_addr_inferior;
+}
+
const struct solib_ops svr4_so_ops =
{
svr4_relocate_section_addresses,
@@ -3364,11 +3369,11 @@ const struct solib_ops svr4_so_ops =
open_symbol_file_object,
svr4_in_dynsym_resolve_code,
solib_bfd_open,
- nullptr,
svr4_same,
svr4_keep_data_in_core,
svr4_update_solib_event_breakpoints,
svr4_handle_solib_event,
+ svr4_find_solib_addr,
};
void _initialize_svr4_solib ();
diff --git a/gdb/solib-target.c b/gdb/solib-target.c
index 6563da0..8f73d5d 100644
--- a/gdb/solib-target.c
+++ b/gdb/solib-target.c
@@ -226,10 +226,10 @@ solib_target_parse_libraries (const char *library)
}
#endif
-static intrusive_list<solib>
+static owning_intrusive_list<solib>
solib_target_current_sos (void)
{
- intrusive_list<solib> sos;
+ owning_intrusive_list<solib> sos;
/* Fetch the list of shared libraries. */
std::optional<gdb::char_vector> library_document
@@ -245,15 +245,12 @@ solib_target_current_sos (void)
/* Build a struct solib for each entry on the list. */
for (lm_info_target_up &info : library_list)
{
- solib *new_solib = new solib;
+ auto &new_solib = sos.emplace_back ();
/* 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->lm_info = std::move (info);
-
- /* Add it to the list. */
- sos.push_back (*new_solib);
+ new_solib.so_name = std::move (info->name);
+ new_solib.so_original_name = new_solib.so_name;
+ new_solib.lm_info = std::move (info);
}
return sos;
@@ -412,4 +409,9 @@ const solib_ops solib_target_so_ops =
solib_target_open_symbol_file_object,
solib_target_in_dynsym_resolve_code,
solib_bfd_open,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ default_find_solib_addr,
};
diff --git a/gdb/solib.c b/gdb/solib.c
index 881f0d9..5c926de 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -46,7 +46,6 @@
#include "gdb_bfd.h"
#include "gdbsupport/filestuff.h"
#include "gdbsupport/scoped_fd.h"
-#include "debuginfod-support.h"
#include "source.h"
#include "cli/cli-style.h"
@@ -114,7 +113,6 @@ show_solib_search_path (struct ui_file *file, int from_tty,
static gdb::unique_xmalloc_ptr<char>
solib_find_1 (const char *in_pathname, int *fd, bool is_solib)
{
- const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
int found_file = -1;
gdb::unique_xmalloc_ptr<char> temp_pathname;
const char *fskind = effective_target_file_system_kind ();
@@ -297,12 +295,6 @@ solib_find_1 (const char *in_pathname, int *fd, bool is_solib)
target_lbasename (fskind, in_pathname),
O_RDONLY | O_BINARY, &temp_pathname);
- /* If not found, and we're looking for a solib, try to use target
- supplied solib search method. */
- if (is_solib && found_file < 0 && ops->find_and_open_solib)
- found_file = ops->find_and_open_solib (in_pathname, O_RDONLY | O_BINARY,
- &temp_pathname);
-
/* If not found, next search the inferior's $PATH environment variable. */
if (found_file < 0 && sysroot == NULL)
found_file = openp (current_inferior ()->environment.get ("PATH"),
@@ -476,58 +468,6 @@ solib_bfd_open (const char *pathname)
return abfd;
}
-/* Mapping of a core file's shared library sonames to their respective
- build-ids. Added to the registries of core file bfds. */
-
-typedef std::unordered_map<std::string, std::string> soname_build_id_map;
-
-/* Key used to associate a soname_build_id_map to a core file bfd. */
-
-static const struct registry<bfd>::key<soname_build_id_map>
- cbfd_soname_build_id_data_key;
-
-/* See solib.h. */
-
-void
-set_cbfd_soname_build_id (gdb_bfd_ref_ptr abfd, const char *soname,
- const bfd_build_id *build_id)
-{
- gdb_assert (abfd.get () != nullptr);
- gdb_assert (soname != nullptr);
- gdb_assert (build_id != nullptr);
-
- soname_build_id_map *mapptr
- = cbfd_soname_build_id_data_key.get (abfd.get ());
-
- if (mapptr == nullptr)
- mapptr = cbfd_soname_build_id_data_key.emplace (abfd.get ());
-
- (*mapptr)[soname] = build_id_to_string (build_id);
-}
-
-/* If SONAME had a build-id associated with it in ABFD's registry by a
- previous call to set_cbfd_soname_build_id then return the build-id
- as a NULL-terminated hex string. */
-
-static gdb::unique_xmalloc_ptr<char>
-get_cbfd_soname_build_id (gdb_bfd_ref_ptr abfd, const char *soname)
-{
- if (abfd.get () == nullptr || soname == nullptr)
- return {};
-
- soname_build_id_map *mapptr
- = cbfd_soname_build_id_data_key.get (abfd.get ());
-
- if (mapptr == nullptr)
- return {};
-
- auto it = mapptr->find (lbasename (soname));
- if (it == mapptr->end ())
- return {};
-
- return make_unique_xstrdup (it->second.c_str ());
-}
-
/* 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
@@ -547,36 +487,54 @@ solib_map_sections (solib &so)
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> build_id_hexstr
- = get_cbfd_soname_build_id (current_program_space->cbfd,
- so.so_name.c_str ());
+
+ /* 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
+ to load. Grab those hints now and use the below to validate or find
+ the shared libraries.
+
+ 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 <const core_target_mapped_file_info> mapped_file_info
+ = core_target_find_mapped_file (so.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
found, attempt to query debuginfod for the correct solib. */
- if (build_id_hexstr.get () != nullptr)
+ if (mapped_file_info.has_value ())
{
- bool mismatch = false;
+ bool mismatch = (abfd != nullptr
+ && build_id_bfd_get (abfd.get ()) != nullptr
+ && !build_id_equal (mapped_file_info->build_id (),
+ build_id_bfd_get (abfd.get ())));
- if (abfd != nullptr && abfd->build_id != nullptr)
- {
- std::string build_id = build_id_to_string (abfd->build_id);
-
- if (build_id != build_id_hexstr.get ())
- mismatch = true;
- }
if (abfd == nullptr || mismatch)
{
- scoped_fd fd = debuginfod_exec_query (
- (const unsigned char *) build_id_hexstr.get (), 0,
- so.so_name.c_str (), &filename);
-
- if (fd.get () >= 0)
- abfd = ops->bfd_open (filename.get ());
- else if (mismatch)
- warning (_ ("Build-id of %ps does not match core file."),
- styled_string (file_name_style.style (),
- filename.get ()));
+ /* If GDB found a suitable file during the file mapping
+ processing stage then lets use that. We don't check the
+ build-id after opening this file, either this file was found
+ by build-id, in which case it's going to match, or this file
+ doesn't have a build-id, so checking tells us nothing.
+ 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 ());
+ else
+ abfd = nullptr;
+
+ if (abfd == nullptr)
+ abfd = find_objfile_by_build_id (mapped_file_info->build_id (),
+ so.so_name.c_str ());
+
+ if (abfd == nullptr && mismatch)
+ {
+ warning (_ ("Build-id of %ps does not match core file."),
+ styled_string (file_name_style.style (),
+ filename.get ()));
+ abfd = nullptr;
+ }
}
}
@@ -710,15 +668,16 @@ solib_read_symbols (solib &so, symfile_add_flags flags)
return false;
}
-/* Return true if KNOWN->objfile is used by any other so_list object
- in the list of shared libraries. Return false otherwise. */
+/* Return true if KNOWN->objfile is used by any other solib object
+ in PSPACE's list of shared libraries. Return false otherwise. */
static bool
-solib_used (const solib &known)
+solib_used (program_space *pspace, const solib &known)
{
- for (const solib &pivot : current_program_space->solibs ())
+ for (const solib &pivot : pspace->solibs ())
if (&pivot != &known && pivot.objfile == known.objfile)
return true;
+
return false;
}
@@ -796,8 +755,8 @@ update_solib_list (int from_tty)
the time we're done walking GDB's list, the inferior's list
contains only the new shared objects, which we then add. */
- intrusive_list<solib> inferior = ops->current_sos ();
- intrusive_list<solib>::iterator gdb_iter
+ 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 ())
{
@@ -826,7 +785,6 @@ update_solib_list (int from_tty)
if (inferior_iter != inferior.end ())
{
inferior.erase (inferior_iter);
- delete &*inferior_iter;
++gdb_iter;
}
@@ -839,21 +797,17 @@ update_solib_list (int from_tty)
current_program_space->deleted_solibs.push_back (gdb_iter->so_name);
- intrusive_list<solib>::iterator gdb_iter_next
- = current_program_space->so_list.erase (gdb_iter);
-
/* Unless the user loaded it explicitly, free SO's objfile. */
if (gdb_iter->objfile != nullptr
&& !(gdb_iter->objfile->flags & OBJF_USERLOADED)
- && !solib_used (*gdb_iter))
+ && !solib_used (current_program_space, *gdb_iter))
gdb_iter->objfile->unlink ();
/* Some targets' section tables might be referring to
sections from so.abfd; remove them. */
current_program_space->remove_target_sections (&*gdb_iter);
- delete &*gdb_iter;
- gdb_iter = gdb_iter_next;
+ gdb_iter = current_program_space->so_list.erase (gdb_iter);
}
}
@@ -1192,11 +1146,13 @@ clear_solib (program_space *pspace)
disable_breakpoints_in_shlibs (pspace);
- pspace->so_list.clear_and_dispose ([pspace] (solib *so) {
- notify_solib_unloaded (pspace, *so);
- pspace->remove_target_sections (so);
- delete so;
- });
+ for (solib &so : pspace->so_list)
+ {
+ notify_solib_unloaded (pspace, so);
+ pspace->remove_target_sections (&so);
+ };
+
+ pspace->so_list.clear ();
if (ops->clear_solib != nullptr)
ops->clear_solib (pspace);
@@ -1234,21 +1190,29 @@ sharedlibrary_command (const char *args, int from_tty)
solib_add (args, from_tty, 1);
}
-/* Implements the command "nosharedlibrary", which discards symbols
- that have been auto-loaded from shared libraries. Symbols from
- shared libraries that were added by explicit request of the user
- are not discarded. Also called from remote.c. */
+/* See solib.h. */
void
-no_shared_libraries (const char *ignored, int from_tty)
+no_shared_libraries (program_space *pspace)
{
/* The order of the two routines below is important: clear_solib notifies
the solib_unloaded observers, and some of these observers might need
access to their associated objfiles. Therefore, we can not purge the
solibs' objfiles before clear_solib has been called. */
- clear_solib (current_program_space);
- objfile_purge_solibs ();
+ clear_solib (pspace);
+ objfile_purge_solibs (pspace);
+}
+
+/* Implements the command "nosharedlibrary", which discards symbols
+ that have been auto-loaded from shared libraries. Symbols from
+ shared libraries that were added by explicit request of the user
+ are not discarded. */
+
+static void
+no_shared_libraries_command (const char *ignored, int from_tty)
+{
+ no_shared_libraries (current_program_space);
}
/* See solib.h. */
@@ -1313,7 +1277,7 @@ reload_shared_libraries_1 (int from_tty)
&& filename_cmp (found_pathname, so.so_name.c_str ()) != 0))
{
if (so.objfile && !(so.objfile->flags & OBJF_USERLOADED)
- && !solib_used (so))
+ && !solib_used (current_program_space, so))
so.objfile->unlink ();
current_program_space->remove_target_sections (&so);
so.clear ();
@@ -1700,12 +1664,20 @@ remove_user_added_objfile (struct objfile *objfile)
{
if (objfile->flags & OBJF_USERLOADED)
{
- for (solib &so : objfile->pspace->solibs ())
+ for (solib &so : objfile->pspace ()->solibs ())
if (so.objfile == objfile)
so.objfile = nullptr;
}
}
+/* See solist.h. */
+
+std::optional<CORE_ADDR>
+default_find_solib_addr (solib &so)
+{
+ return {};
+}
+
void _initialize_solib ();
void
@@ -1725,7 +1697,7 @@ _initialize_solib ()
= add_info ("sharedlibrary", info_sharedlibrary_command,
_ ("Status of loaded shared object libraries."));
add_info_alias ("dll", info_sharedlibrary_cmd, 1);
- add_com ("nosharedlibrary", class_files, no_shared_libraries,
+ add_com ("nosharedlibrary", class_files, no_shared_libraries_command,
_ ("Unload all shared object library symbols."));
add_setshow_boolean_cmd ("auto-solib-add", class_support, &auto_solib_add,
diff --git a/gdb/solib.h b/gdb/solib.h
index f7a93c0..eacff65 100644
--- a/gdb/solib.h
+++ b/gdb/solib.h
@@ -80,9 +80,9 @@ extern bool solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size);
extern bool in_solib_dynsym_resolve_code (CORE_ADDR);
-/* Discard symbols that were auto-loaded from shared libraries. */
+/* Discard symbols that were auto-loaded from shared libraries in PSPACE. */
-extern void no_shared_libraries (const char *ignored, int from_tty);
+extern void no_shared_libraries (program_space *pspace);
/* Synchronize GDB's shared object list with inferior's.
@@ -136,11 +136,4 @@ extern void update_solib_breakpoints (void);
extern void handle_solib_event (void);
-/* Associate SONAME with BUILD_ID in ABFD's registry so that it can be
- retrieved with get_cbfd_soname_build_id. */
-
-extern void set_cbfd_soname_build_id (gdb_bfd_ref_ptr abfd,
- const char *soname,
- const bfd_build_id *build_id);
-
#endif /* SOLIB_H */
diff --git a/gdb/solist.h b/gdb/solist.h
index f0d2208..336bb01 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -20,9 +20,11 @@
#define 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. */
@@ -119,7 +121,7 @@ struct solib_ops
inferior --- we don't examine any of the shared library files
themselves. The declaration of `struct solib' says which fields
we provide values for. */
- intrusive_list<solib> (*current_sos) ();
+ 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. */
@@ -132,14 +134,6 @@ struct solib_ops
/* Find and open shared library binary file. */
gdb_bfd_ref_ptr (*bfd_open) (const char *pathname);
- /* Optional extra hook for finding and opening a solib.
- If TEMP_PATHNAME is non-NULL: If the file is successfully opened a
- pointer to a malloc'd and realpath'd copy of SONAME is stored there,
- otherwise NULL is stored there. */
- int (*find_and_open_solib) (const char *soname,
- unsigned o_flags,
- gdb::unique_xmalloc_ptr<char> *temp_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.
@@ -167,6 +161,23 @@ struct solib_ops
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);
};
/* A unique pointer to a so_list. */
@@ -186,4 +197,9 @@ 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
diff --git a/gdb/source-cache.c b/gdb/source-cache.c
index 6af984f..f08c872 100644
--- a/gdb/source-cache.c
+++ b/gdb/source-cache.c
@@ -195,7 +195,7 @@ get_language_name (enum language lang)
#endif /* HAVE_SOURCE_HIGHLIGHT */
/* Try to highlight CONTENTS from file FULLNAME in language LANG using
- the GNU source-higlight library. Return true if highlighting
+ the GNU source-highlight library. Return true if highlighting
succeeded. */
static bool
@@ -282,6 +282,12 @@ static void gnu_source_highlight_test ()
{
res = try_source_highlight (styled_prog, language_c, fullname);
}
+ catch (const gdb_exception &e)
+ {
+ if (e.reason != RETURN_ERROR)
+ throw;
+ saw_exception = true;
+ }
catch (...)
{
saw_exception = true;
diff --git a/gdb/source.c b/gdb/source.c
index 9e528d3..292d2bf 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -231,16 +231,15 @@ get_source_location (program_space *pspace)
return loc;
}
-/* Return the current source file for listing and next line to list.
- NOTE: The returned sal pc and end fields are not valid. */
+/* See source.h. */
-struct symtab_and_line
-get_current_source_symtab_and_line (void)
+symtab_and_line
+get_current_source_symtab_and_line (program_space *pspace)
{
symtab_and_line cursal;
- current_source_location *loc = get_source_location (current_program_space);
+ current_source_location *loc = get_source_location (pspace);
- cursal.pspace = current_program_space;
+ cursal.pspace = pspace;
cursal.symtab = loc->symtab ();
cursal.line = loc->line ();
cursal.pc = 0;
@@ -260,8 +259,9 @@ get_current_source_symtab_and_line (void)
void
set_default_source_symtab_and_line (void)
{
- if (!have_full_symbols () && !have_partial_symbols ())
- error (_("No symbol table is loaded. Use the \"file\" command."));
+ if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space))
+ error (_ ("No symbol table is loaded. Use the \"file\" command."));
/* Pull in a current source symtab if necessary. */
current_source_location *loc = get_source_location (current_program_space);
@@ -298,9 +298,9 @@ set_current_source_symtab_and_line (const symtab_and_line &sal)
/* Reset any information stored about a default file and line to print. */
void
-clear_current_source_symtab_and_line (void)
+clear_current_source_symtab_and_line (program_space *pspace)
{
- current_source_location *loc = get_source_location (current_program_space);
+ current_source_location *loc = get_source_location (pspace);
loc->set (nullptr, 0);
}
@@ -319,13 +319,13 @@ select_source_symtab ()
SEARCH_FUNCTION_DOMAIN, nullptr);
if (bsym.symbol != nullptr)
{
- symtab_and_line sal = find_function_start_sal (bsym.symbol, true);
+ symtab_and_line sal = find_function_start_sal (bsym.symbol, false);
if (sal.symtab == NULL)
/* We couldn't find the location of `main', possibly due to missing
line number info, fall back to line 1 in the corresponding file. */
loc->set (bsym.symbol->symtab (), 1);
else
- loc->set (sal.symtab, std::max (sal.line - (lines_to_list - 1), 1));
+ loc->set (sal.symtab, sal.line);
return;
}
@@ -1345,7 +1345,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
fields. ui_source_list is set only for CLI, not for
TUI. */
- uiout->field_signed ("line", line);
+ uiout->field_signed ("line", line, line_number_style.style ());
uiout->text ("\tin ");
uiout->field_string ("file", symtab_to_filename_for_display (s),
@@ -1386,11 +1386,15 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
last_line_listed = loc->line ();
if (flags & PRINT_SOURCE_LINES_FILENAME)
{
- uiout->text (symtab_to_filename_for_display (s));
+ uiout->message ("%ps",
+ styled_string (file_name_style.style (),
+ symtab_to_filename_for_display (s)));
uiout->text (":");
}
- xsnprintf (buf, sizeof (buf), "%d\t", new_lineno++);
- uiout->text (buf);
+
+ uiout->message ("%ps\t", styled_string (line_number_style.style (),
+ pulongest (new_lineno)));
+ ++new_lineno;
while (*iter != '\0')
{
@@ -1551,9 +1555,11 @@ info_line_command (const char *arg, int from_tty)
if (start_pc == end_pc)
{
- gdb_printf ("Line %d of \"%s\"",
- sal.line,
- symtab_to_filename_for_display (sal.symtab));
+ gdb_printf ("Line %ps of \"%ps\"",
+ styled_string (line_number_style.style (),
+ pulongest (sal.line)),
+ styled_string (file_name_style.style (),
+ symtab_to_filename_for_display (sal.symtab)));
gdb_stdout->wrap_here (2);
gdb_printf (" is at address ");
print_address (gdbarch, start_pc, gdb_stdout);
@@ -1562,9 +1568,11 @@ info_line_command (const char *arg, int from_tty)
}
else
{
- gdb_printf ("Line %d of \"%s\"",
- sal.line,
- symtab_to_filename_for_display (sal.symtab));
+ gdb_printf ("Line %ps of \"%ps\"",
+ styled_string (line_number_style.style (),
+ pulongest (sal.line)),
+ styled_string (file_name_style.style (),
+ symtab_to_filename_for_display (sal.symtab)));
gdb_stdout->wrap_here (2);
gdb_printf (" starts at address ");
print_address (gdbarch, start_pc, gdb_stdout);
@@ -1589,8 +1597,11 @@ info_line_command (const char *arg, int from_tty)
/* Is there any case in which we get here, and have an address
which the user would want to see? If we have debugging symbols
and no line numbers? */
- gdb_printf (_("Line number %d is out of range for \"%s\".\n"),
- sal.line, symtab_to_filename_for_display (sal.symtab));
+ gdb_printf (_("Line number %ps is out of range for \"%ps\".\n"),
+ styled_string (line_number_style.style (),
+ pulongest (sal.line)),
+ styled_string (file_name_style.style (),
+ symtab_to_filename_for_display (sal.symtab)));
}
}
@@ -1915,7 +1926,7 @@ directory in which the source file was compiled into object code.\n\
With no argument, reset the search path to $cdir:$cwd, the default."),
&cmdlist);
- set_cmd_completer (directory_cmd, filename_completer);
+ set_cmd_completer (directory_cmd, deprecated_filename_completer);
add_setshow_optional_filename_cmd ("directories",
class_files,
diff --git a/gdb/source.h b/gdb/source.h
index 144ee48..541ee3b 100644
--- a/gdb/source.h
+++ b/gdb/source.h
@@ -21,7 +21,9 @@
#include "gdbsupport/scoped_fd.h"
+struct program_space;
struct symtab;
+struct symtab_and_line;
/* See openp function definition for their description. */
@@ -107,7 +109,8 @@ extern int get_lines_to_list (void);
/* Return the current source file for listing and next line to list.
NOTE: The returned sal pc and end fields are not valid. */
-extern struct symtab_and_line get_current_source_symtab_and_line (void);
+extern symtab_and_line get_current_source_symtab_and_line
+ (program_space *pspace);
/* If the current source file for listing is not set, try and get a default.
Usually called before get_current_source_symtab_and_line() is called.
@@ -126,7 +129,7 @@ extern symtab_and_line set_current_source_symtab_and_line
(const symtab_and_line &sal);
/* Reset any information stored about a default file and line to print. */
-extern void clear_current_source_symtab_and_line (void);
+extern void clear_current_source_symtab_and_line (program_space *pspace);
/* Add a source path substitution rule. */
extern void add_substitute_path_rule (const char *, const char *);
diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
index edbc038..e97a7d9 100644
--- a/gdb/sparc-tdep.c
+++ b/gdb/sparc-tdep.c
@@ -769,7 +769,7 @@ sparc_alloc_frame_cache (void)
return cache;
}
-/* GCC generates several well-known sequences of instructions at the begining
+/* GCC generates several well-known sequences of instructions at the beginning
of each function prologue when compiling with -fstack-check. If one of
such sequences starts at START_PC, then return the address of the
instruction immediately past this sequence. Otherwise, return START_PC. */
diff --git a/gdb/stabsread.c b/gdb/stabsread.c
index 1158519..e479820 100644
--- a/gdb/stabsread.c
+++ b/gdb/stabsread.c
@@ -33,6 +33,7 @@
#include "symfile.h"
#include "objfiles.h"
#include "aout/stab_gnu.h"
+#include "psymtab.h"
#include "libaout.h"
#include "aout/aout64.h"
#include "gdb-stabs.h"
@@ -46,6 +47,8 @@
#include "cp-abi.h"
#include "cp-support.h"
#include <ctype.h>
+#include "block.h"
+#include "filenames.h"
#include "stabsread.h"
@@ -61,6 +64,26 @@ int *this_object_header_files;
int n_this_object_header_files;
int n_allocated_this_object_header_files;
+/* See stabsread.h. */
+
+const registry<objfile>::key<dbx_symfile_info> dbx_objfile_data_key;
+
+dbx_symfile_info::~dbx_symfile_info ()
+{
+ if (header_files != NULL)
+ {
+ int i = n_header_files;
+ struct header_file *hfiles = header_files;
+
+ while (--i >= 0)
+ {
+ xfree (hfiles[i].name);
+ xfree (hfiles[i].vector);
+ }
+ xfree (hfiles);
+ }
+}
+
struct stabs_nextfield
{
struct stabs_nextfield *next;
@@ -165,6 +188,26 @@ void stabsread_clear_cache (void);
static const char vptr_name[] = "_vptr$";
static const char vb_name[] = "_vb$";
+void
+unknown_symtype_complaint (const char *arg1)
+{
+ complaint (_("unknown symbol type %s"), arg1);
+}
+
+void
+lbrac_mismatch_complaint (int arg1)
+{
+ complaint (_("N_LBRAC/N_RBRAC symbol mismatch at symtab pos %d"), arg1);
+}
+
+void
+repeated_header_complaint (const char *arg1, int arg2)
+{
+ complaint (_("\"repeated\" header file %s not "
+ "previously seen, at symtab pos %d"),
+ arg1, arg2);
+}
+
static void
invalid_cpp_abbrev_complaint (const char *arg1)
{
@@ -184,6 +227,14 @@ stabs_general_complaint (const char *arg1)
complaint ("%s", arg1);
}
+static void
+function_outside_compilation_unit_complaint (const char *arg1)
+{
+ complaint (_("function `%s' appears to be defined "
+ "outside of all compilation units"),
+ arg1);
+}
+
/* Make a list of forward references which haven't been defined. */
static struct type **undef_types;
@@ -491,6 +542,2440 @@ read_type_number (const char **pp, int *typenums)
}
+/* Free up old header file tables. */
+
+void
+free_header_files (void)
+{
+ if (this_object_header_files)
+ {
+ xfree (this_object_header_files);
+ this_object_header_files = NULL;
+ }
+ n_allocated_this_object_header_files = 0;
+}
+
+/* Allocate new header file tables. */
+
+void
+init_header_files (void)
+{
+ n_allocated_this_object_header_files = 10;
+ this_object_header_files = XNEWVEC (int, 10);
+}
+
+/* Close off the current usage of PST.
+ Returns PST or NULL if the partial symtab was empty and thrown away.
+
+ FIXME: List variables and peculiarities of same. */
+
+legacy_psymtab *
+stabs_end_psymtab (struct objfile *objfile, psymtab_storage *partial_symtabs,
+ legacy_psymtab *pst,
+ const char **include_list, int num_includes,
+ int capping_symbol_offset, unrelocated_addr capping_text,
+ legacy_psymtab **dependency_list,
+ int number_dependencies,
+ int textlow_not_set)
+{
+ int i;
+ struct gdbarch *gdbarch = objfile->arch ();
+ dbx_symfile_info *key = dbx_objfile_data_key. get (objfile);
+
+ if (capping_symbol_offset != -1)
+ LDSYMLEN (pst) = capping_symbol_offset - LDSYMOFF (pst);
+ pst->set_text_high (capping_text);
+
+ /* Under Solaris, the N_SO symbols always have a value of 0,
+ instead of the usual address of the .o file. Therefore,
+ we have to do some tricks to fill in texthigh and textlow.
+ The first trick is: if we see a static
+ or global function, and the textlow for the current pst
+ is not set (ie: textlow_not_set), then we use that function's
+ address for the textlow of the pst. */
+
+ /* Now, to fill in texthigh, we remember the last function seen
+ in the .o file. Also, there's a hack in
+ bfd/elf.c and gdb/elfread.c to pass the ELF st_size field
+ to here via the misc_info field. Therefore, we can fill in
+ a reliable texthigh by taking the address plus size of the
+ last function in the file. */
+
+ if (!pst->text_high_valid && key->ctx.last_function_name
+ && gdbarch_sofun_address_maybe_missing (gdbarch))
+ {
+ int n;
+
+ const char *colon = strchr (key->ctx.last_function_name, ':');
+ if (colon == NULL)
+ n = 0;
+ else
+ n = colon - key->ctx.last_function_name;
+ char *p = (char *) alloca (n + 2);
+ strncpy (p, key->ctx.last_function_name, n);
+ p[n] = 0;
+
+ bound_minimal_symbol minsym
+ = lookup_minimal_symbol (current_program_space, p, objfile,
+ pst->filename);
+ if (minsym.minsym == NULL)
+ {
+ /* Sun Fortran appends an underscore to the minimal symbol name,
+ try again with an appended underscore if the minimal symbol
+ was not found. */
+ p[n] = '_';
+ p[n + 1] = 0;
+ minsym = lookup_minimal_symbol (current_program_space, p, objfile,
+ pst->filename);
+ }
+
+ if (minsym.minsym)
+ pst->set_text_high
+ (unrelocated_addr (CORE_ADDR (minsym.minsym->unrelocated_address ())
+ + minsym.minsym->size ()));
+
+ key->ctx.last_function_name = NULL;
+ }
+
+ if (!gdbarch_sofun_address_maybe_missing (gdbarch))
+ ;
+ /* This test will be true if the last .o file is only data. */
+ else if (textlow_not_set)
+ pst->set_text_low (pst->unrelocated_text_high ());
+ else
+ {
+ /* If we know our own starting text address, then walk through all other
+ psymtabs for this objfile, and if any didn't know their ending text
+ address, set it to our starting address. Take care to not set our
+ own ending address to our starting address. */
+
+ for (partial_symtab *p1 : partial_symtabs->range ())
+ if (!p1->text_high_valid && p1->text_low_valid && p1 != pst)
+ p1->set_text_high (pst->unrelocated_text_low ());
+ }
+
+ /* End of kludge for patching Solaris textlow and texthigh. */
+
+ pst->end ();
+
+ pst->number_of_dependencies = number_dependencies;
+ if (number_dependencies)
+ {
+ pst->dependencies
+ = partial_symtabs->allocate_dependencies (number_dependencies);
+ memcpy (pst->dependencies, dependency_list,
+ number_dependencies * sizeof (legacy_psymtab *));
+ }
+ else
+ pst->dependencies = 0;
+
+ for (i = 0; i < num_includes; i++)
+ {
+ legacy_psymtab *subpst =
+ new legacy_psymtab (include_list[i], partial_symtabs, objfile->per_bfd);
+
+ subpst->read_symtab_private =
+ XOBNEW (&objfile->objfile_obstack, struct symloc);
+ LDSYMOFF (subpst) =
+ LDSYMLEN (subpst) = 0;
+
+ /* We could save slight bits of space by only making one of these,
+ shared by the entire set of include files. FIXME-someday. */
+ subpst->dependencies =
+ partial_symtabs->allocate_dependencies (1);
+ subpst->dependencies[0] = pst;
+ subpst->number_of_dependencies = 1;
+
+ subpst->legacy_read_symtab = pst->legacy_read_symtab;
+ subpst->legacy_expand_psymtab = pst->legacy_expand_psymtab;
+ }
+
+ if (num_includes == 0
+ && number_dependencies == 0
+ && pst->empty ()
+ && key->ctx.has_line_numbers == 0)
+ {
+ /* Throw away this psymtab, it's empty. */
+ /* Empty psymtabs happen as a result of header files which don't have
+ any symbols in them. There can be a lot of them. But this check
+ is wrong, in that a psymtab with N_SLINE entries but nothing else
+ is not empty, but we don't realize that. Fixing that without slowing
+ things down might be tricky. */
+
+ partial_symtabs->discard_psymtab (pst);
+
+ /* Indicate that psymtab was thrown away. */
+ pst = NULL;
+ }
+ return pst;
+}
+
+/* Set namestring based on nlist. If the string table index is invalid,
+ give a fake name, and print a single error message per symbol file read,
+ rather than abort the symbol reading or flood the user with messages. */
+
+static const char *
+set_namestring (struct objfile *objfile, const struct internal_nlist *nlist)
+{
+ const char *namestring;
+ struct dbx_symfile_info *key = dbx_objfile_data_key.get (objfile);
+
+ if (nlist->n_strx + key->ctx.file_string_table_offset
+ >= DBX_STRINGTAB_SIZE (objfile)
+ || nlist->n_strx + key->ctx.file_string_table_offset < nlist->n_strx)
+ {
+ complaint (_("bad string table offset in symbol %d"),
+ symnum);
+ namestring = "<bad string table offset>";
+ }
+ else
+ namestring = (nlist->n_strx + key->ctx.file_string_table_offset
+ + DBX_STRINGTAB (objfile));
+ return namestring;
+}
+
+static void
+stabs_seek (int sym_offset, struct objfile *objfile)
+{
+ dbx_symfile_info *key = dbx_objfile_data_key.get (objfile);
+ if (key->ctx.stabs_data)
+ {
+ key->ctx.symbuf_read += sym_offset;
+ key->ctx.symbuf_left -= sym_offset;
+ }
+ else
+ if (bfd_seek (objfile->obfd.get (), sym_offset, SEEK_CUR) != 0)
+ perror_with_name (bfd_get_filename (objfile->obfd.get ()));
+}
+
+/* Buffer for reading the symbol table entries. */
+static struct external_nlist symbuf[4096];
+static int symbuf_idx;
+static int symbuf_end;
+
+/* Refill the symbol table input buffer
+ and set the variables that control fetching entries from it.
+ Reports an error if no data available.
+ This function can read past the end of the symbol table
+ (into the string table) but this does no harm. */
+
+static void
+fill_symbuf (bfd *sym_bfd, struct objfile *objfile)
+{
+ unsigned int count;
+ int nbytes;
+ struct dbx_symfile_info *key = dbx_objfile_data_key.get (objfile);
+
+ if (key->ctx.stabs_data)
+ {
+ nbytes = sizeof (symbuf);
+ if (nbytes > key->ctx.symbuf_left)
+ nbytes = key->ctx.symbuf_left;
+ memcpy (symbuf, key->ctx.stabs_data + key->ctx.symbuf_read, nbytes);
+ }
+ else if (key->ctx.symbuf_sections == NULL)
+ {
+ count = sizeof (symbuf);
+ nbytes = bfd_read (symbuf, count, sym_bfd);
+ }
+ else
+ {
+ if (key->ctx.symbuf_left <= 0)
+ {
+ file_ptr filepos = (*key->ctx.symbuf_sections)[key->ctx.sect_idx]->filepos;
+
+ if (bfd_seek (sym_bfd, filepos, SEEK_SET) != 0)
+ perror_with_name (bfd_get_filename (sym_bfd));
+ key->ctx.symbuf_left = bfd_section_size ((*key->ctx.symbuf_sections)[key->ctx.sect_idx]);
+ key->ctx.symbol_table_offset = filepos - key->ctx.symbuf_read;
+ ++key->ctx.sect_idx;
+ }
+
+ count = key->ctx.symbuf_left;
+ if (count > sizeof (symbuf))
+ count = sizeof (symbuf);
+ nbytes = bfd_read (symbuf, count, sym_bfd);
+ }
+
+ if (nbytes < 0)
+ perror_with_name (bfd_get_filename (sym_bfd));
+ else if (nbytes == 0)
+ error (_("Premature end of file reading symbol table"));
+ symbuf_end = nbytes / key->ctx.symbol_size;
+ symbuf_idx = 0;
+ key->ctx.symbuf_left -= nbytes;
+ key->ctx.symbuf_read += nbytes;
+}
+
+/* Read in a defined section of a specific object file's symbols. */
+
+static void
+read_ofile_symtab (struct objfile *objfile, legacy_psymtab *pst)
+{
+ const char *namestring;
+ struct external_nlist *bufp;
+ struct internal_nlist nlist;
+ unsigned char type;
+ unsigned max_symnum;
+ bfd *abfd;
+ int sym_offset; /* Offset to start of symbols to read */
+ int sym_size; /* Size of symbols to read */
+ CORE_ADDR text_offset; /* Start of text segment for symbols */
+ int text_size; /* Size of text segment for symbols */
+ struct dbx_symfile_info *key = dbx_objfile_data_key.get (objfile);
+
+ sym_offset = LDSYMOFF (pst);
+ sym_size = LDSYMLEN (pst);
+ text_offset = pst->text_low (objfile);
+ text_size = pst->text_high (objfile) - pst->text_low (objfile);
+ const section_offsets &section_offsets = objfile->section_offsets;
+
+ key->ctx.stringtab_global = DBX_STRINGTAB (objfile);
+ set_last_source_file (NULL);
+
+ abfd = objfile->obfd.get ();
+ symbuf_end = symbuf_idx = 0;
+ key->ctx.symbuf_read = 0;
+ key->ctx.symbuf_left = sym_offset + sym_size;
+
+ /* It is necessary to actually read one symbol *before* the start
+ of this symtab's symbols, because the GCC_COMPILED_FLAG_SYMBOL
+ occurs before the N_SO symbol.
+
+ Detecting this in read_stabs_symtab
+ would slow down initial readin, so we look for it here instead. */
+ if (!key->ctx.processing_acc_compilation && sym_offset >= (int) key->ctx.symbol_size)
+ {
+ stabs_seek (sym_offset - key->ctx.symbol_size, objfile);
+ fill_symbuf (abfd, objfile);
+ bufp = &symbuf[symbuf_idx++];
+ INTERNALIZE_SYMBOL (nlist, bufp, abfd);
+ OBJSTAT (objfile, n_stabs++);
+
+ namestring = set_namestring (objfile, &nlist);
+
+ processing_gcc_compilation = 0;
+ if (nlist.n_type == N_TEXT)
+ {
+ const char *tempstring = namestring;
+
+ if (strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL) == 0)
+ processing_gcc_compilation = 1;
+ else if (strcmp (namestring, GCC2_COMPILED_FLAG_SYMBOL) == 0)
+ processing_gcc_compilation = 2;
+ if (*tempstring != '\0'
+ && *tempstring == bfd_get_symbol_leading_char (objfile->obfd.get ()))
+ ++tempstring;
+ if (startswith (tempstring, "__gnu_compiled"))
+ processing_gcc_compilation = 2;
+ }
+ }
+ else
+ {
+ /* The N_SO starting this symtab is the first symbol, so we
+ better not check the symbol before it. I'm not this can
+ happen, but it doesn't hurt to check for it. */
+ stabs_seek (sym_offset, objfile);
+ processing_gcc_compilation = 0;
+ }
+
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf (abfd, objfile);
+ bufp = &symbuf[symbuf_idx];
+ if (bfd_h_get_8 (abfd, bufp->e_type) != N_SO)
+ error (_("First symbol in segment of executable not a source symbol"));
+
+ max_symnum = sym_size / key->ctx.symbol_size;
+
+ for (symnum = 0;
+ symnum < max_symnum;
+ symnum++)
+ {
+ QUIT; /* Allow this to be interruptable. */
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf (abfd, objfile);
+ bufp = &symbuf[symbuf_idx++];
+ INTERNALIZE_SYMBOL (nlist, bufp, abfd);
+ OBJSTAT (objfile, n_stabs++);
+
+ type = bfd_h_get_8 (abfd, bufp->e_type);
+
+ namestring = set_namestring (objfile, &nlist);
+
+ if (type & N_STAB)
+ {
+ if (sizeof (nlist.n_value) > 4
+ /* We are a 64-bit debugger debugging a 32-bit program. */
+ && (type == N_LSYM || type == N_PSYM))
+ /* We have to be careful with the n_value in the case of N_LSYM
+ and N_PSYM entries, because they are signed offsets from frame
+ pointer, but we actually read them as unsigned 32-bit values.
+ This is not a problem for 32-bit debuggers, for which negative
+ values end up being interpreted correctly (as negative
+ offsets) due to integer overflow.
+ But we need to sign-extend the value for 64-bit debuggers,
+ or we'll end up interpreting negative values as very large
+ positive offsets. */
+ nlist.n_value = (nlist.n_value ^ 0x80000000) - 0x80000000;
+ process_one_symbol (type, nlist.n_desc, nlist.n_value,
+ namestring, section_offsets, objfile,
+ PST_LANGUAGE (pst));
+ }
+ /* We skip checking for a new .o or -l file; that should never
+ happen in this routine. */
+ else if (type == N_TEXT)
+ {
+ /* I don't think this code will ever be executed, because
+ the GCC_COMPILED_FLAG_SYMBOL usually is right before
+ the N_SO symbol which starts this source file.
+ However, there is no reason not to accept
+ the GCC_COMPILED_FLAG_SYMBOL anywhere. */
+
+ if (strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL) == 0)
+ processing_gcc_compilation = 1;
+ else if (strcmp (namestring, GCC2_COMPILED_FLAG_SYMBOL) == 0)
+ processing_gcc_compilation = 2;
+ }
+ else if (type & N_EXT || type == (unsigned char) N_TEXT
+ || type == (unsigned char) N_NBTEXT)
+ {
+ /* Global symbol: see if we came across a dbx definition for
+ a corresponding symbol. If so, store the value. Remove
+ syms from the chain when their values are stored, but
+ search the whole chain, as there may be several syms from
+ different files with the same name. */
+ /* This is probably not true. Since the files will be read
+ in one at a time, each reference to a global symbol will
+ be satisfied in each file as it appears. So we skip this
+ section. */
+ ;
+ }
+ }
+
+ /* In a Solaris elf file, this variable, which comes from the value
+ of the N_SO symbol, will still be 0. Luckily, text_offset, which
+ comes from low text address of PST, is correct. */
+ if (get_last_source_start_addr () == 0)
+ set_last_source_start_addr (text_offset);
+
+ /* In reordered executables last_source_start_addr may not be the
+ lower bound for this symtab, instead use text_offset which comes
+ from the low text address of PST, which is correct. */
+ if (get_last_source_start_addr () > text_offset)
+ set_last_source_start_addr (text_offset);
+
+ pst->compunit_symtab = end_compunit_symtab (text_offset + text_size);
+
+ end_stabs ();
+
+}
+
+static void
+dbx_expand_psymtab (legacy_psymtab *pst, struct objfile *objfile)
+{
+ gdb_assert (!pst->readin);
+ struct dbx_symfile_info *key = dbx_objfile_data_key.get (objfile);
+
+ /* Read in all partial symtabs on which this one is dependent. */
+ pst->expand_dependencies (objfile);
+
+ if (LDSYMLEN (pst)) /* Otherwise it's a dummy. */
+ {
+ /* Init stuff necessary for reading in symbols */
+ stabsread_init ();
+ scoped_free_pendings free_pending;
+ key->ctx.file_string_table_offset = FILE_STRING_OFFSET (pst);
+ key->ctx.symbol_size = SYMBOL_SIZE (pst);
+
+ /* Read in this file's symbols. */
+ if (bfd_seek (objfile->obfd.get (), SYMBOL_OFFSET (pst), SEEK_SET) == 0)
+ read_ofile_symtab (objfile, pst);
+ }
+
+ pst->readin = true;
+}
+
+/* Invariant: The symbol pointed to by symbuf_idx is the first one
+ that hasn't been swapped. Swap the symbol at the same time
+ that symbuf_idx is incremented. */
+
+/* dbx allows the text of a symbol name to be continued into the
+ next symbol name! When such a continuation is encountered
+ (a \ at the end of the text of a name)
+ call this function to get the continuation. */
+
+static const char *
+dbx_next_symbol_text (struct objfile *objfile)
+{
+ struct internal_nlist nlist;
+ dbx_symfile_info *key = dbx_objfile_data_key.get (objfile);
+
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf (objfile->obfd.get (), objfile);
+
+ symnum++;
+ INTERNALIZE_SYMBOL (nlist, &symbuf[symbuf_idx], objfile->obfd.get ());
+ OBJSTAT (objfile, n_stabs++);
+
+ symbuf_idx++;
+
+ return nlist.n_strx + key->ctx.stringtab_global
+ + key->ctx.file_string_table_offset;
+}
+
+/* Read in all of the symbols for a given psymtab for real.
+ Be verbose about it if the user wants that. SELF is not NULL. */
+
+static void
+stabs_read_symtab (legacy_psymtab *self, struct objfile *objfile)
+{
+ gdb_assert (!self->readin);
+
+ if (LDSYMLEN (self) || self->number_of_dependencies)
+ {
+ next_symbol_text_func = dbx_next_symbol_text;
+ dbx_symfile_info *key = dbx_objfile_data_key.get (objfile);
+
+ {
+ scoped_restore restore_stabs_data = make_scoped_restore (&key->ctx.stabs_data);
+ gdb::unique_xmalloc_ptr<gdb_byte> data_holder;
+ if (DBX_STAB_SECTION (objfile))
+ {
+ key->ctx.stabs_data
+ = symfile_relocate_debug_section (objfile,
+ DBX_STAB_SECTION (objfile),
+ NULL);
+ data_holder.reset (key->ctx.stabs_data);
+ }
+
+ self->expand_psymtab (objfile);
+ }
+
+ /* Match with global symbols. This only needs to be done once,
+ after all of the symtabs and dependencies have been read in. */
+ scan_file_globals (objfile);
+ }
+}
+
+static void
+record_minimal_symbol (minimal_symbol_reader &reader,
+ const char *name, unrelocated_addr address, int type,
+ struct objfile *objfile)
+{
+ enum minimal_symbol_type ms_type;
+ int section;
+ struct dbx_symfile_info *key = dbx_objfile_data_key.get (objfile);
+
+ switch (type)
+ {
+ case N_TEXT | N_EXT:
+ ms_type = mst_text;
+ section = SECT_OFF_TEXT (objfile);
+ break;
+ case N_DATA | N_EXT:
+ ms_type = mst_data;
+ section = SECT_OFF_DATA (objfile);
+ break;
+ case N_BSS | N_EXT:
+ ms_type = mst_bss;
+ section = SECT_OFF_BSS (objfile);
+ break;
+ case N_ABS | N_EXT:
+ ms_type = mst_abs;
+ section = -1;
+ break;
+#ifdef N_SETV
+ case N_SETV | N_EXT:
+ ms_type = mst_data;
+ section = SECT_OFF_DATA (objfile);
+ break;
+ case N_SETV:
+ /* I don't think this type actually exists; since a N_SETV is the result
+ of going over many .o files, it doesn't make sense to have one
+ file local. */
+ ms_type = mst_file_data;
+ section = SECT_OFF_DATA (objfile);
+ break;
+#endif
+ case N_TEXT:
+ case N_NBTEXT:
+ case N_FN:
+ case N_FN_SEQ:
+ ms_type = mst_file_text;
+ section = SECT_OFF_TEXT (objfile);
+ break;
+ case N_DATA:
+ ms_type = mst_file_data;
+
+ /* Check for __DYNAMIC, which is used by Sun shared libraries.
+ Record it as global even if it's local, not global, so
+ lookup_minimal_symbol can find it. We don't check symbol_leading_char
+ because for SunOS4 it always is '_'. */
+ if (strcmp ("__DYNAMIC", name) == 0)
+ ms_type = mst_data;
+
+ /* Same with virtual function tables, both global and static. */
+ {
+ const char *tempstring = name;
+
+ if (*tempstring != '\0'
+ && *tempstring == bfd_get_symbol_leading_char (objfile->obfd.get ()))
+ ++tempstring;
+ if (is_vtable_name (tempstring))
+ ms_type = mst_data;
+ }
+ section = SECT_OFF_DATA (objfile);
+ break;
+ case N_BSS:
+ ms_type = mst_file_bss;
+ section = SECT_OFF_BSS (objfile);
+ break;
+ default:
+ ms_type = mst_unknown;
+ section = -1;
+ break;
+ }
+
+ if ((ms_type == mst_file_text || ms_type == mst_text)
+ && address < key->ctx.lowest_text_address)
+ key->ctx.lowest_text_address = address;
+
+ reader.record_with_info (name, address, ms_type, section);
+}
+
+/* Given a name, value pair, find the corresponding
+ bincl in the list. Return the partial symtab associated
+ with that header_file_location. */
+
+static legacy_psymtab *
+find_corresponding_bincl_psymtab (const char *name, int instance,
+ struct objfile* objfile)
+{
+ stabsread_context ctx = dbx_objfile_data_key.get (objfile) -> ctx;
+ for (const header_file_location &bincl : ctx.bincl_list)
+ if (bincl.instance == instance
+ && strcmp (name, bincl.name) == 0)
+ return bincl.pst;
+
+ repeated_header_complaint (name, symnum);
+ return (legacy_psymtab *) 0;
+}
+
+/* Allocate and partially fill a partial symtab. It will be
+ completely filled at the end of the symbol list.
+
+ SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR
+ is the address relative to which its symbols are (incremental) or 0
+ (normal). */
+
+static legacy_psymtab *
+start_psymtab (psymtab_storage *partial_symtabs, struct objfile *objfile,
+ const char *filename, unrelocated_addr textlow, int ldsymoff)
+{
+ legacy_psymtab *result = new legacy_psymtab (filename, partial_symtabs,
+ objfile->per_bfd, textlow);
+
+ struct dbx_symfile_info *key = dbx_objfile_data_key.get(objfile);
+
+ result->read_symtab_private =
+ XOBNEW (&objfile->objfile_obstack, struct symloc);
+ LDSYMOFF (result) = ldsymoff;
+ result->legacy_read_symtab = stabs_read_symtab;
+ result->legacy_expand_psymtab = dbx_expand_psymtab;
+ SYMBOL_SIZE (result) = key->ctx.symbol_size;
+ SYMBOL_OFFSET (result) = key->ctx.symbol_table_offset;
+ STRING_OFFSET (result) = 0; /* This used to be an uninitialized global. */
+ FILE_STRING_OFFSET (result) = key->ctx.file_string_table_offset;
+
+ /* Deduce the source language from the filename for this psymtab. */
+ key->ctx.psymtab_language = deduce_language_from_filename (filename);
+ PST_LANGUAGE (result) = key->ctx.psymtab_language;
+
+ return result;
+}
+
+/* See stabsread.h. */
+
+static void
+read_stabs_symtab_1 (minimal_symbol_reader &reader,
+ psymtab_storage *partial_symtabs,
+ struct objfile *objfile)
+{
+ struct gdbarch *gdbarch = objfile->arch ();
+ struct external_nlist *bufp = 0; /* =0 avoids gcc -Wall glitch. */
+ struct internal_nlist nlist;
+ CORE_ADDR text_addr;
+ int text_size;
+ const char *sym_name;
+ int sym_len;
+ unsigned int next_file_string_table_offset = 0;
+ struct dbx_symfile_info *dbx = dbx_objfile_data_key.get(objfile);
+
+ const char *namestring;
+ int nsl;
+ int past_first_source_file = 0;
+ CORE_ADDR last_function_start = 0;
+ bfd *abfd;
+ int textlow_not_set;
+ int data_sect_index;
+
+ /* Current partial symtab. */
+ legacy_psymtab *pst;
+
+ /* List of current psymtab's include files. */
+ const char **psymtab_include_list;
+ int includes_allocated;
+ int includes_used;
+
+ /* Index within current psymtab dependency list. */
+ legacy_psymtab **dependency_list;
+ int dependencies_used, dependencies_allocated;
+
+ text_addr = DBX_TEXT_ADDR (objfile);
+ text_size = DBX_TEXT_SIZE (objfile);
+
+ /* FIXME. We probably want to change stringtab_global rather than add this
+ while processing every symbol entry. FIXME. */
+ dbx->ctx.file_string_table_offset = 0;
+
+ dbx->ctx.stringtab_global = DBX_STRINGTAB (objfile);
+
+ pst = (legacy_psymtab *) 0;
+
+ includes_allocated = 30;
+ includes_used = 0;
+ psymtab_include_list = (const char **) alloca (includes_allocated *
+ sizeof (const char *));
+
+ dependencies_allocated = 30;
+ dependencies_used = 0;
+ dependency_list =
+ (legacy_psymtab **) alloca (dependencies_allocated *
+ sizeof (legacy_psymtab *));
+
+ /* Init bincl list */
+ std::vector<struct header_file_location> bincl_storage;
+ scoped_restore restore_bincl_global
+ = make_scoped_restore (&(dbx->ctx.bincl_list), bincl_storage);
+
+ set_last_source_file (NULL);
+
+ dbx->ctx.lowest_text_address = (unrelocated_addr) -1;
+
+ abfd = objfile->obfd.get ();
+ symbuf_end = symbuf_idx = 0;
+ next_symbol_text_func = dbx_next_symbol_text;
+ textlow_not_set = 1;
+ dbx->ctx.has_line_numbers = 0;
+
+ /* FIXME: jimb/2003-09-12: We don't apply the right section's offset
+ to global and static variables. The stab for a global or static
+ variable doesn't give us any indication of which section it's in,
+ so we can't tell immediately which offset in
+ objfile->section_offsets we should apply to the variable's
+ address.
+
+ We could certainly find out which section contains the variable
+ by looking up the variable's unrelocated address with
+ find_pc_section, but that would be expensive; this is the
+ function that constructs the partial symbol tables by examining
+ every symbol in the entire executable, and it's
+ performance-critical. So that expense would not be welcome. I'm
+ not sure what to do about this at the moment.
+
+ What we have done for years is to simply assume that the .data
+ section's offset is appropriate for all global and static
+ variables. Recently, this was expanded to fall back to the .bss
+ section's offset if there is no .data section, and then to the
+ .rodata section's offset. */
+ data_sect_index = objfile->sect_index_data;
+ if (data_sect_index == -1)
+ data_sect_index = SECT_OFF_BSS (objfile);
+ if (data_sect_index == -1)
+ data_sect_index = SECT_OFF_RODATA (objfile);
+
+ /* If data_sect_index is still -1, that's okay. It's perfectly fine
+ for the file to have no .data, no .bss, and no .text at all, if
+ it also has no global or static variables. */
+
+ for (symnum = 0; symnum < DBX_SYMCOUNT (objfile); symnum++)
+ {
+ /* Get the symbol for this run and pull out some info. */
+ QUIT; /* Allow this to be interruptable. */
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf (abfd, objfile);
+ bufp = &symbuf[symbuf_idx++];
+
+ /*
+ * Special case to speed up readin.
+ */
+ if (bfd_h_get_8 (abfd, bufp->e_type) == N_SLINE)
+ {
+ dbx->ctx.has_line_numbers = 1;
+ continue;
+ }
+
+ INTERNALIZE_SYMBOL (nlist, bufp, abfd);
+ OBJSTAT (objfile, n_stabs++);
+
+ /* Ok. There is a lot of code duplicated in the rest of this
+ switch statement (for efficiency reasons). Since I don't
+ like duplicating code, I will do my penance here, and
+ describe the code which is duplicated:
+
+ *) The assignment to namestring.
+ *) The call to strchr.
+ *) The addition of a partial symbol the two partial
+ symbol lists. This last is a large section of code, so
+ I've embedded it in the following macro. */
+
+ switch (nlist.n_type)
+ {
+ /*
+ * Standard, external, non-debugger, symbols
+ */
+
+ case N_TEXT | N_EXT:
+ case N_NBTEXT | N_EXT:
+ goto record_it;
+
+ case N_DATA | N_EXT:
+ case N_NBDATA | N_EXT:
+ goto record_it;
+
+ case N_BSS:
+ case N_BSS | N_EXT:
+ case N_NBBSS | N_EXT:
+ case N_SETV | N_EXT: /* FIXME, is this in BSS? */
+ goto record_it;
+
+ case N_ABS | N_EXT:
+ record_it:
+ namestring = set_namestring (objfile, &nlist);
+
+ record_minimal_symbol (reader, namestring,
+ unrelocated_addr (nlist.n_value),
+ nlist.n_type, objfile); /* Always */
+ continue;
+
+ /* Standard, local, non-debugger, symbols. */
+
+ case N_NBTEXT:
+
+ /* We need to be able to deal with both N_FN or N_TEXT,
+ because we have no way of knowing whether the sys-supplied ld
+ or GNU ld was used to make the executable. Sequents throw
+ in another wrinkle -- they renumbered N_FN. */
+
+ case N_FN:
+ case N_FN_SEQ:
+ case N_TEXT:
+ namestring = set_namestring (objfile, &nlist);
+
+ if ((namestring[0] == '-' && namestring[1] == 'l')
+ || (namestring[(nsl = strlen (namestring)) - 1] == 'o'
+ && namestring[nsl - 2] == '.'))
+ {
+ unrelocated_addr unrel_val = unrelocated_addr (nlist.n_value);
+
+ if (past_first_source_file && pst
+ /* The gould NP1 uses low values for .o and -l symbols
+ which are not the address. */
+ && unrel_val >= pst->unrelocated_text_low ())
+ {
+ stabs_end_psymtab (objfile, partial_symtabs,
+ pst, psymtab_include_list,
+ includes_used, symnum * dbx->ctx.symbol_size,
+ unrel_val > pst->unrelocated_text_high ()
+ ? unrel_val : pst->unrelocated_text_high (),
+ dependency_list, dependencies_used,
+ textlow_not_set);
+ pst = (legacy_psymtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ dbx->ctx.has_line_numbers = 0;
+ }
+ else
+ past_first_source_file = 1;
+ }
+ else
+ goto record_it;
+ continue;
+
+ case N_DATA:
+ goto record_it;
+
+ case N_UNDF | N_EXT:
+ /* The case (nlist.n_value != 0) is a "Fortran COMMON" symbol.
+ We used to rely on the target to tell us whether it knows
+ where the symbol has been relocated to, but none of the
+ target implementations actually provided that operation.
+ So we just ignore the symbol, the same way we would do if
+ we had a target-side symbol lookup which returned no match.
+
+ All other symbols (with nlist.n_value == 0), are really
+ undefined, and so we ignore them too. */
+ continue;
+
+ case N_UNDF:
+ if (dbx->ctx.processing_acc_compilation && nlist.n_strx == 1)
+ {
+ /* Deal with relative offsets in the string table
+ used in ELF+STAB under Solaris. If we want to use the
+ n_strx field, which contains the name of the file,
+ we must adjust file_string_table_offset *before* calling
+ set_namestring(). */
+ past_first_source_file = 1;
+ dbx->ctx.file_string_table_offset = next_file_string_table_offset;
+ next_file_string_table_offset =
+ dbx->ctx.file_string_table_offset + nlist.n_value;
+ if (next_file_string_table_offset < dbx->ctx.file_string_table_offset)
+ error (_("string table offset backs up at %d"), symnum);
+ /* FIXME -- replace error() with complaint. */
+ continue;
+ }
+ continue;
+
+ /* Lots of symbol types we can just ignore. */
+
+ case N_ABS:
+ case N_NBDATA:
+ case N_NBBSS:
+ continue;
+
+ /* Keep going . . . */
+
+ /*
+ * Special symbol types for GNU
+ */
+ case N_INDR:
+ case N_INDR | N_EXT:
+ case N_SETA:
+ case N_SETA | N_EXT:
+ case N_SETT:
+ case N_SETT | N_EXT:
+ case N_SETD:
+ case N_SETD | N_EXT:
+ case N_SETB:
+ case N_SETB | N_EXT:
+ case N_SETV:
+ continue;
+
+ /*
+ * Debugger symbols
+ */
+
+ case N_SO:
+ {
+ CORE_ADDR valu;
+ static int prev_so_symnum = -10;
+ static int first_so_symnum;
+ const char *p;
+ static const char *dirname_nso;
+ int prev_textlow_not_set;
+
+ valu = nlist.n_value;
+
+ prev_textlow_not_set = textlow_not_set;
+
+ /* A zero value is probably an indication for the SunPRO 3.0
+ compiler. stabs_end_psymtab explicitly tests for zero, so
+ don't relocate it. */
+
+ if (nlist.n_value == 0
+ && gdbarch_sofun_address_maybe_missing (gdbarch))
+ {
+ textlow_not_set = 1;
+ valu = 0;
+ }
+ else
+ textlow_not_set = 0;
+
+ past_first_source_file = 1;
+
+ if (prev_so_symnum != symnum - 1)
+ { /* Here if prev stab wasn't N_SO. */
+ first_so_symnum = symnum;
+
+ if (pst)
+ {
+ unrelocated_addr unrel_value = unrelocated_addr (valu);
+ stabs_end_psymtab (objfile, partial_symtabs,
+ pst, psymtab_include_list,
+ includes_used, symnum * dbx->ctx.symbol_size,
+ unrel_value > pst->unrelocated_text_high ()
+ ? unrel_value
+ : pst->unrelocated_text_high (),
+ dependency_list, dependencies_used,
+ prev_textlow_not_set);
+ pst = (legacy_psymtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ dbx->ctx.has_line_numbers = 0;
+ }
+ }
+
+ prev_so_symnum = symnum;
+
+ /* End the current partial symtab and start a new one. */
+
+ namestring = set_namestring (objfile, &nlist);
+
+ /* Null name means end of .o file. Don't start a new one. */
+ if (*namestring == '\000')
+ continue;
+
+ /* Some compilers (including gcc) emit a pair of initial N_SOs.
+ The first one is a directory name; the second the file name.
+ If pst exists, is empty, and has a filename ending in '/',
+ we assume the previous N_SO was a directory name. */
+
+ p = lbasename (namestring);
+ if (p != namestring && *p == '\000')
+ {
+ /* Save the directory name SOs locally, then save it into
+ the psymtab when it's created below. */
+ dirname_nso = namestring;
+ continue;
+ }
+
+ /* Some other compilers (C++ ones in particular) emit useless
+ SOs for non-existant .c files. We ignore all subsequent SOs
+ that immediately follow the first. */
+
+ if (!pst)
+ {
+ pst = start_psymtab (partial_symtabs, objfile,
+ namestring,
+ unrelocated_addr (valu),
+ first_so_symnum * dbx->ctx.symbol_size);
+ pst->dirname = dirname_nso;
+ dirname_nso = NULL;
+ }
+ continue;
+ }
+
+ case N_BINCL:
+ {
+ enum language tmp_language;
+
+ /* Add this bincl to the bincl_list for future EXCLs. No
+ need to save the string; it'll be around until
+ read_stabs_symtab function returns. */
+
+ namestring = set_namestring (objfile, &nlist);
+ tmp_language = deduce_language_from_filename (namestring);
+
+ /* Only change the psymtab's language if we've learned
+ something useful (eg. tmp_language is not language_unknown).
+ In addition, to match what start_subfile does, never change
+ from C++ to C. */
+ if (tmp_language != language_unknown
+ && (tmp_language != language_c
+ || dbx->ctx.psymtab_language != language_cplus))
+ dbx->ctx.psymtab_language = tmp_language;
+
+ if (pst == NULL)
+ {
+ /* FIXME: we should not get here without a PST to work on.
+ Attempt to recover. */
+ complaint (_("N_BINCL %s not in entries for "
+ "any file, at symtab pos %d"),
+ namestring, symnum);
+ continue;
+ }
+ dbx->ctx.bincl_list.emplace_back (namestring, nlist.n_value, pst);
+
+ /* Mark down an include file in the current psymtab. */
+
+ goto record_include_file;
+ }
+
+ case N_SOL:
+ {
+ enum language tmp_language;
+
+ /* Mark down an include file in the current psymtab. */
+ namestring = set_namestring (objfile, &nlist);
+ tmp_language = deduce_language_from_filename (namestring);
+
+ /* Only change the psymtab's language if we've learned
+ something useful (eg. tmp_language is not language_unknown).
+ In addition, to match what start_subfile does, never change
+ from C++ to C. */
+ if (tmp_language != language_unknown
+ && (tmp_language != language_c
+ || dbx->ctx.psymtab_language != language_cplus))
+ dbx->ctx.psymtab_language = tmp_language;
+
+ /* In C++, one may expect the same filename to come round many
+ times, when code is coming alternately from the main file
+ and from inline functions in other files. So I check to see
+ if this is a file we've seen before -- either the main
+ source file, or a previously included file.
+
+ This seems to be a lot of time to be spending on N_SOL, but
+ things like "break c-exp.y:435" need to work (I
+ suppose the psymtab_include_list could be hashed or put
+ in a binary tree, if profiling shows this is a major hog). */
+ if (pst && filename_cmp (namestring, pst->filename) == 0)
+ continue;
+ {
+ int i;
+
+ for (i = 0; i < includes_used; i++)
+ if (filename_cmp (namestring, psymtab_include_list[i]) == 0)
+ {
+ i = -1;
+ break;
+ }
+ if (i == -1)
+ continue;
+ }
+
+ record_include_file:
+
+ psymtab_include_list[includes_used++] = namestring;
+ if (includes_used >= includes_allocated)
+ {
+ const char **orig = psymtab_include_list;
+
+ psymtab_include_list = (const char **)
+ alloca ((includes_allocated *= 2) * sizeof (const char *));
+ memcpy (psymtab_include_list, orig,
+ includes_used * sizeof (const char *));
+ }
+ continue;
+ }
+ case N_LSYM: /* Typedef or automatic variable. */
+ case N_STSYM: /* Data seg var -- static. */
+ case N_LCSYM: /* BSS " */
+ case N_ROSYM: /* Read-only data seg var -- static. */
+ case N_NBSTS: /* Gould nobase. */
+ case N_NBLCS: /* symbols. */
+ case N_FUN:
+ case N_GSYM: /* Global (extern) variable; can be
+ data or bss (sigh FIXME). */
+
+ /* Following may probably be ignored; I'll leave them here
+ for now (until I do Pascal and Modula 2 extensions). */
+
+ case N_PC: /* I may or may not need this; I
+ suspect not. */
+ case N_M2C: /* I suspect that I can ignore this here. */
+ case N_SCOPE: /* Same. */
+ {
+ const char *p;
+
+ namestring = set_namestring (objfile, &nlist);
+
+ /* See if this is an end of function stab. */
+ if (pst && nlist.n_type == N_FUN && *namestring == '\000')
+ {
+ unrelocated_addr valu;
+
+ /* It's value is the size (in bytes) of the function for
+ function relative stabs, or the address of the function's
+ end for old style stabs. */
+ valu = unrelocated_addr (nlist.n_value + last_function_start);
+ if (pst->unrelocated_text_high () == unrelocated_addr (0)
+ || valu > pst->unrelocated_text_high ())
+ pst->set_text_high (valu);
+ break;
+ }
+
+ p = (char *) strchr (namestring, ':');
+ if (!p)
+ continue; /* Not a debugging symbol. */
+
+ sym_len = 0;
+ sym_name = NULL; /* pacify "gcc -Werror" */
+ if (dbx->ctx.psymtab_language == language_cplus)
+ {
+ std::string name (namestring, p - namestring);
+ gdb::unique_xmalloc_ptr<char> new_name
+ = cp_canonicalize_string (name.c_str ());
+ if (new_name != nullptr)
+ {
+ sym_len = strlen (new_name.get ());
+ sym_name = obstack_strdup (&objfile->objfile_obstack,
+ new_name.get ());
+ }
+ }
+ else if (dbx->ctx.psymtab_language == language_c)
+ {
+ std::string name (namestring, p - namestring);
+ gdb::unique_xmalloc_ptr<char> new_name
+ = c_canonicalize_name (name.c_str ());
+ if (new_name != nullptr)
+ {
+ sym_len = strlen (new_name.get ());
+ sym_name = obstack_strdup (&objfile->objfile_obstack,
+ new_name.get ());
+ }
+ }
+
+ if (sym_len == 0)
+ {
+ sym_name = namestring;
+ sym_len = p - namestring;
+ }
+
+ /* Main processing section for debugging symbols which
+ the initial read through the symbol tables needs to worry
+ about. If we reach this point, the symbol which we are
+ considering is definitely one we are interested in.
+ p must also contain the (valid) index into the namestring
+ which indicates the debugging type symbol. */
+
+ switch (p[1])
+ {
+ case 'S':
+ if (pst != nullptr)
+ pst->add_psymbol (std::string_view (sym_name, sym_len), true,
+ VAR_DOMAIN, LOC_STATIC,
+ data_sect_index,
+ psymbol_placement::STATIC,
+ unrelocated_addr (nlist.n_value),
+ dbx->ctx.psymtab_language,
+ partial_symtabs, objfile);
+ else
+ complaint (_("static `%*s' appears to be defined "
+ "outside of all compilation units"),
+ sym_len, sym_name);
+ continue;
+
+ case 'G':
+ /* The addresses in these entries are reported to be
+ wrong. See the code that reads 'G's for symtabs. */
+ if (pst != nullptr)
+ pst->add_psymbol (std::string_view (sym_name, sym_len), true,
+ VAR_DOMAIN, LOC_STATIC,
+ data_sect_index,
+ psymbol_placement::GLOBAL,
+ unrelocated_addr (nlist.n_value),
+ dbx->ctx.psymtab_language,
+ partial_symtabs, objfile);
+ else
+ complaint (_("global `%*s' appears to be defined "
+ "outside of all compilation units"),
+ sym_len, sym_name);
+ continue;
+
+ case 'T':
+ /* When a 'T' entry is defining an anonymous enum, it
+ may have a name which is the empty string, or a
+ single space. Since they're not really defining a
+ symbol, those shouldn't go in the partial symbol
+ table. We do pick up the elements of such enums at
+ 'check_enum:', below. */
+ if (p >= namestring + 2
+ || (p == namestring + 1
+ && namestring[0] != ' '))
+ {
+ if (pst != nullptr)
+ pst->add_psymbol (std::string_view (sym_name, sym_len),
+ true, STRUCT_DOMAIN, LOC_TYPEDEF, -1,
+ psymbol_placement::STATIC,
+ unrelocated_addr (0),
+ dbx->ctx.psymtab_language,
+ partial_symtabs, objfile);
+ else
+ complaint (_("enum, struct, or union `%*s' appears "
+ "to be defined outside of all "
+ "compilation units"),
+ sym_len, sym_name);
+ if (p[2] == 't')
+ {
+ /* Also a typedef with the same name. */
+ if (pst != nullptr)
+ pst->add_psymbol (std::string_view (sym_name, sym_len),
+ true, VAR_DOMAIN, LOC_TYPEDEF, -1,
+ psymbol_placement::STATIC,
+ unrelocated_addr (0),
+ dbx->ctx.psymtab_language,
+ partial_symtabs, objfile);
+ else
+ complaint (_("typedef `%*s' appears to be defined "
+ "outside of all compilation units"),
+ sym_len, sym_name);
+ p += 1;
+ }
+ }
+ goto check_enum;
+
+ case 't':
+ if (p != namestring) /* a name is there, not just :T... */
+ {
+ if (pst != nullptr)
+ pst->add_psymbol (std::string_view (sym_name, sym_len),
+ true, VAR_DOMAIN, LOC_TYPEDEF, -1,
+ psymbol_placement::STATIC,
+ unrelocated_addr (0),
+ dbx->ctx.psymtab_language,
+ partial_symtabs, objfile);
+ else
+ complaint (_("typename `%*s' appears to be defined "
+ "outside of all compilation units"),
+ sym_len, sym_name);
+ }
+ check_enum:
+ /* If this is an enumerated type, we need to
+ add all the enum constants to the partial symbol
+ table. This does not cover enums without names, e.g.
+ "enum {a, b} c;" in C, but fortunately those are
+ rare. There is no way for GDB to find those from the
+ enum type without spending too much time on it. Thus
+ to solve this problem, the compiler needs to put out the
+ enum in a nameless type. GCC2 does this. */
+
+ /* We are looking for something of the form
+ <name> ":" ("t" | "T") [<number> "="] "e"
+ {<constant> ":" <value> ","} ";". */
+
+ /* Skip over the colon and the 't' or 'T'. */
+ p += 2;
+ /* This type may be given a number. Also, numbers can come
+ in pairs like (0,26). Skip over it. */
+ while ((*p >= '0' && *p <= '9')
+ || *p == '(' || *p == ',' || *p == ')'
+ || *p == '=')
+ p++;
+
+ if (*p++ == 'e')
+ {
+ /* The aix4 compiler emits extra crud before the members. */
+ if (*p == '-')
+ {
+ /* Skip over the type (?). */
+ while (*p != ':')
+ p++;
+
+ /* Skip over the colon. */
+ p++;
+ }
+
+ /* We have found an enumerated type. */
+ /* According to comments in read_enum_type
+ a comma could end it instead of a semicolon.
+ I don't know where that happens.
+ Accept either. */
+ while (*p && *p != ';' && *p != ',')
+ {
+ const char *q;
+
+ /* Check for and handle cretinous dbx symbol name
+ continuation! */
+ if (*p == '\\' || (*p == '?' && p[1] == '\0'))
+ p = next_symbol_text (objfile);
+
+ /* Point to the character after the name
+ of the enum constant. */
+ for (q = p; *q && *q != ':'; q++)
+ ;
+ /* Note that the value doesn't matter for
+ enum constants in psymtabs, just in symtabs. */
+ if (pst != nullptr)
+ pst->add_psymbol (std::string_view (p, q - p), true,
+ VAR_DOMAIN, LOC_CONST, -1,
+ psymbol_placement::STATIC,
+ unrelocated_addr (0),
+ dbx->ctx.psymtab_language,
+ partial_symtabs, objfile);
+ else
+ complaint (_("enum constant `%*s' appears to be defined "
+ "outside of all compilation units"),
+ ((int) (q - p)), p);
+ /* Point past the name. */
+ p = q;
+ /* Skip over the value. */
+ while (*p && *p != ',')
+ p++;
+ /* Advance past the comma. */
+ if (*p)
+ p++;
+ }
+ }
+ continue;
+
+ case 'c':
+ /* Constant, e.g. from "const" in Pascal. */
+ if (pst != nullptr)
+ pst->add_psymbol (std::string_view (sym_name, sym_len), true,
+ VAR_DOMAIN, LOC_CONST, -1,
+ psymbol_placement::STATIC,
+ unrelocated_addr (0),
+ dbx->ctx.psymtab_language,
+ partial_symtabs, objfile);
+ else
+ complaint (_("constant `%*s' appears to be defined "
+ "outside of all compilation units"),
+ sym_len, sym_name);
+
+ continue;
+
+ case 'f':
+ if (! pst)
+ {
+ std::string name (namestring, (p - namestring));
+ function_outside_compilation_unit_complaint (name.c_str ());
+ }
+ /* Kludges for ELF/STABS with Sun ACC. */
+ dbx->ctx.last_function_name = namestring;
+ /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
+ value for the bottom of the text seg in those cases. */
+ if (nlist.n_value == 0
+ && gdbarch_sofun_address_maybe_missing (gdbarch))
+ {
+ bound_minimal_symbol minsym
+ = find_stab_function (namestring,
+ pst ? pst->filename : NULL, objfile);
+ if (minsym.minsym != NULL)
+ nlist.n_value
+ = CORE_ADDR (minsym.minsym->unrelocated_address ());
+ }
+ if (pst && textlow_not_set
+ && gdbarch_sofun_address_maybe_missing (gdbarch))
+ {
+ pst->set_text_low (unrelocated_addr (nlist.n_value));
+ textlow_not_set = 0;
+ }
+ /* End kludge. */
+
+ /* Keep track of the start of the last function so we
+ can handle end of function symbols. */
+ last_function_start = nlist.n_value;
+
+ /* In reordered executables this function may lie outside
+ the bounds created by N_SO symbols. If that's the case
+ use the address of this function as the low bound for
+ the partial symbol table. */
+ if (pst
+ && (textlow_not_set
+ || (unrelocated_addr (nlist.n_value)
+ < pst->unrelocated_text_low ()
+ && (nlist.n_value != 0))))
+ {
+ pst->set_text_low (unrelocated_addr (nlist.n_value));
+ textlow_not_set = 0;
+ }
+ if (pst != nullptr)
+ pst->add_psymbol (std::string_view (sym_name, sym_len), true,
+ VAR_DOMAIN, LOC_BLOCK,
+ SECT_OFF_TEXT (objfile),
+ psymbol_placement::STATIC,
+ unrelocated_addr (nlist.n_value),
+ dbx->ctx.psymtab_language,
+ partial_symtabs, objfile);
+ continue;
+
+ /* Global functions were ignored here, but now they
+ are put into the global psymtab like one would expect.
+ They're also in the minimal symbol table. */
+ case 'F':
+ if (! pst)
+ {
+ std::string name (namestring, (p - namestring));
+ function_outside_compilation_unit_complaint (name.c_str ());
+ }
+ /* Kludges for ELF/STABS with Sun ACC. */
+ dbx->ctx.last_function_name = namestring;
+ /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
+ value for the bottom of the text seg in those cases. */
+ if (nlist.n_value == 0
+ && gdbarch_sofun_address_maybe_missing (gdbarch))
+ {
+ bound_minimal_symbol minsym
+ = find_stab_function (namestring,
+ pst ? pst->filename : NULL, objfile);
+ if (minsym.minsym != NULL)
+ nlist.n_value
+ = CORE_ADDR (minsym.minsym->unrelocated_address ());
+ }
+ if (pst && textlow_not_set
+ && gdbarch_sofun_address_maybe_missing (gdbarch))
+ {
+ pst->set_text_low (unrelocated_addr (nlist.n_value));
+ textlow_not_set = 0;
+ }
+ /* End kludge. */
+
+ /* Keep track of the start of the last function so we
+ can handle end of function symbols. */
+ last_function_start = nlist.n_value;
+
+ /* In reordered executables this function may lie outside
+ the bounds created by N_SO symbols. If that's the case
+ use the address of this function as the low bound for
+ the partial symbol table. */
+ if (pst
+ && (textlow_not_set
+ || (unrelocated_addr (nlist.n_value)
+ < pst->unrelocated_text_low ()
+ && (nlist.n_value != 0))))
+ {
+ pst->set_text_low (unrelocated_addr (nlist.n_value));
+ textlow_not_set = 0;
+ }
+ if (pst != nullptr)
+ pst->add_psymbol (std::string_view (sym_name, sym_len), true,
+ VAR_DOMAIN, LOC_BLOCK,
+ SECT_OFF_TEXT (objfile),
+ psymbol_placement::GLOBAL,
+ unrelocated_addr (nlist.n_value),
+ dbx->ctx.psymtab_language,
+ partial_symtabs, objfile);
+ continue;
+
+ /* Two things show up here (hopefully); static symbols of
+ local scope (static used inside braces) or extensions
+ of structure symbols. We can ignore both. */
+ case 'V':
+ case '(':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-':
+ case '#': /* For symbol identification (used in live ranges). */
+ continue;
+
+ case ':':
+ /* It is a C++ nested symbol. We don't need to record it
+ (I don't think); if we try to look up foo::bar::baz,
+ then symbols for the symtab containing foo should get
+ read in, I think. */
+ /* Someone says sun cc puts out symbols like
+ /foo/baz/maclib::/usr/local/bin/maclib,
+ which would get here with a symbol type of ':'. */
+ continue;
+
+ default:
+ /* Unexpected symbol descriptor. The second and subsequent stabs
+ of a continued stab can show up here. The question is
+ whether they ever can mimic a normal stab--it would be
+ nice if not, since we certainly don't want to spend the
+ time searching to the end of every string looking for
+ a backslash. */
+
+ complaint (_("unknown symbol descriptor `%c'"),
+ p[1]);
+
+ /* Ignore it; perhaps it is an extension that we don't
+ know about. */
+ continue;
+ }
+ }
+
+ case N_EXCL:
+
+ namestring = set_namestring (objfile, &nlist);
+
+ /* Find the corresponding bincl and mark that psymtab on the
+ psymtab dependency list. */
+ {
+ legacy_psymtab *needed_pst =
+ find_corresponding_bincl_psymtab (namestring, nlist.n_value, objfile);
+
+ /* If this include file was defined earlier in this file,
+ leave it alone. */
+ if (needed_pst == pst)
+ continue;
+
+ if (needed_pst)
+ {
+ int i;
+ int found = 0;
+
+ for (i = 0; i < dependencies_used; i++)
+ if (dependency_list[i] == needed_pst)
+ {
+ found = 1;
+ break;
+ }
+
+ /* If it's already in the list, skip the rest. */
+ if (found)
+ continue;
+
+ dependency_list[dependencies_used++] = needed_pst;
+ if (dependencies_used >= dependencies_allocated)
+ {
+ legacy_psymtab **orig = dependency_list;
+
+ dependency_list =
+ (legacy_psymtab **)
+ alloca ((dependencies_allocated *= 2)
+ * sizeof (legacy_psymtab *));
+ memcpy (dependency_list, orig,
+ (dependencies_used
+ * sizeof (legacy_psymtab *)));
+#ifdef DEBUG_INFO
+ gdb_printf (gdb_stderr,
+ "Had to reallocate "
+ "dependency list.\n");
+ gdb_printf (gdb_stderr,
+ "New dependencies allocated: %d\n",
+ dependencies_allocated);
+#endif
+ }
+ }
+ }
+ continue;
+
+ case N_ENDM:
+ /* Solaris 2 end of module, finish current partial symbol
+ table. stabs_end_psymtab will set the high text address of
+ PST to the proper value, which is necessary if a module
+ compiled without debugging info follows this module. */
+ if (pst && gdbarch_sofun_address_maybe_missing (gdbarch))
+ {
+ stabs_end_psymtab (objfile, partial_symtabs, pst,
+ psymtab_include_list, includes_used,
+ symnum * dbx->ctx.symbol_size,
+ (unrelocated_addr) 0, dependency_list,
+ dependencies_used, textlow_not_set);
+ pst = (legacy_psymtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ dbx->ctx.has_line_numbers = 0;
+ }
+ continue;
+
+ case N_RBRAC:
+#ifdef HANDLE_RBRAC
+ HANDLE_RBRAC (nlist.n_value);
+ continue;
+#endif
+ case N_EINCL:
+ case N_DSLINE:
+ case N_BSLINE:
+ case N_SSYM: /* Claim: Structure or union element.
+ Hopefully, I can ignore this. */
+ case N_ENTRY: /* Alternate entry point; can ignore. */
+ case N_MAIN: /* Can definitely ignore this. */
+ case N_CATCH: /* These are GNU C++ extensions */
+ case N_EHDECL: /* that can safely be ignored here. */
+ case N_LENG:
+ case N_BCOMM:
+ case N_ECOMM:
+ case N_ECOML:
+ case N_FNAME:
+ case N_SLINE:
+ case N_RSYM:
+ case N_PSYM:
+ case N_BNSYM:
+ case N_ENSYM:
+ case N_LBRAC:
+ case N_NSYMS: /* Ultrix 4.0: symbol count */
+ case N_DEFD: /* GNU Modula-2 */
+ case N_ALIAS: /* SunPro F77: alias name, ignore for now. */
+
+ case N_OBJ: /* Useless types from Solaris. */
+ case N_OPT:
+ case N_PATCH:
+ /* These symbols aren't interesting; don't worry about them. */
+ continue;
+
+ default:
+ /* If we haven't found it yet, ignore it. It's probably some
+ new type we don't know about yet. */
+ unknown_symtype_complaint (hex_string (nlist.n_type));
+ continue;
+ }
+ }
+
+ /* If there's stuff to be cleaned up, clean it up. */
+ if (pst)
+ {
+ /* Don't set high text address of PST lower than it already
+ is. */
+ unrelocated_addr text_end
+ = (unrelocated_addr
+ ((dbx->ctx.lowest_text_address == (unrelocated_addr) -1
+ ? text_addr
+ : CORE_ADDR (dbx->ctx.lowest_text_address))
+ + text_size));
+
+ stabs_end_psymtab (objfile, partial_symtabs,
+ pst, psymtab_include_list, includes_used,
+ symnum * dbx->ctx.symbol_size,
+ (text_end > pst->unrelocated_text_high ()
+ ? text_end : pst->unrelocated_text_high ()),
+ dependency_list, dependencies_used, textlow_not_set);
+ }
+}
+
+/* Scan and build partial symbols for a symbol file.
+ We have been initialized by a call to dbx_symfile_init, which
+ put all the relevant info into a "struct dbx_symfile_info",
+ hung off the objfile structure. */
+
+void
+read_stabs_symtab (struct objfile *objfile, symfile_add_flags symfile_flags)
+{
+ bfd *sym_bfd;
+ int val;
+ struct dbx_symfile_info *key = dbx_objfile_data_key.get (objfile);
+
+ sym_bfd = objfile->obfd.get ();
+
+ /* .o and .nlm files are relocatables with text, data and bss segs based at
+ 0. This flag disables special (Solaris stabs-in-elf only) fixups for
+ symbols with a value of 0. */
+
+ key->ctx.symfile_relocatable = bfd_get_file_flags (sym_bfd) & HAS_RELOC;
+
+ val = bfd_seek (sym_bfd, DBX_SYMTAB_OFFSET (objfile), SEEK_SET);
+ if (val < 0)
+ perror_with_name (objfile_name (objfile));
+
+ key->ctx.symbol_size = DBX_SYMBOL_SIZE (objfile);
+ key->ctx.symbol_table_offset = DBX_SYMTAB_OFFSET (objfile);
+
+ scoped_free_pendings free_pending;
+
+ minimal_symbol_reader reader (objfile);
+
+ /* Read stabs data from executable file and define symbols. */
+
+ psymbol_functions *psf = new psymbol_functions ();
+ psymtab_storage *partial_symtabs = psf->get_partial_symtabs ().get ();
+ objfile->qf.emplace_front (psf);
+ read_stabs_symtab_1 (reader, partial_symtabs, objfile);
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+
+ reader.install ();
+}
+
+/* Record the namespace that the function defined by SYMBOL was
+ defined in, if necessary. BLOCK is the associated block; use
+ OBSTACK for allocation. */
+
+static void
+cp_set_block_scope (const struct symbol *symbol,
+ struct block *block,
+ struct obstack *obstack)
+{
+ if (symbol->demangled_name () != NULL)
+ {
+ /* Try to figure out the appropriate namespace from the
+ demangled name. */
+
+ /* FIXME: carlton/2003-04-15: If the function in question is
+ a method of a class, the name will actually include the
+ name of the class as well. This should be harmless, but
+ is a little unfortunate. */
+
+ const char *name = symbol->demangled_name ();
+ unsigned int prefix_len = cp_entire_prefix_len (name);
+
+ block->set_scope (obstack_strndup (obstack, name, prefix_len),
+ obstack);
+ }
+}
+
+bound_minimal_symbol
+find_stab_function (const char *namestring, const char *filename,
+ struct objfile *objfile)
+{
+ int n;
+
+ const char *colon = strchr (namestring, ':');
+ if (colon == NULL)
+ n = 0;
+ else
+ n = colon - namestring;
+
+ char *p = (char *) alloca (n + 2);
+ strncpy (p, namestring, n);
+ p[n] = 0;
+
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, p, objfile, filename);
+ if (msym.minsym == NULL)
+ {
+ /* Sun Fortran appends an underscore to the minimal symbol name,
+ try again with an appended underscore if the minimal symbol
+ was not found. */
+ p[n] = '_';
+ p[n + 1] = 0;
+ msym
+ = lookup_minimal_symbol (current_program_space, p, objfile, filename);
+ }
+
+ if (msym.minsym == NULL && filename != NULL)
+ {
+ /* Try again without the filename. */
+ p[n] = 0;
+ msym = lookup_minimal_symbol (current_program_space, p, objfile);
+ }
+ if (msym.minsym == NULL && filename != NULL)
+ {
+ /* And try again for Sun Fortran, but without the filename. */
+ p[n] = '_';
+ p[n + 1] = 0;
+ msym = lookup_minimal_symbol (current_program_space, p, objfile);
+ }
+
+ return msym;
+}
+
+/* Add header file number I for this object file
+ at the next successive FILENUM. */
+
+static void
+add_this_object_header_file (int i)
+{
+ if (n_this_object_header_files == n_allocated_this_object_header_files)
+ {
+ n_allocated_this_object_header_files *= 2;
+ this_object_header_files
+ = (int *) xrealloc ((char *) this_object_header_files,
+ n_allocated_this_object_header_files * sizeof (int));
+ }
+
+ this_object_header_files[n_this_object_header_files++] = i;
+}
+
+/* Add to this file an "old" header file, one already seen in
+ a previous object file. NAME is the header file's name.
+ INSTANCE is its instance code, to select among multiple
+ symbol tables for the same header file. */
+
+static void
+add_old_header_file (const char *name, int instance, struct objfile *objfile)
+{
+ struct header_file *p = HEADER_FILES (objfile);
+ int i;
+
+ for (i = 0; i < N_HEADER_FILES (objfile); i++)
+ if (filename_cmp (p[i].name, name) == 0 && instance == p[i].instance)
+ {
+ add_this_object_header_file (i);
+ return;
+ }
+ repeated_header_complaint (name, symnum);
+}
+
+/* Add to this file a "new" header file: definitions for its types follow.
+ NAME is the header file's name.
+ Most often this happens only once for each distinct header file,
+ but not necessarily. If it happens more than once, INSTANCE has
+ a different value each time, and references to the header file
+ use INSTANCE values to select among them.
+
+ dbx output contains "begin" and "end" markers for each new header file,
+ but at this level we just need to know which files there have been;
+ so we record the file when its "begin" is seen and ignore the "end". */
+
+static void
+add_new_header_file (const char *name, int instance, struct objfile *objfile)
+{
+ int i;
+ struct header_file *hfile;
+
+ /* Make sure there is room for one more header file. */
+
+ i = N_ALLOCATED_HEADER_FILES (objfile);
+
+ if (N_HEADER_FILES (objfile) == i)
+ {
+ if (i == 0)
+ {
+ N_ALLOCATED_HEADER_FILES (objfile) = 10;
+ HEADER_FILES (objfile) = (struct header_file *)
+ xmalloc (10 * sizeof (struct header_file));
+ }
+ else
+ {
+ i *= 2;
+ N_ALLOCATED_HEADER_FILES (objfile) = i;
+ HEADER_FILES (objfile) = (struct header_file *)
+ xrealloc ((char *) HEADER_FILES (objfile),
+ (i * sizeof (struct header_file)));
+ }
+ }
+
+ /* Create an entry for this header file. */
+
+ i = N_HEADER_FILES (objfile)++;
+ hfile = HEADER_FILES (objfile) + i;
+ hfile->name = xstrdup (name);
+ hfile->instance = instance;
+ hfile->length = 10;
+ hfile->vector = XCNEWVEC (struct type *, 10);
+
+ add_this_object_header_file (i);
+}
+
+/* See stabsread.h. */
+
+void
+process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
+ const section_offsets &section_offsets,
+ struct objfile *objfile, enum language language)
+{
+ struct gdbarch *gdbarch = objfile->arch ();
+ struct context_stack *newobj;
+ struct context_stack cstk;
+ /* This remembers the address of the start of a function. It is
+ used because in Solaris 2, N_LBRAC, N_RBRAC, and N_SLINE entries
+ are relative to the current function's start address. On systems
+ other than Solaris 2, this just holds the SECT_OFF_TEXT value,
+ and is used to relocate these symbol types rather than
+ SECTION_OFFSETS. */
+ static CORE_ADDR function_start_offset;
+
+ /* This holds the address of the start of a function, without the
+ system peculiarities of function_start_offset. */
+ static CORE_ADDR last_function_start;
+
+ /* If this is nonzero, we've seen an N_SLINE since the start of the
+ current function. We use this to tell us to move the first sline
+ to the beginning of the function regardless of what its given
+ value is. */
+ static int sline_found_in_function = 1;
+
+ /* If this is nonzero, we've seen a non-gcc N_OPT symbol for this
+ source file. Used to detect the SunPRO solaris compiler. */
+ static int n_opt_found;
+
+ /* The section index for this symbol. */
+ int section_index = -1;
+
+ struct dbx_symfile_info *key = dbx_objfile_data_key.get (objfile);
+
+ /* Something is wrong if we see real data before seeing a source
+ file name. */
+
+ if (get_last_source_file () == NULL && type != (unsigned char) N_SO)
+ {
+ /* Ignore any symbols which appear before an N_SO symbol.
+ Currently no one puts symbols there, but we should deal
+ gracefully with the case. A complain()t might be in order,
+ but this should not be an error (). */
+ return;
+ }
+
+ switch (type)
+ {
+ case N_FUN:
+ case N_FNAME:
+
+ if (*name == '\000')
+ {
+ /* This N_FUN marks the end of a function. This closes off
+ the current block. */
+ struct block *block;
+
+ if (outermost_context_p ())
+ {
+ lbrac_mismatch_complaint (symnum);
+ break;
+ }
+
+ /* The following check is added before recording line 0 at
+ end of function so as to handle hand-generated stabs
+ which may have an N_FUN stabs at the end of the function,
+ but no N_SLINE stabs. */
+ if (sline_found_in_function)
+ {
+ CORE_ADDR addr = last_function_start + valu;
+
+ record_line
+ (get_current_subfile (), 0,
+ unrelocated_addr (gdbarch_addr_bits_remove (gdbarch, addr)
+ - objfile->text_section_offset ()));
+ }
+
+ within_function = 0;
+ cstk = pop_context ();
+
+ /* Make a block for the local symbols within. */
+ block = finish_block (cstk.name,
+ cstk.old_blocks, NULL,
+ cstk.start_addr, cstk.start_addr + valu);
+
+ /* For C++, set the block's scope. */
+ if (cstk.name->language () == language_cplus)
+ cp_set_block_scope (cstk.name, block, &objfile->objfile_obstack);
+
+ /* May be switching to an assembler file which may not be using
+ block relative stabs, so reset the offset. */
+ function_start_offset = 0;
+
+ break;
+ }
+
+ sline_found_in_function = 0;
+
+ /* Relocate for dynamic loading. */
+ section_index = SECT_OFF_TEXT (objfile);
+ valu += section_offsets[SECT_OFF_TEXT (objfile)];
+ valu = gdbarch_addr_bits_remove (gdbarch, valu);
+ last_function_start = valu;
+
+ goto define_a_symbol;
+
+ case N_LBRAC:
+ /* This "symbol" just indicates the start of an inner lexical
+ context within a function. */
+
+ /* Ignore extra outermost context from SunPRO cc and acc. */
+ if (n_opt_found && desc == 1)
+ break;
+
+ valu += function_start_offset;
+
+ push_context (desc, valu);
+ break;
+
+ case N_RBRAC:
+ /* This "symbol" just indicates the end of an inner lexical
+ context that was started with N_LBRAC. */
+
+ /* Ignore extra outermost context from SunPRO cc and acc. */
+ if (n_opt_found && desc == 1)
+ break;
+
+ valu += function_start_offset;
+
+ if (outermost_context_p ())
+ {
+ lbrac_mismatch_complaint (symnum);
+ break;
+ }
+
+ cstk = pop_context ();
+ if (desc != cstk.depth)
+ lbrac_mismatch_complaint (symnum);
+
+ if (*get_local_symbols () != NULL)
+ {
+ /* GCC development snapshots from March to December of
+ 2000 would output N_LSYM entries after N_LBRAC
+ entries. As a consequence, these symbols are simply
+ discarded. Complain if this is the case. */
+ complaint (_("misplaced N_LBRAC entry; discarding local "
+ "symbols which have no enclosing block"));
+ }
+ *get_local_symbols () = cstk.locals;
+
+ if (get_context_stack_depth () > 1)
+ {
+ /* This is not the outermost LBRAC...RBRAC pair in the
+ function, its local symbols preceded it, and are the ones
+ just recovered from the context stack. Define the block
+ for them (but don't bother if the block contains no
+ symbols. Should we complain on blocks without symbols?
+ I can't think of any useful purpose for them). */
+ if (*get_local_symbols () != NULL)
+ {
+ /* Muzzle a compiler bug that makes end < start.
+
+ ??? Which compilers? Is this ever harmful?. */
+ if (cstk.start_addr > valu)
+ {
+ complaint (_("block start larger than block end"));
+ cstk.start_addr = valu;
+ }
+ /* Make a block for the local symbols within. */
+ finish_block (0, cstk.old_blocks, NULL,
+ cstk.start_addr, valu);
+ }
+ }
+ else
+ {
+ /* This is the outermost LBRAC...RBRAC pair. There is no
+ need to do anything; leave the symbols that preceded it
+ to be attached to the function's own block. We need to
+ indicate that we just moved outside of the function. */
+ within_function = 0;
+ }
+
+ break;
+
+ case N_FN:
+ case N_FN_SEQ:
+ /* This kind of symbol indicates the start of an object file.
+ Relocate for dynamic loading. */
+ section_index = SECT_OFF_TEXT (objfile);
+ valu += section_offsets[SECT_OFF_TEXT (objfile)];
+ break;
+
+ case N_SO:
+ /* This type of symbol indicates the start of data for one
+ source file. Finish the symbol table of the previous source
+ file (if any) and start accumulating a new symbol table.
+ Relocate for dynamic loading. */
+ section_index = SECT_OFF_TEXT (objfile);
+ valu += section_offsets[SECT_OFF_TEXT (objfile)];
+
+ n_opt_found = 0;
+
+ if (get_last_source_file ())
+ {
+ /* Check if previous symbol was also an N_SO (with some
+ sanity checks). If so, that one was actually the
+ directory name, and the current one is the real file
+ name. Patch things up. */
+ if (previous_stab_code == (unsigned char) N_SO)
+ {
+ patch_subfile_names (get_current_subfile (), name);
+ break; /* Ignore repeated SOs. */
+ }
+ end_compunit_symtab (valu);
+ end_stabs ();
+ }
+
+ /* Null name means this just marks the end of text for this .o
+ file. Don't start a new symtab in this case. */
+ if (*name == '\000')
+ break;
+
+ function_start_offset = 0;
+
+ start_stabs ();
+ start_compunit_symtab (objfile, name, NULL, valu, language);
+ record_debugformat ("stabs");
+ break;
+
+ case N_SOL:
+ /* This type of symbol indicates the start of data for a
+ sub-source-file, one whose contents were copied or included
+ in the compilation of the main source file (whose name was
+ given in the N_SO symbol). Relocate for dynamic loading. */
+ section_index = SECT_OFF_TEXT (objfile);
+ valu += section_offsets[SECT_OFF_TEXT (objfile)];
+ start_subfile (name);
+ break;
+
+ case N_BINCL:
+ push_subfile ();
+ add_new_header_file (name, valu, objfile);
+ start_subfile (name);
+ break;
+
+ case N_EINCL:
+ start_subfile (pop_subfile ());
+ break;
+
+ case N_EXCL:
+ add_old_header_file (name, valu, objfile);
+ break;
+
+ case N_SLINE:
+ /* This type of "symbol" really just records one line-number --
+ core-address correspondence. Enter it in the line list for
+ this symbol table. */
+
+ /* Relocate for dynamic loading and for ELF acc
+ function-relative symbols. */
+ valu += function_start_offset;
+
+ /* GCC 2.95.3 emits the first N_SLINE stab somewhere in the
+ middle of the prologue instead of right at the start of the
+ function. To deal with this we record the address for the
+ first N_SLINE stab to be the start of the function instead of
+ the listed location. We really shouldn't to this. When
+ compiling with optimization, this first N_SLINE stab might be
+ optimized away. Other (non-GCC) compilers don't emit this
+ stab at all. There is no real harm in having an extra
+ numbered line, although it can be a bit annoying for the
+ user. However, it totally screws up our testsuite.
+
+ So for now, keep adjusting the address of the first N_SLINE
+ stab, but only for code compiled with GCC. */
+
+ if (within_function && sline_found_in_function == 0)
+ {
+ CORE_ADDR addr = processing_gcc_compilation == 2 ?
+ last_function_start : valu;
+
+ record_line
+ (get_current_subfile (), desc,
+ unrelocated_addr (gdbarch_addr_bits_remove (gdbarch, addr)
+ - objfile->text_section_offset ()));
+ sline_found_in_function = 1;
+ }
+ else
+ record_line
+ (get_current_subfile (), desc,
+ unrelocated_addr (gdbarch_addr_bits_remove (gdbarch, valu)
+ - objfile->text_section_offset ()));
+ break;
+
+ case N_BCOMM:
+ common_block_start (name, objfile);
+ break;
+
+ case N_ECOMM:
+ common_block_end (objfile);
+ break;
+
+ /* The following symbol types need to have the appropriate
+ offset added to their value; then we process symbol
+ definitions in the name. */
+
+ case N_STSYM: /* Static symbol in data segment. */
+ case N_LCSYM: /* Static symbol in BSS segment. */
+ case N_ROSYM: /* Static symbol in read-only data segment. */
+ /* HORRID HACK DEPT. However, it's Sun's furgin' fault.
+ Solaris 2's stabs-in-elf makes *most* symbols relative but
+ leaves a few absolute (at least for Solaris 2.1 and version
+ 2.0.1 of the SunPRO compiler). N_STSYM and friends sit on
+ the fence. .stab "foo:S...",N_STSYM is absolute (ld
+ relocates it) .stab "foo:V...",N_STSYM is relative (section
+ base subtracted). This leaves us no choice but to search for
+ the 'S' or 'V'... (or pass the whole section_offsets stuff
+ down ONE MORE function call level, which we really don't want
+ to do). */
+ {
+ const char *p;
+
+ /* Normal object file and NLMs have non-zero text seg offsets,
+ but don't need their static syms offset in this fashion.
+ XXX - This is really a crock that should be fixed in the
+ solib handling code so that I don't have to work around it
+ here. */
+
+ if (!key->ctx.symfile_relocatable)
+ {
+ p = strchr (name, ':');
+ if (p != 0 && p[1] == 'S')
+ {
+ /* The linker relocated it. We don't want to add a
+ Sun-stabs Tfoo.foo-like offset, but we *do*
+ want to add whatever solib.c passed to
+ symbol_file_add as addr (this is known to affect
+ SunOS 4, and I suspect ELF too). Since there is no
+ Ttext.text symbol, we can get addr from the text offset. */
+ section_index = SECT_OFF_TEXT (objfile);
+ valu += section_offsets[SECT_OFF_TEXT (objfile)];
+ goto define_a_symbol;
+ }
+ }
+ /* Since it's not the kludge case, re-dispatch to the right
+ handler. */
+ switch (type)
+ {
+ case N_STSYM:
+ goto case_N_STSYM;
+ case N_LCSYM:
+ goto case_N_LCSYM;
+ case N_ROSYM:
+ goto case_N_ROSYM;
+ default:
+ internal_error (_("failed internal consistency check"));
+ }
+ }
+
+ case_N_STSYM: /* Static symbol in data segment. */
+ case N_DSLINE: /* Source line number, data segment. */
+ section_index = SECT_OFF_DATA (objfile);
+ valu += section_offsets[SECT_OFF_DATA (objfile)];
+ goto define_a_symbol;
+
+ case_N_LCSYM: /* Static symbol in BSS segment. */
+ case N_BSLINE: /* Source line number, BSS segment. */
+ /* N_BROWS: overlaps with N_BSLINE. */
+ section_index = SECT_OFF_BSS (objfile);
+ valu += section_offsets[SECT_OFF_BSS (objfile)];
+ goto define_a_symbol;
+
+ case_N_ROSYM: /* Static symbol in read-only data segment. */
+ section_index = SECT_OFF_RODATA (objfile);
+ valu += section_offsets[SECT_OFF_RODATA (objfile)];
+ goto define_a_symbol;
+
+ case N_ENTRY: /* Alternate entry point. */
+ /* Relocate for dynamic loading. */
+ section_index = SECT_OFF_TEXT (objfile);
+ valu += section_offsets[SECT_OFF_TEXT (objfile)];
+ goto define_a_symbol;
+
+ /* The following symbol types we don't know how to process.
+ Handle them in a "default" way, but complain to people who
+ care. */
+ default:
+ case N_CATCH: /* Exception handler catcher. */
+ case N_EHDECL: /* Exception handler name. */
+ case N_PC: /* Global symbol in Pascal. */
+ case N_M2C: /* Modula-2 compilation unit. */
+ /* N_MOD2: overlaps with N_EHDECL. */
+ case N_SCOPE: /* Modula-2 scope information. */
+ case N_ECOML: /* End common (local name). */
+ case N_NBTEXT: /* Gould Non-Base-Register symbols??? */
+ case N_NBDATA:
+ case N_NBBSS:
+ case N_NBSTS:
+ case N_NBLCS:
+ unknown_symtype_complaint (hex_string (type));
+
+ define_a_symbol:
+ [[fallthrough]];
+ /* These symbol types don't need the address field relocated,
+ since it is either unused, or is absolute. */
+ case N_GSYM: /* Global variable. */
+ case N_NSYMS: /* Number of symbols (Ultrix). */
+ case N_NOMAP: /* No map? (Ultrix). */
+ case N_RSYM: /* Register variable. */
+ case N_DEFD: /* Modula-2 GNU module dependency. */
+ case N_SSYM: /* Struct or union element. */
+ case N_LSYM: /* Local symbol in stack. */
+ case N_PSYM: /* Parameter variable. */
+ case N_LENG: /* Length of preceding symbol type. */
+ if (name)
+ {
+ int deftype;
+ const char *colon_pos = strchr (name, ':');
+
+ if (colon_pos == NULL)
+ deftype = '\0';
+ else
+ deftype = colon_pos[1];
+
+ switch (deftype)
+ {
+ case 'f':
+ case 'F':
+ /* Deal with the SunPRO 3.0 compiler which omits the
+ address from N_FUN symbols. */
+ if (type == N_FUN
+ && valu == section_offsets[SECT_OFF_TEXT (objfile)]
+ && gdbarch_sofun_address_maybe_missing (gdbarch))
+ {
+ bound_minimal_symbol minsym
+ = find_stab_function (name, get_last_source_file (),
+ objfile);
+ if (minsym.minsym != NULL)
+ valu = minsym.value_address ();
+ }
+
+ /* These addresses are absolute. */
+ function_start_offset = valu;
+
+ within_function = 1;
+
+ if (get_context_stack_depth () > 1)
+ {
+ complaint (_("unmatched N_LBRAC before symtab pos %d"),
+ symnum);
+ break;
+ }
+
+ if (!outermost_context_p ())
+ {
+ struct block *block;
+
+ cstk = pop_context ();
+ /* Make a block for the local symbols within. */
+ block = finish_block (cstk.name,
+ cstk.old_blocks, NULL,
+ cstk.start_addr, valu);
+
+ /* For C++, set the block's scope. */
+ if (cstk.name->language () == language_cplus)
+ cp_set_block_scope (cstk.name, block,
+ &objfile->objfile_obstack);
+ }
+
+ newobj = push_context (0, valu);
+ newobj->name = define_symbol (valu, name, desc, type, objfile);
+ if (newobj->name != nullptr)
+ newobj->name->set_section_index (section_index);
+ break;
+
+ default:
+ {
+ struct symbol *sym = define_symbol (valu, name, desc, type,
+ objfile);
+ if (sym != nullptr)
+ sym->set_section_index (section_index);
+ }
+ break;
+ }
+ }
+ break;
+
+ /* We use N_OPT to carry the gcc2_compiled flag. Sun uses it
+ for a bunch of other flags, too. Someday we may parse their
+ flags; for now we ignore theirs and hope they'll ignore ours. */
+ case N_OPT: /* Solaris 2: Compiler options. */
+ if (name)
+ {
+ if (strcmp (name, GCC2_COMPILED_FLAG_SYMBOL) == 0)
+ {
+ processing_gcc_compilation = 2;
+ }
+ else
+ n_opt_found = 1;
+ }
+ break;
+
+ case N_MAIN: /* Name of main routine. */
+ /* FIXME: If one has a symbol file with N_MAIN and then replaces
+ it with a symbol file with "main" and without N_MAIN. I'm
+ not sure exactly what rule to follow but probably something
+ like: N_MAIN takes precedence over "main" no matter what
+ objfile it is in; If there is more than one N_MAIN, choose
+ the one in the symfile_objfile; If there is more than one
+ N_MAIN within a given objfile, complain() and choose
+ arbitrarily. (kingdon) */
+ if (name != NULL)
+ set_objfile_main_name (objfile, name, language_unknown);
+ break;
+
+ /* The following symbol types can be ignored. */
+ case N_OBJ: /* Solaris 2: Object file dir and name. */
+ case N_PATCH: /* Solaris 2: Patch Run Time Checker. */
+ /* N_UNDF: Solaris 2: File separator mark. */
+ /* N_UNDF: -- we will never encounter it, since we only process
+ one file's symbols at once. */
+ case N_ENDM: /* Solaris 2: End of module. */
+ case N_ALIAS: /* SunPro F77: alias name, ignore for now. */
+ break;
+ }
+
+ /* '#' is a GNU C extension to allow one symbol to refer to another
+ related symbol.
+
+ Generally this is used so that an alias can refer to its main
+ symbol. */
+ gdb_assert (name);
+ if (name[0] == '#')
+ {
+ /* Initialize symbol reference names and determine if this is a
+ definition. If a symbol reference is being defined, go ahead
+ and add it. Otherwise, just return. */
+
+ const char *s = name;
+ int refnum;
+
+ /* If this stab defines a new reference ID that is not on the
+ reference list, then put it on the reference list.
+
+ We go ahead and advance NAME past the reference, even though
+ it is not strictly necessary at this time. */
+ refnum = symbol_reference_defined (&s);
+ if (refnum >= 0)
+ if (!ref_search (refnum))
+ ref_add (refnum, 0, name, valu);
+ name = s;
+ }
+
+ previous_stab_code = type;
+}
+
#define VISIBILITY_PRIVATE '0' /* Stabs character for private field */
#define VISIBILITY_PROTECTED '1' /* Stabs character for protected fld */
#define VISIBILITY_PUBLIC '2' /* Stabs character for public field */
@@ -2289,7 +4774,7 @@ read_member_functions (struct stab_field_info *fip, const char **pp,
if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && is_cplus_marker ((*pp)[2]))
{
- /* This is a completely wierd case. In order to stuff in the
+ /* This is a completely weird case. In order to stuff in the
names that might contain colons (the usual name delimiter),
Mike Tiemann defined a different name format which is
signalled if the identifier is "op$". In that case, the
@@ -3911,7 +6396,7 @@ read_huge_number (const char **pp, int end, int *bits,
}
/* -0x7f is the same as 0x80. So deal with it by adding one to
- the number of bits. Two's complement represention octals
+ the number of bits. Two's complement representation octals
can't have a '-' in front. */
if (sign == -1 && !twos_complement_representation)
++nbits;
diff --git a/gdb/stabsread.h b/gdb/stabsread.h
index 0a86840..565038a 100644
--- a/gdb/stabsread.h
+++ b/gdb/stabsread.h
@@ -1,5 +1,5 @@
-/* Include file for stabs debugging format support functions.
- Copyright (C) 1986-2024 Free Software Foundation, Inc.
+ /* Include file for stabs debugging format support functions.
+ Copyright (C) 1986-2024 Free Software Foundation, Inc.
This file is part of GDB.
@@ -54,7 +54,7 @@ extern unsigned char processing_gcc_compilation;
extern int within_function;
/* Hash table of global symbols whose values are not known yet.
- They are chained thru the SYMBOL_VALUE_CHAIN, since we don't
+ They are chained through the SYMBOL_VALUE_CHAIN, since we don't
have the correct data for that slot yet.
The use of the LOC_BLOCK code in this chain is nonstandard--
@@ -173,7 +173,7 @@ class psymtab_storage;
/* Functions exported by dbxread.c. These are not in stabsread.c because
they are only used by some stabs readers. */
-extern legacy_psymtab *dbx_end_psymtab
+extern legacy_psymtab *stabs_end_psymtab
(struct objfile *objfile, psymtab_storage *partial_symtabs,
legacy_psymtab *pst,
const char **include_list, int num_includes,
@@ -185,6 +185,12 @@ extern void process_one_symbol (int, int, CORE_ADDR, const char *,
const section_offsets &,
struct objfile *, enum language);
+/* Setup partial_symtab's describing each source file for which
+ debugging information is available. */
+
+void
+read_stabs_symtab (struct objfile *, symfile_add_flags);
+
extern void elfstab_build_psymtabs (struct objfile *objfile,
asection *stabsect,
file_ptr stabstroffset,
@@ -215,4 +221,91 @@ extern void init_header_files (void);
extern void scan_file_globals (struct objfile *objfile);
+/* Complaints about the symbols we have encountered. */
+
+void
+unknown_symtype_complaint (const char *);
+
+void
+lbrac_mismatch_complaint (int);
+
+void
+repeated_header_complaint (const char *, int);
+
+bound_minimal_symbol
+find_stab_function (const char *, const char *, struct objfile *);
+
+/* This handles a single symbol from the symbol-file, building symbols
+ into a GDB symtab. It takes these arguments and an implicit argument.
+
+ TYPE is the type field of the ".stab" symbol entry.
+ DESC is the desc field of the ".stab" entry.
+ VALU is the value field of the ".stab" entry.
+ NAME is the symbol name, in our address space.
+ SECTION_OFFSETS is a set of amounts by which the sections of this
+ object file were relocated when it was loaded into memory. Note
+ that these section_offsets are not the objfile->section_offsets but
+ the pst->section_offsets. All symbols that refer to memory
+ locations need to be offset by these amounts.
+ OBJFILE is the object file from which we are reading symbols. It
+ is used in end_compunit_symtab.
+ LANGUAGE is the language of the symtab.
+*/
+
+void
+process_one_symbol (int, int, CORE_ADDR, const char *,
+ const section_offsets &,
+ struct objfile *, enum language);
+
+#define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff)
+#define LDSYMLEN(p) (((struct symloc *)((p)->read_symtab_private))->ldsymlen)
+#define SYMLOC(p) ((struct symloc *)((p)->read_symtab_private))
+#define SYMBOL_SIZE(p) (SYMLOC(p)->symbol_size)
+#define SYMBOL_OFFSET(p) (SYMLOC(p)->symbol_offset)
+#define STRING_OFFSET(p) (SYMLOC(p)->string_offset)
+#define FILE_STRING_OFFSET(p) (SYMLOC(p)->file_string_offset)
+#define PST_LANGUAGE(p) (SYMLOC(p)->pst_language)
+
+#define INTERNALIZE_SYMBOL(intern, extern, abfd) \
+ { \
+ (intern).n_strx = bfd_h_get_32 (abfd, (extern)->e_strx); \
+ (intern).n_type = bfd_h_get_8 (abfd, (extern)->e_type); \
+ (intern).n_other = 0; \
+ (intern).n_desc = bfd_h_get_16 (abfd, (extern)->e_desc); \
+ if (bfd_get_sign_extend_vma (abfd)) \
+ (intern).n_value = bfd_h_get_signed_32 (abfd, (extern)->e_value); \
+ else \
+ (intern).n_value = bfd_h_get_32 (abfd, (extern)->e_value); \
+ }
+
+/* We put a pointer to this structure in the read_symtab_private field
+ of the psymtab. */
+
+struct symloc
+ {
+ /* Offset within the file symbol table of first local symbol for this
+ file. */
+
+ int ldsymoff;
+
+ /* Length (in bytes) of the section of the symbol table devoted to
+ this file's symbols (actually, the section bracketed may contain
+ more than just this file's symbols). If ldsymlen is 0, the only
+ reason for this thing's existence is the dependency list. Nothing
+ else will happen when it is read in. */
+
+ int ldsymlen;
+
+ /* The size of each symbol in the symbol file (in external form). */
+
+ int symbol_size;
+
+ /* Further information needed to locate the symbols if they are in
+ an ELF file. */
+
+ int symbol_offset;
+ int string_offset;
+ int file_string_offset;
+ enum language pst_language;
+ };
#endif /* STABSREAD_H */
diff --git a/gdb/stack.c b/gdb/stack.c
index b36193b..4a3e7e4 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -50,7 +50,6 @@
#include "linespec.h"
#include "cli/cli-utils.h"
#include "objfiles.h"
-#include "annotate.h"
#include "symfile.h"
#include "extension.h"
@@ -1299,13 +1298,12 @@ find_frame_funname (const frame_info_ptr &frame, enum language *funlang,
}
else
{
- struct bound_minimal_symbol msymbol;
CORE_ADDR pc;
if (!get_frame_address_in_block_if_available (frame, &pc))
return funname;
- msymbol = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (pc);
if (msymbol.minsym != NULL)
{
funname.reset (xstrdup (msymbol.minsym->print_name ()));
@@ -1419,7 +1417,7 @@ print_frame (struct ui_out *uiout,
annotate_frame_source_file_end ();
uiout->text (":");
annotate_frame_source_line ();
- uiout->field_signed ("line", sal.line);
+ uiout->field_signed ("line", sal.line, line_number_style.style ());
annotate_frame_source_end ();
}
@@ -1529,9 +1527,7 @@ info_frame_command_core (const frame_info_ptr &fi, bool selected_frame_p)
}
else if (frame_pc_p)
{
- struct bound_minimal_symbol msymbol;
-
- 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 ();
diff --git a/gdb/stubs/ia64vms-stub.c b/gdb/stubs/ia64vms-stub.c
index e7578d8..7e08119 100644
--- a/gdb/stubs/ia64vms-stub.c
+++ b/gdb/stubs/ia64vms-stub.c
@@ -210,7 +210,7 @@ union ia64_ireg
/* Predicate registers: There are 64 of these 1-bit registers. We
define a single register which is used to communicate these values
to/from the target. We will somehow contrive to make it appear
- that IA64_PR0_REGNUM thru IA64_PR63_REGNUM hold the actual values. */
+ that IA64_PR0_REGNUM through IA64_PR63_REGNUM hold the actual values. */
#define IA64_PR_REGNUM 330
/* Instruction pointer: 64 bits wide. */
@@ -311,7 +311,7 @@ term_raw_write (const char *str, unsigned int len)
LIB$SIGNAL (status);
}
-/* Flush ther term buffer. */
+/* Flush the term buffer. */
static void
term_flush (void)
diff --git a/gdb/stubs/m32r-stub.c b/gdb/stubs/m32r-stub.c
index 1f55f85..16be231 100644
--- a/gdb/stubs/m32r-stub.c
+++ b/gdb/stubs/m32r-stub.c
@@ -409,7 +409,7 @@ handle_exception (int exceptionVector)
hex2mem (ptr, (unsigned char *) &registers[regno], 4, 0);
/*
* Since we just changed a single CPU register, let's
- * make sure to keep the several stack pointers consistant.
+ * make sure to keep the several stack pointers consistent.
*/
stackmode = registers[PSW] & 0x80;
if (regno == R15) /* stack pointer changed */
@@ -975,7 +975,7 @@ isShortBranch (unsigned char *instr)
if (instr0 == 0x1E || instr0 == 0x1F) /* JL or JMP */
if ((instr[1] & 0xF0) == 0xC0)
- return 2; /* jump thru a register */
+ return 2; /* jump through a register. */
if (instr0 == 0x7C || instr0 == 0x7D || /* BC, BNC, BL, BRA */
instr0 == 0x7E || instr0 == 0x7F)
@@ -1088,7 +1088,7 @@ branchDestination (unsigned char *instr, int branchCode)
case 1: /* RTE */
return registers[BPC] & ~3; /* pop BPC into PC */
case 2: /* JL or JMP */
- return registers[instr[1] & 0x0F] & ~3; /* jump thru a register */
+ return registers[instr[1] & 0x0F] & ~3; /* jump through a register. */
case 3: /* BC, BNC, BL, BRA (short, 8-bit relative offset) */
return (((int) instr) & ~3) + ((char) instr[1] << 2);
case 4: /* BC, BNC, BL, BRA (long, 24-bit relative offset) */
diff --git a/gdb/symfile-debug.c b/gdb/symfile-debug.c
index 3a223d0..6bf8dc3 100644
--- a/gdb/symfile-debug.c
+++ b/gdb/symfile-debug.c
@@ -376,7 +376,8 @@ objfile::expand_symtabs_matching
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
block_search_flags search_flags,
- domain_search_flags domain)
+ domain_search_flags domain,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher)
{
/* This invariant is documented in quick-functions.h. */
gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
@@ -393,13 +394,14 @@ objfile::expand_symtabs_matching
for (const auto &iter : qf)
if (!iter->expand_symtabs_matching (this, file_matcher, lookup_name,
symbol_matcher, expansion_notify,
- search_flags, domain))
+ search_flags, domain,
+ lang_matcher))
return false;
return true;
}
struct compunit_symtab *
-objfile::find_pc_sect_compunit_symtab (struct bound_minimal_symbol msymbol,
+objfile::find_pc_sect_compunit_symtab (bound_minimal_symbol msymbol,
CORE_ADDR pc,
struct obj_section *section,
int warn_if_readin)
diff --git a/gdb/symfile.c b/gdb/symfile.c
index b0510b4..1502fdb 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -91,8 +91,6 @@ static void symbol_file_add_main_1 (const char *args, symfile_add_flags add_flag
static const struct sym_fns *find_sym_fns (bfd *);
-static void overlay_invalidate_all (void);
-
static void simple_free_overlay_table (void);
static void read_target_long_array (CORE_ADDR, unsigned int *, int, int,
@@ -1026,7 +1024,6 @@ symbol_file_add_with_addrs (const gdb_bfd_ref_ptr &abfd, const char *name,
section_addr_info *addrs,
objfile_flags flags, struct objfile *parent)
{
- struct objfile *objfile;
const int from_tty = add_flags & SYMFILE_VERBOSE;
const int mainline = add_flags & SYMFILE_MAINLINE;
const int always_confirm = add_flags & SYMFILE_ALWAYS_CONFIRM;
@@ -1053,14 +1050,17 @@ symbol_file_add_with_addrs (const gdb_bfd_ref_ptr &abfd, const char *name,
if (from_tty
&& (always_confirm
- || ((have_full_symbols () || have_partial_symbols ())
+ || ((have_full_symbols (current_program_space)
+ || have_partial_symbols (current_program_space))
&& mainline))
- && !query (_("Load new symbol table from \"%s\"? "), name))
+ && !query (_ ("Load new symbol table from \"%s\"? "), name))
error (_("Not confirmed."));
if (mainline)
flags |= OBJF_MAINLINE;
- objfile = objfile::make (abfd, name, flags, parent);
+
+ objfile *objfile
+ = objfile::make (abfd, current_program_space, name, flags, parent);
/* We either created a new mapped symbol table, mapped an existing
symbol table file which has not had initial symbol reading
@@ -1199,7 +1199,8 @@ symbol_file_add_main_1 (const char *args, symfile_add_flags add_flags,
void
symbol_file_clear (int from_tty)
{
- if ((have_full_symbols () || have_partial_symbols ())
+ if ((have_full_symbols (current_program_space)
+ || have_partial_symbols (current_program_space))
&& from_tty
&& (current_program_space->symfile_object_file
? !query (_("Discard symbol table from `%s'? "),
@@ -1209,7 +1210,7 @@ symbol_file_clear (int from_tty)
/* solib descriptors may have handles to objfiles. Wipe them before their
objfiles get stale by free_all_objfiles. */
- no_shared_libraries (NULL, from_tty);
+ no_shared_libraries (current_program_space);
current_program_space->free_all_objfiles ();
@@ -1370,17 +1371,13 @@ find_separate_debug_file (const char *dir,
objfile_name (objfile));
/* First try in the same directory as the original file. */
- std::string debugfile = dir;
- debugfile += debuglink;
+ std::string debugfile = path_join (dir, debuglink);
if (separate_debug_file_exists (debugfile, crc32, objfile, warnings))
return debugfile;
/* Then try in the subdirectory named DEBUG_SUBDIRECTORY. */
- debugfile = dir;
- debugfile += DEBUG_SUBDIRECTORY;
- debugfile += "/";
- debugfile += debuglink;
+ debugfile = path_join (dir, DEBUG_SUBDIRECTORY, debuglink);
if (separate_debug_file_exists (debugfile, crc32, objfile, warnings))
return debugfile;
@@ -1393,10 +1390,13 @@ find_separate_debug_file (const char *dir,
bool target_prefix = is_target_filename (dir);
const char *dir_notarget
= target_prefix ? dir + strlen (TARGET_SYSROOT_PREFIX) : dir;
+ const char *target_prefix_str = target_prefix ? TARGET_SYSROOT_PREFIX : "";
std::vector<gdb::unique_xmalloc_ptr<char>> debugdir_vec
= dirnames_to_char_ptr_vec (debug_file_directory.c_str ());
- gdb::unique_xmalloc_ptr<char> canon_sysroot
- = gdb_realpath (gdb_sysroot.c_str ());
+ const char *sysroot_str = gdb_sysroot.c_str ();
+ if (is_target_filename (sysroot_str) && target_filesystem_is_local ())
+ sysroot_str += strlen (TARGET_SYSROOT_PREFIX);
+ gdb::unique_xmalloc_ptr<char> canon_sysroot = gdb_realpath (sysroot_str);
/* MS-Windows/MS-DOS don't allow colons in file names; we must
convert the drive letter into a one-letter directory, so that the
@@ -1421,12 +1421,8 @@ find_separate_debug_file (const char *dir,
for (const gdb::unique_xmalloc_ptr<char> &debugdir : debugdir_vec)
{
- debugfile = target_prefix ? TARGET_SYSROOT_PREFIX : "";
- debugfile += debugdir;
- debugfile += "/";
- debugfile += drive;
- debugfile += dir_notarget;
- debugfile += debuglink;
+ debugfile = path_join (target_prefix_str, debugdir.get (),
+ drive.c_str (), dir_notarget, debuglink);
if (separate_debug_file_exists (debugfile, crc32, objfile, warnings))
return debugfile;
@@ -1443,39 +1439,18 @@ find_separate_debug_file (const char *dir,
{
/* If the file is in the sysroot, try using its base path in
the global debugfile directory. */
- debugfile = target_prefix ? TARGET_SYSROOT_PREFIX : "";
- debugfile += debugdir;
- debugfile += "/";
- debugfile += base_path;
- debugfile += "/";
- debugfile += debuglink;
+ debugfile = path_join (target_prefix_str, debugdir.get (),
+ base_path, debuglink);
if (separate_debug_file_exists (debugfile, crc32, objfile, warnings))
return debugfile;
/* If the file is in the sysroot, try using its base path in
- the sysroot's global debugfile directory. GDB_SYSROOT
- might refer to a target: path; we strip the "target:"
- prefix -- but if that would yield the empty string, we
- don't bother at all, because that would just give the
- same result as above. */
+ the sysroot's global debugfile directory. */
if (gdb_sysroot != TARGET_SYSROOT_PREFIX)
{
- debugfile = target_prefix ? TARGET_SYSROOT_PREFIX : "";
- if (is_target_filename (gdb_sysroot))
- {
- std::string root
- = gdb_sysroot.substr (strlen (TARGET_SYSROOT_PREFIX));
- gdb_assert (!root.empty ());
- debugfile += root;
- }
- else
- debugfile += gdb_sysroot;
- debugfile += debugdir;
- debugfile += "/";
- debugfile += base_path;
- debugfile += "/";
- debugfile += debuglink;
+ debugfile = path_join (gdb_sysroot.c_str (), debugdir.get (),
+ base_path, debuglink);
if (separate_debug_file_exists (debugfile, crc32, objfile,
warnings))
@@ -2355,39 +2330,90 @@ add_symbol_file_command (const char *args, int from_tty)
}
+/* Option support for 'remove-symbol-file' command. */
+
+struct remove_symbol_file_options
+{
+ /* True when the '-a' flag was passed. */
+ bool address_flag = false;
+};
+
+using remove_symbol_file_options_opt_def
+ = gdb::option::flag_option_def<remove_symbol_file_options>;
+
+static const gdb::option::option_def remove_symbol_file_opt_defs[] = {
+ remove_symbol_file_options_opt_def {
+ "a",
+ [] (remove_symbol_file_options *opt) { return &opt->address_flag; },
+ N_("Select a symbol file containing ADDRESS.")
+ },
+};
+
+static inline gdb::option::option_def_group
+make_remove_symbol_file_def_group (remove_symbol_file_options *opts)
+{
+ return {{remove_symbol_file_opt_defs}, opts};
+}
+
+/* Completion function for 'remove-symbol-file' command. */
+
+static void
+remove_symbol_file_command_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char * /* word */)
+{
+ /* Unlike many command completion functions we do gather the option
+ values here. How we complete the rest of the command depends on
+ whether the '-a' flag has been given or not. */
+ remove_symbol_file_options opts;
+ auto grp = make_remove_symbol_file_def_group (&opts);
+ if (gdb::option::complete_options
+ (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp))
+ return;
+
+ /* Complete the rest of the command line as either a filename or an
+ expression (which will evaluate to an address) if the '-a' flag was
+ given. */
+ if (!opts.address_flag)
+ {
+ const char *word
+ = advance_to_filename_maybe_quoted_complete_word_point (tracker, text);
+ filename_maybe_quoted_completer (ignore, tracker, text, word);
+ }
+ else
+ {
+ const char *word
+ = advance_to_expression_complete_word_point (tracker, text);
+ symbol_completer (ignore, tracker, text, word);
+ }
+}
+
/* This function removes a symbol file that was added via add-symbol-file. */
static void
remove_symbol_file_command (const char *args, int from_tty)
{
- struct objfile *objf = NULL;
- struct program_space *pspace = current_program_space;
-
dont_repeat ();
- if (args == NULL)
- error (_("remove-symbol-file: no symbol file provided"));
+ remove_symbol_file_options opts;
+ auto grp = make_remove_symbol_file_def_group (&opts);
+ gdb::option::process_options
+ (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp);
- gdb_argv argv (args);
+ struct objfile *objf = nullptr;
- if (strcmp (argv[0], "-a") == 0)
+ if (opts.address_flag)
{
- /* Interpret the next argument as an address. */
- CORE_ADDR addr;
+ if (args == nullptr || *args == '\0')
+ error (_("remove-symbol-file: no address provided"));
- if (argv[1] == NULL)
- error (_("Missing address argument"));
-
- if (argv[2] != NULL)
- error (_("Junk after %s"), argv[1]);
-
- addr = parse_and_eval_address (argv[1]);
+ CORE_ADDR addr = parse_and_eval_address (args);
for (objfile *objfile : current_program_space->objfiles ())
{
if ((objfile->flags & OBJF_USERLOADED) != 0
&& (objfile->flags & OBJF_SHARED) != 0
- && objfile->pspace == pspace
+ && objfile->pspace () == current_program_space
&& is_addr_in_objfile (addr, objfile))
{
objf = objfile;
@@ -2395,21 +2421,18 @@ remove_symbol_file_command (const char *args, int from_tty)
}
}
}
- else if (argv[0] != NULL)
+ else
{
- /* Interpret the current argument as a file name. */
-
- if (argv[1] != NULL)
- error (_("Junk after %s"), argv[0]);
-
- gdb::unique_xmalloc_ptr<char> filename (tilde_expand (argv[0]));
+ std::string filename = extract_single_filename_arg (args);
+ if (filename.empty ())
+ error (_("remove-symbol-file: no symbol file provided"));
for (objfile *objfile : current_program_space->objfiles ())
{
if ((objfile->flags & OBJF_USERLOADED) != 0
&& (objfile->flags & OBJF_SHARED) != 0
- && objfile->pspace == pspace
- && filename_cmp (filename.get (), objfile_name (objfile)) == 0)
+ && objfile->pspace () == current_program_space
+ && filename_cmp (filename.c_str (), objfile_name (objfile)) == 0)
{
objf = objfile;
break;
@@ -2611,7 +2634,7 @@ reread_symbols (int from_tty)
making the dangling pointers point to correct data
again. */
- objfiles_changed ();
+ objfiles_changed (current_program_space);
/* Recompute section offsets and section indices. */
objfile->sf->sym_offsets (objfile, {});
@@ -2884,7 +2907,7 @@ clear_symtab_users (symfile_add_flags add_flags)
/* Clear the "current" symtab first, because it is no longer valid.
breakpoint_re_set may try to access the current symtab. */
- clear_current_source_symtab_and_line ();
+ clear_current_source_symtab_and_line (current_program_space);
clear_displays ();
clear_last_displayed_sal ();
@@ -2969,13 +2992,13 @@ section_is_overlay (struct obj_section *section)
return 0;
}
-/* Function: overlay_invalidate_all (void)
- Invalidate the mapped state of all overlay sections (mark it as stale). */
+/* Invalidate the mapped state of all overlay sections (mark it as stale) in
+ PSPACE. */
static void
-overlay_invalidate_all (void)
+overlay_invalidate_all (program_space *pspace)
{
- for (objfile *objfile : current_program_space->objfiles ())
+ for (objfile *objfile : pspace->objfiles ())
for (obj_section *sect : objfile->sections ())
if (section_is_overlay (sect))
sect->ovly_mapped = -1;
@@ -3011,7 +3034,7 @@ section_is_mapped (struct obj_section *osect)
{
if (overlay_cache_invalid)
{
- overlay_invalidate_all ();
+ overlay_invalidate_all (current_program_space);
overlay_cache_invalid = 0;
}
if (osect->ovly_mapped == -1)
@@ -3427,14 +3450,13 @@ read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr,
static int
simple_read_overlay_table (void)
{
- struct bound_minimal_symbol novlys_msym;
- struct bound_minimal_symbol ovly_table_msym;
struct gdbarch *gdbarch;
int word_size;
enum bfd_endian byte_order;
simple_free_overlay_table ();
- novlys_msym = lookup_minimal_symbol ("_novlys", NULL, NULL);
+ bound_minimal_symbol novlys_msym
+ = lookup_minimal_symbol (current_program_space, "_novlys");
if (! novlys_msym.minsym)
{
error (_("Error reading inferior's overlay table: "
@@ -3443,7 +3465,8 @@ simple_read_overlay_table (void)
return 0;
}
- ovly_table_msym = lookup_bound_minimal_symbol ("_ovly_table");
+ bound_minimal_symbol ovly_table_msym
+ = lookup_minimal_symbol (current_program_space, "_ovly_table");
if (! ovly_table_msym.minsym)
{
error (_("Error reading inferior's overlay table: couldn't find "
@@ -3522,8 +3545,8 @@ simple_overlay_update (struct obj_section *osect)
{
/* Does its cached location match what's currently in the
symtab? */
- struct bound_minimal_symbol minsym
- = lookup_minimal_symbol ("_ovly_table", NULL, NULL);
+ bound_minimal_symbol minsym
+ = lookup_minimal_symbol (current_program_space, "_ovly_table");
if (minsym.minsym == NULL)
error (_("Error reading inferior's overlay table: couldn't "
@@ -3722,7 +3745,7 @@ static void
symfile_free_objfile (struct objfile *objfile)
{
/* Remove the target sections owned by this objfile. */
- objfile->pspace->remove_target_sections (objfile);
+ objfile->pspace ()->remove_target_sections (objfile);
}
/* Wrapper around the quick_symbol_functions expand_symtabs_matching "method".
@@ -3736,7 +3759,8 @@ expand_symtabs_matching
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
block_search_flags search_flags,
- domain_search_flags domain)
+ domain_search_flags domain,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher)
{
for (objfile *objfile : current_program_space->objfiles ())
if (!objfile->expand_symtabs_matching (file_matcher,
@@ -3744,7 +3768,8 @@ expand_symtabs_matching
symbol_matcher,
expansion_notify,
search_flags,
- domain))
+ domain,
+ lang_matcher))
return false;
return true;
}
@@ -3839,7 +3864,7 @@ Usage: symbol-file [-readnow | -readnever] [-o OFF] FILE\n\
OFF is an optional offset which is added to each section address.\n\
The `file' command can also load symbol tables, as well as setting the file\n\
to execute.\n" READNOW_READNEVER_HELP), &cmdlist);
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, filename_maybe_quoted_completer);
c = add_cmd ("add-symbol-file", class_files, add_symbol_file_command, _("\
Load symbols from FILE, assuming FILE has been dynamically loaded.\n\
@@ -3853,16 +3878,24 @@ OFF is an optional offset which is added to the default load addresses\n\
of all sections for which no other address was specified.\n"
READNOW_READNEVER_HELP),
&cmdlist);
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, filename_maybe_quoted_completer);
- c = add_cmd ("remove-symbol-file", class_files,
- remove_symbol_file_command, _("\
+ const auto remove_symbol_file_opts
+ = make_remove_symbol_file_def_group (nullptr);
+ static std::string remove_symbol_file_cmd_help
+ = gdb::option::build_help (_("\
Remove a symbol file added via the add-symbol-file command.\n\
Usage: remove-symbol-file FILENAME\n\
remove-symbol-file -a ADDRESS\n\
The file to remove can be identified by its filename or by an address\n\
-that lies within the boundaries of this symbol file in memory."),
+that lies within the boundaries of this symbol file in memory.\n\
+Options:\n\
+%OPTIONS%"), remove_symbol_file_opts);
+ c = add_cmd ("remove-symbol-file", class_files,
+ remove_symbol_file_command,
+ remove_symbol_file_cmd_help.c_str (),
&cmdlist);
+ set_cmd_completer_handle_brkchars (c, remove_symbol_file_command_completer);
c = add_cmd ("load", class_files, load_command, _("\
Dynamically load FILE into the running program.\n\
@@ -3871,7 +3904,7 @@ Usage: load [FILE] [OFFSET]\n\
An optional load OFFSET may also be given as a literal address.\n\
When OFFSET is provided, FILE must also be provided. FILE can be provided\n\
on its own."), &cmdlist);
- set_cmd_completer (c, filename_completer);
+ set_cmd_completer (c, deprecated_filename_completer);
cmd_list_element *overlay_cmd
= add_basic_prefix_cmd ("overlay", class_support,
diff --git a/gdb/symfile.h b/gdb/symfile.h
index 508ba48..74187c8 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -352,7 +352,9 @@ bool expand_symtabs_matching
gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
block_search_flags search_flags,
- domain_search_flags kind);
+ domain_search_flags kind,
+ gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher
+ = nullptr);
void map_symbol_filenames (gdb::function_view<symbol_filename_ftype> fun,
bool need_fullname);
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
index b4e0360..a484fb2 100644
--- a/gdb/symmisc.c
+++ b/gdb/symmisc.c
@@ -366,8 +366,7 @@ dump_symtab (struct symtab *symtab, struct ui_file *outfile)
But use only real languages, not placeholders. */
if (symtab->language () != language_unknown)
{
- scoped_restore_current_language save_lang;
- set_language (symtab->language ());
+ scoped_restore_current_language save_lang (symtab->language ());
dump_symtab_1 (symtab, outfile);
}
else
@@ -378,7 +377,9 @@ static void
maintenance_print_symbols (const char *args, int from_tty)
{
struct ui_file *outfile = gdb_stdout;
- char *address_arg = NULL, *source_arg = NULL, *objfile_arg = NULL;
+ const char *address_arg = nullptr;
+ const char *source_arg = nullptr;
+ const char *objfile_arg = nullptr;
int i, outfile_idx;
dont_repeat ();
@@ -656,7 +657,7 @@ static void
maintenance_print_msymbols (const char *args, int from_tty)
{
struct ui_file *outfile = gdb_stdout;
- char *objfile_arg = NULL;
+ const char *objfile_arg = nullptr;
int i, outfile_idx;
dont_repeat ();
@@ -888,7 +889,7 @@ maintenance_check_symtabs (const char *ignore, int from_tty)
static void
maintenance_expand_symtabs (const char *args, int from_tty)
{
- char *regexp = NULL;
+ const char *regexp = nullptr;
/* We use buildargv here so that we handle spaces in the regexp
in a way that allows adding more arguments later. */
@@ -904,18 +905,25 @@ maintenance_expand_symtabs (const char *args, int from_tty)
}
}
- if (regexp)
- re_comp (regexp);
+ if (regexp == nullptr)
+ {
+ for (struct program_space *pspace : program_spaces)
+ for (objfile *objfile : pspace->objfiles ())
+ objfile->expand_all_symtabs ();
+
+ return;
+ }
+
+ re_comp (regexp);
for (struct program_space *pspace : program_spaces)
for (objfile *objfile : pspace->objfiles ())
objfile->expand_symtabs_matching
([&] (const char *filename, bool basenames)
- {
- /* KISS: Only apply the regexp to the complete file name. */
- return (!basenames
- && (regexp == NULL || re_exec (filename)));
- },
+ {
+ /* KISS: Only apply the regexp to the complete file name. */
+ return !basenames && re_exec (filename);
+ },
NULL,
NULL,
NULL,
@@ -991,7 +999,8 @@ maintenance_print_one_line_table (struct symtab *symtab, void *data)
ui_out_emit_tuple tuple_emitter (uiout, nullptr);
uiout->field_signed ("index", i);
if (item->line > 0)
- uiout->field_signed ("line", item->line);
+ uiout->field_signed ("line", item->line,
+ line_number_style.style ());
else
uiout->field_string ("line", _("END"));
uiout->field_core_addr ("rel-address", objfile->arch (),
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 41d71be..a479e92 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -700,15 +700,10 @@ iterate_over_some_symtabs (const char *name,
return false;
}
-/* Check for a symtab of a specific name; first in symtabs, then in
- psymtabs. *If* there is no '/' in the name, a match after a '/'
- in the symtab filename will also work.
-
- Calls CALLBACK with each symtab that is found. If CALLBACK returns
- true, the search stops. */
+/* See symtab.h. */
void
-iterate_over_symtabs (const char *name,
+iterate_over_symtabs (program_space *pspace, const char *name,
gdb::function_view<bool (symtab *)> callback)
{
gdb::unique_xmalloc_ptr<char> real_path;
@@ -721,34 +716,28 @@ iterate_over_symtabs (const char *name,
gdb_assert (IS_ABSOLUTE_PATH (real_path.get ()));
}
- for (objfile *objfile : current_program_space->objfiles ())
- {
- if (iterate_over_some_symtabs (name, real_path.get (),
- objfile->compunit_symtabs, NULL,
- callback))
+ for (objfile *objfile : pspace->objfiles ())
+ if (iterate_over_some_symtabs (name, real_path.get (),
+ objfile->compunit_symtabs, nullptr,
+ callback))
return;
- }
- /* Same search rules as above apply here, but now we look thru the
+ /* Same search rules as above apply here, but now we look through the
psymtabs. */
-
- for (objfile *objfile : current_program_space->objfiles ())
- {
- if (objfile->map_symtabs_matching_filename (name, real_path.get (),
- callback))
- return;
- }
+ for (objfile *objfile : pspace->objfiles ())
+ if (objfile->map_symtabs_matching_filename (name, real_path.get (),
+ callback))
+ return;
}
-/* A wrapper for iterate_over_symtabs that returns the first matching
- symtab, or NULL. */
+/* See symtab.h. */
-struct symtab *
-lookup_symtab (const char *name)
+symtab *
+lookup_symtab (program_space *pspace, const char *name)
{
struct symtab *result = NULL;
- iterate_over_symtabs (name, [&] (symtab *symtab)
+ iterate_over_symtabs (pspace, name, [&] (symtab *symtab)
{
result = symtab;
return true;
@@ -1563,6 +1552,7 @@ symbol_cache_mark_not_found (struct block_symbol_cache *bsc,
static void
symbol_cache_flush (struct program_space *pspace)
{
+ ada_clear_symbol_cache (pspace);
struct symbol_cache *cache = symbol_cache_key.get (pspace);
int pass;
@@ -1755,7 +1745,7 @@ maintenance_print_symbol_cache_statistics (const char *args, int from_tty)
static void
symtab_new_objfile_observer (struct objfile *objfile)
{
- symbol_cache_flush (objfile->pspace);
+ symbol_cache_flush (objfile->pspace ());
}
/* This module's 'all_objfiles_removed' observer. */
@@ -1774,7 +1764,7 @@ symtab_all_objfiles_removed (program_space *pspace)
static void
symtab_free_objfile_observer (struct objfile *objfile)
{
- symbol_cache_flush (objfile->pspace);
+ symbol_cache_flush (objfile->pspace ());
}
/* See symtab.h. */
@@ -1928,6 +1918,28 @@ lookup_name_info::match_any ()
return lookup_name;
}
+/* See symtab.h. */
+
+unsigned int
+lookup_name_info::search_name_hash (language lang) const
+{
+ /* This works around an obscure problem. If currently in Ada mode,
+ and the name is wrapped in '<...>' (indicating verbatim mode),
+ force the use of the Ada language here so that the '<' and '>'
+ will be removed. */
+ if (current_language->la_language == language_ada && ada ().verbatim_p ())
+ lang = language_ada;
+
+ /* Only compute each language's hash once. */
+ if (!m_demangled_hashes_p[lang])
+ {
+ m_demangled_hashes[lang]
+ = ::search_name_hash (lang, language_lookup_name (lang));
+ m_demangled_hashes_p[lang] = true;
+ }
+ return m_demangled_hashes[lang];
+}
+
/* Compute the demangled form of NAME as used by the various symbol
lookup functions. The result can either be the input NAME
directly, or a pointer to a buffer owned by the STORAGE object.
@@ -2439,7 +2451,7 @@ lookup_symbol_in_objfile_from_linkage_name (struct objfile *objfile,
/* A helper function that throws an exception when a symbol was found
in a psymtab but not in a symtab. */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
error_in_psymtab_expansion (enum block_enum block_index, const char *name,
struct compunit_symtab *cust)
{
@@ -2892,14 +2904,14 @@ find_pc_sect_compunit_symtab (CORE_ADDR pc, struct obj_section *section)
{
struct compunit_symtab *best_cust = NULL;
CORE_ADDR best_cust_range = 0;
- struct bound_minimal_symbol msymbol;
/* If we know that this is not a text address, return failure. This is
necessary because we loop based on the block's high and low code
addresses, which do not include the data ranges, and because
we call find_pc_sect_psymtab which has a similar restriction based
on the partial_symtab's texthigh and textlow. */
- msymbol = lookup_minimal_symbol_by_pc_section (pc, section);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol_by_pc_section (pc, section);
if (msymbol.minsym && msymbol.minsym->data_p ())
return NULL;
@@ -2980,7 +2992,7 @@ find_pc_sect_compunit_symtab (CORE_ADDR pc, struct obj_section *section)
section. */
}
- /* Cust is best found sofar, save it. */
+ /* Cust is best found so far, save it. */
best_cust = cust;
best_cust_range = range;
}
@@ -3091,7 +3103,6 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
int len;
const linetable_entry *item;
const struct blockvector *bv;
- struct bound_minimal_symbol msymbol;
/* Info on best line seen so far, and where it starts, and its file. */
@@ -3170,13 +3181,14 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
* check for the address being the same, to avoid an
* infinite recursion.
*/
- msymbol = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (pc);
if (msymbol.minsym != NULL)
if (msymbol.minsym->type () == mst_solib_trampoline)
{
- struct bound_minimal_symbol mfunsym
- = lookup_minimal_symbol_text (msymbol.minsym->linkage_name (),
- NULL);
+ bound_minimal_symbol mfunsym
+ = lookup_minimal_symbol_text (current_program_space,
+ msymbol.minsym->linkage_name (),
+ nullptr);
if (mfunsym.minsym == NULL)
/* I eliminated this warning since it is coming out
@@ -3919,7 +3931,7 @@ skip_prologue_sal (struct symtab_and_line *sal)
}
else
{
- struct bound_minimal_symbol msymbol
+ bound_minimal_symbol msymbol
= lookup_minimal_symbol_by_pc_section (sal->pc, sal->section);
if (msymbol.minsym == NULL)
@@ -4764,8 +4776,9 @@ info_sources_worker (struct ui_out *uiout,
static void
info_sources_command (const char *args, int from_tty)
{
- if (!have_full_symbols () && !have_partial_symbols ())
- error (_("No symbol table is loaded. Use the \"file\" command."));
+ if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space))
+ error (_ ("No symbol table is loaded. Use the \"file\" command."));
filename_partial_match_opts match_opts;
auto group = make_info_sources_options_def_group (&match_opts);
@@ -5289,7 +5302,7 @@ print_symbol_info (struct symbol *sym, int block, const char *last)
for non-debugging symbols to gdb_stdout. */
static void
-print_msymbol_info (struct bound_minimal_symbol msymbol)
+print_msymbol_info (bound_minimal_symbol msymbol)
{
struct gdbarch *gdbarch = msymbol.objfile->arch ();
const char *tmp;
@@ -6293,7 +6306,7 @@ collect_file_symbol_completion_matches (completion_tracker &tracker,
/* Go through symtabs for SRCFILE and check the externs and statics
for symbols which match. */
- iterate_over_symtabs (srcfile, [&] (symtab *s)
+ iterate_over_symtabs (current_program_space, srcfile, [&] (symtab *s)
{
add_symtab_completions (s->compunit (),
tracker, mode, lookup_name,
@@ -6381,7 +6394,8 @@ make_source_files_completion_list (const char *text, const char *word)
const char *base_name;
struct add_partial_filename_data datum;
- if (!have_full_symbols () && !have_partial_symbols ())
+ if (!have_full_symbols (current_program_space)
+ && !have_partial_symbols (current_program_space))
return list;
filename_seen_cache filenames_seen;
@@ -6775,10 +6789,12 @@ symbol::get_maybe_copied_address () const
gdb_assert (this->aclass () == LOC_STATIC);
const char *linkage_name = this->linkage_name ();
- bound_minimal_symbol minsym = lookup_minimal_symbol_linkage (linkage_name,
- false);
+ bound_minimal_symbol minsym
+ = lookup_minimal_symbol_linkage (this->objfile ()->pspace (), linkage_name,
+ false);
if (minsym.minsym != nullptr)
return minsym.value_address ();
+
return this->m_value.address;
}
@@ -6791,10 +6807,11 @@ minimal_symbol::get_maybe_copied_address (objfile *objf) const
gdb_assert ((objf->flags & OBJF_MAINLINE) == 0);
const char *linkage_name = this->linkage_name ();
- bound_minimal_symbol found = lookup_minimal_symbol_linkage (linkage_name,
- true);
+ bound_minimal_symbol found
+ = lookup_minimal_symbol_linkage (objf->pspace (), linkage_name, true);
if (found.minsym != nullptr)
return found.value_address ();
+
return (this->m_value.address
+ objf->section_offsets[this->section_index ()]);
}
diff --git a/gdb/symtab.h b/gdb/symtab.h
index a5631a2..aa86a80 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -266,17 +266,7 @@ class lookup_name_info final
}
/* Get the search name hash for searches in language LANG. */
- unsigned int search_name_hash (language lang) const
- {
- /* Only compute each language's hash once. */
- if (!m_demangled_hashes_p[lang])
- {
- m_demangled_hashes[lang]
- = ::search_name_hash (lang, language_lookup_name (lang));
- m_demangled_hashes_p[lang] = true;
- }
- return m_demangled_hashes[lang];
- }
+ unsigned int search_name_hash (language lang) const;
/* Get the search name for searches in language LANG. */
const char *language_lookup_name (language lang) const
@@ -611,20 +601,20 @@ struct general_symbol_info
section_offsets for this objfile. Negative means that the symbol
does not get relocated relative to a section. */
- short m_section;
+ int m_section;
/* Set the index into the obj_section list (within the containing
objfile) for the section that contains this symbol. See M_SECTION
for more details. */
- void set_section_index (short idx)
+ void set_section_index (int idx)
{ m_section = idx; }
/* Return the index into the obj_section list (within the containing
objfile) for the section that contains this symbol. See M_SECTION
for more details. */
- short section_index () const
+ auto section_index () const
{ return m_section; }
/* Return the obj_section from OBJFILE for this symbol. The symbol
@@ -818,7 +808,7 @@ struct minimal_symbol : public general_symbol_info
m_target_flag_2 = target_flag_2;
}
- /* Size of this symbol. dbx_end_psymtab in dbxread.c uses this
+ /* Size of this symbol. stabs_end_psymtab in stabsread.c uses this
information to calculate the end of the partial symtab based on the
address of the last symbol plus the size of the last symbol. */
@@ -2099,9 +2089,9 @@ extern const char multiple_symbols_cancel[];
const char *multiple_symbols_select_mode (void);
-/* lookup a symbol table by source file name. */
+/* Lookup a symbol table in PSPACE by source file name. */
-extern struct symtab *lookup_symtab (const char *);
+extern symtab *lookup_symtab (program_space *pspace, const char *name);
/* An object of this type is passed as the 'is_a_field_of_this'
argument to lookup_symbol and lookup_symbol_in_language. */
@@ -2599,7 +2589,7 @@ struct symbol_search
/* If msymbol is non-null, then a match was made on something for
which only minimal_symbols exist. */
- struct bound_minimal_symbol msymbol;
+ bound_minimal_symbol msymbol;
private:
@@ -2818,9 +2808,15 @@ bool iterate_over_some_symtabs (const char *name,
struct compunit_symtab *after_last,
gdb::function_view<bool (symtab *)> callback);
-void iterate_over_symtabs (const char *name,
- gdb::function_view<bool (symtab *)> callback);
+/* Check in PSPACE for a symtab of a specific name; first in symtabs, then in
+ psymtabs. *If* there is no '/' in the name, a match after a '/' in the
+ symtab filename will also work.
+
+ Call CALLBACK with each symtab that is found. If CALLBACK returns
+ true, the search stops. */
+void iterate_over_symtabs (program_space *pspace, const char *name,
+ gdb::function_view<bool (symtab *)> callback);
std::vector<CORE_ADDR> find_pcs_for_symtab_line
(struct symtab *symtab, int line, const linetable_entry **best_entry);
diff --git a/gdb/target-debug.h b/gdb/target-debug.h
index b5eb338..4a4e72e 100644
--- a/gdb/target-debug.h
+++ b/gdb/target-debug.h
@@ -26,7 +26,7 @@
behavior is needed.
References to these printers are automatically generated by
- make-target-delegates. See the generated file target-delegates.c.
+ make-target-delegates. See the generated file target-delegates-gen.c.
In a couple cases, a special printing function is defined and then
used via the TARGET_DEBUG_PRINTER macro. See target.h.
@@ -46,8 +46,8 @@
#include "target/waitstatus.h"
/* The functions defined in this header file are not marked "inline", such
- that any function not used by target-delegates.c (the only user of this file)
- will be flagged as unused. */
+ that any function not used by target-delegates-gen.c (the only user of this
+ file) will be flagged as unused. */
static std::string
target_debug_print_target_object (target_object object)
@@ -368,8 +368,6 @@ target_debug_print_x86_xsave_layout (const x86_xsave_layout &layout)
string_appendf (s, ", " #region "_offset=%d", layout.region##_offset);
POFFS(avx);
- POFFS(bndregs);
- POFFS(bndcfg);
POFFS(k);
POFFS(zmm_h);
POFFS(zmm);
diff --git a/gdb/target-delegates.c b/gdb/target-delegates-gen.c
index dd20e14..dd20e14 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates-gen.c
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index 4f21044..1bd22c2 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -500,7 +500,7 @@ target_find_description (void)
struct gdbarch_info info;
info.target_desc = tdesc_info->tdesc;
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
{
warning (_("Architecture rejected target-supplied description"));
tdesc_info->tdesc = nullptr;
@@ -537,18 +537,16 @@ target_clear_description (void)
tdesc_info->tdesc = nullptr;
gdbarch_info info;
- if (!gdbarch_update_p (info))
+ if (!gdbarch_update_p (current_inferior (), info))
internal_error (_("Could not remove target-supplied description"));
}
-/* Return the global current target description. This should only be
- used by gdbarch initialization code; most access should be through
- an existing gdbarch. */
+/* See target-descriptions.h. */
-const struct target_desc *
-target_current_description (void)
+const target_desc *
+target_current_description (inferior *inf)
{
- target_desc_info *tdesc_info = &current_inferior ()->tdesc_info;
+ target_desc_info *tdesc_info = &inf->tdesc_info;
if (tdesc_info->fetched)
return tdesc_info->tdesc;
@@ -1202,12 +1200,6 @@ set_tdesc_architecture (struct target_desc *target_desc,
/* See gdbsupport/tdesc.h. */
void
-set_tdesc_osabi (struct target_desc *target_desc, const char *name)
-{
- set_tdesc_osabi (target_desc, osabi_from_tdesc_string (name));
-}
-
-void
set_tdesc_osabi (struct target_desc *target_desc, enum gdb_osabi osabi)
{
target_desc->osabi = osabi;
@@ -1319,9 +1311,8 @@ public:
if (tdesc_osabi (e) > GDB_OSABI_UNKNOWN
&& tdesc_osabi (e) < GDB_OSABI_INVALID)
{
- gdb_printf
- (" set_tdesc_osabi (result.get (), osabi_from_tdesc_string (\"%s\"));\n",
- gdbarch_osabi_name (tdesc_osabi (e)));
+ const char *enum_name = gdbarch_osabi_enum_name (tdesc_osabi (e));
+ gdb_printf (" set_tdesc_osabi (result.get (), %s);\n", enum_name);
gdb_printf ("\n");
}
@@ -1693,14 +1684,15 @@ static void
maint_print_c_tdesc_cmd (const char *args, int from_tty)
{
const struct target_desc *tdesc;
- const char *filename;
maint_print_c_tdesc_options opts;
auto grp = make_maint_print_c_tdesc_options_def_group (&opts);
gdb::option::process_options
(&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp);
- if (args == NULL)
+ std::string filename = extract_single_filename_arg (args);
+
+ if (filename.empty ())
{
/* Use the global target-supplied description, not the current
architecture's. This lets a GDB for one architecture generate C
@@ -1708,26 +1700,24 @@ maint_print_c_tdesc_cmd (const char *args, int from_tty)
initialization code will reject the new description. */
target_desc_info *tdesc_info = &current_inferior ()->tdesc_info;
tdesc = tdesc_info->tdesc;
- filename = tdesc_info->filename.data ();
+ if (tdesc_info->filename.data () != nullptr)
+ filename = std::string (tdesc_info->filename.data ());
}
else
{
/* Use the target description from the XML file. */
- filename = args;
- tdesc = file_read_description_xml (filename);
+ tdesc = file_read_description_xml (filename.c_str ());
}
if (tdesc == NULL)
error (_("There is no target description to print."));
- if (filename == NULL)
+ if (filename.empty ())
filename = "fetched from target";
- std::string filename_after_features (filename);
- auto loc = filename_after_features.rfind ("/features/");
-
+ auto loc = filename.rfind ("/features/");
if (loc != std::string::npos)
- filename_after_features = filename_after_features.substr (loc + 10);
+ filename = filename.substr (loc + 10);
/* Print c files for target features instead of target descriptions,
because c files got from target features are more flexible than the
@@ -1738,13 +1728,13 @@ maint_print_c_tdesc_cmd (const char *args, int from_tty)
error (_("only target descriptions with 1 feature can be used "
"with -single-feature option"));
- print_c_feature v (filename_after_features);
+ print_c_feature v (filename);
tdesc->accept (v);
}
else
{
- print_c_tdesc v (filename_after_features);
+ print_c_tdesc v (filename);
tdesc->accept (v);
}
@@ -1762,8 +1752,8 @@ maint_print_c_tdesc_cmd_completer (struct cmd_list_element *ignore,
(tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp))
return;
- word = advance_to_filename_complete_word_point (tracker, text);
- filename_completer (ignore, tracker, text, word);
+ word = advance_to_filename_maybe_quoted_complete_word_point (tracker, text);
+ filename_maybe_quoted_completer (ignore, tracker, text, word);
}
/* Implement the maintenance print xml-tdesc command. */
@@ -1947,7 +1937,7 @@ that feature within an already existing target_desc object."), grp);
cmd = add_cmd ("xml-tdesc", class_maintenance, maint_print_xml_tdesc_cmd, _("\
Print the current target description as an XML file."),
&maintenanceprintlist);
- set_cmd_completer (cmd, filename_completer);
+ set_cmd_completer (cmd, deprecated_filename_completer);
cmd = add_cmd ("xml-descriptions", class_maintenance,
maintenance_check_xml_descriptions, _("\
@@ -1956,5 +1946,5 @@ Check the target descriptions created in GDB equal the descriptions\n\
created from XML files in the directory.\n\
The parameter is the directory name."),
&maintenancechecklist);
- set_cmd_completer (cmd, filename_completer);
+ set_cmd_completer (cmd, deprecated_filename_completer);
}
diff --git a/gdb/target-descriptions.h b/gdb/target-descriptions.h
index 54c1f23..dc83db0 100644
--- a/gdb/target-descriptions.h
+++ b/gdb/target-descriptions.h
@@ -39,11 +39,10 @@ void target_find_description (void);
void target_clear_description (void);
-/* Return the current inferior's target description. This should only
- be used by gdbarch initialization code; most access should be
- through an existing gdbarch. */
+/* Return INF's target description. This should only be used by gdbarch
+ initialization code; most access should be through an existing gdbarch. */
-const struct target_desc *target_current_description (void);
+const target_desc *target_current_description (inferior *inf);
/* Record architecture-specific functions to call for pseudo-register
support. If tdesc_use_registers is called and gdbarch_num_pseudo_regs
@@ -220,7 +219,6 @@ int tdesc_register_in_reggroup_p (struct gdbarch *gdbarch, int regno,
void set_tdesc_architecture (struct target_desc *,
const struct bfd_arch_info *);
-void set_tdesc_osabi (struct target_desc *, enum gdb_osabi osabi);
void set_tdesc_property (struct target_desc *,
const char *key, const char *value);
void tdesc_add_compatible (struct target_desc *,
diff --git a/gdb/target.c b/gdb/target.c
index 1b5aa11..4378c05 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -56,7 +56,7 @@
#include "cli/cli-decode.h"
#include "cli/cli-style.h"
-static void generic_tls_error (void) ATTRIBUTE_NORETURN;
+[[noreturn]] static void generic_tls_error (void);
static void default_rcmd (struct target_ops *, const char *, struct ui_file *);
@@ -64,7 +64,7 @@ static int default_verify_memory (struct target_ops *self,
const gdb_byte *data,
CORE_ADDR memaddr, ULONGEST size);
-static void tcomplain (void) ATTRIBUTE_NORETURN;
+[[noreturn]] static void tcomplain (void);
/* Mapping between target_info objects (which have address identity)
and corresponding open/factory function/callback. Each add_target
@@ -1754,7 +1754,7 @@ target_xfer_partial (struct target_ops *ops,
If an error occurs, no guarantee is made about the contents of the data at
MYADDR. In particular, the caller should not depend upon partial reads
filling the buffer with good data. There is no way for the caller to know
- how much good data might have been transfered anyway. Callers that can
+ how much good data might have been transferred anyway. Callers that can
deal with partial reads should call target_read (which will retry until
it makes no progress, and then return how much was transferred). */
@@ -2428,7 +2428,7 @@ info_target_command (const char *args, int from_tty)
resets (things which might change between targets). */
void
-target_pre_inferior (int from_tty)
+target_pre_inferior ()
{
/* Clear out solib state. Otherwise the solib state of the previous
inferior might have survived and is entirely wrong for the new
@@ -2452,7 +2452,7 @@ target_pre_inferior (int from_tty)
memory regions and features. */
if (!gdbarch_has_global_solist (current_inferior ()->arch ()))
{
- no_shared_libraries (NULL, from_tty);
+ no_shared_libraries (current_program_space);
invalidate_target_mem_regions ();
@@ -2504,7 +2504,7 @@ target_preopen (int from_tty)
live process to a core of the same program. */
current_inferior ()->pop_all_targets_above (file_stratum);
- target_pre_inferior (from_tty);
+ target_pre_inferior ();
}
/* See target.h. */
@@ -2575,18 +2575,12 @@ target_wait (ptid_t ptid, struct target_waitstatus *status,
if (!target_can_async_p (target))
gdb_assert ((options & TARGET_WNOHANG) == 0);
- try
- {
- gdb::observers::target_pre_wait.notify (ptid);
- ptid_t event_ptid = target->wait (ptid, status, options);
- gdb::observers::target_post_wait.notify (event_ptid);
- return event_ptid;
- }
- catch (...)
- {
- gdb::observers::target_post_wait.notify (null_ptid);
- throw;
- }
+ ptid_t event_ptid = null_ptid;
+ SCOPE_EXIT { gdb::observers::target_post_wait.notify (event_ptid); };
+ gdb::observers::target_pre_wait.notify (ptid);
+ event_ptid = target->wait (ptid, status, options);
+
+ return event_ptid;
}
/* See target.h. */
@@ -3199,6 +3193,14 @@ 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_errno = FILEIO_ENOSYS;
+ return -1;
+}
+
+int
target_ops::fileio_close (int fd, fileio_error *target_errno)
{
*target_errno = FILEIO_ENOSYS;
@@ -3318,6 +3320,29 @@ 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)
+{
+ for (target_ops *t = default_fileio_target (); t != NULL; t = t->beneath ())
+ {
+ int ret = t->fileio_stat (inf, filename, sb, target_errno);
+
+ if (ret == -1 && *target_errno == FILEIO_ENOSYS)
+ continue;
+
+ target_debug_printf_nofunc ("target_fileio_stat (%s) = %d (%d)",
+ filename, ret,
+ ret != -1 ? 0 : *target_errno);
+ return ret;
+ }
+
+ *target_errno = FILEIO_ENOSYS;
+ return -1;
+}
+
+/* See target.h. */
+
+int
target_fileio_close (int fd, fileio_error *target_errno)
{
fileio_fh_t *fh = fileio_fd_to_fh (fd);
@@ -3667,7 +3692,7 @@ dummy_make_corefile_notes (struct target_ops *self,
return NULL;
}
-#include "target-delegates.c"
+#include "target-delegates-gen.c"
/* The initial current target, so that there is always a semi-valid
current target. */
diff --git a/gdb/target.h b/gdb/target.h
index 81de4a6..6da58c7 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -134,7 +134,7 @@ enum inferior_event_type
INF_EXEC_COMPLETE,
};
-/* Target objects which can be transfered using target_read,
+/* Target objects which can be transferred using target_read,
target_write, et cetera. */
enum target_object
@@ -156,7 +156,7 @@ enum target_object
TARGET_OBJECT_CODE_MEMORY,
/* Kernel Unwind Table. See "ia64-tdep.c". */
TARGET_OBJECT_UNWIND_TABLE,
- /* Transfer auxilliary vector. */
+ /* Transfer auxiliary vector. */
TARGET_OBJECT_AUXV,
/* StackGhost cookie. See "sparc-tdep.c". */
TARGET_OBJECT_WCOOKIE,
@@ -177,7 +177,7 @@ enum target_object
/* Currently loaded libraries specific to AIX systems, in XML format. */
TARGET_OBJECT_LIBRARIES_AIX,
/* Get OS specific data. The ANNEX specifies the type (running
- processes, etc.). The data being transfered is expected to follow
+ processes, etc.). The data being transferred is expected to follow
the DTD specified in features/osdata.dtd. */
TARGET_OBJECT_OSDATA,
/* Extra signal info. Usually the contents of `siginfo_t' on unix
@@ -821,7 +821,7 @@ struct target_ops
transferring if desired. This is handled in target.c.
The interface does not support a "retry" mechanism. Instead it
- assumes that at least one addressable unit will be transfered on each
+ assumes that at least one addressable unit will be transferred on each
successful call.
NOTE: cagney/2003-10-17: The current interface can lead to
@@ -1011,6 +1011,14 @@ struct target_ops
*TARGET_ERRNO). */
virtual int fileio_fstat (int fd, struct stat *sb, fileio_error *target_errno);
+ /* Get information about the file FILENAME and put it in SB. Look for
+ FILENAME in the filesystem as seen by INF. If INF is NULL, use the
+ 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);
+
/* Close FD on the target. Return 0, or -1 if an error occurs
(and set *TARGET_ERRNO). */
virtual int fileio_close (int fd, fileio_error *target_errno);
@@ -2220,6 +2228,14 @@ extern int target_fileio_pread (int fd, gdb_byte *read_buf, int len,
extern int target_fileio_fstat (int fd, struct stat *sb,
fileio_error *target_errno);
+/* Get information about the file at FILENAME on the target and put it in
+ SB. Look in the filesystem as seen by INF. If INF is NULL, use the
+ 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);
+
/* Close FD on the target. Return 0, or -1 if an error occurs
(and set *TARGET_ERRNO). */
extern int target_fileio_close (int fd, fileio_error *target_errno);
@@ -2427,7 +2443,7 @@ struct target_unpusher
typedef std::unique_ptr<struct target_ops, target_unpusher> target_unpush_up;
-extern void target_pre_inferior (int);
+extern void target_pre_inferior ();
extern void target_preopen (int);
@@ -2490,7 +2506,7 @@ extern int default_memory_insert_breakpoint (struct gdbarch *,
extern void initialize_targets (void);
-extern void noprocess (void) ATTRIBUTE_NORETURN;
+[[noreturn]] extern void noprocess (void);
extern void target_require_runnable (void);
diff --git a/gdb/testsuite/gdb.ada/O2_float_param.exp b/gdb/testsuite/gdb.ada/O2_float_param.exp
index d44f2e5..86b67ff 100644
--- a/gdb/testsuite/gdb.ada/O2_float_param.exp
+++ b/gdb/testsuite/gdb.ada/O2_float_param.exp
@@ -26,10 +26,8 @@ if {[is_aarch64_target]} {
}
}
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug \
- optimize=-O2 \
- additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug optimize=-O2
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/access_to_unbounded_array.exp b/gdb/testsuite/gdb.ada/access_to_unbounded_array.exp
index 7f7bfb3..eeaceb0 100644
--- a/gdb/testsuite/gdb.ada/access_to_unbounded_array.exp
+++ b/gdb/testsuite/gdb.ada/access_to_unbounded_array.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp b/gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp
index 569bb2e..4ecb4f8 100644
--- a/gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp
+++ b/gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile enum_with_gap_main
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" \
executable $flags] != ""} {
diff --git a/gdb/testsuite/gdb.ada/arr_enum_idx_w_gap.exp b/gdb/testsuite/gdb.ada/arr_enum_idx_w_gap.exp
index 5a88f5f..491402b 100644
--- a/gdb/testsuite/gdb.ada/arr_enum_idx_w_gap.exp
+++ b/gdb/testsuite/gdb.ada/arr_enum_idx_w_gap.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo_q418_043
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/array_of_symbolic_length.exp b/gdb/testsuite/gdb.ada/array_of_symbolic_length.exp
index bcf7369..134b448 100644
--- a/gdb/testsuite/gdb.ada/array_of_symbolic_length.exp
+++ b/gdb/testsuite/gdb.ada/array_of_symbolic_length.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/array_of_variable_length.exp b/gdb/testsuite/gdb.ada/array_of_variable_length.exp
index 3397760..3c68c80 100644
--- a/gdb/testsuite/gdb.ada/array_of_variable_length.exp
+++ b/gdb/testsuite/gdb.ada/array_of_variable_length.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/array_of_variant.exp b/gdb/testsuite/gdb.ada/array_of_variant.exp
index 1a155d4..8b83f4e 100644
--- a/gdb/testsuite/gdb.ada/array_of_variant.exp
+++ b/gdb/testsuite/gdb.ada/array_of_variant.exp
@@ -20,7 +20,7 @@ require allow_ada_tests
standard_ada_testfile p
-set old_gcc [expr [test_compiler_info {gcc-[0-7]-*}]]
+set old_gcc [gnat_version_compare <= 7]
proc gdb_test_with_xfail { cmd re re_xfail msg } {
global scenario old_gcc
@@ -40,8 +40,8 @@ proc gdb_test_with_xfail { cmd re re_xfail msg } {
}
}
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/array_ptr_renaming.exp b/gdb/testsuite/gdb.ada/array_ptr_renaming.exp
index b013fc7..eadfcb6 100644
--- a/gdb/testsuite/gdb.ada/array_ptr_renaming.exp
+++ b/gdb/testsuite/gdb.ada/array_ptr_renaming.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/arrayidx.exp b/gdb/testsuite/gdb.ada/arrayidx.exp
index 051e82d..bc76cd3 100644
--- a/gdb/testsuite/gdb.ada/arrayidx.exp
+++ b/gdb/testsuite/gdb.ada/arrayidx.exp
@@ -23,8 +23,7 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} {
return -1
}
-set old_gcc [expr [test_compiler_info {gcc-[0-3]-*}] \
- || [test_compiler_info {gcc-4-[0-6]-*}]]
+set old_gcc [gnat_version_compare <= {4 6}]
clean_restart ${testfile}
diff --git a/gdb/testsuite/gdb.ada/arrayparam.exp b/gdb/testsuite/gdb.ada/arrayparam.exp
index 2921d64..ef00037 100644
--- a/gdb/testsuite/gdb.ada/arrayparam.exp
+++ b/gdb/testsuite/gdb.ada/arrayparam.exp
@@ -22,8 +22,8 @@ standard_ada_testfile foo
# Note we don't test the "none" (no -fgnat-encodings option) scenario
# here, because "all" and "minimal" cover the cases, and this way we
# don't have to update the test when gnat changes its default.
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/arrayptr.exp b/gdb/testsuite/gdb.ada/arrayptr.exp
index ca48993..b8c2eab 100644
--- a/gdb/testsuite/gdb.ada/arrayptr.exp
+++ b/gdb/testsuite/gdb.ada/arrayptr.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
@@ -55,7 +55,7 @@ foreach_with_prefix scenario {all minimal} {
# GNAT >= 12.0 has the needed fix here.
set xfail_expected 0
- if {$scenario == "minimal" && ![test_compiler_info {gcc-1[2-9]-*}]} {
+ if {$scenario == "minimal" && [gnat_version_compare < 12]} {
set xfail_expected 1
}
diff --git a/gdb/testsuite/gdb.ada/big_packed_array.exp b/gdb/testsuite/gdb.ada/big_packed_array.exp
index 1ba2c48..33b1dfd 100644
--- a/gdb/testsuite/gdb.ada/big_packed_array.exp
+++ b/gdb/testsuite/gdb.ada/big_packed_array.exp
@@ -19,10 +19,10 @@ require allow_ada_tests
standard_ada_testfile foo_ra24_010
-set old_gcc [expr [test_compiler_info {gcc-[0-8]-*}]]
+set old_gcc [gnat_version_compare < 9]
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/bp_c_mixed_case.exp b/gdb/testsuite/gdb.ada/bp_c_mixed_case.exp
index 8ab5f03..2286e46 100644
--- a/gdb/testsuite/gdb.ada/bp_c_mixed_case.exp
+++ b/gdb/testsuite/gdb.ada/bp_c_mixed_case.exp
@@ -92,14 +92,14 @@ gdb_test "p <NoDebugMixedCaseFunc>" \
set test "break <MixedCaseFunc>, in C"
gdb_test_multiple "break <MixedCaseFunc>" $test {
- -re "Function \"<MixedCaseFunc>\" not defined\..*Make breakpoint pending on future shared library load.*y or .n.. $" {
+ -re "Function \"<MixedCaseFunc>\" not defined\\..*Make breakpoint pending on future shared library load.*y or .n.. $" {
gdb_test_no_output "n" $test
}
}
set test "break <NoDebugMixedCaseFunc>, in C"
gdb_test_multiple "break <NoDebugMixedCaseFunc>" $test {
- -re "Function \"<NoDebugMixedCaseFunc>\" not defined\..*Make breakpoint pending on future shared library load.*y or .n.. $" {
+ -re "Function \"<NoDebugMixedCaseFunc>\" not defined\\..*Make breakpoint pending on future shared library load.*y or .n.. $" {
gdb_test_no_output "n" $test
}
}
diff --git a/gdb/testsuite/gdb.ada/bp_inlined_func.exp b/gdb/testsuite/gdb.ada/bp_inlined_func.exp
index 761d103..db56a11 100644
--- a/gdb/testsuite/gdb.ada/bp_inlined_func.exp
+++ b/gdb/testsuite/gdb.ada/bp_inlined_func.exp
@@ -48,5 +48,5 @@ for {set i 0} {$i < 4} {incr i} {
}
gdb_test "continue" \
- "Continuing\..*$inferior_exited_re.*" \
+ "Continuing\\..*$inferior_exited_re.*" \
"continuing to program completion"
diff --git a/gdb/testsuite/gdb.ada/call_pn.exp b/gdb/testsuite/gdb.ada/call_pn.exp
index 5d3f9d6..9114d30 100644
--- a/gdb/testsuite/gdb.ada/call_pn.exp
+++ b/gdb/testsuite/gdb.ada/call_pn.exp
@@ -35,7 +35,10 @@ if {![runto "foo.adb:$bp_location"]} {
# related to PR25764 - "LOC_UNRESOLVED symbol missing from partial symtab".
# Stabilize test results by ensuring that the xfail triggers for the "before"
# print.
-gdb_test_no_output "maint expand-symtabs"
+gdb_test_no_output {maint expand-symtabs "\(pck\|foo\)\.adb"}
+
+set gcc_major_version [gcc_major_version]
+set have_xfail [expr $gcc_major_version >= 8 && $gcc_major_version <= 9]
# The xfail is for PR gcc/94469, which occurs with target board
# unix/-flto/-O0/-flto-partition=none/-ffat-lto-objects and gcc-8 and later.
@@ -45,14 +48,17 @@ set xfail_re \
[multi_line \
"Multiple matches for last_node_id" \
"\\\[0\\\] cancel" \
- "\\\[1\\\] pck\.last_node_id at .*.adb:17" \
- "\\\[2\\\] pck\.last_node_id at .*.adb:17" \
+ "\\\[1\\\] pck\\.last_node_id at .*.adb:17" \
+ "\\\[2\\\] pck\\.last_node_id at .*.adb:17" \
"> $"]
# Make sure that last_node_id is set to zero...
gdb_test_multiple "print last_node_id" "print last_node_id before calling pn" {
-re $xfail_re {
- xfail $gdb_test_name
+ if { $have_xfail } {
+ setup_xfail *-*-*
+ }
+ fail $gdb_test_name
# One of the choices will print the correct value, the other one
# <optimized out>. Since we don't known which one to choose to get
# the correct value, cancel.
@@ -74,7 +80,10 @@ gdb_test "print pn(4321)" "= 4321"
# Make sure that last_node_id now has the correct value...
gdb_test_multiple "print last_node_id" "print last_node_id after calling pn" {
-re $xfail_re {
- xfail $gdb_test_name
+ if { $have_xfail } {
+ setup_xfail *-*-*
+ }
+ fail $gdb_test_name
# Cancel
gdb_test_multiple "0" "cancel after xfail 2" {
-re -wrap "cancelled" {
diff --git a/gdb/testsuite/gdb.ada/catch_assert_if.exp b/gdb/testsuite/gdb.ada/catch_assert_if.exp
index 312b7aa..48b1c85 100644
--- a/gdb/testsuite/gdb.ada/catch_assert_if.exp
+++ b/gdb/testsuite/gdb.ada/catch_assert_if.exp
@@ -52,9 +52,9 @@ set bp_location [gdb_get_line_number "STOP" ${testdir}/bla.adb]
set catchpoint_msg \
"Catchpoint $decimal, failed assertion at $hex in bla \\\(\\\).*at .*bla.adb:$bp_location"
gdb_test "continue" \
- "Continuing\.$eol$eol$catchpoint_msg$eol.*STOP" \
+ "Continuing\\.$eol$eol$catchpoint_msg$eol.*STOP" \
"continuing to expected failed assertion"
gdb_test "continue" \
- "Continuing\..*$inferior_exited_re.*" \
+ "Continuing\\..*$inferior_exited_re.*" \
"continuing to program completion"
diff --git a/gdb/testsuite/gdb.ada/catch_ex.exp b/gdb/testsuite/gdb.ada/catch_ex.exp
index 0fcc013..48ace25 100644
--- a/gdb/testsuite/gdb.ada/catch_ex.exp
+++ b/gdb/testsuite/gdb.ada/catch_ex.exp
@@ -55,13 +55,13 @@ gdb_test "info break" \
set catchpoint_msg \
"Catchpoint $any_nb, CONSTRAINT_ERROR (\\\(ignore C_E\\\) )?at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
gdb_test "continue" \
- "Continuing\.$eol$eol$catchpoint_msg$eol.*SPOT1" \
+ "Continuing\\.$eol$eol$catchpoint_msg$eol.*SPOT1" \
"continuing to first exception"
set catchpoint_msg \
"Catchpoint $any_nb, PROGRAM_ERROR (\\\(foo\\.adb:$decimal explicit raise\\\) )?at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
gdb_test "continue" \
- "Continuing\.$eol$eol$catchpoint_msg$eol.*SPOT2" \
+ "Continuing\\.$eol$eol$catchpoint_msg$eol.*SPOT2" \
"continuing to second exception"
################################################
@@ -108,23 +108,23 @@ gdb_test "info break" \
set catchpoint_msg \
"Catchpoint $any_nb, PROGRAM_ERROR (\\\(foo.adb:$decimal explicit raise\\\) )?at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
gdb_test "continue" \
- "Continuing\.$eol$eol$catchpoint_msg$eol.*SPOT2" \
+ "Continuing\\.$eol$eol$catchpoint_msg$eol.*SPOT2" \
"continuing to Program_Error exception"
set catchpoint_msg \
"Catchpoint $any_nb, failed assertion at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
gdb_test "continue" \
- "Continuing\.$eol$eol$catchpoint_msg$eol.*SPOT3" \
+ "Continuing\\.$eol$eol$catchpoint_msg$eol.*SPOT3" \
"continuing to failed assertion"
set catchpoint_msg \
"Catchpoint $any_nb, unhandled CONSTRAINT_ERROR at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
gdb_test "continue" \
- "Continuing\.$eol$eol$catchpoint_msg$eol.*SPOT4" \
+ "Continuing\\.$eol$eol$catchpoint_msg$eol.*SPOT4" \
"continuing to unhandled exception"
gdb_test "continue" \
- "Continuing\..*$inferior_exited_re.*" \
+ "Continuing\\..*$inferior_exited_re.*" \
"continuing to program completion"
#################################
@@ -148,12 +148,12 @@ gdb_test "tcatch exception" \
set temp_catchpoint_msg \
"Temporary catchpoint $any_nb, CONSTRAINT_ERROR (\\\(.*\\\) )?at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
gdb_test "continue" \
- "Continuing\.$eol$eol$temp_catchpoint_msg$eol.*SPOT1" \
+ "Continuing\\.$eol$eol$temp_catchpoint_msg$eol.*SPOT1" \
"continuing to temporary catchpoint"
with_test_prefix "temporary catchpoint" {
gdb_test "continue" \
- "Continuing\..*$inferior_exited_re.*" \
+ "Continuing\\..*$inferior_exited_re.*" \
"continuing to program completion"
}
diff --git a/gdb/testsuite/gdb.ada/catch_ex_std.exp b/gdb/testsuite/gdb.ada/catch_ex_std.exp
index dbd3729..2eae854 100644
--- a/gdb/testsuite/gdb.ada/catch_ex_std.exp
+++ b/gdb/testsuite/gdb.ada/catch_ex_std.exp
@@ -73,7 +73,7 @@ gdb_test "catch exception some_kind_of_error" \
"Catchpoint \[0-9\]+: `some_kind_of_error' Ada exception"
gdb_test "cont" \
- "Catchpoint \[0-9\]+, .* at .*foo\.adb:\[0-9\]+.*" \
+ "Catchpoint \[0-9\]+, .* at .*foo\\.adb:\[0-9\]+.*" \
"caught the exception"
gdb_test "print \$_ada_exception = some_package.some_kind_of_error'Address" \
diff --git a/gdb/testsuite/gdb.ada/complete.exp b/gdb/testsuite/gdb.ada/complete.exp
index 41ea8ae..6263c4e 100644
--- a/gdb/testsuite/gdb.ada/complete.exp
+++ b/gdb/testsuite/gdb.ada/complete.exp
@@ -124,7 +124,7 @@ test_gdb_complete "pck.my" \
"p pck.my_global_variable"
# A fully qualified package name
-test_gdb_complete "pck.inne" \
+test_gdb_complete "pck.inner" \
"p pck.inner.inside_variable" \
"complete fully qualified package name"
@@ -214,7 +214,7 @@ test_gdb_complete "ambiguous_f" \
test_gdb_complete "ambiguous_func" \
"p ambiguous_func"
-# Perform a test intented to verify the behavior where the number
+# Perform a test intended to verify the behavior where the number
# of possible completions is very large. The goal is not to verify
# precisely the list returned by the complete command (this depends
# on too many parameters -- targets, compiler version, runtime, etc).
diff --git a/gdb/testsuite/gdb.ada/enum_idx_packed.exp b/gdb/testsuite/gdb.ada/enum_idx_packed.exp
index 1976092..cf70e9a 100644
--- a/gdb/testsuite/gdb.ada/enum_idx_packed.exp
+++ b/gdb/testsuite/gdb.ada/enum_idx_packed.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
@@ -29,8 +29,9 @@ foreach_with_prefix scenario {all minimal} {
clean_restart ${testfile}-${scenario}
# GNAT 9 and 10 are known to fail.
- if {$scenario == "minimal" && ([test_compiler_info {gcc-9-*}] \
- || [test_compiler_info {gcc-10-*}])} {
+ if {$scenario == "minimal"
+ && [gnat_version_compare >= 9]
+ && [gnat_version_compare <= 10]} {
set old_compiler 1
} else {
set old_compiler 0
diff --git a/gdb/testsuite/gdb.ada/excep_handle.exp b/gdb/testsuite/gdb.ada/excep_handle.exp
index ad92aff..2a99457 100644
--- a/gdb/testsuite/gdb.ada/excep_handle.exp
+++ b/gdb/testsuite/gdb.ada/excep_handle.exp
@@ -55,7 +55,7 @@ gdb_test "catch handlers" \
# Continue. The program should stop at first exception handling.
gdb_test "continue" \
- "Continuing\.$eol$eol$catchpoint_constraint_error_msg" \
+ "Continuing\\.$eol$eol$catchpoint_constraint_error_msg" \
"continuing to first Constraint_Error exception handlers"
# Resume the program's exception.
@@ -66,7 +66,7 @@ gdb_test "continue" \
# the next exception being raised.
gdb_test "continue" \
- "Continuing\.$eol$eol$catchpoint_storage_error_msg" \
+ "Continuing\\.$eol$eol$catchpoint_storage_error_msg" \
"continuing and stopping in Storage_Error exception handlers"
gdb_test_no_output "delete 2" \
@@ -85,7 +85,7 @@ gdb_test "catch handlers Program_Error" \
# Continue, we should not stop at ABORT_SIGNAL but at Program_Error one.
gdb_test "continue" \
- "Continuing\.$eol$eol$catchpoint_program_error_msg" \
+ "Continuing\\.$eol$eol$catchpoint_program_error_msg" \
"continuing without stopping to Program_Error exception handlers"
gdb_test_no_output \
@@ -101,7 +101,7 @@ gdb_test "catch handlers Storage_Error" \
# Continue, we should stop at Storage_Error handlers.
gdb_test "continue" \
- "Continuing\.$eol$eol$catchpoint_storage_error_msg" \
+ "Continuing\\.$eol$eol$catchpoint_storage_error_msg" \
"continuing without stopping to Storage_Error exception handlers"
gdb_test_no_output \
@@ -126,7 +126,7 @@ gdb_test "info breakpoint" "stop only if Global_Var = 2" \
# Continue, we should not stop at ABORT_SIGNAL but at Program_Error one.
gdb_test "continue" \
- "Continuing\.$eol$eol$catchpoint_constraint_error_msg" \
+ "Continuing\\.$eol$eol$catchpoint_constraint_error_msg" \
"continuing to second Constraint_Error exception handlers"
gdb_test_no_output \
@@ -148,11 +148,11 @@ gdb_test "catch handlers Program_Error if Global_Var = 4" \
# the second one.
gdb_test "continue" \
- "Continuing\.$eol$eol$catchpoint_program_error_msg" \
+ "Continuing\\.$eol$eol$catchpoint_program_error_msg" \
"continuing to Program_Error exception handlers"
# Continue, the program should exit properly.
gdb_test "continue" \
- "Continuing\..*$inferior_exited_re.*" \
+ "Continuing\\..*$inferior_exited_re.*" \
"continuing to program completion"
diff --git a/gdb/testsuite/gdb.ada/exception-lto.c b/gdb/testsuite/gdb.ada/exception-lto.c
new file mode 100644
index 0000000..c5ee69d
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/exception-lto.c
@@ -0,0 +1,40 @@
+/* This test program is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* We need a few extra functions here to ensure that the dictionary
+ for the global block has more than one slot. */
+
+void f1 () { }
+void f2 () { }
+void f3 () { }
+void f4 () { }
+
+void
+__gnat_debug_raise_exception ()
+{
+}
+
+void
+__gnat_begin_handler_v1 ()
+{
+}
+
+int
+main ()
+{
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.ada/exception-lto.exp b/gdb/testsuite/gdb.ada/exception-lto.exp
new file mode 100644
index 0000000..21059a3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/exception-lto.exp
@@ -0,0 +1,35 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This test mimics the situation where an Ada program (including the
+# runtime) is built with -flto. In this situation, gcc emits the
+# exception handling functions in the DWARF -- but in a CU that is
+# marked as coming from "C". This then triggered a bug causing the
+# Ada catchpoint code not to find the underlying runtime functions.
+
+require allow_ada_tests
+
+standard_testfile .c
+
+if {[build_executable "failed to prepare" $testfile $srcfile] == -1} {
+ return -1
+}
+
+# Try this test in both the C and Ada language modes.
+foreach_with_prefix lang {c ada} {
+ clean_restart $testfile
+ gdb_test_no_output "set lang $lang"
+ gdb_test "catch exception" "Catchpoint 1: all Ada exceptions"
+}
diff --git a/gdb/testsuite/gdb.ada/exec_changed.exp b/gdb/testsuite/gdb.ada/exec_changed.exp
index 8fb8d1c..69f386e 100644
--- a/gdb/testsuite/gdb.ada/exec_changed.exp
+++ b/gdb/testsuite/gdb.ada/exec_changed.exp
@@ -86,7 +86,7 @@ if { [gdb_start_cmd] < 0 } {
clean_restart "${binfile}$EXEEXT"
-# Ensure we don't accidently use the main symbol cache.
+# Ensure we don't accidentally use the main symbol cache.
gdb_test_no_output "mt set symbol-cache-size 0"
# Put something in the symbol lookup cache that will get looked up when
diff --git a/gdb/testsuite/gdb.ada/fixed_cmp.exp b/gdb/testsuite/gdb.ada/fixed_cmp.exp
index de506fd..dcd4745 100644
--- a/gdb/testsuite/gdb.ada/fixed_cmp.exp
+++ b/gdb/testsuite/gdb.ada/fixed_cmp.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile fixed
-foreach_with_prefix gnat_encodings {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$gnat_encodings]
+foreach_gnat_encoding gnat_encodings flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${gnat_encodings}" executable $flags] != "" } {
return -1
diff --git a/gdb/testsuite/gdb.ada/fixed_points.exp b/gdb/testsuite/gdb.ada/fixed_points.exp
index 4665595..b2b3df4 100644
--- a/gdb/testsuite/gdb.ada/fixed_points.exp
+++ b/gdb/testsuite/gdb.ada/fixed_points.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile fixed_points
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
}
@@ -88,12 +88,12 @@ foreach_with_prefix scenario {all minimal} {
gdb_test "print fp4_var / 1" $fp4
# This only started working in GCC 11.
- if {$scenario == "minimal" && [test_compiler_info {gcc-11-*}]} {
+ if {$scenario == "minimal" && [gnat_version_compare >= 11]} {
gdb_test "print fp5_var" " = 3e-19"
}
# This failed before GCC 10.
- if {$scenario == "all" && [test_compiler_info {gcc-10-*}]} {
+ if {$scenario == "all" && [gnat_version_compare < 10]} {
gdb_test "p Float(Another_Fixed) = Float(Another_Delta * 5)" "true" \
"value of another_fixed"
}
diff --git a/gdb/testsuite/gdb.ada/frame_arg_lang.exp b/gdb/testsuite/gdb.ada/frame_arg_lang.exp
index 918a922..b629c42 100644
--- a/gdb/testsuite/gdb.ada/frame_arg_lang.exp
+++ b/gdb/testsuite/gdb.ada/frame_arg_lang.exp
@@ -27,11 +27,10 @@ gdb_compile "${csrcfile}" "${cobject}" object [list debug]
# Note we don't test the "none" (no -fgnat-encodings option) scenario
# here, because "all" and "minimal" cover the cases, and this way we
# don't have to update the test when gnat changes its default.
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-largs \
- additional_flags=${cobject} \
- additional_flags=-margs \
- additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug additional_flags=-largs \
+ additional_flags=${cobject} \
+ additional_flags=-margs
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/fun_overload_menu.exp b/gdb/testsuite/gdb.ada/fun_overload_menu.exp
index ec5465d..8e7a3fb 100644
--- a/gdb/testsuite/gdb.ada/fun_overload_menu.exp
+++ b/gdb/testsuite/gdb.ada/fun_overload_menu.exp
@@ -54,8 +54,8 @@ proc test_menu {expr function menu_entries selection output} {
with_test_prefix "func" {
test_menu "f (1, null)" "f" \
[multi_line \
- "\\\[1\\\] foo\.f \\(integer; foo\.integer_access\\) return boolean at .*foo.adb:.*" \
- "\\\[2\\\] foo\.f \\(foo\.new_integer; foo\.integer_access\\) return boolean at .*foo.adb:.*"] \
+ "\\\[1\\\] foo\\.f \\(integer; foo\\.integer_access\\) return boolean at .*foo.adb:.*" \
+ "\\\[2\\\] foo\\.f \\(foo\\.new_integer; foo\\.integer_access\\) return boolean at .*foo.adb:.*"] \
"1" "= true"
}
@@ -63,8 +63,8 @@ with_test_prefix "func" {
with_test_prefix "proc" {
test_menu "p (1, null)" "p" \
[multi_line \
- "\\\[1\\\] foo\.p \\(integer; foo\.integer_access\\) at .*foo.adb:.*" \
- "\\\[2\\\] foo\.p \\(foo\.new_integer; foo\.integer_access\\) at .*foo.adb:.*" ] \
+ "\\\[1\\\] foo\\.p \\(integer; foo\\.integer_access\\) at .*foo.adb:.*" \
+ "\\\[2\\\] foo\\.p \\(foo\\.new_integer; foo\\.integer_access\\) at .*foo.adb:.*" ] \
"1" "= (void)"
}
@@ -73,7 +73,7 @@ gdb_test "set ada print-signatures off" ""
with_test_prefix "signatures disabled" {
test_menu "f (1, null)" "f" \
[multi_line \
- "\\\[1\\\] foo\.f at .*foo.adb:.*" \
- "\\\[2\\\] foo\.f at .*foo.adb:.*"] \
+ "\\\[1\\\] foo\\.f at .*foo.adb:.*" \
+ "\\\[2\\\] foo\\.f at .*foo.adb:.*"] \
"1" "= true"
}
diff --git a/gdb/testsuite/gdb.ada/fun_renaming.exp b/gdb/testsuite/gdb.ada/fun_renaming.exp
index 33c9b95..21f80db 100644
--- a/gdb/testsuite/gdb.ada/fun_renaming.exp
+++ b/gdb/testsuite/gdb.ada/fun_renaming.exp
@@ -37,11 +37,11 @@ gdb_test "print fun_rename_test_next(1)" " = 2"
set test "print fun_rename_test_n(1)"
gdb_test_multiple $test $test {
- -re " = 2\..*$gdb_prompt $" {
+ -wrap -re " = 2" {
pass $test
}
- -re "No definition of \"fun_rename_test_n\" in current context\..*$gdb_prompt $" {
- if {[test_compiler_info {gcc-6*}]} {
+ -wrap -re "No definition of \"fun_rename_test_n\" in current context\\." {
+ if {[gnat_version_compare >= 6]} {
fail $test
} else {
xfail $test
@@ -51,11 +51,11 @@ gdb_test_multiple $test $test {
}
set test "print renamed_fun_rename_test_next(1)"
gdb_test_multiple $test $test {
- -re " = 2\..*$gdb_prompt $" {
+ -wrap -re " = 2" {
pass $test
}
- -re "No definition of \"renamed_fun_rename_test_next\" in current context\..*$gdb_prompt $" {
- if {[test_compiler_info {gcc-6*}]} {
+ -wrap -re "No definition of \"renamed_fun_rename_test_next\" in current context\\." {
+ if {[gnat_version_compare >= 6]} {
fail $test
} else {
xfail $test
@@ -65,18 +65,18 @@ gdb_test_multiple $test $test {
set test "print pack.renamed_fun_rename_test_next(1)"
gdb_test_multiple $test $test {
- -re " = 2\..*$gdb_prompt $" {
+ -wrap -re " = 2" {
pass $test
}
- -re "No definition of \"pack\.renamed_fun_rename_test_next\" in current context\..*$gdb_prompt $" {
- if {[test_compiler_info {gcc-6*}]} {
+ -wrap -re "No definition of \"pack\\.renamed_fun_rename_test_next\" in current context\\." {
+ if {[gnat_version_compare >= 6]} {
fail $test
} else {
xfail $test
}
}
- -re "Type <data variable, no debug info> is not a structure or union type\..*$gdb_prompt $" {
- if {[test_compiler_info {gcc-6*}]} {
+ -wrap -re "Type <data variable, no debug info> is not a structure or union type\\." {
+ if {[gnat_version_compare >= 6]} {
fail $test
} else {
xfail $test
diff --git a/gdb/testsuite/gdb.ada/funcall_ref.exp b/gdb/testsuite/gdb.ada/funcall_ref.exp
index 518ceb7..1c28392 100644
--- a/gdb/testsuite/gdb.ada/funcall_ref.exp
+++ b/gdb/testsuite/gdb.ada/funcall_ref.exp
@@ -22,8 +22,8 @@ standard_ada_testfile foo
# Note we don't test the "none" (no -fgnat-encodings option) scenario
# here, because "all" and "minimal" cover the cases, and this way we
# don't have to update the test when gnat changes its default.
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/homonym.exp b/gdb/testsuite/gdb.ada/homonym.exp
index 64a6edf..91a4e62 100644
--- a/gdb/testsuite/gdb.ada/homonym.exp
+++ b/gdb/testsuite/gdb.ada/homonym.exp
@@ -76,7 +76,7 @@ gdb_test "print lcl" \
set bp_location [gdb_get_line_number "BREAK_2" ${testdir}/homonym.adb]
gdb_test "break homonym.adb:$bp_location" \
- "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: file .*homonym\.adb, line \[0-9\]+\." \
+ "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: file .*homonym\\.adb, line \[0-9\]+\\." \
"break at BREAK_2"
gdb_test "continue" \
diff --git a/gdb/testsuite/gdb.ada/mi_string_access.exp b/gdb/testsuite/gdb.ada/mi_string_access.exp
index 15b8cf1..8fd116b 100644
--- a/gdb/testsuite/gdb.ada/mi_string_access.exp
+++ b/gdb/testsuite/gdb.ada/mi_string_access.exp
@@ -22,8 +22,8 @@ standard_ada_testfile bar
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/mi_task_arg.exp b/gdb/testsuite/gdb.ada/mi_task_arg.exp
index 098396d..b4b7b49 100644
--- a/gdb/testsuite/gdb.ada/mi_task_arg.exp
+++ b/gdb/testsuite/gdb.ada/mi_task_arg.exp
@@ -49,7 +49,8 @@ set frame1 "frame=\{level=\"1\",args=\\\[${frame1_args}(,$frame1_opt_args)?\\\]\
# Frame for system.tasking.stages.task_wrapper
set frame2_args "(\{name=\"self_id\",value=\"($hex|<optimized out>)\"\})?"
set frame2 "frame=\{level=\"2\",args=\\\[$frame2_args\\\]\}"
-mi_gdb_test "-stack-list-arguments 1" \
- "\\^done,stack-args=\\\[$frame0,$frame1,$frame2,.*" \
- "-stack-list-arguments 1"
+set frames "$frame0,$frame1,${frame2}(,.*)?"
+mi_gdb_test "-stack-list-arguments 1" \
+ "\\^done,stack-args=\\\[$frames\\\]" \
+ "-stack-list-arguments 1"
diff --git a/gdb/testsuite/gdb.ada/mi_var_access.exp b/gdb/testsuite/gdb.ada/mi_var_access.exp
index b71c8f3..15419bb 100644
--- a/gdb/testsuite/gdb.ada/mi_var_access.exp
+++ b/gdb/testsuite/gdb.ada/mi_var_access.exp
@@ -41,9 +41,10 @@ mi_continue_to_line \
# The value of NUMCHILD may vary on different systems. Use generic $decimal
# to match possible values.
set re_ok "\\^done,name=\"A_String_Access\",numchild=\"$decimal\",.*"
-set re_error "\\^error,msg=\"Value out of range\.\".*"
+set re_error "\\^error,msg=\"Value out of range\\.\".*"
+set re_error2 "\\^error,msg=\"Cannot access memory at address $hex\""
mi_gdb_test "-var-create A_String_Access * A_String_Access" \
- "($re_ok|$re_error)" \
+ "($re_ok|$re_error|$re_error2)" \
"Create varobj"
set bp_location [gdb_get_line_number "STOP2" ${testdir}/mi_access.adb]
diff --git a/gdb/testsuite/gdb.ada/mi_var_array.exp b/gdb/testsuite/gdb.ada/mi_var_array.exp
index 2b50481..dd770a1 100644
--- a/gdb/testsuite/gdb.ada/mi_var_array.exp
+++ b/gdb/testsuite/gdb.ada/mi_var_array.exp
@@ -22,11 +22,8 @@ standard_ada_testfile bar
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-foreach_with_prefix scenario {none all minimal} {
- set flags {debug}
- if {$scenario != "none"} {
- lappend flags additional_flags=-fgnat-encodings=$scenario
- }
+foreach_gnat_encoding scenario flags {none all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != "" } {
return -1
diff --git a/gdb/testsuite/gdb.ada/mi_var_union.exp b/gdb/testsuite/gdb.ada/mi_var_union.exp
index eb23c0a..64bfe33 100644
--- a/gdb/testsuite/gdb.ada/mi_var_union.exp
+++ b/gdb/testsuite/gdb.ada/mi_var_union.exp
@@ -24,11 +24,8 @@ set MIFLAGS "-i=mi"
set float "\\-?((\[0-9\]+(\\.\[0-9\]+)?(e\[-+\]\[0-9\]+)?)|(nan\\($hex\\)))"
-foreach_with_prefix scenario {none all minimal} {
- set flags {debug}
- if {$scenario != "none"} {
- lappend flags additional_flags=-fgnat-encodings=$scenario
- }
+foreach_gnat_encoding scenario flags {none all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != "" } {
return -1
diff --git a/gdb/testsuite/gdb.ada/mi_variant.exp b/gdb/testsuite/gdb.ada/mi_variant.exp
index 7f10b3c..f4be5a0 100644
--- a/gdb/testsuite/gdb.ada/mi_variant.exp
+++ b/gdb/testsuite/gdb.ada/mi_variant.exp
@@ -23,11 +23,8 @@ standard_ada_testfile pkg
load_lib mi-support.exp
set MIFLAGS "-i=mi"
-foreach_with_prefix scenario {none all minimal} {
- set flags {debug}
- if {$scenario != "none"} {
- lappend flags additional_flags=-fgnat-encodings=$scenario
- }
+foreach_gnat_encoding scenario flags {none all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/mod_from_name.exp b/gdb/testsuite/gdb.ada/mod_from_name.exp
index c6acc80..99effb0 100644
--- a/gdb/testsuite/gdb.ada/mod_from_name.exp
+++ b/gdb/testsuite/gdb.ada/mod_from_name.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
@@ -34,8 +34,9 @@ foreach_with_prefix scenario {all minimal} {
}
# GNAT 9 and 10 are known to fail.
- if {$scenario == "minimal" && ([test_compiler_info {gcc-9-*}] \
- || [test_compiler_info {gcc-10-*}])} {
+ if {$scenario == "minimal"
+ && [gnat_version_compare >= 9]
+ && [gnat_version_compare <= 10]} {
setup_kfail "minimal encodings" *-*-*
}
gdb_test "print xp" \
diff --git a/gdb/testsuite/gdb.ada/multiarray.exp b/gdb/testsuite/gdb.ada/multiarray.exp
index 3475647..91ba1ec 100644
--- a/gdb/testsuite/gdb.ada/multiarray.exp
+++ b/gdb/testsuite/gdb.ada/multiarray.exp
@@ -19,10 +19,11 @@ require allow_ada_tests
standard_ada_testfile p
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
- if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable {debug}] != ""} {
+ if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" \
+ executable $flags] != ""} {
return -1
}
diff --git a/gdb/testsuite/gdb.ada/null_array.exp b/gdb/testsuite/gdb.ada/null_array.exp
index 4a04945..7fa7c19 100644
--- a/gdb/testsuite/gdb.ada/null_array.exp
+++ b/gdb/testsuite/gdb.ada/null_array.exp
@@ -28,8 +28,7 @@ clean_restart ${testfile}
set bp_location [gdb_get_line_number "START" ${testdir}/foo.adb]
runto "foo.adb:$bp_location"
-if {[test_compiler_info {gcc-[0-3]-*}]
- || [test_compiler_info {gcc-4-[0-4]-*}]} {
+if {[gnat_version_compare <= 4.4]} {
# Ada array bounds are missing in older GCCs.
setup_xfail *-*-*
}
diff --git a/gdb/testsuite/gdb.ada/operator_bp.exp b/gdb/testsuite/gdb.ada/operator_bp.exp
index ff81a9f..2335d49 100644
--- a/gdb/testsuite/gdb.ada/operator_bp.exp
+++ b/gdb/testsuite/gdb.ada/operator_bp.exp
@@ -36,7 +36,7 @@ runto "ops_test.adb:$bp_location"
set bp_re "Breakpoint $decimal at $hex"
foreach op { "+" "-" } {
set op_re [string_to_regexp $op]
- gdb_test "break \"$op\"" "$bp_re: \"$op_re\"\. \\($decimal locations\\).*"
+ gdb_test "break \"$op\"" "$bp_re: \"$op_re\"\\. \\($decimal locations\\).*"
}
foreach op { "*" "/" "mod" "rem" "**" "<" "<=" ">" ">=" "=" "and" "or" "xor" "&" "abs" "not"} {
@@ -45,7 +45,7 @@ foreach op { "*" "/" "mod" "rem" "**" "<" "<=" ">" ">=" "=" "and" "or" "xor" "&"
-re -wrap "$bp_re: file .*ops.adb, line $decimal." {
pass $gdb_test_name
}
- -re -wrap "$bp_re: \"$op_re\"\. \\($decimal locations\\).*" {
+ -re -wrap "$bp_re: \"$op_re\"\\. \\($decimal locations\\).*" {
pass $gdb_test_name
}
}
@@ -72,7 +72,7 @@ runto "ops_test.adb:$bp_location"
foreach op { "+" "-" } {
set op_re [string_to_regexp $op]
gdb_test "break ops.\"$op\"" \
- "Breakpoint $decimal at $hex: ops\\.\"$op_re\"\. \\(2 locations\\)"
+ "Breakpoint $decimal at $hex: ops\\.\"$op_re\"\\. \\(2 locations\\)"
}
foreach op { "*" "/" "mod" "rem" "**" "<" "<=" ">" ">=" "=" "and" "or" "xor" "&" "abs" "not"} {
diff --git a/gdb/testsuite/gdb.ada/out_of_line_in_inlined.exp b/gdb/testsuite/gdb.ada/out_of_line_in_inlined.exp
index eaa88a3..2adef97 100644
--- a/gdb/testsuite/gdb.ada/out_of_line_in_inlined.exp
+++ b/gdb/testsuite/gdb.ada/out_of_line_in_inlined.exp
@@ -19,10 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo_o224_021
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug \
- optimize=-O2 \
- additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug optimize=-O2
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/packed_array.exp b/gdb/testsuite/gdb.ada/packed_array.exp
index a3d7136..85bc59d 100644
--- a/gdb/testsuite/gdb.ada/packed_array.exp
+++ b/gdb/testsuite/gdb.ada/packed_array.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile pa
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/packed_array_assign.exp b/gdb/testsuite/gdb.ada/packed_array_assign.exp
index ee2b395..47e48f9 100644
--- a/gdb/testsuite/gdb.ada/packed_array_assign.exp
+++ b/gdb/testsuite/gdb.ada/packed_array_assign.exp
@@ -54,7 +54,7 @@ set re \
"packed_array_assign_y => 1\\)\\)"]
# GNAT >= 12.0 has the needed fix here.
-set zeros_expected [expr {![test_compiler_info {gcc-1[2-9]-*}]}]
+set zeros_expected [gnat_version_compare >= 12]
set all_zeros \
[string_to_regexp "((packed_array_assign_w => 0, packed_array_assign_x => 0, packed_array_assign_y => 0), (packed_array_assign_w => 0, packed_array_assign_x => 0, packed_array_assign_y => 0), (packed_array_assign_w => 0, packed_array_assign_x => 0, packed_array_assign_y => 0))"]
diff --git a/gdb/testsuite/gdb.ada/packed_record.exp b/gdb/testsuite/gdb.ada/packed_record.exp
index fa058f7..f347953 100644
--- a/gdb/testsuite/gdb.ada/packed_record.exp
+++ b/gdb/testsuite/gdb.ada/packed_record.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile pr
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
@@ -38,7 +38,7 @@ foreach_with_prefix scenario {all minimal} {
}
-re " = .*more than max-value-size.*\[\r\n\]+$gdb_prompt $" {
# GNAT >= 12.0 has the needed fix here.
- if {$scenario == "minimal" && ![test_compiler_info {gcc-1[2-9]-*}]} {
+ if {$scenario == "minimal" && [gnat_version_compare >= 12]} {
setup_kfail "minimal encodings" *-*-*
}
fail $test
diff --git a/gdb/testsuite/gdb.ada/packed_tagged.exp b/gdb/testsuite/gdb.ada/packed_tagged.exp
index faccc14..1c9e5a0 100644
--- a/gdb/testsuite/gdb.ada/packed_tagged.exp
+++ b/gdb/testsuite/gdb.ada/packed_tagged.exp
@@ -22,11 +22,8 @@ standard_ada_testfile comp_bug
# Note we don't test the "none" (no -fgnat-encodings option) scenario
# here, because "all" and "minimal" cover the cases, and this way we
# don't have to update the test when gnat changes its default.
-foreach_with_prefix scenario {all minimal} {
- set flags {debug}
- if {$scenario != "none"} {
- lappend flags additional_flags=-fgnat-encodings=$scenario
- }
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/pckd_arr_ren.exp b/gdb/testsuite/gdb.ada/pckd_arr_ren.exp
index 083ee13..694cc23 100644
--- a/gdb/testsuite/gdb.ada/pckd_arr_ren.exp
+++ b/gdb/testsuite/gdb.ada/pckd_arr_ren.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
@@ -32,8 +32,9 @@ foreach_with_prefix scenario {all minimal} {
runto "foo.adb:$bp_location"
# GNAT 9 and 10 are known to fail.
- if {$scenario == "minimal" && ([test_compiler_info {gcc-9-*}] \
- || [test_compiler_info {gcc-10-*}])} {
+ if {$scenario == "minimal"
+ && [gnat_version_compare >= 9]
+ && [gnat_version_compare <= 10]} {
setup_kfail "minimal encodings" *-*-*
}
gdb_test "print A2" \
diff --git a/gdb/testsuite/gdb.ada/ptype-o.exp b/gdb/testsuite/gdb.ada/ptype-o.exp
index f778219..5038ee1 100644
--- a/gdb/testsuite/gdb.ada/ptype-o.exp
+++ b/gdb/testsuite/gdb.ada/ptype-o.exp
@@ -21,8 +21,8 @@ require allow_ada_tests
standard_ada_testfile prog
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/rec_comp.exp b/gdb/testsuite/gdb.ada/rec_comp.exp
index 4638786..641ebb6 100644
--- a/gdb/testsuite/gdb.ada/rec_comp.exp
+++ b/gdb/testsuite/gdb.ada/rec_comp.exp
@@ -33,6 +33,6 @@ if {![runto "bar_o203_012.adb:$bp_location"]} {
gdb_test "whatis r.ia" " = bar_o203_012.int_access"
gdb_test "ptype r" \
- " = record\r\n *ia: bar_o203_012\.int_access;\r\nend record"
+ " = record\r\n *ia: bar_o203_012\\.int_access;\r\nend record"
gdb_test "ptype r.ia" " = access <$decimal-byte integer>"
diff --git a/gdb/testsuite/gdb.ada/rec_ptype.exp b/gdb/testsuite/gdb.ada/rec_ptype.exp
index f75d09b..fc7bb8b 100644
--- a/gdb/testsuite/gdb.ada/rec_ptype.exp
+++ b/gdb/testsuite/gdb.ada/rec_ptype.exp
@@ -22,8 +22,8 @@ standard_ada_testfile main
# Note we don't test the "none" (no -fgnat-encodings option) scenario
# here, because "all" and "minimal" cover the cases, and this way we
# don't have to update the test when gnat changes its default.
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/same_component_name.exp b/gdb/testsuite/gdb.ada/same_component_name.exp
index 7167a41..84a48b4 100644
--- a/gdb/testsuite/gdb.ada/same_component_name.exp
+++ b/gdb/testsuite/gdb.ada/same_component_name.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != "" } {
return -1
diff --git a/gdb/testsuite/gdb.ada/set_pckd_arr_elt.exp b/gdb/testsuite/gdb.ada/set_pckd_arr_elt.exp
index d77f8fe..2979cb9 100644
--- a/gdb/testsuite/gdb.ada/set_pckd_arr_elt.exp
+++ b/gdb/testsuite/gdb.ada/set_pckd_arr_elt.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/tagged-lookup.exp b/gdb/testsuite/gdb.ada/tagged-lookup.exp
index 3803319..f1473aa 100644
--- a/gdb/testsuite/gdb.ada/tagged-lookup.exp
+++ b/gdb/testsuite/gdb.ada/tagged-lookup.exp
@@ -51,11 +51,7 @@ gdb_test_multiple "print *the_local_var" "only one CU expanded" -lbl {
-re ".symtab-create. start_subfile: name = \[^,\]*, name_for_id = \[^\r\n\]*\r\n" {
exp_continue
}
- -re -wrap ".* = \\\(n => $decimal\\\)" {
- if {$found_pck + $found_pck2 <= 1} {
- pass $gdb_test_name
- } else {
- fail $gdb_test_name
- }
+ -re -wrap "" {
+ gdb_assert {$found_pck + $found_pck2 <= 1} $gdb_test_name
}
}
diff --git a/gdb/testsuite/gdb.ada/tagged_access.exp b/gdb/testsuite/gdb.ada/tagged_access.exp
index 9b4ac6c..57f7440 100644
--- a/gdb/testsuite/gdb.ada/tagged_access.exp
+++ b/gdb/testsuite/gdb.ada/tagged_access.exp
@@ -21,17 +21,22 @@ require gnat_runtime_has_debug_info
standard_ada_testfile p
-if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug]] != "" } {
- return -1
-}
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
+
+ if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" \
+ executable $flags] != ""} {
+ return -1
+ }
-clean_restart ${testfile}
+ clean_restart ${testfile}-${scenario}
-set bp_location [gdb_get_line_number "BREAK" ${testdir}/p.adb]
-runto "p.adb:$bp_location"
+ set bp_location [gdb_get_line_number "BREAK" ${testdir}/p.adb]
+ runto "p.adb:$bp_location"
-gdb_test "ptype c.all" \
- " = new pack\\.interactive_command with record\r\n\\s+menu_name: pack\\.string_access;\r\nend record"
+ gdb_test "ptype c.all" \
+ " = new pack\\.interactive_command with record\r\n\\s+menu_name: pack\\.string_access;\r\nend record"
-gdb_test "ptype c.menu_name" \
- " = access array \\(<>\\) of character"
+ gdb_test "ptype c.menu_name" \
+ " = access array \\(<>\\) of character"
+}
diff --git a/gdb/testsuite/gdb.ada/task_bp.exp b/gdb/testsuite/gdb.ada/task_bp.exp
index cf6251e..4b32a3d 100644
--- a/gdb/testsuite/gdb.ada/task_bp.exp
+++ b/gdb/testsuite/gdb.ada/task_bp.exp
@@ -37,7 +37,7 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug]] != "" }
proc test_bp { loc msg } {
gdb_test "break $loc" \
- "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: file .*pck.adb, line \[0-9\]+\." \
+ "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: file .*pck.adb, line \[0-9\]+\\." \
"break $loc - $msg"
gdb_run_cmd
diff --git a/gdb/testsuite/gdb.ada/task_switch_in_core.exp b/gdb/testsuite/gdb.ada/task_switch_in_core.exp
index 63a951c..dd63bb8 100644
--- a/gdb/testsuite/gdb.ada/task_switch_in_core.exp
+++ b/gdb/testsuite/gdb.ada/task_switch_in_core.exp
@@ -41,7 +41,7 @@ if {!$core_supported} {
return -1
}
-# Now taht the core file has been created, we can start the real
+# Now that the core file has been created, we can start the real
# part of this testcase, which is to debug using that core file.
# Restart GDB and load that core file.
diff --git a/gdb/testsuite/gdb.ada/tasks.exp b/gdb/testsuite/gdb.ada/tasks.exp
index 6e58840..ecbfbd5 100644
--- a/gdb/testsuite/gdb.ada/tasks.exp
+++ b/gdb/testsuite/gdb.ada/tasks.exp
@@ -55,11 +55,11 @@ gdb_test "watch j task 1 task 3" "You can specify only one task\\."
# Check that attempting to combine 'task' and 'thread' gives an error.
gdb_test "break break_me task 1 thread 1" \
- "You can specify only one of thread or task\\."
+ "You can specify only one of thread, inferior, or task\\."
gdb_test "break break_me thread 1 task 1" \
- "You can specify only one of thread or task\\."
+ "You can specify only one of thread, inferior, or task\\."
gdb_test "break break_me inferior 1 task 1" \
- "You can specify only one of inferior or task\\."
+ "You can specify only one of thread, inferior, or task\\."
gdb_test "watch j task 1 thread 1" \
"You can specify only one of thread or task\\."
gdb_test "watch j thread 1 task 1" \
diff --git a/gdb/testsuite/gdb.ada/unc_arr_ptr_in_var_rec.exp b/gdb/testsuite/gdb.ada/unc_arr_ptr_in_var_rec.exp
index 6b2a6fd..2bcc027 100644
--- a/gdb/testsuite/gdb.ada/unc_arr_ptr_in_var_rec.exp
+++ b/gdb/testsuite/gdb.ada/unc_arr_ptr_in_var_rec.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/unchecked_union.exp b/gdb/testsuite/gdb.ada/unchecked_union.exp
index bff71bd..5d3256b 100644
--- a/gdb/testsuite/gdb.ada/unchecked_union.exp
+++ b/gdb/testsuite/gdb.ada/unchecked_union.exp
@@ -51,11 +51,8 @@ set pair_string { case ? is
}
set pair_full "type = record\n${inner_string}${pair_string}end record"
-foreach_with_prefix scenario {none all minimal} {
- set flags {debug}
- if {$scenario != "none"} {
- lappend flags additional_flags=-fgnat-encodings=$scenario
- }
+foreach_gnat_encoding scenario flags {none all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/var_rec_arr.exp b/gdb/testsuite/gdb.ada/var_rec_arr.exp
index a859108..20598ea 100644
--- a/gdb/testsuite/gdb.ada/var_rec_arr.exp
+++ b/gdb/testsuite/gdb.ada/var_rec_arr.exp
@@ -22,8 +22,8 @@ standard_ada_testfile foo_na09_042
# Note we don't test the "none" (no -fgnat-encodings option) scenario
# here, because "all" and "minimal" cover the cases, and this way we
# don't have to update the test when gnat changes its default.
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/variant.exp b/gdb/testsuite/gdb.ada/variant.exp
index 9fbc449..227331c 100644
--- a/gdb/testsuite/gdb.ada/variant.exp
+++ b/gdb/testsuite/gdb.ada/variant.exp
@@ -20,11 +20,8 @@ require allow_ada_tests
standard_ada_testfile pkg
-foreach_with_prefix scenario {none all minimal} {
- set flags {debug}
- if {$scenario != "none"} {
- lappend flags additional_flags=-fgnat-encodings=$scenario
- }
+foreach_gnat_encoding scenario flags {none all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
diff --git a/gdb/testsuite/gdb.ada/variant_record_packed_array.exp b/gdb/testsuite/gdb.ada/variant_record_packed_array.exp
index f6b4e41..22b67cc 100644
--- a/gdb/testsuite/gdb.ada/variant_record_packed_array.exp
+++ b/gdb/testsuite/gdb.ada/variant_record_packed_array.exp
@@ -19,8 +19,8 @@ require allow_ada_tests
standard_ada_testfile foo
-foreach_with_prefix scenario {all minimal} {
- set flags [list debug additional_flags=-fgnat-encodings=$scenario]
+foreach_gnat_encoding scenario flags {all minimal} {
+ lappend flags debug
if {[gdb_compile_ada "${srcfile}" "${binfile}-${scenario}" executable $flags] != ""} {
return -1
@@ -41,7 +41,7 @@ foreach_with_prefix scenario {all minimal} {
}
-re " = \\(size => 8, length => 8, buffer => warning: could not find bounds information on packed array.*$gdb_prompt $" {
# GNAT >= 11.0 has the needed fix here.
- if {$scenario == "minimal" && ![test_compiler_info {gcc-1[1-9]-*}]} {
+ if {$scenario == "minimal" && [gnat_version_compare >= 11]} {
setup_kfail "minimal encodings" *-*-*
}
fail $test
@@ -62,7 +62,7 @@ foreach_with_prefix scenario {all minimal} {
}
-re " = \\(size => 8, length => 8, buffer => warning: could not find bounds information on packed array.*$gdb_prompt $" {
# GNAT >= 11.0 has the needed fix here.
- if {$scenario == "minimal" && ![test_compiler_info {gcc-1[1-9]-*}]} {
+ if {$scenario == "minimal" && [gnat_version_compare >= 11]} {
setup_kfail "minimal encodings" *-*-*
}
fail $test
diff --git a/gdb/testsuite/gdb.arch/amd64-disp-step-self-call.exp b/gdb/testsuite/gdb.arch/amd64-disp-step-self-call.exp
index 762d19a..2db3ff2 100644
--- a/gdb/testsuite/gdb.arch/amd64-disp-step-self-call.exp
+++ b/gdb/testsuite/gdb.arch/amd64-disp-step-self-call.exp
@@ -77,6 +77,6 @@ gdb_assert {[expr $sp == $new_sp]} \
"check stack pointer was updated as expected"
# Check the contents of the stack were updated to the expected value.
-set next_insn_addr 0x[format %016X $next_insn_addr]
+set next_insn_addr 0x[format %016x $next_insn_addr]
gdb_test "x/1gx 0x[format %x $sp]" "$hex:\\s+$next_insn_addr" \
"check return address was updated correctly"
diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c
index 49b0553..adda4b8 100644
--- a/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c
+++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c
@@ -24,10 +24,17 @@ break_here_c (uint64_t value)
{
}
+__attribute__((target("arm")))
+uint64_t
+caller_trampoline (void)
+{
+ return caller ();
+}
+
int
main (void)
{
- uint64_t value = caller ();
+ uint64_t value = caller_trampoline ();
break_here_c (value);
return 0;
}
diff --git a/gdb/testsuite/gdb.arch/arm-pseudo-unwind.c b/gdb/testsuite/gdb.arch/arm-pseudo-unwind.c
index 49b0553..adda4b8 100644
--- a/gdb/testsuite/gdb.arch/arm-pseudo-unwind.c
+++ b/gdb/testsuite/gdb.arch/arm-pseudo-unwind.c
@@ -24,10 +24,17 @@ break_here_c (uint64_t value)
{
}
+__attribute__((target("arm")))
+uint64_t
+caller_trampoline (void)
+{
+ return caller ();
+}
+
int
main (void)
{
- uint64_t value = caller ();
+ uint64_t value = caller_trampoline ();
break_here_c (value);
return 0;
}
diff --git a/gdb/testsuite/gdb.arch/arm-single-step-kernel-helper.c b/gdb/testsuite/gdb.arch/arm-single-step-kernel-helper.c
index 393004e..9b5e137 100644
--- a/gdb/testsuite/gdb.arch/arm-single-step-kernel-helper.c
+++ b/gdb/testsuite/gdb.arch/arm-single-step-kernel-helper.c
@@ -15,7 +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/>. */
-static int *kernel_user_helper_version = (int *) 0xffff0ffc;
+static int *kernel_user_helper_version_ptr = (int *) 0xffff0ffc;
+static int kernel_user_helper_version;
typedef void * (kernel_user_func_t)(void);
#define kernel_user_get_tls (*(kernel_user_func_t *) 0xffff0fe0)
@@ -25,6 +26,8 @@ main (void)
{
int i;
+ kernel_user_helper_version = *kernel_user_helper_version_ptr;
+
for (i = 0; i < 8; i++)
kernel_user_get_tls ();
}
diff --git a/gdb/testsuite/gdb.arch/arm-single-step-kernel-helper.exp b/gdb/testsuite/gdb.arch/arm-single-step-kernel-helper.exp
index 27be5d5..788bc86 100644
--- a/gdb/testsuite/gdb.arch/arm-single-step-kernel-helper.exp
+++ b/gdb/testsuite/gdb.arch/arm-single-step-kernel-helper.exp
@@ -26,10 +26,13 @@ if { ![runto_main] } {
return -1
}
+# Initialize kernel_user_helper_version.
+gdb_test "next" "for .*"
+
# Check kernel helpers are supported or not.
set kernel_helper_supported 0
-gdb_test_multiple "p *kernel_user_helper_version" \
+gdb_test_multiple "p kernel_user_helper_version" \
"check kernel helper version" {
-re " = ($decimal)\r\n$gdb_prompt $" {
if { $expect_out(1,string) >= 1 } {
diff --git a/gdb/testsuite/gdb.arch/e500-prologue.exp b/gdb/testsuite/gdb.arch/e500-prologue.exp
index 50837ff..7732393 100644
--- a/gdb/testsuite/gdb.arch/e500-prologue.exp
+++ b/gdb/testsuite/gdb.arch/e500-prologue.exp
@@ -53,7 +53,7 @@ proc insert_breakpoint {function expected_location} {
# If we managed to get the breakpoing address, then check that
# we inserted it at the expected location by examining the
# instruction at that address (we're not interested in the insn
- # itself, but rather at the address printed at the begining of
+ # itself, but rather at the address printed at the beginning of
# the instruction).
if {$address != ""} {
gdb_test "x /i $address" \
diff --git a/gdb/testsuite/gdb.arch/ftrace-insn-reloc.exp b/gdb/testsuite/gdb.arch/ftrace-insn-reloc.exp
index 9549b59..4ea86b4 100644
--- a/gdb/testsuite/gdb.arch/ftrace-insn-reloc.exp
+++ b/gdb/testsuite/gdb.arch/ftrace-insn-reloc.exp
@@ -33,6 +33,7 @@ if ![gdb_target_supports_trace] {
return -1
}
+require allow_in_proc_agent
set libipa [get_in_proc_agent]
# Can't use prepare_for_testing, because that splits compiling into
diff --git a/gdb/testsuite/gdb.arch/i386-disp-step-self-call.exp b/gdb/testsuite/gdb.arch/i386-disp-step-self-call.exp
index b2cb902..5de7ebc 100644
--- a/gdb/testsuite/gdb.arch/i386-disp-step-self-call.exp
+++ b/gdb/testsuite/gdb.arch/i386-disp-step-self-call.exp
@@ -77,6 +77,6 @@ gdb_assert {[expr $sp == $new_sp]} \
"check stack pointer was updated as expected"
# Check the contents of the stack were updated to the expected value.
-set next_insn_addr 0x[format %08X $next_insn_addr]
+set next_insn_addr 0x[format %08x $next_insn_addr]
gdb_test "x/1wx 0x[format %x $sp]" "$hex:\\s+$next_insn_addr" \
"check return address was updated correctly"
diff --git a/gdb/testsuite/gdb.arch/i386-mpx-call.c b/gdb/testsuite/gdb.arch/i386-mpx-call.c
deleted file mode 100644
index 5949202..0000000
--- a/gdb/testsuite/gdb.arch/i386-mpx-call.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* Test for inferior function calls MPX context.
-
- Copyright (C) 2017-2024 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include <stdlib.h>
-#include <string.h>
-
-/* Defined size for arrays. */
-#define ARRAY_LENGTH 5
-
-
-int
-upper (int *a, int *b, int *c, int *d, int len)
-{
- int value;
-
- value = *(a + len);
- value = *(b + len);
- value = *(c + len);
- value = *(d + len);
-
- value = value - *a + 1;
- return value;
-}
-
-
-int
-lower (int *a, int *b, int *c, int *d, int len)
-{
- int value;
-
- value = *(a - len);
- value = *(b - len);
- value = *(c - len);
- value = *(d - len);
-
- value = value - *a + 1;
- return value;
-}
-
-
-char
-char_upper (char *str, int length)
-{
- char ch;
- ch = *(str + length);
-
- return ch;
-}
-
-
-char
-char_lower (char *str, int length)
-{
- char ch;
- ch = *(str - length);
-
- return ch;
-}
-
-
-int
-main (void)
-{
- int sa[ARRAY_LENGTH];
- int sb[ARRAY_LENGTH];
- int sc[ARRAY_LENGTH];
- int sd[ARRAY_LENGTH];
- int *x, *a, *b, *c, *d;
- char mchar;
- char hello[] = "Hello";
-
- x = malloc (sizeof (int) * ARRAY_LENGTH);
- a = malloc (sizeof (int) * ARRAY_LENGTH);
- b = malloc (sizeof (int) * ARRAY_LENGTH);
- c = malloc (sizeof (int) * ARRAY_LENGTH);
- d = malloc (sizeof (int) * ARRAY_LENGTH);
-
- *x = upper (sa, sb, sc, sd, 0); /* bkpt 1. */
- *x = lower (a, b, c, d, 0);
-
- mchar = char_upper (hello, 10);
- mchar = char_lower (hello, 10);
-
- free (x);
- free (a);
- free (b);
- free (c);
- free (d);
-
- return 0;
-}
diff --git a/gdb/testsuite/gdb.arch/i386-mpx-call.exp b/gdb/testsuite/gdb.arch/i386-mpx-call.exp
deleted file mode 100644
index e225484..0000000
--- a/gdb/testsuite/gdb.arch/i386-mpx-call.exp
+++ /dev/null
@@ -1,398 +0,0 @@
-# Copyright (C) 2017-2024 Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-require {is_any_target "i?86-*-*" "x86_64-*-*"}
-
-standard_testfile
-
-require supports_mpx_check_pointer_bounds have_mpx
-
-set comp_flags "-mmpx -fcheck-pointer-bounds -I${srcdir}/../nat"
-
-if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
- [list debug additional_flags=${comp_flags}]] } {
- return -1
-}
-
-if ![runto_main] {
- return -1
-}
-
-set bounds_table 0
-gdb_test_multiple "disassemble upper" "" {
- -re -wrap "bndldx.*" {
- set bounds_table 1
- }
- -re -wrap "" {
- }
-}
-
-# Convenience for returning from an inferior call that causes a BND violation.
-#
-gdb_test_no_output "set confirm off"
-
-# Convenience variable.
-#
-set bound_reg " = \\\{lbound = $hex, ubound = $hex\\\}.*"
-set int_braw_reg " = \\\{lbound = 0x0, ubound_raw = 0x0\\\}.*"
-set bndcfg_reg " = \\\{raw = $hex, config = \\\{base = $hex, reserved = $hex,\
- preserved = $hex, enabled = $hex\\\}\\\}"
-set bndstatus_reg " = \\\{raw = $hex, status = \\\{bde = $hex,\
- error = $hex\\\}\\\}"
-set u_fault [multi_line "Program received signal SIGSEGV, Segmentation fault" \
- "Upper bound violation while accessing address $hex" \
- "Bounds: \\\[lower = $hex, upper = $hex\\\]"]
-
-
-# Simplify the tests below.
-#
-proc sanity_check_bndregs {arglist} {
-
- global int_braw_reg
-
- foreach a $arglist {
- gdb_test "p /x $a" "$int_braw_reg"\
- "$a"
- }
-}
-
-# Set bnd register to have no access to memory.
-#
-proc remove_memory_access {reg} {
- global hex
-
- sanity_check_bndregs {"\$bnd0raw" "\$bnd1raw" "\$bnd2raw" "\$bnd3raw"}
-
- gdb_test "p /x $reg.lbound = $reg.ubound" "= $hex"\
- "$reg lower bound set"
- gdb_test "p /x $reg.ubound = 0" " = 0x0"\
- "$reg upper bound set"
-}
-
-
-# Prepare convenience variables for bndconfig and status
-# for posterior comparison.
-#
-proc prepare_bndcfg_bndstatus {} {
-
- global bndcfg_reg
- global bndstatus_reg
-
- gdb_test "p /x \$temp_bndcfgu = \$bndcfgu" "$bndcfg_reg"\
- "bndcfgu should not change"
-
- gdb_test "p /x \$temp_bndstatus = \$bndstatus" "$bndstatus_reg"\
- "bndstatus should not change"
-}
-
-# Compare values set for convenience variables and actual values of bndconfig
-# and bndstatus registers.
-#
-proc compare_bndstatus_with_convenience {} {
-
- gdb_test "p \$temp_bndcfgu == \$bndcfgu" "= 1"\
- "bndcfgu compare before and after"
- gdb_test "p \$temp_bndstatus == \$bndstatus" "= 1"\
- "bndstatus compare before and after"
-}
-
-# Perform an inferior call defined in func.
-#
-proc perform_a_call {func} {
-
- global inf_call_stopped
- global gdb_prompt
-
- gdb_test "p /x $func" [multi_line "The program being debugged\
- stopped while in a function called from GDB." \
- "Evaluation of the expression containing the\
- function.*" \
- ] "inferior call stopped"
-}
-
-# Perform an inferior call defined in func.
-#
-proc check_bound_violation {parm parm_type is_positive} {
-
- global u_fault bounds_table
-
- set have_bnd_violation 0
- gdb_test_multiple "continue" "continue to a bnd violation" {
- -re -wrap "Continuing\." {
- if { $bounds_table } {
- pass $gdb_test_name
- } else {
- fail $gdb_test_name
- }
- }
- -re -wrap "$u_fault.*" {
- pass $gdb_test_name
- set have_bnd_violation 1
- }
- }
- if { ! $have_bnd_violation } {
- return
- }
-
- set message "access only one position"
- if {$is_positive == 1} {
- gdb_test "p (((void *)\$_siginfo._sifields._sigfault.si_addr\
- - (void*)$parm))/sizeof($parm_type) == 1"\
- " = 1" $message
- } else {
- gdb_test "p ((void*)$parm\
- - (void *)\$_siginfo._sifields._sigfault.si_addr)\
- /sizeof($parm_type) == 1"\
- " = 1" $message
- }
- gdb_test "return" "\\\#.*main.*i386-mpx-call\\\.c:.*" "return from the fault"
-}
-
-
-# Start testing!
-#
-
-# Set up for stopping in the middle of main for calling a function in the
-# inferior.
-#
-set break "bkpt 1."
-gdb_breakpoint [gdb_get_line_number "${break}"]
-gdb_continue_to_breakpoint "${break}" ".*${break}.*"
-
-
-# Consistency:
-# default run execution of call should succeed without violations.
-#
-with_test_prefix "default_run" {
-
- gdb_test "p \$keep_bnd0_value=\$bnd0" $bound_reg\
- "store bnd0 register in a convenience variable"
-
- gdb_test "p /x upper (a, b, c, d, 0)" " = $hex"\
- "default inferior call"
-
- gdb_test "p ((\$bnd0.lbound==\$keep_bnd0_value.lbound) &&\
- (\$bnd0.ubound==\$keep_bnd0_value.ubound))" "= 1" \
- "bnd register value after and before call"
-}
-
-# Consistency: Examine bnd registers values before and after the call.
-#
-#
-with_test_prefix "verify_default_values" {
-
- prepare_bndcfg_bndstatus
-
- gdb_breakpoint "*upper"
- perform_a_call "upper (a, b, c, d, 1)"
-
- sanity_check_bndregs {"\$bnd0raw" "\$bnd1raw" "\$bnd2raw" "\$bnd3raw"}
-
- compare_bndstatus_with_convenience
-
- gdb_test_multiple "continue" "inferior call test" {
- -re ".*Continuing.\r\n$gdb_prompt " {
- pass "inferior call performed"
- }
- }
-}
-
-# Examine: Cause an upper bound violation changing BND0.
-#
-#
-with_test_prefix "upper_bnd0" {
-
- prepare_bndcfg_bndstatus
-
- gdb_breakpoint "*upper"
- perform_a_call "upper (a, b, c, d, 1)"
-
- remove_memory_access "\$bnd0"
-
- compare_bndstatus_with_convenience
-
- check_bound_violation "a" "int" 1
-}
-
-# Examine: Cause an upper bound violation changing BND1.
-#
-#
-with_test_prefix "upper_bnd1" {
-
- prepare_bndcfg_bndstatus
-
- gdb_breakpoint "*upper"
- perform_a_call "upper (a, b, c, d, 1)"
-
- remove_memory_access "\$bnd1"
-
- compare_bndstatus_with_convenience
-
- check_bound_violation "b" "int" 1
-}
-
-# Examine: Cause an upper bound violation changing BND2.
-#
-#
-with_test_prefix "upper_bnd2" {
-
- prepare_bndcfg_bndstatus
-
- gdb_breakpoint "*upper"
- perform_a_call "upper (a, b, c, d, 1)"
-
- remove_memory_access "\$bnd2"
-
- compare_bndstatus_with_convenience
-
- check_bound_violation "c" "int" 1
-}
-
-# Examine: Cause an upper bound violation changing BND3.
-#
-#
-with_test_prefix "upper_bnd3" {
- prepare_bndcfg_bndstatus
-
- gdb_breakpoint "*upper"
- perform_a_call "upper (a, b, c, d, 1)"
-
- remove_memory_access "\$bnd3"
-
- compare_bndstatus_with_convenience
-
- check_bound_violation "d" "int" 1
-}
-
-# Examine: Cause a lower bound violation changing BND0.
-#
-#
-with_test_prefix "lower_bnd0" {
-
- prepare_bndcfg_bndstatus
-
- gdb_breakpoint "*lower"
- perform_a_call "lower (a, b, c, d, 1)"
-
- remove_memory_access "\$bnd0"
-
- compare_bndstatus_with_convenience
-
- check_bound_violation "a" "int" 0
-}
-
-# Examine: Cause a lower bound violation changing BND1.
-#
-#
-with_test_prefix "lower_bnd1" {
-
- prepare_bndcfg_bndstatus
-
- gdb_breakpoint "*lower"
- perform_a_call "lower (a, b, c, d, 1)"
-
- remove_memory_access "\$bnd1"
-
- compare_bndstatus_with_convenience
-
- check_bound_violation "b" "int" 0
-}
-
-# Examine: Cause a lower bound violation changing BND2.
-#
-#
-with_test_prefix "lower_bnd2" {
-
- prepare_bndcfg_bndstatus
-
- gdb_breakpoint "*lower"
- perform_a_call "lower (a, b, c, d, 1)"
-
- remove_memory_access "\$bnd2"
-
- compare_bndstatus_with_convenience
-
- check_bound_violation "c" "int" 0
-}
-
-# Examine: Cause a lower bound violation changing BND3.
-#
-#
-with_test_prefix "lower_bnd3" {
-
- prepare_bndcfg_bndstatus
-
- gdb_breakpoint "*lower"
- perform_a_call "lower (a, b, c, d, 1)"
-
- remove_memory_access "\$bnd3"
-
- compare_bndstatus_with_convenience
-
- check_bound_violation "d" "int" 0
-}
-
-# Examine: String causing a upper bound violation changing BND0.
-#
-#
-with_test_prefix "chars_up" {
-
- prepare_bndcfg_bndstatus
-
- gdb_breakpoint "*char_upper"
- perform_a_call "char_upper (hello, 1)"
-
- remove_memory_access "\$bnd0"
-
- compare_bndstatus_with_convenience
-
- check_bound_violation "str" "char" 1
-}
-
-
-# Examine: String causing an lower bound violation changing BND0.
-#
-#
-with_test_prefix "chars_low" {
-
- prepare_bndcfg_bndstatus
-
- gdb_breakpoint "*char_lower"
- perform_a_call "char_lower (hello, 1)"
-
- remove_memory_access "\$bnd0"
-
- compare_bndstatus_with_convenience
-
- check_bound_violation "str" "char" 0
-}
-
-# Examine: String causing an lower bound violation changing BND0.
-#
-#
-with_test_prefix "chars_low_adhoc_parm" {
-
- prepare_bndcfg_bndstatus
-
- gdb_breakpoint "*char_lower"
- perform_a_call "char_lower (\"tryme\", 1)"
-
- remove_memory_access "\$bnd0"
-
- compare_bndstatus_with_convenience
-
- check_bound_violation "str" "char" 0
-}
diff --git a/gdb/testsuite/gdb.arch/i386-mpx-map.c b/gdb/testsuite/gdb.arch/i386-mpx-map.c
deleted file mode 100644
index c072e74..0000000
--- a/gdb/testsuite/gdb.arch/i386-mpx-map.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Test program for MPX map allocated bounds.
-
- Copyright 2015-2024 Free Software Foundation, Inc.
-
- Contributed by Intel Corp. <walfred.tedeschi@intel.com>
- <mircea.gherzan@intel.com>
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include <stdlib.h>
-#define SIZE 5
-
-typedef int T;
-
-void
-foo (T *p)
-{
- T *x;
-
-#if defined __GNUC__ && !defined __INTEL_COMPILER
- __bnd_store_ptr_bounds (p, &p);
-#endif
-
- x = p + SIZE - 1;
-
-#if defined __GNUC__ && !defined __INTEL_COMPILER
- __bnd_store_ptr_bounds (x, &x);
-#endif
- /* Dummy assign. */
- x = x + 1; /* after-assign */
- return;
-}
-
-int
-main (void)
-{
- T *a = NULL;
-
- a = calloc (SIZE, sizeof (T)); /* after-decl */
-#if defined __GNUC__ && !defined __INTEL_COMPILER
- __bnd_store_ptr_bounds (a, &a);
-#endif
-
- foo (a); /* after-alloc */
- free (a);
-
- return 0;
-}
diff --git a/gdb/testsuite/gdb.arch/i386-mpx-map.exp b/gdb/testsuite/gdb.arch/i386-mpx-map.exp
deleted file mode 100644
index d955187..0000000
--- a/gdb/testsuite/gdb.arch/i386-mpx-map.exp
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright 2015-2024 Free Software Foundation, Inc.
-#
-# Contributed by Intel Corp. <walfred.tedeschi@intel.com>,
-# <mircea.gherzan@intel.com>
-#
-# 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_any_target i?86-*-* x86_64-*-*}
-
-standard_testfile
-
-require supports_mpx_check_pointer_bounds have_mpx
-
-set comp_flags "-mmpx -fcheck-pointer-bounds -I${srcdir}/../nat/"
-
-if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
- [list debug nowarnings additional_flags=${comp_flags}]] } {
- return -1
-}
-
-if ![runto_main] {
- return -1
-}
-
-gdb_breakpoint [ gdb_get_line_number "after-decl" ]
-gdb_breakpoint [ gdb_get_line_number "after-alloc" ]
-gdb_breakpoint [ gdb_get_line_number "after-assign" ]
-
-gdb_test "show mpx bound 0x0" "Invalid bounds directory entry at $hex." "NULL address of the pointer"
-
-gdb_continue_to_breakpoint "after-decl" ".*after-decl.*"
-gdb_test "show mpx bound a" "Invalid bounds directory entry at $hex." "pointer instead of pointer address"
-
-gdb_continue_to_breakpoint "after-alloc" ".*after-alloc.*"
-gdb_test "show mpx bound a" "\\\{lbound = $hex, ubound = $hex\\\}: pointer value = $hex, size = \[8, 4\], metadata = 0x0+" "pointer after allocation"
-
-gdb_continue_to_breakpoint "after-assign" ".*after-assign.*"
-gdb_test "show mpx bound x" "\\\{lbound = $hex, ubound = $hex\\\}: pointer value = $hex, size = \[8, 4\], metadata = 0x0+" "pointer after assignment"
-gdb_test "set mpx bound 0x0, 0x1, 0x2" "Invalid bounds directory entry at $hex." "set mpx bound: NULL address of the pointer"
-gdb_test_no_output "set mpx bound x, 0xcafebabe, 0xdeadbeef" "set mpx bound: set bounds for a valid pointer address"
-gdb_test "show mpx bound x" "\\\{lbound = .*cafebabe, ubound = .*deadbeef\\\}: pointer value = $hex, size = $decimal, metadata = 0x0+" "set mpx bound: bounds map entry after set mpx bound"
-
-
-gdb_test "set mpx bound 0x0, 0x1 0x2" "A syntax error in expression.*" "set mpx bound: Controlling syntax error, missing comma "
-gdb_test "set mpx bound 0x0, 0x1" "Wrong number of arguments.*" "set mpx bound: Controlling syntax error, missing argument "
diff --git a/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.c b/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.c
deleted file mode 100644
index 54722e3..0000000
--- a/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Copyright (C) 2015-2024 Free Software Foundation, Inc.
-
- Contributed by Intel Corp. <walfred.tedeschi@intel.com>
-
- 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 OUR_SIZE 5
-
-int gx[OUR_SIZE];
-int ga[OUR_SIZE];
-int gb[OUR_SIZE];
-int gc[OUR_SIZE];
-int gd[OUR_SIZE];
-
-int
-bp1 (int value)
-{
- return 1;
-}
-
-int
-bp2 (int value)
-{
- return 1;
-}
-
-void
-upper (int * p, int * a, int * b, int * c, int * d, int len)
-{
- int value;
- value = *(p + len);
- value = *(a + len);
- value = *(b + len);
- value = *(c + len);
- value = *(d + len);
-}
-
-void
-lower (int * p, int * a, int * b, int * c, int * d, int len)
-{
- int value;
- value = *(p - len);
- value = *(a - len);
- value = *(b - len);
- value = *(c - len);
- bp2 (value);
- value = *(d - len);
-}
-
-int
-main (void)
-{
- int sx[OUR_SIZE];
- int sa[OUR_SIZE];
- int sb[OUR_SIZE];
- int sc[OUR_SIZE];
- int sd[OUR_SIZE];
- int *x, *a, *b, *c, *d;
-
- x = calloc (OUR_SIZE, sizeof (int));
- a = calloc (OUR_SIZE, sizeof (int));
- b = calloc (OUR_SIZE, sizeof (int));
- c = calloc (OUR_SIZE, sizeof (int));
- d = calloc (OUR_SIZE, sizeof (int));
-
- upper (x, a, b, c, d, OUR_SIZE + 2);
- upper (sx, sa, sb, sc, sd, OUR_SIZE + 2);
- upper (gx, ga, gb, gc, gd, OUR_SIZE + 2);
- lower (x, a, b, c, d, 1);
- lower (sx, sa, sb, sc, sd, 1);
- bp1 (*x);
- lower (gx, ga, gb, gc, gd, 1);
-
- free (x);
- free (a);
- free (b);
- free (c);
- free (d);
-
- return 0;
-}
diff --git a/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.exp b/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.exp
deleted file mode 100644
index 75f7e65..0000000
--- a/gdb/testsuite/gdb.arch/i386-mpx-sigsegv.exp
+++ /dev/null
@@ -1,64 +0,0 @@
-# Copyright (C) 2015-2024 Free Software Foundation, Inc.
-#
-# Contributed by Intel Corp. <walfred.tedeschi@intel.com>
-#
-# 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_any_target "i?86-*-*" "x86_64-*-*"}
-
-standard_testfile
-
-require supports_mpx_check_pointer_bounds have_mpx
-
-set comp_flags "-mmpx -fcheck-pointer-bounds -I${srcdir}/../nat/"
-
-if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
- [list debug nowarnings additional_flags=${comp_flags}]] } {
- return -1
-}
-
-if ![runto_main] {
- return -1
-}
-
-set u_fault [multi_line "Program received signal SIGSEGV, Segmentation fault" \
- "Upper bound violation while accessing address $hex" \
- "Bounds: \\\[lower = $hex, upper = $hex\\\]"]
-
-set l_fault [multi_line "Program received signal SIGSEGV, Segmentation fault" \
- "Lower bound violation while accessing address $hex" \
- "Bounds: \\\[lower = $hex, upper = $hex\\\]"]
-
-for {set i 0} {$i < 15} {incr i} {
- set message "MPX signal segv Upper: ${i}"
-
- if {[gdb_test "continue" "$u_fault.*" $message] != 0} {
- break
- }
-
- gdb_test "where" ".*#0 $hex in upper.*"\
- "$message: should be in upper"
-}
-
-for {set i 0} {$i < 15} {incr i} {
- set message "MPX signal segv Lower: ${i}"
-
- if {[gdb_test "continue" "$l_fault.*" $message] != 0} {
- break
- }
-
- gdb_test "where" ".*#0 $hex in lower.*"\
- "$message: should be in lower"
-}
diff --git a/gdb/testsuite/gdb.arch/i386-mpx-simple_segv.exp b/gdb/testsuite/gdb.arch/i386-mpx-simple_segv.exp
deleted file mode 100644
index 8a6c9dd..0000000
--- a/gdb/testsuite/gdb.arch/i386-mpx-simple_segv.exp
+++ /dev/null
@@ -1,124 +0,0 @@
-# Copyright (C) 2015-2024 Free Software Foundation, Inc.
-#
-# Contributed by Intel Corp. <walfred.tedeschi@intel.com>
-#
-# 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/>.
-
-# Testing handle setup together with boundary violation signals.
-#
-# Some states are not allowed as reported on the manual, as noprint
-# implies nostop, but nostop might print.
-#
-# Caveat: Setting the handle to nopass, ends up in a endless loop.
-
-require {is_any_target i?86-*-* x86_64-*-*}
-
-standard_testfile
-
-require supports_mpx_check_pointer_bounds have_mpx
-
-set comp_flags "-mmpx -fcheck-pointer-bounds -I${srcdir}/../nat/"
-
-if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
- [list debug nowarnings additional_flags=${comp_flags}]] } {
- return -1
-}
-
-if ![runto_main] {
- return -1
-}
-
-set violation [multi_line "Program received signal SIGSEGV, Segmentation fault" \
- "Upper bound violation while accessing address $hex" \
- "Bounds: \\\[lower = $hex, upper = $hex\\\]"]
-
-set segv_with_exit "Program received signal SIGSEGV,\
- Segmentation fault.*$inferior_exited_re.*"
-
-
-# Test handler for segmentation fault for:
-# print pass stop
-#
-set parameters "print pass stop"
-with_test_prefix "$parameters" {
- if ![runto_main] {
- return -1
- }
-
- gdb_test "handle SIGSEGV $parameters"\
- ".*SIGSEGV.*Yes.*Yes.*Yes.*Segmentation fault.*"\
- "set parameters"
-
- gdb_test "continue" ".*$violation.*" "display"
-
- gdb_test "where" ".*#0 $hex in upper.*"\
- "should be in upper"
-}
-
-# Test handler for segmentation fault for:
-# print pass nostop
-#
-set parameters "print pass nostop"
-with_test_prefix "$parameters" {
- if ![runto_main] {
- return -1
- }
-
- gdb_test "handle SIGSEGV $parameters"\
- ".*SIGSEGV.*No.*Yes.*Yes.*Segmentation fault.*"\
- "set parameters"
-
- gdb_test "continue" ".*$segv_with_exit.*" "display"
-
- gdb_test "where" "No stack." "no inferior"
-}
-
-# Test handler for segmentation fault for:
-# print nopass stop
-#
-set parameters "print nopass stop"
-with_test_prefix "$parameters" {
- if ![runto_main] {
- return -1
- }
-
- gdb_test "handle SIGSEGV $parameters"\
- ".*SIGSEGV.*Yes.*Yes.*No.*Segmentation fault.*"\
- "set parameters"
-
- gdb_test "continue" ".*$violation.*" "display"
-
- gdb_test "where" ".*#0 $hex in upper.*"\
- "should be in upper"
-}
-
-# Test handler for segmentation fault for:
-# print nopass stop
-#
-set parameters "noprint pass nostop"
-with_test_prefix "$parameters" {
- if ![runto_main] {
- return -1
- }
-
- gdb_test "handle SIGSEGV $parameters"\
- ".*SIGSEGV.*No.*No.*Yes.*Segmentation fault.*"\
- "set parameters"
-
- gdb_test "continue" "Continuing\..*$inferior_exited_re.*"\
- "Display"
-
- gdb_test "where" "No stack." "no inferior"
-}
-
diff --git a/gdb/testsuite/gdb.arch/i386-mpx.c b/gdb/testsuite/gdb.arch/i386-mpx.c
deleted file mode 100644
index 99f6744..0000000
--- a/gdb/testsuite/gdb.arch/i386-mpx.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Test program for MPX registers.
-
- Copyright 2013-2024 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/>. */
-
-int
-main (void)
-{
-#ifdef __x86_64__
- asm ("mov $10, %rax\n\t"
- "mov $9, %rdx\n\t"
- "bndmk (%rax,%rdx), %bnd0\n\t"
- "mov $20, %rax\n\t"
- "mov $9, %rdx\n\t"
- "bndmk (%rax,%rdx), %bnd1\n\t"
- "mov $30, %rax\n\t"
- "mov $9, %rdx\n\t"
- "bndmk (%rax,%rdx), %bnd2\n\t"
- "mov $40, %rax\n\t"
- "mov $9, %rdx\n\t"
- "bndmk (%rax,%rdx), %bnd3\n\t"
- "bndstx %bnd3, (%rax) \n\t"
- "nop\n\t"
- );
-#else
- asm ("mov $10, %eax\n\t"
- "mov $9, %edx\n\t"
- "bndmk (%eax,%edx), %bnd0\n\t"
- "mov $20, %eax\n\t"
- "mov $9, %edx\n\t"
- "bndmk (%eax,%edx), %bnd1\n\t"
- "mov $30, %eax\n\t"
- "mov $9, %edx\n\t"
- "bndmk (%eax,%edx), %bnd2\n\t"
- "mov $40, %eax\n\t"
- "mov $9, %edx\n\t"
- "bndmk (%eax,%edx), %bnd3\n\t"
- "bndstx %bnd3, (%eax)\n\t"
- "nop\n\t"
- );
-#endif
- asm ("nop\n\t"); /* break here. */
-
- return 0;
-}
diff --git a/gdb/testsuite/gdb.arch/i386-mpx.exp b/gdb/testsuite/gdb.arch/i386-mpx.exp
deleted file mode 100644
index 9d71feb..0000000
--- a/gdb/testsuite/gdb.arch/i386-mpx.exp
+++ /dev/null
@@ -1,123 +0,0 @@
-# Copyright 2013-2024 Free Software Foundation, Inc.
-#
-# Contributed by Intel Corp. <walfred.tedeschi@intel.com>
-#
-# 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_any_target i?86-*-* x86_64-*-*}
-
-standard_testfile
-
-require {is_any_target i?86-*-* x86_64-*-*}
-
-require supports_mpx_check_pointer_bounds have_mpx
-
-set comp_flags "-mmpx -fcheck-pointer-bounds -I${srcdir}/../nat/"
-
-if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
- [list debug nowarnings additional_flags=${comp_flags}]] } {
- return -1
-}
-
-if ![runto_main] {
- return -1
-}
-
-# Test bndcfg register and bndstatus at startup
-set test_string "\\\{raw = 0x\[0-9a-f\]+, config = \\\{base = \[0-9\]+,\
-reserved = \[0-9\]+, preserved = \[0-9\]+, enabled = \[0-9\]+\\\}\\\}"
-
-gdb_test "print \$bndcfgu" $test_string "bndcfgu formating"
-gdb_test "print \$bndcfgu.config.enabled" "= 1" "test if bndstatus is enabled"
-gdb_test "print \$bndstatus" "\\\{raw = 0x0, status = \\\{bde = 0, error = 0\\\}\\\}" \
- "bndstatus formating"
-gdb_test "print \$bndstatus.raw" "= \\\(void \\\*\\\) 0x0" "bndstatus is zero by startup"
-
-# Read values from pseudo registers.
-gdb_breakpoint [ gdb_get_line_number "break here" ]
-gdb_continue_to_breakpoint "break here" ".*break here.*"
-
-set test_string ".*\\\{lbound = 0xa, ubound = 0x13\\\}.*"
-gdb_test "info register bnd0" ".*bnd0$test_string" "pure bnd0 register"
-
-set test_string ".*\\\{lbound = 0x14, ubound = 0x1d\\\}.*"
-gdb_test "info register bnd1" ".*bnd1$test_string" "pure bnd1 register"
-
-set test_string ".*\\\{lbound = 0x1e, ubound = 0x27\\\}.*"
-gdb_test "info register bnd2" ".*bnd2$test_string" "pure bnd2 register"
-
-set test_string ".*\\\{lbound = 0x28, ubound = 0x31\\\}.*"
-gdb_test "info register bnd3" ".*bnd3$test_string" "pure bnd3 register"
-
-# Read value from registers bndrs.
-
-set test_string ".*\\\{lbound = 0xa, ubound_raw = 0x\[f\]+ec\\\}.*"
-gdb_test "info register bnd0raw" ".*bnd0$test_string" "pure bnd0r register"
-
-set test_string ".*\\\{lbound = 0x14, ubound_raw = 0x\[f\]+e2\\\}.*"
-gdb_test "info register bnd1raw" ".*bnd1$test_string" "pure bnd1r register"
-
-set test_string ".*\\\{lbound = 0x1e, ubound_raw = 0x\[f\]+d8\\\}.*"
-gdb_test "info register bnd2raw" ".*bnd2$test_string" "pure bnd2r register"
-
-set test_string ".*\\\{lbound = 0x28, ubound_raw = 0x\[f\]+ce\\\}.*"
-gdb_test "info register bnd3raw" ".*bnd3$test_string" "pure bnd3r register"
-
-# Setting fields on bnds
-set test_string ".*\\\{lbound = 0xa, ubound = 0x400\\\}.*"
-gdb_test "print \$bnd0.ubound = 0x400" "= \\\(void \\\*\\\) 0x400" "set value for bnd0.ubound"
-gdb_test "print \$bnd0" "$test_string" "after setting bnd0.ubound"
-set test_string ".*\\\{lbound = 0xa, ubound_raw = 0x\[f\]+bff\\\}.*"
-gdb_test "print /x \$bnd0raw" "$test_string" "bnd0raw after set bnd0.ubound"
-
-set test_string ".*\\\{lbound = 0x1, ubound = 0x400\\\}.*"
-gdb_test "print \$bnd0.lbound = 0x1" "= \\\(void \\\*\\\) 0x1" "set value for bnd0.lbound"
-gdb_test "print \$bnd0" "$test_string" "after setting bnd0.lbound"
-set test_string ".*\\\{lbound = 0x1, ubound_raw = 0x\[f\]+bff\\\}.*"
-gdb_test "print /x \$bnd0raw" "$test_string" "bnd0raw after set bnd0.lbound"
-
-# Setting fields on bnd0raw.
-set test_string ".*\\\{lbound = 0x1, ubound_raw = 0x600\\\}.*"
-gdb_test "print /x \$bnd0raw.ubound_raw = 0x600" "= 0x600" "set value for bnd0raw.ubound"
-gdb_test "print /x \$bnd0raw" "$test_string" "bnd0raw after setting bnd0raw.ubound"
-set test_string ".*\\\{lbound = 0x1, ubound = 0x\[f\]+9ff\\\}.*"
-gdb_test "print /x \$bnd0" "$test_string" "bnd0 after set bnd0raw.ubound"
-
-set test_string ".*\\\{lbound = 0x100, ubound_raw = 0x600\\\}.*"
-gdb_test "print /x \$bnd0raw.lbound = 0x100" "= 0x100" "set value for bnd0raw.lbound"
-gdb_test "print /x \$bnd0raw" "$test_string" "bnd0raw after setting bnd0raw.lbound"
-set test_string ".*\\\{lbound = 0x100, ubound = 0x\[f\]+9ff\\\}.*"
-gdb_test "print /x \$bnd0" "$test_string" "bnd0 after set bnd0raw.lbound"
-
-# Set full value bnd raw
-set test_string ".*\\\{lbound = 0x10, ubound_raw = 0x\[f\]+cff\\\}.*"
-gdb_test "print /x \$bnd0raw = {0x10, ~0x300}" "$test_string" "set full value for bnd0raw"
-set test_string ".*\\\{lbound = 0x10, ubound = 0x300\\\}.*"
-gdb_test "print /x \$bnd0" "$test_string" "bnd0raw after setting full bnd0raw"
-
-# Set full value bnd
-set test_string ".*\\\{lbound = 0x10, ubound = 0x300\\\}.*"
-gdb_test "print /x \$bnd0 = {0x10, 0x300}" "$test_string" "set full value for bnd0"
-set test_string ".*\\\{lbound = 0x10, ubound_raw = 0x\[f\]+cff\\\}.*"
-gdb_test "print /x \$bnd0raw" "$test_string" "bnd0raw after setting full bnd0"
-
-# Test bndcfg register and bndstatus after a failure on bndstr
-gdb_test "print \$bndstatus.status.error" "= 2" "bndstatus error is 2\
-after a failure on allocating an entry"
-
-# Going to test the python extension for lenght.
-if { ![allow_python_tests] } { continue }
-# Verify if size is right
-set test_string ".*\\\: size 0x11.*"
-gdb_test "print /x \$bnd0 = {0x10, 0x20}" "$test_string" "verify size for bnd0"
diff --git a/gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp b/gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp
index 24c3129..ed595d4 100644
--- a/gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp
+++ b/gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp
@@ -54,7 +54,7 @@ proc insert_breakpoint {function expected_location} {
# If we managed to get the breakpoing address, then check that
# we inserted it at the expected location by examining the
# instruction at that address (we're not interested in the insn
- # itself, but rather at the address printed at the begining of
+ # itself, but rather at the address printed at the beginning of
# the instruction).
if {$address != ""} {
gdb_test "x /i $address" \
diff --git a/gdb/testsuite/gdb.arch/ppc64-break-on-_exit.exp b/gdb/testsuite/gdb.arch/ppc64-break-on-_exit.exp
index d60f63e..f91bebe 100644
--- a/gdb/testsuite/gdb.arch/ppc64-break-on-_exit.exp
+++ b/gdb/testsuite/gdb.arch/ppc64-break-on-_exit.exp
@@ -18,7 +18,7 @@
# if the breakpoint is set past the syscall due to faulty prologue skipping,
# the breakpoint will not trigger.
#
-# In particular, we're trying to excercise the instruction analysis
+# In particular, we're trying to exercise the instruction analysis
# functionality of prologue skipping. If non-minimal symbols are
# read, then that functionality might not be used because f.i.
# line-info is used instead. So, we use nodebug.
diff --git a/gdb/testsuite/gdb.arch/riscv-tdesc-loading.exp b/gdb/testsuite/gdb.arch/riscv-tdesc-loading.exp
index 0e009b4..1cf9848 100644
--- a/gdb/testsuite/gdb.arch/riscv-tdesc-loading.exp
+++ b/gdb/testsuite/gdb.arch/riscv-tdesc-loading.exp
@@ -29,7 +29,7 @@ foreach filename [lsort [glob $srcdir/$subdir/riscv-tdesc-loading-*.xml]] {
}
# Currently it is expected that all of the target descriptions in
- # this test will load successfully, so we expect no additonal
+ # this test will load successfully, so we expect no additional
# output from GDB.
gdb_test_no_output "set tdesc filename $test_path" \
"check [file tail $filename]"
diff --git a/gdb/testsuite/gdb.arch/riscv-tdesc-regs.exp b/gdb/testsuite/gdb.arch/riscv-tdesc-regs.exp
index bd4ba38..58859d1 100644
--- a/gdb/testsuite/gdb.arch/riscv-tdesc-regs.exp
+++ b/gdb/testsuite/gdb.arch/riscv-tdesc-regs.exp
@@ -156,17 +156,5 @@ gdb_test_no_output "set tdesc filename $remote_file" \
"load the target description that lacks fflags and frm"
foreach reg {fflags frm} {
- gdb_test_multiple "info registers $reg" "" {
- -re "^info registers $reg\r\n" {
- exp_continue
- }
-
- -wrap -re "^Invalid register `$reg`" {
- fail $gdb_test_name
- }
-
- -wrap -re "^$reg\\s+\[^\r\n\]+" {
- pass $gdb_test_name
- }
- }
+ gdb_test "info registers $reg" "^$reg\\s+\[^\r\n\]+"
}
diff --git a/gdb/testsuite/gdb.arch/skip-prologue.c b/gdb/testsuite/gdb.arch/skip-prologue.c
new file mode 100644
index 0000000..08ceacb
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/skip-prologue.c
@@ -0,0 +1,54 @@
+/* Copyright 2024 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/>. */
+
+void
+f1 (void)
+{
+ asm ("f1_prologue_end: .globl f1_prologue_end");
+}
+
+int
+f2 (int a)
+{
+ asm ("f2_prologue_end: .globl f2_prologue_end");
+ return a;
+}
+
+void
+f3 (void)
+{
+ asm ("f3_prologue_end: .globl f3_prologue_end");
+ f1 ();
+}
+
+int
+f4 (int a)
+{
+ asm ("f4_prologue_end: .globl f4_prologue_end");
+ return f2 (a);
+}
+
+int
+main (void)
+{
+ f1 ();
+ f2 (0);
+ f3 ();
+ f4 (0);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/skip-prologue.exp b/gdb/testsuite/gdb.arch/skip-prologue.exp
new file mode 100644
index 0000000..89d2225
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/skip-prologue.exp
@@ -0,0 +1,76 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test-case that checks architecture-specific prologue analyzers.
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
+ {nodebug}] } {
+ return -1
+}
+
+proc do_test { f } {
+ set bp_addr ""
+ gdb_test_multiple "break $f" "" {
+ -re -wrap "Breakpoint $::decimal at ($::hex)" {
+ set bp_addr $expect_out(1,string)
+ pass $gdb_test_name
+ }
+ }
+
+ if { $bp_addr == "" } {
+ return
+ }
+
+ set prologue_end_addr ""
+ gdb_test_multiple "p /x &${f}_prologue_end" "" {
+ -re -wrap " = ($::hex)" {
+ set prologue_end_addr $expect_out(1,string)
+ pass $gdb_test_name
+ }
+ }
+
+ if { $prologue_end_addr == "" } {
+ return
+ }
+
+ set test {$bp_addr == $prologue_end_addr}
+ if { [expr $test] } {
+ pass $test
+ } elseif { $bp_addr < $prologue_end_addr } {
+ # We'll allow this. For instance, amd64 has a prologue
+ # analyzer that doesn't skip the 3rd instruction here, which saves an
+ # argument register to stack:
+ #
+ # 00000000004004ae <f2>:
+ # 4004ae: 55 push %rbp
+ # 4004af: 48 89 e5 mov %rsp,%rbp
+ # 4004b2: 89 7d fc mov %edi,-0x4(%rbp)
+ # 00000000004004b5 <f2_prologue_end>:
+ #
+ pass "$test (skipped less than possible)"
+ } elseif { $bp_addr > $prologue_end_addr } {
+ fail "$test (skipped too much)"
+ } else {
+ fail "$test"
+ }
+}
+
+foreach f { f1 f2 f3 f4 } {
+ with_test_prefix $f {
+ do_test $f
+ }
+}
diff --git a/gdb/testsuite/gdb.arch/sparc64-adi.c b/gdb/testsuite/gdb.arch/sparc64-adi.c
index aee5aca..97f6a99 100644
--- a/gdb/testsuite/gdb.arch/sparc64-adi.c
+++ b/gdb/testsuite/gdb.arch/sparc64-adi.c
@@ -31,7 +31,6 @@
#include <string.h>
#include <signal.h>
#include <sys/shm.h>
-#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
diff --git a/gdb/testsuite/gdb.base/assign.exp b/gdb/testsuite/gdb.base/assign.exp
index 675ded4..38c2b2e 100644
--- a/gdb/testsuite/gdb.base/assign.exp
+++ b/gdb/testsuite/gdb.base/assign.exp
@@ -60,7 +60,7 @@ gdb_test_multiple "print v_int+=57" "v_int+=57" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (2)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 2"
gdb_test_multiple "print v_int-=57" "v_int-=57" {
-re " = -51.*$gdb_prompt $" {
@@ -68,7 +68,7 @@ gdb_test_multiple "print v_int-=57" "v_int-=57" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (3)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 3"
gdb_test_multiple "print v_int*=5" "v_int*=5" {
-re " = 30.*$gdb_prompt $" {
@@ -76,7 +76,7 @@ gdb_test_multiple "print v_int*=5" "v_int*=5" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (4)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 4"
gdb_test_multiple "print v_int/=4" "v_int/=4" {
-re " = 1.*$gdb_prompt $" {
@@ -84,7 +84,7 @@ gdb_test_multiple "print v_int/=4" "v_int/=4" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (5)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 5"
gdb_test_multiple "print v_int%=4" "v_int%=4" {
-re " = 2.*$gdb_prompt $" {
@@ -92,7 +92,7 @@ gdb_test_multiple "print v_int%=4" "v_int%=4" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (6)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 6"
gdb_test_multiple "print v_int+=v_char" "v_int+=char" {
-re " = 71.*$gdb_prompt $" {
@@ -100,7 +100,7 @@ gdb_test_multiple "print v_int+=v_char" "v_int+=char" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (7)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 7"
gdb_test_multiple "print v_int+=v_signed_char" "v_int+=signed_char" {
-re " = 72.*$gdb_prompt $" {
@@ -108,7 +108,7 @@ gdb_test_multiple "print v_int+=v_signed_char" "v_int+=signed_char" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (8)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 8"
gdb_test_multiple "print v_int+=v_unsigned_char" "v_int+=unsigned_char" {
-re " = 73.*$gdb_prompt $" {
@@ -116,7 +116,7 @@ gdb_test_multiple "print v_int+=v_unsigned_char" "v_int+=unsigned_char" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (9)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 9"
gdb_test_multiple "print v_int+=v_short" "v_int+=short" {
-re " = 9.*$gdb_prompt $" {
@@ -124,7 +124,7 @@ gdb_test_multiple "print v_int+=v_short" "v_int+=short" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (10)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 10"
gdb_test_multiple "print v_int+=v_signed_short" "v_int+=signed_short" {
-re " = 10.*$gdb_prompt $" {
@@ -132,7 +132,7 @@ gdb_test_multiple "print v_int+=v_signed_short" "v_int+=signed_short" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (11)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 11"
gdb_test_multiple "print v_int+=v_unsigned_short" "v_int=+unsigned_short" {
-re " = 11.*$gdb_prompt $" {
@@ -140,7 +140,7 @@ gdb_test_multiple "print v_int+=v_unsigned_short" "v_int=+unsigned_short" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (12)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 12"
gdb_test_multiple "print v_int+=v_signed_int" "v_int+=signed_int" {
-re " = 13.*$gdb_prompt $" {
@@ -148,7 +148,7 @@ gdb_test_multiple "print v_int+=v_signed_int" "v_int+=signed_int" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (13)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 13"
gdb_test_multiple "print v_int+=v_unsigned_int" "v_int+=unsigned_int" {
-re " = 14.*$gdb_prompt $" {
@@ -156,7 +156,7 @@ gdb_test_multiple "print v_int+=v_unsigned_int" "v_int+=unsigned_int" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (14)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 14"
gdb_test_multiple "print v_int+=v_long" "v_int+=long" {
-re " = 15.*$gdb_prompt $" {
@@ -164,7 +164,7 @@ gdb_test_multiple "print v_int+=v_long" "v_int+=long" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (15)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 15"
gdb_test_multiple "print v_int+=v_signed_long" "v_int+=signed_long" {
-re " = 16.*$gdb_prompt $" {
@@ -172,7 +172,7 @@ gdb_test_multiple "print v_int+=v_signed_long" "v_int+=signed_long" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (16)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 16"
gdb_test_multiple "print v_int+=v_unsigned_long" "v_int+=unsigned_long" {
-re " = 17.*$gdb_prompt $" {
@@ -180,7 +180,7 @@ gdb_test_multiple "print v_int+=v_unsigned_long" "v_int+=unsigned_long" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (17)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 17"
gdb_test_multiple "print v_int+=v_float" "v_int+=v_float" {
-re " = 106.*$gdb_prompt $" {
@@ -188,7 +188,7 @@ gdb_test_multiple "print v_int+=v_float" "v_int+=v_float" {
}
}
-gdb_test_no_output "set variable v_int = 6" "set v_int to 6 (18)"
+gdb_test_no_output "set variable v_int = 6" "set v_int to 6, 18"
gdb_test_multiple "print v_int+=v_double" "v_int+=double" {
-re " = 206.*$gdb_prompt $" {
diff --git a/gdb/testsuite/gdb.base/attach-deleted-exec.exp b/gdb/testsuite/gdb.base/attach-deleted-exec.exp
index 3e31c36..1196115 100644
--- a/gdb/testsuite/gdb.base/attach-deleted-exec.exp
+++ b/gdb/testsuite/gdb.base/attach-deleted-exec.exp
@@ -45,9 +45,27 @@ clean_restart
# Attach. GDB should spot that the executable is gone and fallback to
# use /proc/PID/exe.
-gdb_test "attach $testpid" \
- "Attaching to process $decimal\r\nReading symbols from /proc/${testpid}/exe\\.\\.\\..*" \
- "attach to process with deleted executable"
+set test "attach to process with deleted executable"
+set re \
+ [multi_line \
+ "Attaching to process $decimal" \
+ "Reading symbols from (\[^\r\n\]+)[string_to_regexp ...]" \
+ ".*"]
+set filename ""
+gdb_test_multiple "attach $testpid" $test {
+ -re -wrap $re {
+ set filename $expect_out(1,string)
+ pass $gdb_test_name
+ }
+}
+
+set test "filename /proc/PID/exe"
+set re_nfs \[^\r\n\]+[string_to_regexp /.nfs]\[^\r\n\]+
+if { [regexp $re_nfs $filename] } {
+ unsupported $test
+} else {
+ gdb_assert { [string equal $filename /proc/${testpid}/exe] } $test
+}
# Cleanup.
kill_wait_spawned_process $test_spawn_id
diff --git a/gdb/testsuite/gdb.base/batch-exit-status.exp b/gdb/testsuite/gdb.base/batch-exit-status.exp
index 3721fd5..5151464 100644
--- a/gdb/testsuite/gdb.base/batch-exit-status.exp
+++ b/gdb/testsuite/gdb.base/batch-exit-status.exp
@@ -92,5 +92,5 @@ test_exit_status 1 "-batch -x $good_commands -ex \"set not-a-thing 4\"" \
set test "No such file or directory"
set no_such_re ": $test\\."
test_exit_status 1 "-batch \"\"" "1x: $test" ^[multi_line $no_such_re ""]$
-test_exit_status 1 "-batch \"\" \"\"" "2x: $test" \
- ^[multi_line $no_such_re $no_such_re ""]$
+test_exit_status 1 "-batch \"\" \"\"" "$test and No core file specified" \
+ ^[multi_line $no_such_re "No core file specified\\." ""]$
diff --git a/gdb/testsuite/gdb.base/bitfields.exp b/gdb/testsuite/gdb.base/bitfields.exp
index ce420fa..6954a35 100644
--- a/gdb/testsuite/gdb.base/bitfields.exp
+++ b/gdb/testsuite/gdb.base/bitfields.exp
@@ -45,23 +45,23 @@ proc bitfield_uniqueness {} {
# treat it correctly as a signed 1bit field (values 0 or -1) while
# printing its value does not cause a spurious failure. We do the
# signedness preservation test later.
- gdb_test "print flags" ".*uc = 0 .*, s1 = (1|-1), u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness (s1)"
+ gdb_test "print flags" ".*uc = 0 .*, s1 = (1|-1), u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness, s1"
gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #2"
- gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 1, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness (u1)"
+ gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 1, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness, u1"
gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #3"
- gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 1, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness (s2)"
+ gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 1, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness, s2"
gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #4"
- gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 1, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness (u2)"
+ gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 1, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness, u2"
gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #5"
- gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 1, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness (s3)"
+ gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 1, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness, s3"
gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #6"
- gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 1, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness (u3)"
+ gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 1, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness, u3"
gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #7"
- gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 1, u9 = 0, sc = 0.*" "bitfield uniqueness (s9)"
+ gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 1, u9 = 0, sc = 0.*" "bitfield uniqueness, s9"
gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #8"
- gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 1, sc = 0.*" "bitfield uniqueness (u9)"
+ gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 1, sc = 0.*" "bitfield uniqueness, u9"
gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #9"
- gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 1.*" "bitfield uniqueness (sc)"
+ gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 1.*" "bitfield uniqueness, sc"
}
diff --git a/gdb/testsuite/gdb.base/bp-cond-failure.c b/gdb/testsuite/gdb.base/bp-cond-failure.c
index ffab098..b742139 100644
--- a/gdb/testsuite/gdb.base/bp-cond-failure.c
+++ b/gdb/testsuite/gdb.base/bp-cond-failure.c
@@ -15,8 +15,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/>. */
-static inline int __attribute__((__always_inline__))
-foo ()
+static int
+foo (int x)
+{
+ return 0;
+}
+
+static int
+foo (char c)
{
return 0; /* Multi-location breakpoint here. */
}
@@ -24,7 +30,7 @@ foo ()
static int __attribute__((noinline))
bar ()
{
- int res = foo (); /* Single-location breakpoint here. */
+ int res = foo ('1'); /* Single-location breakpoint here. */
return res;
}
@@ -34,7 +40,7 @@ main ()
{
int res = bar ();
- res = foo ();
+ res = foo (1);
return res;
}
diff --git a/gdb/testsuite/gdb.base/bp-cond-failure.exp b/gdb/testsuite/gdb.base/bp-cond-failure.exp
index a82cedd..b4c046c 100644
--- a/gdb/testsuite/gdb.base/bp-cond-failure.exp
+++ b/gdb/testsuite/gdb.base/bp-cond-failure.exp
@@ -27,7 +27,7 @@
standard_testfile
if { [prepare_for_testing "failed to prepare" ${binfile} "${srcfile}" \
- {debug}] == -1 } {
+ {debug c++}] == -1 } {
return
}
@@ -44,7 +44,7 @@ if { [is_address_zero_readable] } {
return
}
-proc run_test { cond_eval access_type lineno nloc } {
+proc run_test { cond_eval access_type bpexpr nloc } {
clean_restart ${::binfile}
if { ![runto_main] } {
@@ -56,23 +56,37 @@ proc run_test { cond_eval access_type lineno nloc } {
}
# Setup the conditional breakpoint and record its number.
- gdb_breakpoint "${::srcfile}:${lineno} if (*(${access_type} *) 0) == 0"
+ gdb_breakpoint "${bpexpr} if (*(${access_type} *) 0) == 0"
+
+ # This test aims to test that GDB displays the correct breakpoint number
+ # and location when there is an error testing a breakpoint condition,
+ # so it is important to hardcode the breakpoint number into the regex,
+ # along with the location, if applicable.
set bp_num [get_integer_valueof "\$bpnum" "*UNKNOWN*"]
if { $nloc > 1 } {
- set bp_num_pattern "${bp_num}.1"
+ # We hardcode location 2 because, for some reason, Clang will always
+ # order the debug information so we hit the second location. For
+ # simplicity the .c is ordered in such a way that GCC will also order
+ # the debug info to have us land on location 2.
+ gdb_test "continue" \
+ [multi_line \
+ "Continuing\\." \
+ "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\]+" \
+ "${::decimal}\\s+\[^\r\n\]+ breakpoint here\\. \[^\r\n\]+"]
} else {
- set bp_num_pattern "${bp_num}"
+ gdb_test "continue" \
+ [multi_line \
+ "Continuing\\." \
+ "Error in testing condition for breakpoint ${bp_num}:" \
+ "Cannot access memory at address 0x0" \
+ "" \
+ "Breakpoint ${bp_num}, bar \\(\\) at \[^\r\n\]+:\[0-9\]+" \
+ "${::decimal}\\s+\[^\r\n\]+ breakpoint here\\. \[^\r\n\]+"]
}
-
- gdb_test "continue" \
- [multi_line \
- "Continuing\\." \
- "Error in testing condition for breakpoint ${bp_num_pattern}:" \
- "Cannot access memory at address 0x0" \
- "" \
- "Breakpoint ${bp_num_pattern}, \(foo\|bar\) \\(\\) at \[^\r\n\]+:${lineno}" \
- "${::decimal}\\s+\[^\r\n\]+ breakpoint here\\. \[^\r\n\]+"]
}
# If we're using a remote target then conditions could be evaulated
@@ -101,7 +115,7 @@ gdb_test_multiple "show breakpoint condition-evaluation" "" {
}
# Where the breakpoint will be placed.
-set bp_line_multi_loc [gdb_get_line_number "Multi-location breakpoint here"]
+set bp_line_multi_loc "foo"
set bp_line_single_loc [gdb_get_line_number "Single-location breakpoint here"]
foreach_with_prefix access_type { "char" "short" "int" "long long" } {
@@ -110,7 +124,7 @@ foreach_with_prefix access_type { "char" "short" "int" "long long" } {
run_test $cond_eval $access_type $bp_line_multi_loc 2
}
with_test_prefix "single-loc" {
- run_test $cond_eval $access_type $bp_line_single_loc 1
+ run_test $cond_eval $access_type "${srcfile}:${bp_line_single_loc}" 1
}
}
}
diff --git a/gdb/testsuite/gdb.base/break-interp.exp b/gdb/testsuite/gdb.base/break-interp.exp
index 98f67ee..fd8afdd 100644
--- a/gdb/testsuite/gdb.base/break-interp.exp
+++ b/gdb/testsuite/gdb.base/break-interp.exp
@@ -495,26 +495,14 @@ proc test_ld {file ifmain trynosym displacement} {
if $ifmain {
reach $solib_bp run $displacement 3
- # Use two separate gdb_test_multiple statements to avoid timeouts due
- # to slow processing of wildcard capturing long output
- set test "info files"
set entrynohex ""
- set info_line [join [list \
- "\r\n" "\[\t\]" "0x\[0-9af\]+" " - " \
- "0x\[0-9af\]+" " @ " "0x\[0-9af\]+" \
- " is " "\[^\r\n\]+"] ""]
- gdb_test_multiple $test $test {
+ gdb_test_multiple "info files" "" -lbl {
-re "\r\n\[\t \]*Entry point:\[\t \]*0x(\[0-9a-f\]+)\r\n" {
set entrynohex $expect_out(1,string)
- gdb_test_multiple "" $test {
- -re "\r\n$gdb_prompt $" {
- pass $test
- }
- -re $info_line {
- # Avoid timeout with check-read1
- exp_continue
- }
- }
+ exp_continue
+ }
+ -re -wrap "" {
+ gdb_assert { ![string equal $entrynohex ""] } $gdb_test_name
}
}
diff --git a/gdb/testsuite/gdb.base/break-on-linker-gcd-function.exp b/gdb/testsuite/gdb.base/break-on-linker-gcd-function.exp
index 67afe4c..cf1596a 100644
--- a/gdb/testsuite/gdb.base/break-on-linker-gcd-function.exp
+++ b/gdb/testsuite/gdb.base/break-on-linker-gcd-function.exp
@@ -40,10 +40,13 @@ proc set_breakpoint_on_gcd_function {} {
# Single hex digit
set xd {[0-9a-f]}
- # This accepts e.g. "Breakpoint 1 at 0x40968a" (fixed GDB)
- # but rejects e.g. "Breakpoint 1 at 0x4" (broken GDB).
- gdb_test "b [gdb_get_line_number "gdb break here"]" \
- "Breakpoint \[0-9\] at 0x${xd}${xd}+: .*"
+ set lineno [gdb_get_line_number "gdb break here"]
+ gdb_test "set breakpoint pending on"
+ gdb_test "b $lineno" \
+ [multi_line \
+ "^No compiled code for line $lineno in the current file\\." \
+ "Breakpoint $::decimal \\($lineno\\) pending\\."] \
+ "break on line in garbage collected function"
}
set_breakpoint_on_gcd_function
diff --git a/gdb/testsuite/gdb.base/break.exp b/gdb/testsuite/gdb.base/break.exp
index cdb4c22..34ac219 100644
--- a/gdb/testsuite/gdb.base/break.exp
+++ b/gdb/testsuite/gdb.base/break.exp
@@ -476,9 +476,6 @@ proc_with_prefix test_no_break_on_catchpoint {} {
test_no_break_on_catchpoint
-# Verify that GDB responds gracefully when asked to set a breakpoint
-# on a nonexistent source line.
-
proc_with_prefix test_break_nonexistent_line {} {
clean_restart break
@@ -486,9 +483,11 @@ proc_with_prefix test_break_nonexistent_line {} {
return
}
+ # Verify that GDB responds gracefully when asked to set a
+ # breakpoint on a nonexistent source line.
gdb_test_no_output "set breakpoint pending off"
gdb_test "break 999" \
- "No line 999 in the current file." \
+ "^No compiled code for line 999 in the current file\\." \
"break on non-existent source line"
}
diff --git a/gdb/testsuite/gdb.base/build-id-seqno.c b/gdb/testsuite/gdb.base/build-id-seqno.c
new file mode 100644
index 0000000..e2119ba7
--- /dev/null
+++ b/gdb/testsuite/gdb.base/build-id-seqno.c
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+main (void)
+{
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/build-id-seqno.exp b/gdb/testsuite/gdb.base/build-id-seqno.exp
new file mode 100644
index 0000000..9566933
--- /dev/null
+++ b/gdb/testsuite/gdb.base/build-id-seqno.exp
@@ -0,0 +1,134 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2024 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Setup a .build-id/ based debug directory containing multiple entries
+# for the same build-id, with each entry given a different sequence
+# number.
+#
+# Ensure that GDB will scan over broken symlinks for the same build-id
+# (but different sequence number) to find later working symlinks.
+#
+# This test only places debug information on the host, so it is always
+# local to GDB.
+
+require {!is_remote host}
+
+standard_testfile
+
+if {[build_executable "failed to prepare" $testfile $srcfile \
+ {debug build-id}] == -1} {
+ return -1
+}
+
+# Split out BINFILE.debug. Remove debug from BINFILE.
+if {[gdb_gnu_strip_debug $binfile] != 0} {
+ return -1
+}
+
+# Get the '.build-id/xx/xxx...xxx' part of the filename.
+set build_id_filename [build_id_debug_filename_get $binfile]
+
+# Hide (rename) BINFILE.debug, this should ensure GDB can't find it
+# directly but needs to look for the build-id based file in the debug
+# directory.
+set hidden_debuginfo [standard_output_file "hidden_$testfile.debug"]
+remote_exec build "mv ${binfile}.debug $hidden_debuginfo"
+
+# A filename that doesn't exist. Some symlinks will point at this
+# file.
+set missing_debuginfo [host_standard_output_file "missing_debuginfo"]
+
+# Create the debug directory, and the .build-id directory structure
+# within it.
+set debugdir [host_standard_output_file "debug"]
+remote_exec host "mkdir -p $debugdir/[file dirname $build_id_filename]"
+
+set host_hidden_debuginfo [gdb_remote_download host $hidden_debuginfo]
+remote_exec host "ln -fs $host_hidden_debuginfo $debugdir/$build_id_filename"
+
+# Start GDB and load global BINFILE. If FIND_DEBUGINFO is true then
+# we expect GDB to find the debug information matching BINFILE,
+# otherwise, we expect GDB not to find the debug information.
+proc load_binfile_check_debug_is_found { find_debuginfo testname } {
+ with_test_prefix "$testname" {
+ clean_restart
+
+ gdb_test_no_output "set debug-file-directory $::debugdir" \
+ "set debug-file-directory"
+
+ gdb_file_cmd $::binfile
+
+ if { $find_debuginfo } {
+ gdb_assert { [regexp [string_to_regexp \
+ "Reading symbols from $::hidden_debuginfo..."] \
+ $::gdb_file_cmd_msg] } \
+ "debuginfo was read via build-id"
+ } else {
+ gdb_assert { [regexp "\\(No debugging symbols found in \[^\r\n\]+/$::testfile\\)" \
+ $::gdb_file_cmd_msg] } \
+ }
+ }
+}
+
+# Return a copy of FILENAME, which should end '.debug', with NUMBER
+# added, e.g. add_seqno 1 "foo.debug" --> "foo.1.debug".
+proc add_seqno { number filename } {
+ return [regsub "\.debug\$" $filename ".${number}.debug"]
+}
+
+load_binfile_check_debug_is_found true \
+ "find debuginfo with a single build-id file"
+
+remote_exec host "ln -fs $host_hidden_debuginfo \
+ $debugdir/[add_seqno 1 $build_id_filename]"
+remote_exec host "ln -fs $host_hidden_debuginfo \
+ $debugdir/[add_seqno 2 $build_id_filename]"
+remote_exec host "ln -fs $host_hidden_debuginfo \
+ $debugdir/[add_seqno 3 $build_id_filename]"
+
+load_binfile_check_debug_is_found true \
+ "find debuginfo with 4 build-id files"
+
+remote_exec host "ln -fs $missing_debuginfo $debugdir/$build_id_filename"
+
+load_binfile_check_debug_is_found true \
+ "find debuginfo, first build-id file is bad"
+
+remote_exec host "ln -fs $missing_debuginfo \
+ $debugdir/[add_seqno 1 $build_id_filename]"
+remote_exec host "ln -fs $missing_debuginfo \
+ $debugdir/[add_seqno 3 $build_id_filename]"
+
+load_binfile_check_debug_is_found true \
+ "find debuginfo, first 2 build-id files are bad"
+
+remote_exec host "ln -fs $missing_debuginfo \
+ $debugdir/[add_seqno 2 $build_id_filename]"
+
+load_binfile_check_debug_is_found false \
+ "cannot find debuginfo, all build-id files are bad"
+
+remote_exec host "ln -fs $host_hidden_debuginfo \
+ $debugdir/[add_seqno 3 $build_id_filename]"
+
+load_binfile_check_debug_is_found true \
+ "find debuginfo, last build-id file is good"
+
+remote_exec host "rm -f $debugdir/[add_seqno 1 $build_id_filename]"
+
+load_binfile_check_debug_is_found false \
+ "cannot find debuginfo, file with seqno 1 is missing"
diff --git a/gdb/testsuite/gdb.base/call-sc.exp b/gdb/testsuite/gdb.base/call-sc.exp
index c485c9b..91a4e5b 100644
--- a/gdb/testsuite/gdb.base/call-sc.exp
+++ b/gdb/testsuite/gdb.base/call-sc.exp
@@ -184,7 +184,7 @@ proc test_scalar_returns { } {
# known, both failed to print a final "source and line" and misplaced
# the frame ("No frame").
- # The test is writen so that it only reports one FAIL/PASS for the
+ # The test is written so that it only reports one FAIL/PASS for the
# entire operation. The value returned is checked further down.
# "return_value_unknown", if non-empty, records why GDB realised
# that it didn't know where the return value was.
diff --git a/gdb/testsuite/gdb.base/catch-syscall.exp b/gdb/testsuite/gdb.base/catch-syscall.exp
index 075498a..2e20b8f 100644
--- a/gdb/testsuite/gdb.base/catch-syscall.exp
+++ b/gdb/testsuite/gdb.base/catch-syscall.exp
@@ -19,39 +19,18 @@
# It was written by Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>
# on September/2008.
+require supports_catch_syscall
+
standard_testfile
if { [prepare_for_testing "failed to prepare" $testfile ${testfile}.c] } {
return -1
}
-# Check target supports catch syscall or not.
if {![runto_main]} {
return
}
-set test "catch syscall"
-gdb_test_multiple $test $test {
- -re "The feature \'catch syscall\' is not supported.*\r\n$gdb_prompt $" {
- unsupported "catch syscall isn't supported"
- return -1
- }
- -re ".*$gdb_prompt $" {
- pass $test
- }
-}
-
-set test "check catch syscall"
-gdb_test_multiple "continue" $test {
- -re ".*Your system does not support this type\r\nof catchpoint.*$gdb_prompt $" {
- unsupported "catch syscall isn't supported"
- return -1
- }
- -re ".*Catchpoint.*$gdb_prompt $" {
- pass $test
- }
-}
-
# Test-case for PR27313. Verify that negative syscall numbers are refused.
gdb_test "catch syscall -1" "Unknown syscall number '-1'\\."
@@ -171,7 +150,7 @@ proc insert_catch_syscall_with_arg { syscall } {
global decimal
# Trying to set the catchpoint
- set thistest "catch syscall with arguments ($syscall)"
+ set thistest "catch syscall with arguments, $syscall"
gdb_test "catch syscall $syscall" "Catchpoint $decimal \\(syscall \'?${syscall}\'?( \[${decimal}\])?\\)" $thistest
check_info_bp_specific_syscall $syscall
diff --git a/gdb/testsuite/gdb.base/checkpoint.exp b/gdb/testsuite/gdb.base/checkpoint.exp
index f87f528..31b5a13 100644
--- a/gdb/testsuite/gdb.base/checkpoint.exp
+++ b/gdb/testsuite/gdb.base/checkpoint.exp
@@ -295,30 +295,48 @@ clean_restart $binfile
runto_main
gdb_breakpoint $break1_loc
-gdb_test "commands\nsilent\nif (lines % 2)\ncheckpoint\nend\n continue\nend" \
+set cmd \
+ [join \
+ [list \
+ "commands" \
+ "if (lines % 2)" \
+ " checkpoint" \
+ "else" \
+ " continue" \
+ "end" \
+ "end"] \
+ "\n"]
+gdb_test $cmd \
"" \
"set checkpoint breakpoint"
-set prev_timeout $timeout
-set timeout [expr $timeout + 120]
-verbose "Timeout now $timeout sec."
-
-gdb_breakpoint $break2_loc
-gdb_test "continue" "breakpoint 2.*" "break2 with many checkpoints"
+set nr_ok 0
+for {set iter 0} {$iter < 600} {incr iter} {
+ set ok 0
+ gdb_test_multiple "continue" "" {
+ -re -wrap "breakpoint 1.*" {
+ set ok 1
+ }
+ -re -wrap "" {
+ }
+ }
+ if { $ok } {
+ incr nr_ok
+ } else {
+ break
+ }
+}
+gdb_assert { $nr_ok == 600 } "break1 with many checkpoints"
set count 0
set msg "info checkpoints with at least 600 checkpoints"
gdb_test_multiple "info checkpoints" $msg {
- -re " $decimal process \[^\r\]*\r\n" {
+ -re "\r\n $decimal process \[^\r\]*" {
incr count
exp_continue
}
- -re "$gdb_prompt $" {
- if { $count >= 600 } {
- pass $msg
- } else {
- fail $msg
- }
+ -re -wrap "" {
+ gdb_assert { $count == 600 } $gdb_test_name
}
}
@@ -329,10 +347,6 @@ gdb_test_multiple "info checkpoints" $msg {
gdb_test "kill" "" "kill all one with many checkpoints" \
"Kill the program being debugged.*y or n. $" "y"
-# Restore old timeout
-set timeout $prev_timeout
-verbose "Timeout now $timeout sec."
-
#
# Finished: cleanup
#
diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
index 3dbdd0f..57b4d1c 100644
--- a/gdb/testsuite/gdb.base/completion.exp
+++ b/gdb/testsuite/gdb.base/completion.exp
@@ -145,7 +145,7 @@ append regs_output "\n"
append regs_output [capture_command_output "mt print user-registers" \
".*Name.*Nr\[^\n]*\n"]
set all_regs {}
-foreach {- reg} [regexp -all -inline -line {^\s+(\w+)} $regs_output] {
+foreach {- reg} [regexp -all -inline -line {^\s*(\w+)} $regs_output] {
lappend all_regs $reg
}
@@ -543,10 +543,10 @@ gdb_test_multiple "" "$test" {
# Eat the prompt
gdb_expect {
-re "$gdb_prompt " {
- pass "$test (eat prompt)"
+ pass "$test, eat prompt"
}
timeout {
- fail "(timeout) $test (eat prompt)"
+ fail "$test, eat prompt (timeout)"
}
}
@@ -572,10 +572,10 @@ gdb_test_multiple "" "$test" {
# Eat the prompt
gdb_expect {
-re "$gdb_prompt " {
- pass "$test (eat prompt)"
+ pass "$test, eat prompt"
}
timeout {
- fail "(timeout) $test (eat prompt)"
+ fail "$test, eat prompt (timeout)"
}
}
diff --git a/gdb/testsuite/gdb.base/complex-parts.exp b/gdb/testsuite/gdb.base/complex-parts.exp
index e678cfc..40f14f4 100644
--- a/gdb/testsuite/gdb.base/complex-parts.exp
+++ b/gdb/testsuite/gdb.base/complex-parts.exp
@@ -23,12 +23,13 @@ if {![runto_main]} {
return 0
}
-gdb_breakpoint [gdb_get_line_number "Break Here"]
-gdb_continue_to_breakpoint "breakpt" ".* Break Here\\. .*"
+set marker " Break Here. "
+gdb_breakpoint [gdb_get_line_number $marker]
+gdb_continue_to_breakpoint "breakpt" ".*[string_to_regexp $marker].*"
-gdb_test "p z1" " = 1.5 \\+ 4.5i"
-gdb_test "p z2" " = 2.5 \\+ -5.5i"
-gdb_test "p z3" " = 3.5 \\+ 6.5i"
+gdb_test "p z1" [string_to_regexp " = 1.5 + 4.5i"]
+gdb_test "p z2" [string_to_regexp " = 2.5 + -5.5i"]
+gdb_test "p z3" [string_to_regexp " = 3.5 + 6.5i"]
# The following 3 tests are broken for Clang.
# More info at https://github.com/llvm/llvm-project/issues/52996.
@@ -40,59 +41,71 @@ if {[test_compiler_info clang-*-*]} { setup_xfail *-*-* }
gdb_test "ptype z3" " = complex long double"
with_test_prefix "double imaginary" {
- gdb_test "p \$_cimag (z1)" " = 4.5"
- gdb_test "ptype \$" " = double"
+ set expr {$_cimag (z1)}
+ gdb_test "p $expr" " = 4.5"
+ gdb_test {ptype $} " = double"
+ gdb_test "ptype $expr" " = double"
}
with_test_prefix "float imaginary" {
- gdb_test "p \$_cimag (z2)" " = -5.5"
- gdb_test "ptype \$" " = float"
+ set expr {$_cimag (z2)}
+ gdb_test "p $expr" " = -5.5"
+ gdb_test {ptype $} " = float"
+ gdb_test "ptype $expr" " = float"
}
with_test_prefix "long double imaginary" {
- gdb_test "p \$_cimag (z3)" " = 6.5"
- gdb_test "ptype \$" " = long double"
+ set expr {$_cimag (z3)}
+ gdb_test "p $expr" " = 6.5"
+ gdb_test {ptype $} " = long double"
+ gdb_test "ptype $expr" " = long double"
}
with_test_prefix "double real" {
- gdb_test "p \$_creal (z1)" " = 1.5"
- gdb_test "ptype \$" " = double"
+ set expr {$_creal (z1)}
+ gdb_test "p $expr" " = 1.5"
+ gdb_test {ptype $} " = double"
+ gdb_test "ptype $expr" " = double"
}
with_test_prefix "float real" {
- gdb_test "p \$_creal (z2)" " = 2.5"
- gdb_test "ptype \$" " = float"
+ set expr {$_creal (z2)}
+ gdb_test "p $expr" " = 2.5"
+ gdb_test {ptype $} " = float"
+ gdb_test "ptype $expr" " = float"
}
with_test_prefix "long double real" {
- gdb_test "p \$_creal (z3)" " = 3.5"
- gdb_test "ptype \$" " = long double"
+ set expr {$_creal (z3)}
+ gdb_test "p $expr" " = 3.5"
+ gdb_test {ptype $} " = long double"
+ gdb_test "ptype $expr" " = long double"
}
-gdb_test "p \$_cimag (d1)" "expected a complex number"
-gdb_test "p \$_cimag (f1)" "expected a complex number"
-gdb_test "p \$_cimag (i1)" "expected a complex number"
+gdb_test {p $_cimag (d1)} "expected a complex number"
+gdb_test {p $_cimag (f1)} "expected a complex number"
+gdb_test {p $_cimag (i1)} "expected a complex number"
-gdb_test "p \$_creal (d1)" "expected a complex number"
-gdb_test "p \$_creal (f1)" "expected a complex number"
-gdb_test "p \$_creal (i1)" "expected a complex number"
+gdb_test {p $_creal (d1)} "expected a complex number"
+gdb_test {p $_creal (f1)} "expected a complex number"
+gdb_test {p $_creal (i1)} "expected a complex number"
#
# General complex number tests.
#
-gdb_test "print 23 + 7i" " = 23 \\+ 7i"
-gdb_test "print 23.125f + 7i" " = 23.125 \\+ 7i"
-gdb_test "print 23 + 7.25fi" " = 23 \\+ 7.25i"
-gdb_test "print (23 + 7i) + (17 + 10i)" " = 40 \\+ 17i"
-gdb_test "print 23 + -7i" " = 23 \\+ -7i"
-gdb_test "print 23 - 7i" " = 23 \\+ -7i"
+gdb_test "print 23 + 7i" [string_to_regexp " = 23 + 7i"]
+gdb_test "print 23.125f + 7i" [string_to_regexp " = 23.125 + 7i"]
+gdb_test "print 23 + 7.25fi" [string_to_regexp " = 23 + 7.25i"]
+gdb_test "print (23 + 7i) + (17 + 10i)" [string_to_regexp " = 40 + 17i"]
+gdb_test "print 23 + -7i" [string_to_regexp " = 23 + -7i"]
+gdb_test "print 23 - 7i" [string_to_regexp " = 23 + -7i"]
-gdb_test "print -(23 + 7i)" " = -23 \\+ -7i"
-gdb_test "print +(23 + 7i)" " = 23 \\+ 7i"
-gdb_test "print ~(23 + 7i)" " = 23 \\+ -7i"
+gdb_test "print -(23 + 7i)" [string_to_regexp " = -23 + -7i"]
+gdb_test "print +(23 + 7i)" [string_to_regexp " = 23 + 7i"]
+gdb_test "print ~(23 + 7i)" [string_to_regexp " = 23 + -7i"]
-gdb_test "print (5 + 5i) * (2 + 2i)" " = 0 \\+ 20i"
+gdb_test "print (5 + 5i) * (2 + 2i)" [string_to_regexp " = 0 + 20i"]
gdb_test "print (5 + 7i) == (5 + 7i)" " = 1"
gdb_test "print (5 + 7i) == (8 + 7i)" " = 0"
@@ -101,14 +114,16 @@ gdb_test "print (5 + 7i) != (5 + 7i)" " = 0"
gdb_test "print (5 + 7i) != (8 + 7i)" " = 1"
gdb_test "print (5 + 7i) != (5 + 92i)" " = 1"
-gdb_test "print (20 - 4i) / (3 + 2i)" " = 4 \\+ -4i"
+gdb_test "print (20 - 4i) / (3 + 2i)" [string_to_regexp " = 4 + -4i"]
-gdb_test "print (_Complex int) 4" " = 4 \\+ 0i"
-gdb_test "print (_Complex float) 4.5" " = 4.5 \\+ 0i"
+gdb_test "print (_Complex int) 4" [string_to_regexp " = 4 + 0i"]
+gdb_test "print (_Complex float) 4.5" [string_to_regexp " = 4.5 + 0i"]
gdb_test "ptype __complex__ short" " = _Complex short"
-gdb_test "print (_Complex int) (23.75 + 8.88i)" " = 23 \\+ 8i"
+gdb_test "print (_Complex int) (23.75 + 8.88i)" [string_to_regexp " = 23 + 8i"]
-set re_reject_arg "Argument to complex arithmetic operation not supported\\."
+set re_reject_arg \
+ [string_to_regexp \
+ "Argument to complex arithmetic operation not supported."]
gdb_test "print (void *)0 + 5i" $re_reject_arg
gdb_test "print (_Decimal32)0 + 5i" $re_reject_arg
@@ -117,4 +132,4 @@ clean_restart
gdb_test_no_output "set language c++"
# C++ type tests.
-gdb_test "print (bool)1 + 1i" " = 1 \\+ 1i"
+gdb_test "print (bool)1 + 1i" [string_to_regexp "= 1 + 1i"]
diff --git a/gdb/testsuite/gdb.base/cond-expr.exp b/gdb/testsuite/gdb.base/cond-expr.exp
index 5956d68..67918cf 100644
--- a/gdb/testsuite/gdb.base/cond-expr.exp
+++ b/gdb/testsuite/gdb.base/cond-expr.exp
@@ -47,22 +47,22 @@ if {![runto_main]} {
}
gdb_test "print (2 ? 3 : 4)" "\[0-9\]* = 3" \
- "print value of cond expr (const true)"
+ "print value of cond expr, const true"
gdb_test "print (0 ? 3 : 4)" "\[0-9\]* = 4" \
- "print value of cond expr (const false)"
+ "print value of cond expr, const false"
gdb_test_no_output "set variable x=14" "set variable x=14"
gdb_test_no_output "set variable y=2" "set variable y=2"
gdb_test_no_output "set variable z=3" "set variable z=3"
gdb_test "print (x ? y : z)" "\[0-9\]* = 2" \
- "print value of cond expr (var true)"
+ "print value of cond expr, var true"
gdb_test_no_output "set variable x=0" "set variable x=0"
gdb_test "print (x ? y : z)" "\[0-9\]* = 3" \
- "print value of cond expr (var false)"
+ "print value of cond expr, var false"
gdb_test "whatis (0 ? 3 : 4)" "type = int" \
"print whatis of cond expr"
diff --git a/gdb/testsuite/gdb.base/condbreak.exp b/gdb/testsuite/gdb.base/condbreak.exp
index 65d19b3..3b619e4 100644
--- a/gdb/testsuite/gdb.base/condbreak.exp
+++ b/gdb/testsuite/gdb.base/condbreak.exp
@@ -179,6 +179,10 @@ gdb_test "break -q main if (1==1) thread 999" \
"Unknown thread 999\\."
gdb_test "break -q main thread 999 if (1==1)" \
"Unknown thread 999\\."
+gdb_test "break -q main if (1==1) thread 999 -force-condition" \
+ "Unknown thread 999\\."
+gdb_test "break -q main thread 999 if (1==1) -force-condition" \
+ "Unknown thread 999\\."
# Verify that both if and thread can be distinguished from a breakpoint
# address expression.
@@ -186,20 +190,71 @@ gdb_test "break *main if (1==1) thread 999" \
"Unknown thread 999\\."
gdb_test "break *main thread 999 if (1==1)" \
"Unknown thread 999\\."
+gdb_test "break *main if (1==1) thread 999 -force-condition" \
+ "Unknown thread 999\\."
+gdb_test "break *main thread 999 if (1==1) -force-condition" \
+ "Unknown thread 999\\."
# Similarly for task.
gdb_test "break *main if (1==1) task 999" \
"Unknown task 999\\."
gdb_test "break *main task 999 if (1==1)" \
"Unknown task 999\\."
+gdb_test "break *main if (1==1) task 999 -force-condition" \
+ "Unknown task 999\\."
+gdb_test "break *main task 999 if (1==1) -force-condition" \
+ "Unknown task 999\\."
-# GDB accepts abbreviations for "thread" and "task".
+# GDB accepts abbreviations for "thread", "task" and
+# "-force-condition", when these keywords appear after
+# the breakpoint condition.
gdb_test "break *main if (1==1) t 999" \
"Unknown thread 999\\."
gdb_test "break *main if (1==1) th 999" \
"Unknown thread 999\\."
gdb_test "break *main if (1==1) ta 999" \
"Unknown task 999\\."
+gdb_test "break *main if (1==1) t 999 -force" \
+ "Unknown thread 999\\."
+gdb_test "break *main if (1==1) th 999 -force" \
+ "Unknown thread 999\\."
+gdb_test "break *main if (1==1) ta 999 -force" \
+ "Unknown task 999\\."
+
+# Check the use of abbreviations before the condition. This works
+# because, when the location spec starts with '*' GDB is able to
+# figure out that the complete location is '*main'.
+gdb_test "break *main t 999 if (1==1)" \
+ "Unknown thread 999\\."
+gdb_test "break *main th 999 if (1==1)" \
+ "Unknown thread 999\\."
+gdb_test "break *main ta 999 if (1==1)" \
+ "Unknown task 999\\."
+gdb_test "break *main t 999 -force if (1==1)" \
+ "Unknown thread 999\\."
+gdb_test "break *main th 999 -force if (1==1)" \
+ "Unknown thread 999\\."
+gdb_test "break *main ta 999 -force if (1==1)" \
+ "Unknown task 999\\."
+
+# However, when the location spec doesn't start with '*' GDB relies on
+# the linespec parser to spot the keyword which marks the end of the
+# linespec, and this parser doesn't check for abbreviations.
+gdb_test "with breakpoint pending off -- break main t 999 if (1==1)" \
+ "Function \"main t 999\" not defined\\."
+gdb_test "with breakpoint pending off -- break main th 999 if (1==1)" \
+ "Function \"main th 999\" not defined\\."
+gdb_test "with breakpoint pending off -- break main ta 999 if (1==1)" \
+ "Function \"main ta 999\" not defined\\."
+
+# GDB does not treat a "-force-condition" flag that appears
+# immediately after the condition as the flag, but instead treats it
+# as " - force - condition", that is, subtraction of the symbol
+# "force" followed by subtraction of symbol "context". This is really
+# just a quirk of how this used to be implemented, and should maybe be
+# changed in the future. However, for now GDB retains this behaviour.
+gdb_test "break *main if (1==1) -force-condition" \
+ "No symbol \"force\" in current context\\."
set test "run until breakpoint at marker3"
gdb_test_multiple "continue" $test {
diff --git a/gdb/testsuite/gdb.base/coredump-filter-build-id.exp b/gdb/testsuite/gdb.base/coredump-filter-build-id.exp
index b62796f..cddacce 100644
--- a/gdb/testsuite/gdb.base/coredump-filter-build-id.exp
+++ b/gdb/testsuite/gdb.base/coredump-filter-build-id.exp
@@ -30,7 +30,7 @@ if { ![istarget *-*-linux*] } {
}
require is_x86_64_m64_target
-if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile {debug build-id}] } {
return -1
}
diff --git a/gdb/testsuite/gdb.base/corefile-buildid.exp b/gdb/testsuite/gdb.base/corefile-buildid.exp
index e1b9804..fc54cf2 100644
--- a/gdb/testsuite/gdb.base/corefile-buildid.exp
+++ b/gdb/testsuite/gdb.base/corefile-buildid.exp
@@ -268,12 +268,13 @@ proc do_corefile_buildid_tests {args} {
return
}
- # Grab the build-id from the binary, removing ".debug" from the end.
- set buildid [build_id_debug_filename_get $program_to_run]
+ # Get the build-id filename without ".debug" on the end. This
+ # will have the format: '.build-id/xx/xxxxx'
+ set buildid [build_id_debug_filename_get $program_to_run ""]
if {$buildid == ""} {
untested "binary has no build-id"
+ return
}
- regsub {\.debug$} $buildid {} buildid
verbose -log "build-id is $buildid"
locate_exec_from_core_build_id $corefile $buildid \
diff --git a/gdb/testsuite/gdb.base/corefile.exp b/gdb/testsuite/gdb.base/corefile.exp
index 28b723e..f4f102a 100644
--- a/gdb/testsuite/gdb.base/corefile.exp
+++ b/gdb/testsuite/gdb.base/corefile.exp
@@ -195,10 +195,49 @@ gdb_test "x/wx buf3" "$hex:\[ \t\]+0x00000000" \
# test reinit_frame_cache
gdb_load ${binfile}
-gdb_test "up" "#\[0-9\]* *(\[0-9xa-fH'\]* in)? .* \\(.*\\).*" "up (reinit)"
+gdb_test "up" "#\[0-9\]* *(\[0-9xa-fH'\]* in)? .* \\(.*\\).*" "up, reinit"
gdb_test "core" "No core file now."
+# Temporarily move coremmap.data out of the way and reload the core
+# file. We should still be able to read buf2 as the contents of this
+# are written into the core file. In contrast buf2ro should no longer
+# be readable as the contents of this region are not within the core
+# file, GDB relies on reading this from the coremmap.data file, which
+# can no longer be found.
+set coremmap_data_filename \
+ [standard_output_file coredir.[getpid]/coremmap.data]
+set coremmap_data_backup_filename \
+ [standard_output_file coredir.[getpid]/coremmap.data.backup]
+remote_exec host "mv ${coremmap_data_filename} \
+ ${coremmap_data_backup_filename}"
+
+clean_restart $binfile
+
+# Load the core file and check we get a warning about the
+# coremmap.data file being missing.
+gdb_test_multiple "core-file $corefile" "warn about coremmap.data missing" {
+ -re -wrap "warning: Can't open file \[^\r\n\]+/coremmap.data during file-backed mapping note processing\r\n.*" {
+ pass $gdb_test_name
+ }
+}
+
+# This xfail was just copied from earlier in the script where we also
+# read from buf2.
+setup_xfail "*-*-sunos*" "*-*-aix*"
+gdb_test "x/8bd buf2" \
+ ".*:.*0.*1.*2.*3.*4.*5.*6.*7.*" \
+ "accessing mmapped data in core file with coremmap.data removed"
+
+gdb_test "x/8bd buf2ro" \
+ "$hex\[^:\]*:\\s+Cannot access memory at address $hex" \
+ "accessing read-only mmapped data in core file with coremmap.data removed"
+
+# Restore the coremmap.data file so later tests don't give warnings
+# when the core file is reloaded.
+remote_exec host "mv ${coremmap_data_backup_filename} \
+ ${coremmap_data_filename}"
+
# Test that we can unload the core with the "detach" command.
proc_with_prefix corefile_detach {} {
diff --git a/gdb/testsuite/gdb.base/cursal.c b/gdb/testsuite/gdb.base/cursal.c
index 8dc713f..bc1e46f 100644
--- a/gdb/testsuite/gdb.base/cursal.c
+++ b/gdb/testsuite/gdb.base/cursal.c
@@ -31,7 +31,7 @@ func1 ()
int
main ()
-{
+{ /* main prologue */
int v0 = 0;
func1 ();
diff --git a/gdb/testsuite/gdb.base/cursal.exp b/gdb/testsuite/gdb.base/cursal.exp
index 3acced8..6c1fe38 100644
--- a/gdb/testsuite/gdb.base/cursal.exp
+++ b/gdb/testsuite/gdb.base/cursal.exp
@@ -25,9 +25,9 @@ clean_restart
gdb_file_cmd ${binfile}
gdb_test_no_output "set listsize 1"
-# initial sal should be first statement in main
+# initial sal should be main's prologue.
gdb_test "list" \
- "v0 = 0;" \
+ "{ /\\* main prologue \\*/" \
"list before run"
gdb_load ${binfile}
diff --git a/gdb/testsuite/gdb.base/cvexpr.exp b/gdb/testsuite/gdb.base/cvexpr.exp
index fd15efe..439bf71 100644
--- a/gdb/testsuite/gdb.base/cvexpr.exp
+++ b/gdb/testsuite/gdb.base/cvexpr.exp
@@ -47,55 +47,55 @@ proc do_test {dir options} {
gdb_test "whatis (const char) v_char" \
"type = const char" \
- "(const char)"
+ "cast to const char"
gdb_test "whatis (const signed char) v_signed_char" \
"type = const signed char" \
- "(const signed char)"
+ "cast to const signed char"
gdb_test "whatis (const unsigned char) v_unsigned_char" \
"type = const (unsigned char|char)" \
- "(const unsigned char)"
+ "cast to const unsigned char"
gdb_test "whatis (const short) v_short" \
"type = const (short|short int)" \
- "(const short)"
+ "cast to const short"
gdb_test "whatis (const signed short) v_signed_short" \
"type = const (short|short int|signed short|signed short int)" \
- "(const signed short)"
+ "cast to const signed short"
gdb_test "whatis (const unsigned short) v_unsigned_short" \
"type = const (unsigned short|short unsigned int)" \
- "(const unsigned short)"
+ "cast to const unsigned short"
gdb_test "whatis (const int) v_int" \
"type = const int" \
- "(const int)"
+ "cast to const int"
gdb_test "whatis (const signed int) v_signed_int" \
"type = const (signed int|int)" \
- "(const signed int)"
+ "cast to const signed int"
gdb_test "whatis (const unsigned int) v_unsigned_int" \
"type = const unsigned int" \
- "(const unsigned int)"
+ "cast to const unsigned int"
gdb_test "whatis (const long) v_long" \
"type = const (long|long int)" \
- "(const long)"
+ "cast to const long"
gdb_test "whatis (const signed long) v_signed_long" \
"type = const (signed |)long( int|)" \
- "(const signed long)"
+ "cast to const signed long"
gdb_test "whatis (const unsigned long) v_unsigned_long" \
"type = const (unsigned long|long unsigned int)" \
- "(const unsigned long)"
+ "cast to const unsigned long"
gdb_test "whatis (const long long) v_long_long" \
"type = const long long( int|)" \
- "(const long long)"
+ "cast to const long long"
gdb_test "whatis (const signed long long) v_signed_long_long" \
"type = const (signed |)long long( int|)" \
- "(const signed long long)"
+ "cast to const signed long long"
gdb_test "whatis (const unsigned long long) v_unsigned_long_long" \
"type = const (unsigned long long|long long unsigned int)" \
- "(const unsigned long long)"
+ "cast to const unsigned long long"
gdb_test "whatis (const float) v_float" \
"type = const float" \
- "(const float)"
+ "cast to const float"
gdb_test "whatis (const double) v_double" \
"type = const double" \
- "(const double)"
+ "cast to const double"
#
# Test casting a scalar to volatile
@@ -103,55 +103,55 @@ proc do_test {dir options} {
gdb_test "whatis (volatile char) v_char" \
"type = volatile char" \
- "(volatile char)"
+ "cast to volatile char"
gdb_test "whatis (volatile signed char) v_signed_char" \
"type = volatile signed char" \
- "(volatile signed char)"
+ "cast to volatile signed char"
gdb_test "whatis (volatile unsigned char) v_unsigned_char" \
"type = volatile (unsigned char|char)" \
- "(volatile unsigned char)"
+ "cast to volatile unsigned char"
gdb_test "whatis (volatile short) v_short" \
"type = volatile (short|short int)" \
- "(volatile short)"
+ "cast to volatile short"
gdb_test "whatis (volatile signed short) v_signed_short" \
"type = volatile (short|short int|signed short|signed short int)" \
- "(volatile signed short)"
+ "cast to volatile signed short"
gdb_test "whatis (volatile unsigned short) v_unsigned_short" \
"type = volatile (unsigned short|short unsigned int)" \
- "(volatile unsigned short)"
+ "cast to volatile unsigned short"
gdb_test "whatis (volatile int) v_int" \
"type = volatile int" \
- "(volatile int)"
+ "cast to volatile int"
gdb_test "whatis (volatile signed int) v_signed_int" \
"type = volatile (signed int|int)" \
- "(volatile signed int)"
+ "cast to volatile signed int"
gdb_test "whatis (volatile unsigned int) v_unsigned_int" \
"type = volatile unsigned int" \
- "(volatile unsigned int)"
+ "cast to volatile unsigned int"
gdb_test "whatis (volatile long) v_long" \
"type = volatile (long|long int)" \
- "(volatile long)"
+ "cast to volatile long"
gdb_test "whatis (volatile signed long) v_signed_long" \
"type = volatile (signed |)long( int|)" \
- "(volatile signed long)"
+ "cast to volatile signed long"
gdb_test "whatis (volatile unsigned long) v_unsigned_long" \
"type = volatile (unsigned long|long unsigned int)" \
- "(volatile unsigned long)"
+ "cast to volatile unsigned long"
gdb_test "whatis (volatile long long) v_long_long" \
"type = volatile long long( int|)" \
- "(volatile long long)"
+ "cast to volatile long long"
gdb_test "whatis (volatile signed long long) v_signed_long_long" \
"type = volatile (signed |)long long( int|)" \
- "(volatile signed long long)"
+ "cast to volatile signed long long"
gdb_test "whatis (volatile unsigned long long) v_unsigned_long_long" \
"type = volatile (unsigned long long|long long unsigned int)" \
- "(volatile unsigned long long)"
+ "cast to volatile unsigned long long"
gdb_test "whatis (volatile float) v_float" \
"type = volatile float" \
- "(volatile float)"
+ "cast to volatile float"
gdb_test "whatis (volatile double) v_double" \
"type = volatile double" \
- "(volatile double)"
+ "cast to volatile double"
#
# Combine const and volatile
@@ -159,47 +159,47 @@ proc do_test {dir options} {
gdb_test "whatis (const volatile int) v_int" \
"type = const volatile int" \
- "(const volatile int)"
+ "cast to const volatile int"
gdb_test "whatis (volatile const int) v_int" \
"type = const volatile int" \
- "(volatile const int)"
+ "cast to volatile const int"
gdb_test "whatis (const int volatile) v_int" \
"type = const volatile int" \
- "(const int volatile)"
+ "cast to const int volatile"
gdb_test "whatis (volatile int const) v_int" \
"type = const volatile int" \
- "(volatile int const)"
+ "cast to volatile int const"
gdb_test "whatis (int const volatile) v_int" \
"type = const volatile int" \
- "(int const volatile)"
+ "cast to int const volatile"
gdb_test "whatis (int volatile const) v_int" \
"type = const volatile int" \
- "(int volatile const)"
+ "cast to int volatile const"
gdb_test "whatis (const volatile int *) v_int_pointer" \
"type = const volatile int${ws}\\*" \
- "(const volatile int *)"
+ "cast to const volatile int *"
gdb_test "whatis (volatile const int *) v_int_pointer" \
"type = const volatile int${ws}\\*" \
- "(volatile const int *)"
+ "cast to volatile const int *"
gdb_test "whatis (const int volatile *) v_int_pointer" \
"type = const volatile int${ws}\\*" \
- "(const int volatile *)"
+ "cast to const int volatile *"
gdb_test "whatis (volatile int const *) v_int_pointer" \
"type = const volatile int${ws}\\*" \
- "(volatile int const *)"
+ "cast to volatile int const *"
gdb_test "whatis (int const volatile *) v_int_pointer" \
"type = const volatile int${ws}\\*" \
- "(int const volatile *)"
+ "cast to int const volatile *"
gdb_test "whatis (int volatile const *) v_int_pointer" \
"type = const volatile int${ws}\\*" \
- "(int volatile const *)"
+ "cast to int volatile const *"
gdb_test "whatis (int * const volatile) v_int_pointer" \
"type = int${ws}\\*${ws}const volatile" \
- "(int * const volatile)"
+ "cast to int * const volatile"
gdb_test "whatis (int * volatile const) v_int_pointer" \
"type = int${ws}\\*${ws}const volatile" \
- "(int * volatile const)"
+ "cast to int * volatile const"
#
@@ -208,65 +208,65 @@ proc do_test {dir options} {
#gdb_test "whatis (signed const char) v_signed_char" \
# "type = const char" \
- # "(signed const char)"
+ # "cast to signed const char"
#gdb_test "whatis (unsigned const char) v_unsigned_char" \
# "type = const (unsigned char|char)" \
- # "(unsigned const char)"
+ # "cast to unsigned const char"
#gdb_test "whatis (signed const short) v_signed_short" \
# "type = const (short|short int|signed short|signed short int)" \
- # "(signed const short)"
+ # "cast to signed const short"
#gdb_test "whatis (unsigned const short) v_unsigned_short" \
# "type = const (unsigned short|short unsigned int)" \
- # "(unsigned const short)"
+ # "cast to unsigned const short"
#gdb_test "whatis (signed const int) v_signed_int" \
# "type = const (signed int|int)" \
- # "(signed const int)"
+ # "cast to signed const int"
#gdb_test "whatis (unsigned const int) v_unsigned_int" \
# "type = const unsigned int" \
- # "(unsigned const int)"
+ # "cast to unsigned const int"
#gdb_test "whatis (signed const long) v_signed_long" \
# "type = const (signed |)long( int|)" \
- # "(signed const long)"
+ # "cast to signed const long"
#gdb_test "whatis (unsigned const long) v_unsigned_long" \
# "type = const (unsigned long|long unsigned int)" \
- # "(unsigned const long)"
+ # "cast to unsigned const long"
#gdb_test "whatis (signed const long long) v_signed_long_long" \
# "type = const (signed |)long long( int|)" \
- # "(signed const long long)"
+ # "cast to signed const long long"
#gdb_test "whatis (unsigned const long long) v_unsigned_long_long" \
# "type = const (unsigned long long|long long unsigned int)" \
- # "(const unsigned long long)"
+ # "cast to const unsigned long long"
#gdb_test "whatis (signed volatile char) v_signed_char" \
# "type = volatile char" \
- # "(signed volatile char)"
+ # "cast to signed volatile char"
#gdb_test "whatis (unsigned volatile char) v_unsigned_char" \
# "type = volatile (unsigned char|char)" \
- # "(unsigned volatile char)"
+ # "cast to unsigned volatile char"
#gdb_test "whatis (signed volatile short) v_signed_short" \
# "type = volatile (short|short int|signed short|signed short int)" \
- # "(signed volatile short)"
+ # "cast to signed volatile short"
#gdb_test "whatis (unsigned volatile short) v_unsigned_short" \
# "type = volatile (unsigned short|short unsigned int)" \
- # "(unsigned volatile short)"
+ # "cast to unsigned volatile short"
#gdb_test "whatis (signed volatile int) v_signed_int" \
# "type = volatile (signed int|int)" \
- # "(signed volatile int)"
+ # "cast to signed volatile int"
#gdb_test "whatis (unsigned volatile int) v_unsigned_int" \
# "type = volatile unsigned int" \
- # "(unsigned volatile int)"
+ # "cast to unsigned volatile int"
#gdb_test "whatis (signed volatile long) v_signed_long" \
# "type = volatile (signed |)long( int|)" \
- # "(signed volatile long)"
+ # "cast to signed volatile long"
#gdb_test "whatis (unsigned volatile long) v_unsigned_long" \
# "type = volatile (unsigned long|long unsigned int)" \
- # "(unsigned volatile long)"
+ # "cast to unsigned volatile long"
#gdb_test "whatis (signed volatile long long) v_signed_long_long" \
# "type = volatile (signed |)long long( int|)" \
- # "(signed volatile long long)"
+ # "cast to signed volatile long long"
#gdb_test "whatis (unsigned volatile long long) v_unsigned_long_long" \
# "type = volatile (unsigned long long|long long unsigned int)" \
- # "(unsigned volatile long long)"
+ # "cast to unsigned volatile long long"
#
# Now put the 'const' and 'volatile' keywords after the base type.
@@ -274,107 +274,107 @@ proc do_test {dir options} {
gdb_test "whatis (char const) v_char" \
"type = const char" \
- "(char const)"
+ "cast to char const"
gdb_test "whatis (signed char const) v_signed_char" \
"type = const signed char" \
- "(signed char const)"
+ "cast to signed char const"
gdb_test "whatis (unsigned char const) v_unsigned_char" \
"type = const (unsigned char|char)" \
- "(unsigned char const)"
+ "cast to unsigned char const"
gdb_test "whatis (short const) v_short" \
"type = const (short|short int)" \
- "(short const)"
+ "cast to short const"
gdb_test "whatis (signed short const) v_signed_short" \
"type = const (short|short int|signed short|signed short int)" \
- "(signed short const)"
+ "cast to signed short const"
gdb_test "whatis (unsigned short const) v_unsigned_short" \
"type = const (unsigned short|short unsigned int)" \
- "(unsigned short const)"
+ "cast to unsigned short const"
gdb_test "whatis (int const) v_int" \
"type = const int" \
- "(int const)"
+ "cast to int const"
gdb_test "whatis (signed int const) v_signed_int" \
"type = const (signed int|int)" \
- "(signed int const)"
+ "cast to signed int const"
gdb_test "whatis (unsigned int const) v_unsigned_int" \
"type = const unsigned int" \
- "(unsigned int const)"
+ "cast to unsigned int const"
gdb_test "whatis (long const) v_long" \
"type = const (long|long int)" \
- "(long const)"
+ "cast to long const"
gdb_test "whatis (signed long const) v_signed_long" \
"type = const (signed |)long( int|)" \
- "(signed long const)"
+ "cast to signed long const"
gdb_test "whatis (unsigned long const) v_unsigned_long" \
"type = const (unsigned long|long unsigned int)" \
- "(unsigned long const)"
+ "cast to unsigned long const"
gdb_test "whatis (long long const) v_long_long" \
"type = const long long( int|)" \
- "(long long const)"
+ "cast to long long const"
gdb_test "whatis (signed long long const) v_signed_long_long" \
"type = const (signed |)long long( int|)" \
- "(signed long long const)"
+ "cast to signed long long const"
gdb_test "whatis (unsigned long long const) v_unsigned_long_long" \
"type = const (unsigned long long|long long unsigned int)" \
- "(unsigned long long const)"
+ "cast to unsigned long long const"
gdb_test "whatis (float const) v_float" \
"type = const float" \
- "(float const)"
+ "cast to float const"
gdb_test "whatis (double const) v_double" \
"type = const double" \
- "(double const)"
+ "cast to double const"
gdb_test "whatis (char volatile) v_char" \
"type = volatile char" \
- "(char volatile)"
+ "cast to char volatile"
gdb_test "whatis (signed char volatile) v_signed_char" \
"type = volatile signed char" \
- "(signed char volatile)"
+ "cast to signed char volatile"
gdb_test "whatis (unsigned char volatile) v_unsigned_char" \
"type = volatile (unsigned char|char)" \
- "(unsigned char volatile)"
+ "cast to unsigned char volatile"
gdb_test "whatis (short volatile) v_short" \
"type = volatile (short|short int)" \
- "(short volatile)"
+ "cast to short volatile"
gdb_test "whatis (signed short volatile) v_signed_short" \
"type = volatile (short|short int|signed short|signed short int)" \
- "(signed short volatile)"
+ "cast to signed short volatile"
gdb_test "whatis (unsigned short volatile) v_unsigned_short" \
"type = volatile (unsigned short|short unsigned int)" \
- "(unsigned short volatile)"
+ "cast to unsigned short volatile"
gdb_test "whatis (int volatile) v_int" \
"type = volatile int" \
- "(int volatile)"
+ "cast to int volatile"
gdb_test "whatis (signed int volatile) v_signed_int" \
"type = volatile (signed int|int)" \
- "(signed int volatile)"
+ "cast to signed int volatile"
gdb_test "whatis (unsigned int volatile) v_unsigned_int" \
"type = volatile unsigned int" \
- "(unsigned int volatile)"
+ "cast to unsigned int volatile"
gdb_test "whatis (long volatile) v_long" \
"type = volatile (long|long int)" \
- "(long volatile)"
+ "cast to long volatile"
gdb_test "whatis (signed long volatile) v_signed_long" \
"type = volatile (signed |)long( int|)" \
- "(signed long volatile)"
+ "cast to signed long volatile"
gdb_test "whatis (unsigned long volatile) v_unsigned_long" \
"type = volatile (unsigned long|long unsigned int)" \
- "(unsigned long volatile)"
+ "cast to unsigned long volatile"
gdb_test "whatis (long long volatile) v_long_long" \
"type = volatile long long( int|)" \
- "(long long volatile)"
+ "cast to long long volatile"
gdb_test "whatis (signed long long volatile) v_signed_long_long" \
"type = volatile (signed |)long long( int|)" \
- "(signed long long volatile)"
+ "cast to signed long long volatile"
gdb_test "whatis (unsigned long long volatile) v_unsigned_long_long" \
"type = volatile (unsigned long long|long long unsigned int)" \
- "(unsigned long long volatile)"
+ "cast to unsigned long long volatile"
gdb_test "whatis (float volatile) v_float" \
"type = volatile float" \
- "(float volatile)"
+ "cast to float volatile"
gdb_test "whatis (double volatile) v_double" \
"type = volatile double" \
- "(double volatile)"
+ "cast to double volatile"
#
# enums
@@ -382,16 +382,16 @@ proc do_test {dir options} {
gdb_test "whatis (const enum misordered) v_misordered" \
"type = const enum misordered" \
- "(const enum misordered)"
+ "cast to const enum misordered"
gdb_test "whatis (enum misordered const) v_misordered" \
"type = const enum misordered" \
- "(enum misordered const)"
+ "cast to enum misordered const"
gdb_test "whatis (volatile enum misordered) v_misordered" \
"type = volatile enum misordered" \
- "(volatile enum misordered)"
+ "cast to volatile enum misordered"
gdb_test "whatis (enum misordered volatile) v_misordered" \
"type = volatile enum misordered" \
- "(enum misordered volatile)"
+ "cast to enum misordered volatile"
#
# Pointers
@@ -399,41 +399,41 @@ proc do_test {dir options} {
gdb_test "whatis (const int *) v_int_pointer" \
"type = const int${ws}\\*" \
- "(const int *)"
+ "cast to const int *"
gdb_test "whatis (int const *) v_int_pointer" \
"type = const int${ws}\\*" \
- "(int const *)"
+ "cast to int const *"
gdb_test "whatis (int * const) v_int_pointer" \
"type = int \\*${ws}const" \
- "(int * const)"
+ "cast to int * const"
gdb_test "whatis (const int * const) v_int_pointer" \
"type = const int${ws}\\*${ws}const" \
- "(const int * const)"
+ "cast to const int * const"
gdb_test "whatis (int const * const) v_int_pointer" \
"type = const int${ws}\\*${ws}const" \
- "(int const * const)"
+ "cast to int const * const"
gdb_test "whatis (const int **) v_int_pointer_pointer" \
"type = const int${ws}\\*${ws}\\*" \
- "(const int **)"
+ "cast to const int **"
gdb_test "whatis (int const **) v_int_pointer_pointer" \
"type = const int${ws}\\*${ws}\\*" \
- "(int const **)"
+ "cast to int const **"
gdb_test "whatis (int ** const) v_int_pointer_pointer" \
"type = int \\*${ws}\\*${ws}const" \
- "(int ** const)"
+ "cast to int ** const"
gdb_test "whatis (const int * const *) v_int_pointer_pointer" \
"type = const int${ws}\\*${ws}const${ws}\\*" \
- "(const int * const *)"
+ "cast to const int * const *"
gdb_test "whatis (int const * const *) v_int_pointer_pointer" \
"type = const int${ws}\\*${ws}const${ws}\\*" \
- "(int const * const *)"
+ "cast to int const * const *"
gdb_test "whatis (const int * const * const) v_int_pointer_pointer" \
"type = const int${ws}\\*${ws}const${ws}\\*${ws}const" \
- "(const int * const * const)"
+ "cast to const int * const * const"
gdb_test "whatis (int const * const * const) v_int_pointer_pointer" \
"type = const int${ws}\\*${ws}const${ws}\\*${ws}const" \
- "(int const * const * const)"
+ "cast to int const * const * const"
#
# Arrays TODO
@@ -449,46 +449,46 @@ proc do_test {dir options} {
gdb_test "whatis (const struct t_struct) v_struct1" \
"type = const struct t_struct" \
- "(const struct t_struct)"
+ "cast to const struct t_struct"
gdb_test "whatis (const union t_union) v_union" \
"type = const union t_union" \
- "(const union t_union)"
+ "cast to const union t_union"
gdb_test "whatis (struct t_struct const) v_struct1" \
"type = const struct t_struct" \
- "(struct t_struct const)"
+ "cast to struct t_struct const"
gdb_test "whatis (union t_union const) v_union" \
"type = const union t_union" \
- "(union t_union const)"
+ "cast to union t_union const"
gdb_test "whatis (const struct t_struct *) &v_struct1" \
"type = const struct t_struct${ws}\\*" \
- "(const struct t_struct *)"
+ "cast to const struct t_struct *"
gdb_test "whatis (const union t_union *) &v_union" \
"type = const union t_union${ws}\\*" \
- "(const union t_union *)"
+ "cast to const union t_union *"
gdb_test "whatis (struct t_struct const *) &v_struct1" \
"type = const struct t_struct${ws}\\*" \
- "(struct t_struct const *)"
+ "cast to struct t_struct const *"
gdb_test "whatis (union t_union const *) &v_union" \
"type = const union t_union${ws}\\*" \
- "(union t_union const *)"
+ "cast to union t_union const *"
gdb_test "whatis (struct t_struct * const) &v_struct1" \
"type = struct t_struct${ws}\\*${ws}const" \
- "(struct t_struct * const)"
+ "cast to struct t_struct * const"
gdb_test "whatis (union t_union * const) &v_union" \
"type = union t_union${ws}\\*${ws}const" \
- "(union t_union * const)"
+ "cast to union t_union * const"
gdb_test "whatis (const struct t_struct * const) &v_struct1" \
"type = const struct t_struct${ws}\\*${ws}const" \
- "(const struct t_struct * const)"
+ "cast to const struct t_struct * const"
gdb_test "whatis (const union t_union * const) &v_union" \
"type = const union t_union${ws}\\*${ws}const" \
- "(const union t_union * const)"
+ "cast to const union t_union * const"
gdb_test "whatis (struct t_struct const * const) &v_struct1" \
"type = const struct t_struct${ws}\\*${ws}const" \
- "(struct t_struct const * const)"
+ "cast to struct t_struct const * const"
gdb_test "whatis (union t_union const * const) &v_union" \
"type = const union t_union${ws}\\*${ws}const" \
- "(union t_union const * const)"
+ "cast to union t_union const * const"
#
# Function pointers TODO
diff --git a/gdb/testsuite/gdb.base/empty-host-env-vars.exp b/gdb/testsuite/gdb.base/empty-host-env-vars.exp
index e6e9d6e..5fab65a 100644
--- a/gdb/testsuite/gdb.base/empty-host-env-vars.exp
+++ b/gdb/testsuite/gdb.base/empty-host-env-vars.exp
@@ -21,16 +21,14 @@ require {!is_remote host}
set all_env_vars { HOME XDG_CACHE_HOME LOCALAPPDATA XDG_CONFIG_HOME }
-# Record the initial value of the index-cache directory.
+set re_pre \
+ [string_to_regexp {The directory of the index cache is "}]
+set re_post \
+ [string_to_regexp {".}]
+
+# Show the initial value of the index-cache directory.
clean_restart
-set index_cache_directory ""
-gdb_test_multiple "show index-cache directory" "" {
- -re -wrap "The directory of the index cache is \"(.*)\"\\." {
- set index_cache_directory $expect_out(1,string)
- set index_cache_directory [string_to_regexp $index_cache_directory]
- pass $gdb_test_name
- }
-}
+gdb_test "show index-cache directory" $re_pre\[^\r\n\]*$re_post
foreach_with_prefix env_var_name $all_env_vars {
# Restore the original state of the environment variable.
@@ -38,18 +36,7 @@ foreach_with_prefix env_var_name $all_env_vars {
set env($env_var_name) {}
clean_restart
- # Verify that the empty environment variable didn't affect the
- # index-cache directory setting, that we still see the initial value.
- # "HOME" is different, because if that one is unset, GDB isn't even
- # able to compute the default location. In that case, we expect it to
- # be empty.
- if { $env_var_name == "HOME" } {
- gdb_test "show index-cache directory" \
- "The directory of the index cache is \"\"\\."
- } else {
- gdb_test "show index-cache directory" \
- "The directory of the index cache is \"$index_cache_directory\"\\."
- }
+ gdb_test "show index-cache directory" $re_pre\[^\r\n\]*$re_post
}
}
@@ -69,7 +56,6 @@ with_test_prefix "all env vars" {
clean_restart
- gdb_test "show index-cache directory" \
- "The directory of the index cache is \"\"\\."
+ gdb_test "show index-cache directory" $re_pre$re_post
}
}
diff --git a/gdb/testsuite/gdb.base/ending-run.exp b/gdb/testsuite/gdb.base/ending-run.exp
index b9a72b0..90359fd 100644
--- a/gdb/testsuite/gdb.base/ending-run.exp
+++ b/gdb/testsuite/gdb.base/ending-run.exp
@@ -32,24 +32,15 @@ if { [prepare_for_testing "failed to prepare" $testfile $srcfile $flags] } {
}
remote_exec build "rm -f core"
-# CHFts23469: Test that you can "clear" a bp set at
-# a line _before_ the routine (which will default to the
-# first line in the routine, which turns out to correspond
-# to the prolog--that's another bug...)
-#
-
-gdb_test "b ending-run.c:1" ".*Breakpoint.*ending-run.c, line 1.*" \
- "bpt at line before routine"
-
set break1_line [gdb_get_line_number "-break1-"]
gdb_test "b ending-run.c:$break1_line" \
- ".*Note.*also.*Breakpoint 2.*ending-run.c, line $break1_line.*" \
+ "Breakpoint 1 at ${::hex}.*" \
"b ending-run.c:$break1_line, one"
# Set up to go to the next-to-last line of the program
#
set break2_line [gdb_get_line_number "-break2-"]
-gdb_test "b ending-run.c:$break2_line" ".*Breakpoint 3.*ending-run.c, line $break2_line.*"
+gdb_test "b ending-run.c:$break2_line" ".*Breakpoint 2.*ending-run.c, line $break2_line.*"
# Expect to hit the bp at line "1", but symbolize this
# as line "13". Then try to clear it--this should work.
@@ -57,29 +48,28 @@ gdb_test "b ending-run.c:$break2_line" ".*Breakpoint 3.*ending-run.c, line $brea
gdb_run_cmd
gdb_test "" ".*Breakpoint.*1.*callee.*$break1_line.*" "run"
-gdb_test "cle" ".*Deleted breakpoints 1 2.*" "clear worked"
-gdb_test_multiple "i b" "cleared bp at line before routine" {
- -re ".* breakpoint .* breakpoint .*$gdb_prompt $" {
- fail "cleared bp at line before routine"
+gdb_test "cle" "Deleted breakpoint 1 " "clear worked"
+gdb_test_multiple "i b" "cleared bp at stopped line" {
+ -re ".* breakpoint .* breakpoint .*$gdb_prompt $" {
+ fail $gdb_test_name
}
- -re ".*3.*main.*$break2_line.*$gdb_prompt $" {
- pass "cleared bp at line before routine"
+ -re ".*2.*main.*$break2_line.*$gdb_prompt $" {
+ pass $gdb_test_name
}
}
# Test some other "clear" combinations
#
-gdb_test "b ending-run.c:1" ".*Breakpoint.*4.*"
-gdb_test "b ending-run.c:$break1_line" ".*Note.*also.*Breakpoint.*5.*" "b ending-run.c:$break1_line, two"
+gdb_test "b ending-run.c:$break1_line" "Breakpoint 3 at ${::hex}.*" "b ending-run.c:$break1_line, two"
gdb_test "cle ending-run.c:$break1_line" \
- ".*Deleted breakpoints 4 5.*" "Cleared 2 by line"
+ "Deleted breakpoint 3 " "Cleared 2 by line"
gdb_test_multiple "info line ending-run.c:$break1_line" "" {
-re ".*address (0x\[0-9a-fA-F]*).*$gdb_prompt $" {
set line_nine $expect_out(1,string)
- gdb_test "b ending-run.c:$break1_line" ".*Breakpoint 6.*ending-run.c, line $break1_line.*"
- gdb_test "b *$line_nine" ".*Note.*also.*Breakpoint 7.*" "breakpoint 7 at *ending-run.c:$break1_line"
- gdb_test "cle" ".*Deleted breakpoints 6 7.*" "clear 2 by default"
+ gdb_test "b ending-run.c:$break1_line" ".*Breakpoint 4.*ending-run.c, line $break1_line.*"
+ gdb_test "b *$line_nine" ".*Note.*also.*Breakpoint 5.*" "breakpoint 7 at *ending-run.c:$break1_line"
+ gdb_test "cle" "Deleted breakpoints 4 5 " "clear 2 by default"
}
-re ".*$gdb_prompt $" {
fail "need to fix test for new compile outcome"
@@ -90,7 +80,7 @@ gdb_test_multiple "i b" "all set to continue" {
-re ".* breakpoint .* breakpoint .*$gdb_prompt $" {
fail "all set to continue (didn't clear bps)"
}
- -re ".*3.*main.*$break2_line.*$gdb_prompt $" {
+ -re ".*2.*main.*$break2_line.*$gdb_prompt $" {
pass "all set to continue"
}
-re ".*$gdb_prompt $" {
diff --git a/gdb/testsuite/gdb.base/eval-skip.exp b/gdb/testsuite/gdb.base/eval-skip.exp
index 7b28513..e8f766e 100644
--- a/gdb/testsuite/gdb.base/eval-skip.exp
+++ b/gdb/testsuite/gdb.base/eval-skip.exp
@@ -54,86 +54,63 @@ gdb_test_no_output "set variable y=2" "set variable y=2"
gdb_test_no_output "set variable z=2" "set variable z=2"
gdb_test_no_output "set variable w=3" "set variable w=3"
-gdb_test "print (0 && (x+y))" ".$decimal = $false" \
- "print value of (0 && (x+y))"
+proc test { val re } {
+ gdb_test "print $val" $re "print value of $val value"
+}
+
+test "(0 && (x+y))" ".$decimal = $false"
-gdb_test "print (0 && (x-y))" ".$decimal = $false" \
- "print value of (0 && (x-y))"
+test "(0 && (x-y))" ".$decimal = $false"
-gdb_test "print (0 && (x*y))" ".$decimal = $false" \
- "print value of (0 && (x*y))"
+test "(0 && (x*y))" ".$decimal = $false"
-gdb_test "print (0 && (x/y))" ".$decimal = $false" \
- "print value of (0 && (x/y))"
+test "(0 && (x/y))" ".$decimal = $false"
-gdb_test "print (0 && (x%y))" ".$decimal = $false" \
- "print value of (0 && (x%y))"
+test "(0 && (x%y))" ".$decimal = $false"
-gdb_test "print (0 && (x&&y))" ".$decimal = $false" \
- "print value of (0 && (x&&y))"
+test "(0 && (x&&y))" ".$decimal = $false"
-gdb_test "print (0 && (x||y))" ".$decimal = $false" \
- "print value of (0 && (x||y))"
+test "(0 && (x||y))" ".$decimal = $false"
-gdb_test "print (0 && (x&y))" ".$decimal = $false" \
- "print value of (0 && (x&y))"
+test "(0 && (x&y))" ".$decimal = $false"
-gdb_test "print (0 && (x|y))" ".$decimal = $false" \
- "print value of (0 && (x|y))"
+test "(0 && (x|y))" ".$decimal = $false"
-gdb_test "print (0 && (x^y))" ".$decimal = $false" \
- "print value of (0 && (x^y))"
+test "(0 && (x^y))" ".$decimal = $false"
-gdb_test "print (0 && (x < y))" ".$decimal = $false" \
- "print value of (0 && (x < y))"
+test "(0 && (x < y))" ".$decimal = $false"
-gdb_test "print (0 && (x <= y))" ".$decimal = $false" \
- "print value of (0 && (x <= y))"
+test "(0 && (x <= y))" ".$decimal = $false"
-gdb_test "print (0 && (x>y))" ".$decimal = $false" \
- "print value of (0 && (x>y))"
+test "(0 && (x>y))" ".$decimal = $false"
-gdb_test "print (0 && (x>=y))" ".$decimal = $false" \
- "print value of (0 && (x>=y))"
+test "(0 && (x>=y))" ".$decimal = $false"
-gdb_test "print (0 && (x==y))" ".$decimal = $false" \
- "print value of (0 && (x==y))"
+test "(0 && (x==y))" ".$decimal = $false"
-gdb_test "print (0 && (x!=y))" ".$decimal = $false" \
- "print value of (0 && (x!=y))"
+test "(0 && (x!=y))" ".$decimal = $false"
-gdb_test "print (0 && (x<<31))" ".$decimal = $false" \
- "print value of (0 && (x<<31))"
+test "(0 && (x<<31))" ".$decimal = $false"
-gdb_test "print (0 && (x>>31))" ".$decimal = $false" \
- "print value of (0 && (x>>31))"
+test "(0 && (x>>31))" ".$decimal = $false"
-gdb_test "print (0 && (!x))" ".$decimal = $false" \
- "print value of (0 && (!x))"
+test "(0 && (!x))" ".$decimal = $false"
-gdb_test "print (0 && (~x))" ".$decimal = $false" \
- "print value of (0 && (~x))"
+test "(0 && (~x))" ".$decimal = $false"
-gdb_test "print (0 && (-x))" ".$decimal = $false" \
- "print value of (0 && (-x))"
+test "(0 && (-x))" ".$decimal = $false"
-gdb_test "print (0 && (x++))" ".$decimal = $false" \
- "print value of (0 && (x++))"
+test "(0 && (x++))" ".$decimal = $false"
-gdb_test "print (0 && (++x))" ".$decimal = $false" \
- "print value of (0 && (++x))"
+test "(0 && (++x))" ".$decimal = $false"
-gdb_test "print (0 && (x--))" ".$decimal = $false" \
- "print value of (0 && (x--))"
+test "(0 && (x--))" ".$decimal = $false"
-gdb_test "print (0 && (--x))" ".$decimal = $false" \
- "print value of (0 && (--x))"
+test "(0 && (--x))" ".$decimal = $false"
-gdb_test "print (0 && (x+=7))" ".$decimal = $false" \
- "print value of (0 && (x+=7))"
+test "(0 && (x+=7))" ".$decimal = $false"
-gdb_test "print (0 && (x=y))" ".$decimal = $false" \
- "print value of (0 && (x=y))"
+test "(0 && (x=y))" ".$decimal = $false"
gdb_exit
diff --git a/gdb/testsuite/gdb.base/examine-backward.exp b/gdb/testsuite/gdb.base/examine-backward.exp
index dcb1371..fe3d13e 100644
--- a/gdb/testsuite/gdb.base/examine-backward.exp
+++ b/gdb/testsuite/gdb.base/examine-backward.exp
@@ -172,17 +172,17 @@ with_test_prefix "char-width=1, print-max=20" {
}
gdb_test "x/-xb" "0x39" "take 1 char backward again"
gdb_test "x/-s" "\"01234567890123456789\"\.\.\." \
- "take 1 string backward (1/6)"
+ "take 1 string backward, 1/6"
gdb_test "x/-s" "\".+\"" \
- "take 1 string backward (2/6)"
+ "take 1 string backward, 2/6"
gdb_test "x/-s" "\"\"" \
- "take 1 string backward (3/6)"
+ "take 1 string backward, 3/6"
gdb_test "x/-s" "\"\"" \
- "take 1 string backward (4/6)"
+ "take 1 string backward, 4/6"
gdb_test "x/-s" "\"GHIJKLMNOPQRSTUVWXYZ\"" \
- "take 1 string backward (5/6)"
+ "take 1 string backward, 5/6"
gdb_test "x/-s" "\"ABCDEFGHIJKLMNOPQRST\"\.\.\." \
- "take 1 string backward (6/6)"
+ "take 1 string backward, 6/6"
}
with_test_prefix "char-width=2, print-max=20" {
@@ -214,17 +214,17 @@ with_test_prefix "char-width=2, print-max=20" {
}
gdb_test "x/-xh" "0x0039" "take 1 char backward again"
gdb_test "x/-sh" "u\"01234567890123456789\"\.\.\." \
- "take 1 string backward (1/6)"
+ "take 1 string backward, 1/6"
gdb_test "x/-sh" "u\".+\"" \
- "take 1 string backward (2/6)"
+ "take 1 string backward, 2/6"
gdb_test "x/-sh" "u\"\"" \
- "take 1 string backward (3/6)"
+ "take 1 string backward, 3/6"
gdb_test "x/-sh" "u\"\"" \
- "take 1 string backward (4/6)"
+ "take 1 string backward, 4/6"
gdb_test "x/-sh" "u\"GHIJKLMNOPQRSTUVWXYZ\"" \
- "take 1 string backward (5/6)"
+ "take 1 string backward, 5/6"
gdb_test "x/-sh" "u\"ABCDEFGHIJKLMNOPQRST\"\.\.\." \
- "take 1 string backward (6/6)"
+ "take 1 string backward, 6/6"
}
with_test_prefix "char-width=4, print-max=20" {
@@ -256,17 +256,17 @@ with_test_prefix "char-width=4, print-max=20" {
}
gdb_test "x/-xw" "0x00000039" "take 1 char backward again"
gdb_test "x/-sw" "U\"01234567890123456789\"\.\.\." \
- "take 1 string backward (1/6)"
+ "take 1 string backward, 1/6"
gdb_test "x/-sw" "U\".+\"" \
- "take 1 string backward (2/6)"
+ "take 1 string backward, 2/6"
gdb_test "x/-sw" "U\"\"" \
- "take 1 string backward (3/6)"
+ "take 1 string backward, 3/6"
gdb_test "x/-sw" "U\"\"" \
- "take 1 string backward (4/6)"
+ "take 1 string backward, 4/6"
gdb_test "x/-sw" "U\"GHIJKLMNOPQRSTUVWXYZ\"" \
- "take 1 string backward (5/6)"
+ "take 1 string backward, 5/6"
gdb_test "x/-sw" "U\"ABCDEFGHIJKLMNOPQRST\"\.\.\." \
- "take 1 string backward (6/6)"
+ "take 1 string backward, 6/6"
}
with_test_prefix "char-width=2, print-max=0" {
@@ -299,17 +299,17 @@ with_test_prefix "char-width=2, print-max=0" {
}
gdb_test "x/-xh" "0x0000" "take 1 char backward"
gdb_test "x/-sh" "u\"!!!!!!\"" \
- "take 1 string backward (1/6)"
+ "take 1 string backward, 1/6"
gdb_test "x/-sh" "u\"012345678901234567890123456789\"" \
- "take 1 string backward (2/6)"
+ "take 1 string backward, 2/6"
gdb_test "x/-sh" "u\".+\"" \
- "take 1 string backward (3/6)"
+ "take 1 string backward, 3/6"
gdb_test "x/-sh" "u\"\"" \
- "take 1 string backward (4/6)"
+ "take 1 string backward, 4/6"
gdb_test "x/-sh" "u\"\"" \
- "take 1 string backward (5/6)"
+ "take 1 string backward, 5/6"
gdb_test "x/-sh" "u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"" \
- "take 1 string backward (6/6)"
+ "take 1 string backward, 6/6"
}
with_test_prefix "char-width=1, print-max=4" {
@@ -326,13 +326,13 @@ with_test_prefix "char-width=1, print-max=4" {
"\"\""
}
gdb_test "x/-xb" "0x00" "take 1 byte backward"
- gdb_test_sequence "x/-4s" "take 4 strings backward (1/2)" {
+ gdb_test_sequence "x/-4s" "take 4 strings backward, 1/2" {
"\"TUVW\"\.\.\."
"\"XYZ\""
"\"\""
"\"\""
}
- gdb_test_sequence "x/-4s" "take 4 strings backward (2/2)" {
+ gdb_test_sequence "x/-4s" "take 4 strings backward, 2/2" {
"\"CDEF\"\.\.\."
"\"GHIJ\"\.\.\."
"\"KLMN\"\.\.\."
@@ -348,9 +348,9 @@ with_test_prefix "backward disassemble general" {
set main_re "main(\\(\\))?"
gdb_test "x/i main" "0x\[0-9a-fA-F\]+ <$main_re>:\t.*" \
- "move the current position to main (x/i)"
+ "move the current position to main, x/i"
gdb_test "x/-i" "0x\[0-9a-fA-F\]+ <$main_re>:\t.*" \
- "move the current position to main (x/-i)"
+ "move the current position to main, x/-i"
for {set i 0} {$i < [llength $length_to_examine]} {incr i} {
set len [lindex $length_to_examine $i]
set instructions [capture_command_output "x/${len}i" ""]
diff --git a/gdb/testsuite/gdb.base/exprs.exp b/gdb/testsuite/gdb.base/exprs.exp
index 0f8c53b..375af6b 100644
--- a/gdb/testsuite/gdb.base/exprs.exp
+++ b/gdb/testsuite/gdb.base/exprs.exp
@@ -46,9 +46,9 @@ proc test_expr { args } {
}
set last_ent [expr [llength $args] - 1]
set testname [lindex $args $last_ent]
- gdb_test [lindex $args 0] ".*" "$testname (setup)"
+ gdb_test [lindex $args 0] ".*" "$testname, setup"
for {set x 1} {$x < $last_ent} {set x [expr $x + 2]} {
- gdb_test [lindex $args $x] [lindex $args [expr $x + 1]] "$testname ([lindex $args $x])"
+ gdb_test [lindex $args $x] [lindex $args [expr $x + 1]] "$testname, [lindex $args $x]"
}
}
#
diff --git a/gdb/testsuite/gdb.base/fileio.exp b/gdb/testsuite/gdb.base/fileio.exp
index 4b01248..f31a775 100644
--- a/gdb/testsuite/gdb.base/fileio.exp
+++ b/gdb/testsuite/gdb.base/fileio.exp
@@ -149,23 +149,23 @@ gdb_test continue \
gdb_test continue \
"Continuing\\..*isatty 1:.*OK$stop_msg" \
-"Isatty (stdin)"
+"Isatty, stdin"
gdb_test continue \
"Continuing\\..*isatty 2:.*OK$stop_msg" \
-"Isatty (stdout)"
+"Isatty, stdout"
gdb_test continue \
"Continuing\\..*isatty 3:.*OK$stop_msg" \
-"Isatty (stderr)"
+"Isatty, stderr"
gdb_test continue \
"Continuing\\..*isatty 4:.*OK$stop_msg" \
-"Isatty (invalid fd)"
+"Isatty, invalid fd"
gdb_test continue \
"Continuing\\..*isatty 5:.*OK$stop_msg" \
-"Isatty (open file)"
+"Isatty, open file"
gdb_test_no_output "set debug remote 1"
set msg "System says shell is not available"
diff --git a/gdb/testsuite/gdb.base/filename-completion.exp b/gdb/testsuite/gdb.base/filename-completion.exp
index b700977..389e2d7 100644
--- a/gdb/testsuite/gdb.base/filename-completion.exp
+++ b/gdb/testsuite/gdb.base/filename-completion.exp
@@ -23,8 +23,16 @@ load_lib completion-support.exp
#
# root/ [ DIRECTORY ]
# aaa/ [ DIRECTORY ]
+# aa bb [ FILE ]
+# aa cc [ FILE ]
+# aaa/ [ DIRECTORY ]
# bb1/ [ DIRECTORY ]
# bb2/ [ DIRECTORY ]
+# dir 1/ [ DIRECTORY ]
+# unique file [ FILE ]
+# dir 2/ [ DIRECTORY ]
+# file 1 [ FILE ]
+# file 2 [ FILE ]
# cc1/ [ DIRECTORY ]
# cc2 [ FILE ]
proc setup_directory_tree {} {
@@ -36,18 +44,226 @@ proc setup_directory_tree {} {
remote_exec host "mkdir -p ${root}/bb2"
remote_exec host "mkdir -p ${root}/cc1"
remote_exec host "touch ${root}/cc2"
-
remote_exec host "touch \"${root}/aaa/aa bb\""
remote_exec host "touch \"${root}/aaa/aa cc\""
+ remote_exec host "mkdir -p \"${root}/bb2/dir 1\""
+ remote_exec host "mkdir -p \"${root}/bb2/dir 2\""
+ remote_exec host "touch \"${root}/bb2/dir 1/unique file\""
+ remote_exec host "touch \"${root}/bb2/dir 2/file 1\""
+ remote_exec host "touch \"${root}/bb2/dir 2/file 2\""
+
+ remote_exec host "touch \"${root}/bb1/aa\\\"bb\""
+ remote_exec host "touch \"${root}/bb1/aa'bb\""
return $root
}
-# Run filename completetion tests. ROOT is the base directory as
-# returned from setup_directory_tree, though, if ROOT is a
-# sub-directory of the user's home directory ROOT might have been
-# modified to replace the $HOME prefix with a single "~" character.
-proc run_tests { root } {
+# This proc started as a copy of test_gdb_complete_multiple, however, this
+# version does some extra work. See the original test_gdb_complete_multiple
+# for a description of all the arguments.
+#
+# When using the 'complete' command with filenames, GDB will add a trailing
+# quote for filenames, and a trailing "/" for directory names. As the
+# trailing "/" is also added in the tab-completion output the
+# COMPLETION_LIST will include the "/" character, but the trailing quote is
+# only added when using the 'complete' command.
+#
+# Pass the trailing quote will be passed as END_QUOTE_CHAR, this proc will
+# run the tab completion test, and will then add the trailing quote to those
+# entries in COMPLETION_LIST that don't have a trailing "/" before running
+# the 'complete' command test.
+proc test_gdb_complete_filename_multiple {
+ cmd_prefix completion_word add_completed_line completion_list
+ {start_quote_char ""} {end_quote_char ""} {max_completions false}
+ {testname ""}
+} {
+ if { [readline_is_used] } {
+ test_gdb_complete_tab_multiple "$cmd_prefix$completion_word" \
+ $add_completed_line $completion_list $max_completions $testname
+ }
+
+ if { $start_quote_char eq "" } {
+ set updated_completion_list {}
+
+ foreach entry $completion_list {
+ # If ENTRY is quoted with double quotes, then any double
+ # quotes within the entry need to be escaped.
+ if { $end_quote_char eq "\"" } {
+ regsub -all "\"" $entry "\\\"" entry
+ }
+
+ if { $end_quote_char eq "" } {
+ regsub -all " " $entry "\\ " entry
+ regsub -all "\"" $entry "\\\"" entry
+ regsub -all "'" $entry "\\'" entry
+ }
+
+ if {[string range $entry end end] ne "/"} {
+ set entry $entry$end_quote_char
+ }
+ lappend updated_completion_list $entry
+ }
+
+ set completion_list $updated_completion_list
+ set end_quote_char ""
+ }
+
+ test_gdb_complete_cmd_multiple $cmd_prefix $completion_word \
+ $completion_list $start_quote_char $end_quote_char $max_completions \
+ $testname
+}
+
+# Helper proc. Returns a string containing the escape sequence to move the
+# cursor COUNT characters to the left. There's no sanity checking performed
+# on COUNT, so the user of this proc must ensure there are more than COUNT
+# characters on the current line.
+proc c_left { count } {
+ string repeat "\033\[D" $count
+}
+
+# This proc is based off of test_gdb_complete_tab_multiple in
+# completion-support.exp library. This proc however tests completing a
+# filename in the middle of a command line.
+#
+# INPUT_LINE is the line to complete, BACK_COUNT is the number of characters
+# to move the cursor left before sending tab to complete the line.
+# ADD_COMPLETED_LINE is what we expect to be unconditionally added the first
+# time tab is sent. On additional tabs COMPLETION_LIST will be displayed.
+# TESTNAME is used as expected.
+proc test_tab_complete_within_line_multiple { input_line back_count \
+ add_completed_line \
+ completion_list \
+ testname } {
+ global gdb_prompt
+
+ # After displaying the completion list the line will be reprinted, but
+ # now with ADD_COMPLETED_LINE inserted. Build the regexp to match
+ # against this expanded line. The new content will be inserted
+ # BACK_COUNT character from the end of the line.
+ set expanded_line \
+ [join [list \
+ [string range $input_line 0 end-$back_count] \
+ ${add_completed_line} \
+ [string range $input_line end-[expr $back_count - 1] end]] \
+ ""]
+ set expanded_line_re [string_to_regexp $expanded_line]
+
+ # Convert input arguments into regexp.
+ set input_line_re [string_to_regexp $input_line]
+ set add_completed_line_re [string_to_regexp $add_completed_line]
+ set completion_list_re [make_tab_completion_list_re $completion_list]
+
+ # Similar to test_tab_complete_within_line_unique, build two
+ # regexp for matching the line after the first tab. Which regexp
+ # matches will depend on the version and/or configuration of
+ # readline. This first regexp moves the cursor backwards and then
+ # inserts new content into the line.
+ set after_tab_re1 "^$input_line_re"
+ set after_tab_re1 "$after_tab_re1\\\x08{$back_count}"
+ set after_tab_re1 "$after_tab_re1${completion::bell_re}"
+ set after_tab_re1 "$after_tab_re1\\\x1b\\\x5b[string length $add_completed_line]\\\x40"
+ set after_tab_re1 "$after_tab_re1$add_completed_line_re\$"
+
+ # This second regexp moves the cursor backwards and overwrites the
+ # end of the line, then moves the cursor backwards again to the
+ # correct position within the line.
+ set after_tab_re2 "^$input_line_re"
+ set after_tab_re2 "$after_tab_re2\\\x08{$back_count}"
+ set after_tab_re2 "$after_tab_re2${completion::bell_re}"
+ set tail [string range $input_line end-[expr $back_count - 1] end]
+ set after_tab_re2 "$after_tab_re2$add_completed_line_re"
+ set after_tab_re2 "$after_tab_re2[string_to_regexp $tail]"
+ set after_tab_re2 "$after_tab_re2\\\x08{$back_count}"
+
+ send_gdb "$input_line[c_left $back_count]\t"
+ gdb_test_multiple "" "$testname (first tab)" {
+ -re "(?:(?:$after_tab_re1)|(?:$after_tab_re2))" {
+ send_gdb "\t"
+ # If we auto-completed to an ambiguous prefix, we need an
+ # extra tab to show the matches list.
+ if {$add_completed_line != ""} {
+ send_gdb "\t"
+ set maybe_bell ${completion::bell_re}
+ } else {
+ set maybe_bell ""
+ }
+ gdb_test_multiple "" "$testname (second tab)" {
+ -re "^${maybe_bell}\r\n$completion_list_re\r\n$gdb_prompt " {
+ gdb_test_multiple "" "$testname (second tab)" {
+ -re "^$expanded_line_re\\\x08{$back_count}$" {
+ pass $gdb_test_name
+ }
+ }
+ }
+ -re "${maybe_bell}\r\n.+\r\n$gdb_prompt $" {
+ fail $gdb_test_name
+ }
+ }
+ }
+ }
+
+ clear_input_line $testname
+}
+
+# Wrapper around test_gdb_complete_tab_unique to test completing a unique
+# item in the middle of a line. INPUT_LINE is the line to complete.
+# BACK_COUNT is the number of characters to move left within INPUT_LINE
+# before sending tab to perform completion. INSERT_STR is what we expect to
+# see inserted by the completion engine in GDB.
+proc test_tab_complete_within_line_unique { input_line back_count insert_str } {
+ # Build regexp for the line after completion has occurred. As
+ # completion is being performed in the middle of the line the
+ # sequence of characters we see can vary depending on which
+ # version of readline is in use, and/or how readline is
+ # configured. Currently two different approaches are covered as
+ # RE1 and RE2. Both of these regexp cover the complete possible
+ # output.
+ #
+ # In the first case we see the input line followed by some number
+ # of characters to move the cursor backwards. After this we see a
+ # control sequence that tells the terminal that some characters
+ # are going to be inserted into the middle of the line, the new
+ # characters are then emitted. The terminal itself is responsible
+ # for preserving the tail of the line, so these characters are not
+ # re-emitted.
+ set re1 [string_to_regexp $input_line]
+ set re1 $re1\\\x08{$back_count}
+ set re1 $re1\\\x1b\\\x5b[string length $insert_str]\\\x40
+ set re1 $re1[string_to_regexp $insert_str]
+
+ # In this second regexp we again start with the input line
+ # followed by the control characters to move the cursor backwards.
+ # This time though readline emits the new characters and then
+ # re-emits the tail of the original line. This new content will
+ # overwrite the original output on the terminal. Finally, control
+ # characters are emitted to move the cursor back to the correct
+ # place in the middle of the line.
+ set re2 [string_to_regexp $input_line]
+ set re2 $re2\\\x08{$back_count}
+ set re2 $re2[string_to_regexp $insert_str]
+ set tail [string range $input_line end-[expr $back_count - 1] end]
+ set re2 $re2[string_to_regexp $tail]
+ set re2 $re2\\\x08{$back_count}
+
+ # We can now perform the tab-completion, we check for either of
+ # the possible output regexp patterns.
+ test_gdb_complete_tab_unique \
+ "${input_line}[c_left $back_count]" \
+ "(?:(?:$re1)|(?:$re2))" \
+ "" \
+ "complete unique file within command line"
+}
+
+
+# Run filename completion tests for those command that accept quoting and
+# escaping of the filename argument. CMD is the initial part of the command
+# line, paths to complete will be added after CMD.
+#
+# ROOT is the base directory as returned from setup_directory_tree, though,
+# if ROOT is a sub-directory of the user's home directory ROOT might have
+# been modified to replace the $HOME prefix with a single "~" character.
+proc run_quoting_and_escaping_tests_1 { root cmd } {
+ gdb_start
# Completing 'thread apply all ...' commands uses a custom word
# point. At one point we had a bug where doing this would break
@@ -57,47 +273,240 @@ proc run_tests { root } {
"complete a 'thread apply all' command"
foreach_with_prefix qc [list "" "'" "\""] {
- test_gdb_complete_none "file ${qc}${root}/xx" \
+ test_gdb_complete_none "$cmd ${qc}${root}/xx" \
"expand a non-existent filename"
- test_gdb_complete_unique "file ${qc}${root}/a" \
- "file ${qc}${root}/aaa/" "" false \
+ test_gdb_complete_unique "$cmd ${qc}${root}/a" \
+ "$cmd ${qc}${root}/aaa/" "" false \
+ "expand a unique directory name"
+
+ test_gdb_complete_unique "$cmd ${qc}${root}/cc2" \
+ "$cmd ${qc}${root}/cc2${qc}" " " false \
"expand a unique filename"
- test_gdb_complete_multiple "file ${qc}${root}/" \
+ test_gdb_complete_filename_multiple "$cmd ${qc}${root}/" \
"b" "b" {
"bb1/"
"bb2/"
} "" "${qc}" false \
"expand multiple directory names"
- test_gdb_complete_multiple "file ${qc}${root}/" \
+ test_gdb_complete_filename_multiple "$cmd ${qc}${root}/" \
"c" "c" {
"cc1/"
"cc2"
} "" "${qc}" false \
"expand mixed directory and file names"
- # GDB does not currently escape word break characters
- # (e.g. white space) correctly in unquoted filenames.
if { $qc ne "" } {
set sp " "
+ } else {
+ set sp "\\ "
+ }
- test_gdb_complete_multiple "file ${qc}${root}/aaa/" \
- "a" "a${sp}" {
- "aa bb"
- "aa cc"
- } "" "${qc}" false \
- "expand filenames containing spaces"
+ if { $qc eq "'" } {
+ set dq "\""
+ } else {
+ set dq "\\\""
+ }
+
+ test_gdb_complete_unique "${cmd} ${qc}${root}/bb2/dir${sp}1/" \
+ "${cmd} ${qc}${root}/bb2/dir${sp}1/unique${sp}file${qc}" " " \
+ false \
+ "expand a unique file name in a directory containing a space"
+
+ test_gdb_complete_filename_multiple "$cmd ${qc}${root}/bb2/" \
+ "d" "ir${sp}" {
+ "dir 1/"
+ "dir 2/"
+ } "" "${qc}" false \
+ "expand multiple directory names containing spaces"
+
+ test_gdb_complete_filename_multiple "${cmd} ${qc}${root}/bb2/dir${sp}2/" \
+ "f" "ile${sp}" {
+ "file 1"
+ "file 2"
+ } "" "${qc}" false \
+ "expand contents of a directory containing a space"
+
+ test_gdb_complete_filename_multiple "$cmd ${qc}${root}/aaa/" \
+ "a" "a${sp}" {
+ "aa bb"
+ "aa cc"
+ } "" "${qc}" false \
+ "expand filenames containing spaces"
+
+ test_gdb_complete_filename_multiple "$cmd ${qc}${root}/bb1/" \
+ "a" "a" {
+ "aa\"bb"
+ "aa'bb"
+ } "" "${qc}" false \
+ "expand filenames containing quotes"
+
+ test_gdb_complete_unique "$cmd ${qc}${root}/bb1/aa${dq}" \
+ "$cmd ${qc}${root}/bb1/aa${dq}bb${qc}" " " false \
+ "expand unique filename containing double quotes"
+
+ # It is not possible to include a single quote character
+ # within a single quoted string. However, GDB does not do
+ # anything smart if a user tries to do this. Avoid testing
+ # this case. Maybe in the future we'll figure a way to avoid
+ # this situation.
+ if { $qc ne "'" } {
+ if { $qc eq "" } {
+ set sq "\\'"
+ } else {
+ set sq "'"
+ }
+
+ test_gdb_complete_unique "$cmd ${qc}${root}/bb1/aa${sq}" \
+ "$cmd ${qc}${root}/bb1/aa${sq}bb${qc}" " " false \
+ "expand unique filename containing single quote"
}
}
+
+ gdb_exit
}
-gdb_start
+# Tests for completing a filename in the middle of a command line. This
+# represents a user typing out a command line then moving the cursor left
+# (e.g. with the left arrow key), editing a filename argument, and then
+# using tab completion to try and complete the filename even though there is
+# other content on the command line after the filename.
+proc run_mid_line_completion_tests { root cmd } {
+ gdb_start
+
+ test_tab_complete_within_line_unique \
+ "$cmd \"$root/bb2/dir 1/unique fi \"xxx\"" 6 "le\""
+
+ test_tab_complete_within_line_multiple \
+ "$cmd \"$root/aaa/a \"xxx\"" 6 "a " \
+ [list "aa bb" "aa cc"] \
+ "complete filename mid-line with multiple possibilities"
+
+ gdb_exit
+}
+
+# Run filename completion tests for those command that accept quoting and
+# escaping of the filename argument.
+#
+# ROOT is the base directory as returned from setup_directory_tree, though,
+# if ROOT is a sub-directory of the user's home directory ROOT might have
+# been modified to replace the $HOME prefix with a single "~" character.
+proc run_quoting_and_escaping_tests { root } {
+ # Test all the commands which allow quoting of filenames, and
+ # which require whitespace to be escaped in unquoted filenames.
+ foreach_with_prefix cmd { file exec-file symbol-file add-symbol-file \
+ remove-symbol-file \
+ "target core" "target exec" "target tfile" \
+ "maint print c-tdesc" "compile file" \
+ "save gdb-index" "save gdb-index -dwarf-5" } {
+ # Try each test placing the filename as the first argument
+ # then again with a quoted string immediately after the
+ # command. This works because the filename completer will
+ # complete any number of filenames, even if the command only
+ # takes a single filename.
+ foreach_with_prefix filler { "" " \"xxx\"" " 'zzz'" " yyy"} {
+ run_quoting_and_escaping_tests_1 $root "$cmd$filler"
+ }
+
+ run_mid_line_completion_tests $root $cmd
+ }
+}
+
+# Helper for run_unquoted_tests. ROOT is the root directory as setup
+# by setup_directory_tree. CMD is the GDB command to test. PREFIX is
+# a possible prefix filename to prepend to the filename being
+# completed.
+proc run_unquoted_tests_core { root cmd { prefix "" } } {
+ gdb_start
+
+ if { $prefix != "" } {
+ # Platform specific path separator (':' on UNIX, ';' on MS-DOS).
+ set pathsep $::tcl_platform(pathSeparator)
+
+ set prefix ${prefix}${pathsep}
+ }
+
+ test_gdb_complete_none "$cmd ${prefix}${root}${root}/xx" \
+ "expand a non-existent filename"
+
+ test_gdb_complete_unique "$cmd ${prefix}${root}/a" \
+ "$cmd ${prefix}${root}/aaa/" "" false \
+ "expand a unique filename"
+
+ test_gdb_complete_unique "$cmd ${prefix}${root}/bb2/dir 1/uni" \
+ "$cmd ${prefix}${root}/bb2/dir 1/unique file" " " false \
+ "expand a unique filename containing whitespace"
+
+ test_gdb_complete_multiple "$cmd ${prefix}${root}/" \
+ "b" "b" {
+ "bb1/"
+ "bb2/"
+ } "" "" false \
+ "expand multiple directory names"
+
+ test_gdb_complete_multiple "$cmd ${prefix}${root}/" \
+ "c" "c" {
+ "cc1/"
+ "cc2"
+ } "" "" false \
+ "expand mixed directory and file names"
+
+ test_gdb_complete_multiple "$cmd ${prefix}${root}/aaa/" \
+ "a" "a " {
+ "aa bb"
+ "aa cc"
+ } "" "" false \
+ "expand filenames containing spaces"
+
+ test_gdb_complete_multiple "$cmd ${prefix}${root}/bb2/dir 2/" \
+ "fi" "le " {
+ "file 1"
+ "file 2"
+ } "" "" false \
+ "expand filenames containing spaces in path"
+
+ gdb_exit
+}
+
+
+# Run filename completion tests for a sample of commands that take an
+# unquoted, unescaped filename as an argument. Only a sample of commands
+# are (currently) tested as there's a lot of commands that accept this style
+# of filename argument.
+#
+# ROOT is the base directory as returned from setup_directory_tree, though,
+# if ROOT is a sub-directory of the user's home directory ROOT might have
+# been modified to replace the $HOME prefix with a single "~" character.
+proc run_unquoted_tests { root } {
+ # Test all the commands which allow quoting of filenames, and
+ # which require whitespace to be escaped in unquoted filenames.
+ foreach_with_prefix cmd { "set logging file" "add-auto-load-safe-path" } {
+ run_unquoted_tests_core $root $cmd
+ }
+
+ foreach prefix [list \
+ "${root}/bb2/dir 1" \
+ "${root}/bb2/dir 1/unique file" \
+ "${root}/cc1" \
+ "${root}/cc2"] {
+
+ # Don't use the full path in the test name, just use the
+ # part after the ROOT directory.
+ set id [string range $prefix [string length ${root}] end]
+ with_test_prefix "prefix=$id" {
+ foreach_with_prefix cmd { "add-auto-load-safe-path" "path" } {
+ run_unquoted_tests_core $root $cmd $prefix
+ }
+ }
+ }
+}
set root [setup_directory_tree]
-run_tests $root
+run_quoting_and_escaping_tests $root
+run_unquoted_tests $root
# This test relies on using the $HOME directory. We could make this
# work for remote hosts, but right now, this isn't supported.
@@ -114,7 +523,8 @@ if {![is_remote host]} {
with_test_prefix "with tilde" {
# And rerun the tests.
- run_tests $tilde_root
+ run_quoting_and_escaping_tests $tilde_root
+ run_unquoted_tests $tilde_root
}
}
}
diff --git a/gdb/testsuite/gdb.base/foll-exec-mode.exp b/gdb/testsuite/gdb.base/foll-exec-mode.exp
index 65054b5..56a2ffc 100644
--- a/gdb/testsuite/gdb.base/foll-exec-mode.exp
+++ b/gdb/testsuite/gdb.base/foll-exec-mode.exp
@@ -127,7 +127,7 @@ proc do_follow_exec_mode_tests { mode cmd infswitch } {
# past it.
#
if {$cmd == "continue"} {
- gdb_breakpoint "$execd_line"
+ gdb_breakpoint "$execd_line" "allow-pending"
}
# Execute past the exec call.
diff --git a/gdb/testsuite/gdb.base/foll-exec.exp b/gdb/testsuite/gdb.base/foll-exec.exp
index e162cdf..206e713 100644
--- a/gdb/testsuite/gdb.base/foll-exec.exp
+++ b/gdb/testsuite/gdb.base/foll-exec.exp
@@ -139,23 +139,23 @@ proc do_exec_tests {} {
send_gdb "print global_i\n"
gdb_expect {
-re ".* = 0.*$gdb_prompt $"\
- {pass "print execd-program/global_i (after execlp)"}
- -re "$gdb_prompt $" {fail "print execd-program/global_i (after execlp)"}
- timeout {fail "(timeout) print execd-program/global_i (after execlp)"}
+ {pass "print execd-program/global_i, after execlp"}
+ -re "$gdb_prompt $" {fail "print execd-program/global_i, after execlp"}
+ timeout {fail "(timeout) print execd-program/global_i, after execlp"}
}
send_gdb "print local_j\n"
gdb_expect {
-re ".* = 2.*$gdb_prompt $"\
- {pass "print execd-program/local_j (after execlp)"}
- -re "$gdb_prompt $" {fail "print execd-program/local_j (after execlp)"}
- timeout {fail "(timeout) print execd-program/local_j (after execlp)"}
+ {pass "print execd-program/local_j, after execlp"}
+ -re "$gdb_prompt $" {fail "print execd-program/local_j, after execlp"}
+ timeout {fail "(timeout) print execd-program/local_j, after execlp"}
}
send_gdb "print local_k\n"
gdb_expect {
-re "No symbol \"local_k\" in current context.*$gdb_prompt $"\
- {pass "print follow-exec/local_k (after execlp)"}
- -re "$gdb_prompt $" {fail "print follow-exec/local_k (after execlp)"}
- timeout {fail "(timeout) print follow-exec/local_k (after execlp)"}
+ {pass "print follow-exec/local_k, after execlp"}
+ -re "$gdb_prompt $" {fail "print follow-exec/local_k, after execlp"}
+ timeout {fail "(timeout) print follow-exec/local_k, after execlp"}
}
# Explicitly kill this program, or a subsequent rerun actually runs
@@ -288,9 +288,9 @@ proc do_exec_tests {} {
send_gdb "print local_j\n"
gdb_expect {
-re ".* = 3.*$gdb_prompt $"\
- {pass "print execd-program/local_j (after execl)"}
- -re "$gdb_prompt $" {fail "print execd-program/local_j (after execl)"}
- timeout {fail "(timeout) print execd-program/local_j (after execl)"}
+ {pass "print execd-program/local_j, after execl"}
+ -re "$gdb_prompt $" {fail "print execd-program/local_j, after execl"}
+ timeout {fail "(timeout) print execd-program/local_j, after execl"}
}
# Explicitly kill this program, or a subsequent rerun actually runs
@@ -349,9 +349,9 @@ proc do_exec_tests {} {
send_gdb "print local_j\n"
gdb_expect {
-re ".* = 2.*$gdb_prompt $"\
- {pass "print execd-program/local_j (after execv)"}
- -re "$gdb_prompt $" {fail "print execd-program/local_j (after execv)"}
- timeout {fail "(timeout) print execd-program/local_j (after execv)"}
+ {pass "print execd-program/local_j, after execv"}
+ -re "$gdb_prompt $" {fail "print execd-program/local_j, after execv"}
+ timeout {fail "(timeout) print execd-program/local_j, after execv"}
}
# Explicitly kill this program, or a subsequent rerun actually runs
diff --git a/gdb/testsuite/gdb.base/gcorebg.c b/gdb/testsuite/gdb.base/gcorebg.c
new file mode 100644
index 0000000..9b585b5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/gcorebg.c
@@ -0,0 +1,76 @@
+/* Copyright 2007-2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+/* Expects 4 arguments:
+
+ 1. Either 'standard' or 'detached', where 'standard' tests
+ a general gcore script spawn with its controlling terminal available
+ and 'detached' tests gcore script spawn without its controlling
+ terminal available.
+ 2. Path to the gcore script.
+ 3. Path to the data-directory to pass to the gcore script.
+ 4. The core file output name. */
+
+int
+main (int argc, char **argv)
+{
+ pid_t pid = 0;
+ pid_t ppid;
+ char buf[1024*2 + 500];
+ int gotint, res;
+
+ assert (argc == 5);
+
+ pid = fork ();
+
+ switch (pid)
+ {
+ case 0:
+ if (strcmp (argv[1], "detached") == 0)
+ setpgrp ();
+ ppid = getppid ();
+ gotint = snprintf (buf, sizeof (buf), "%s -d %s -o %s %d",
+ argv[2], argv[3], argv[4], (int) ppid);
+ assert (gotint < sizeof (buf));
+ res = system (buf);
+ assert (res != -1);
+ break;
+
+ case -1:
+ perror ("fork err\n");
+ exit (1);
+ break;
+
+ default:
+ do
+ {
+ res = waitpid (pid, NULL, 0);
+ }
+ while (res == -1 && errno == EINTR);
+
+ assert (res == pid);
+ break;
+ }
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/gcorebg.exp b/gdb/testsuite/gdb.base/gcorebg.exp
new file mode 100644
index 0000000..c271251
--- /dev/null
+++ b/gdb/testsuite/gdb.base/gcorebg.exp
@@ -0,0 +1,82 @@
+# Copyright 2007-2024 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# This is a test for the gcore script (not the gcore command from
+# inside GDB). It also tests the gcore script being run without its
+# accessible terminal.
+
+standard_testfile
+require {!is_remote host}
+require {!is_remote target}
+require has_gcore_script
+require can_spawn_for_attach
+
+set corefile [standard_output_file ${testfile}.core]
+
+if {[build_executable "failed to build" $testfile ${srcfile}] == -1 } {
+ return -1
+}
+
+# Cleanup.
+
+proc core_clean {} {
+ global corefile
+
+ foreach file [glob -nocomplain [join [list $corefile *] ""]] {
+ verbose "Delete file $file" 1
+ remote_file target delete $file
+ }
+}
+core_clean
+
+# Generate the core file.
+proc test_body { detached } {
+ global binfile
+ global GCORE
+ global corefile
+ global GDB_DATA_DIRECTORY
+
+ # We can't use gdb_test_multiple here because GDB is not started.
+ set res [remote_spawn target "$binfile $detached $GCORE $GDB_DATA_DIRECTORY $corefile"]
+ if { ![gdb_assert { ![expr {$res < 0 || $res == ""}] } \
+ "spawned gcore"] } {
+ return
+ }
+
+ set saw_corefile_created false
+ set testname "Spawned gcore finished"
+ remote_expect target 20 {
+ timeout {
+ fail "$testname (timeout)"
+ remote_exec target "kill -9 -[exp_pid -i $res]"
+ return
+ }
+ -re "Saved corefile \[^\r\n\]+\r\n" {
+ set saw_corefile_created true
+ exp_continue
+ }
+ eof {
+ gdb_assert { $saw_corefile_created } $testname
+ }
+ }
+
+ gdb_assert {1 == [llength [glob -nocomplain [join [list $corefile *] ""]]]}\
+ "Core file generated by gcore"
+ core_clean
+}
+
+foreach_with_prefix detached { detached standard } {
+ test_body $detached
+}
diff --git a/gdb/testsuite/gdb.base/gnu-ifunc.exp b/gdb/testsuite/gdb.base/gnu-ifunc.exp
index 5bc534b..ff1d561 100644
--- a/gdb/testsuite/gdb.base/gnu-ifunc.exp
+++ b/gdb/testsuite/gdb.base/gnu-ifunc.exp
@@ -225,7 +225,7 @@ proc misc_tests {resolver_attr resolver_debug final_debug} {
return 1
}
- # The "if" condition is artifical to test regression of a former patch.
+ # The "if" condition is artificial to test regression of a former patch.
gdb_breakpoint "[gdb_get_line_number "break-at-nextcall"] if i && (int) gnu_ifunc (i) != 42"
gdb_breakpoint [gdb_get_line_number "break-at-call"]
diff --git a/gdb/testsuite/gdb.base/hbreak-unmapped.exp b/gdb/testsuite/gdb.base/hbreak-unmapped.exp
index ccb4b20..b28af6d 100644
--- a/gdb/testsuite/gdb.base/hbreak-unmapped.exp
+++ b/gdb/testsuite/gdb.base/hbreak-unmapped.exp
@@ -68,8 +68,7 @@ gdb_test "hbreak *0" "Hardware assisted breakpoint \[0-9\]+ at 0x0"
gdb_test "info break" "hw breakpoint.*y.*0x0\+\[ \t\]\+" \
"info break shows hw breakpoint"
-gdb_test_no_output "delete \$bpnum" "" "delete" \
- "delete hw breakpoint"
+gdb_test_no_output "delete \$bpnum" "delete hw breakpoint"
gdb_test "info break" "No breakpoints, watchpoints, tracepoints, or catchpoints\." \
"info break shows no breakpoints, watchpoints, tracepoints, or catchpoints"
diff --git a/gdb/testsuite/gdb.base/hbreak2.exp b/gdb/testsuite/gdb.base/hbreak2.exp
index 8f5735b..37c001a 100644
--- a/gdb/testsuite/gdb.base/hbreak2.exp
+++ b/gdb/testsuite/gdb.base/hbreak2.exp
@@ -150,7 +150,7 @@ delete_breakpoints
#
gdb_test "hbreak -q main" \
"Hardware assisted breakpoint.*at.* file .*$srcfile, line.*" \
- "hardware breakpoint function (2)"
+ "hardware breakpoint function, 2"
gdb_run_cmd
gdb_test "" \
"Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$srcfile:$bp_location6.*$bp_location6\[\t \]+if .argc.* \{.*" \
@@ -162,7 +162,7 @@ delete_breakpoints
#
gdb_test "hbreak $bp_location1" \
"Hardware assisted breakpoint.*at.* file .*$srcfile, line $bp_location1\\." \
- "hardware breakpoint line number (2)"
+ "hardware breakpoint line number, 2"
gdb_test "continue" \
"Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:$bp_location1.*$bp_location1\[\t \]+printf.*factorial.*" \
"run until breakpoint set at a line number"
@@ -173,7 +173,7 @@ delete_breakpoints
#
gdb_test "hbreak $srcfile:factorial" \
"Hardware assisted breakpoint.*at.* file .*$srcfile, line.*" \
- "hardware breakpoint function in file (2)"
+ "hardware breakpoint function in file, 2"
for {set i 6} {$i >= 1} {incr i -1} {
gdb_test "continue" \
"Continuing\\..*Breakpoint \[0-9\]+, factorial \\(value=$i\\) at .*$srcfile:$bp_location7.*$bp_location7\[\t \]+.*if .value > 1. \{.*" \
@@ -186,7 +186,7 @@ delete_breakpoints
#
gdb_test "hbreak \"marker2\"" \
"Hardware assisted breakpoint.*at.* file .*$srcfile1, line.*" \
- "hardware breakpoint quoted function (2)"
+ "hardware breakpoint quoted function, 2"
gdb_test "continue" \
"Continuing\\..*Breakpoint \[0-9\]+, (0x\[0-9a-f\]+ in )?marker2 \\(a=43\\) at .*$srcfile1:$bp_location8.*" \
"run until quoted breakpoint"
@@ -196,7 +196,7 @@ delete_breakpoints
#
gdb_test "hbreak $srcfile:$bp_location2" \
"Hardware assisted breakpoint.*at.* file .*$srcfile, line $bp_location2\\." \
- "hardware breakpoint line number in file (2)"
+ "hardware breakpoint line number in file, 2"
gdb_test "continue" \
"Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:$bp_location2.*$bp_location2\[\t \]+argc = \\(argc == 12345\\);.*" \
"run until file:linenum breakpoint"
@@ -296,7 +296,7 @@ if {![runto_main]} {
#
gdb_test_no_output "set breakpoint pending off"
gdb_test "hbreak 999" \
- "No line 999 in the current file." \
+ "^No compiled code for line 999 in the current file\\." \
"hardware break on non-existent source line"
# Run to the desired default location. If not positioned here, the
diff --git a/gdb/testsuite/gdb.base/history-duplicates.exp b/gdb/testsuite/gdb.base/history-duplicates.exp
index b2f30e6..5ac4a35 100644
--- a/gdb/testsuite/gdb.base/history-duplicates.exp
+++ b/gdb/testsuite/gdb.base/history-duplicates.exp
@@ -46,7 +46,7 @@ proc run_print_on_each_thing { things } {
set index 0
foreach thing $things {
- gdb_test "print $thing" "" "printing $thing (item #$index)"
+ gdb_test "print $thing" "" "printing $thing, item #$index"
incr index
}
}
@@ -90,8 +90,8 @@ with_test_prefix "remove-duplicates=1" {
check_prev_history_entry "print 1"
check_prev_history_entry "print 2"
check_prev_history_entry "print 0"
- check_prev_history_entry "print 1" "(again)"
- check_prev_history_entry "print 0" "(again)"
+ check_prev_history_entry "print 1" ", again"
+ check_prev_history_entry "print 0" ", again"
}
@@ -104,9 +104,9 @@ with_test_prefix "remove-duplicates=0" {
run_print_on_each_thing { 0 0 1 1 }
check_prev_history_entry "print 1"
- check_prev_history_entry "print 1" "(again)"
+ check_prev_history_entry "print 1" ", again"
check_prev_history_entry "print 0"
- check_prev_history_entry "print 0" "(again)"
+ check_prev_history_entry "print 0" ", again"
}
diff --git a/gdb/testsuite/gdb.base/index-cache.exp b/gdb/testsuite/gdb.base/index-cache.exp
index 0e19bfb..af64faa 100644
--- a/gdb/testsuite/gdb.base/index-cache.exp
+++ b/gdb/testsuite/gdb.base/index-cache.exp
@@ -19,7 +19,7 @@
standard_testfile .c -2.c
if { [build_executable "failed to prepare" $testfile [list $srcfile $srcfile2] \
- {debug ldflags=-Wl,--build-id}] } {
+ {debug build-id}] } {
return
}
diff --git a/gdb/testsuite/gdb.base/info_sources_2.exp b/gdb/testsuite/gdb.base/info_sources_2.exp
index aa33f38..90442d0 100644
--- a/gdb/testsuite/gdb.base/info_sources_2.exp
+++ b/gdb/testsuite/gdb.base/info_sources_2.exp
@@ -120,7 +120,7 @@ proc run_info_sources { extra_args args } {
}
}
- # Now check ARGS agaisnt the values held in INFO_SOURCES map.
+ # Now check ARGS against the values held in INFO_SOURCES map.
foreach {objfile sourcefile} $args {
# First, figure out if we're expecting SOURCEFILE to be present,
# or not.
diff --git a/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.exp b/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.exp
index 85e3cc3..45086f6 100644
--- a/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.exp
+++ b/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.exp
@@ -37,7 +37,7 @@
# mechanism such that the fact that "inline_frame" was inlined into
# "normal_frame" would cause GDB to trigger an assertion.
#
-# This text makes use of a Python unwinder which can fake the cyclic
+# This test makes use of a Python unwinder which can fake the cyclic
# stack cycle, further the test sets up multiple levels of normal and
# inline frames. At the point of testing the stack looks like this:
#
diff --git a/gdb/testsuite/gdb.base/interact.exp b/gdb/testsuite/gdb.base/interact.exp
index b7a30e0..5779efc 100644
--- a/gdb/testsuite/gdb.base/interact.exp
+++ b/gdb/testsuite/gdb.base/interact.exp
@@ -38,7 +38,7 @@ gdb_test "source $script" "$script_output" \
gdb_test "print 3" "= 3" "sanity check with interactive-mode auto"
gdb_test "show interactive-mode" \
"Debugger's interactive mode is auto \\(currently .*\\)\\." \
- "show interactive-mode (auto)"
+ "show interactive-mode, auto"
# Test sourcing of the script with interactive mode `on'.
# Verify that evaluating the script does not cause an unexpected
@@ -49,7 +49,7 @@ gdb_test "source $script" "$script_output" \
gdb_test "print 4" "= 4" "sanity check with interactive-mode on"
gdb_test "show interactive-mode" \
"Debugger's interactive mode is on\\." \
- "show interactive-mode (on)"
+ "show interactive-mode, on"
# Test sourcing of the script with interactive mode `off'.
# Verify that evaluating the script does not cause an unexpected
@@ -60,5 +60,5 @@ gdb_test "source $script" "$script_output" \
gdb_test "print 5" "= 5" "sanity check with interactive-mode off"
gdb_test "show interactive-mode" \
"Debugger's interactive mode is off\\." \
- "show interactive-mode (off)"
+ "show interactive-mode, off"
diff --git a/gdb/testsuite/gdb.base/killed-outside.exp b/gdb/testsuite/gdb.base/killed-outside.exp
index 87bd7be..88f4afe 100644
--- a/gdb/testsuite/gdb.base/killed-outside.exp
+++ b/gdb/testsuite/gdb.base/killed-outside.exp
@@ -102,7 +102,7 @@ with_test_prefix "continue" {
}
}
-# Try stepping the program. Stepping may go through diferent code
+# Try stepping the program. Stepping may go through different code
# paths in the target backends.
with_test_prefix "stepi" {
test {
diff --git a/gdb/testsuite/gdb.base/limited-length.c b/gdb/testsuite/gdb.base/limited-length.c
index 627c34d..c8ece16 100644
--- a/gdb/testsuite/gdb.base/limited-length.c
+++ b/gdb/testsuite/gdb.base/limited-length.c
@@ -41,6 +41,8 @@ int large_2d_array[][10] = {
{90, 91, 92, 93, 94, 95, 96, 97, 98, 99}
};
+char large_empty_string[100000] = "";
+
int
main ()
{
diff --git a/gdb/testsuite/gdb.base/limited-length.exp b/gdb/testsuite/gdb.base/limited-length.exp
index a24adcb..2d160e1 100644
--- a/gdb/testsuite/gdb.base/limited-length.exp
+++ b/gdb/testsuite/gdb.base/limited-length.exp
@@ -240,3 +240,13 @@ with_test_prefix "with unlimited print elements" {
"value is not available" \
"output expression referring unavailable element from history"
}
+
+gdb_test_no_output "set max-value-size 10000"
+gdb_test_no_output "set print elements 200"
+
+gdb_test "print large_empty_string" \
+ " = \\\{0 '\\\\000' <repeats 10000 times>, <unavailable> <repeats 90000 times>\\\}" \
+ "print large empty string which is not fully available"
+gdb_test -nonl "output large_empty_string" \
+ "\\\{0 '\\\\000' <repeats 10000 times>, <unavailable> <repeats 90000 times>\\\}" \
+ "output large empty string which is not fully available"
diff --git a/gdb/testsuite/gdb.base/lineinc.exp b/gdb/testsuite/gdb.base/lineinc.exp
index 1fe1390..2386113 100644
--- a/gdb/testsuite/gdb.base/lineinc.exp
+++ b/gdb/testsuite/gdb.base/lineinc.exp
@@ -70,7 +70,7 @@
# #included by a given source file in a list sorted by the line at
# which they were #included; this gives GDB the chance to detect
# multiple #inclusions at the same line, complain, and assign
-# distinct, albiet incorrect, line numbers to each #inclusion.
+# distinct, albeit incorrect, line numbers to each #inclusion.
#
# However, at one point GDB was sorting the list in reverse order,
# while the code to assign new, distinct line numbers assumed it was
diff --git a/gdb/testsuite/gdb.base/list-ambiguous0.c b/gdb/testsuite/gdb.base/list-ambiguous0.c
index cff16e5..db11702 100644
--- a/gdb/testsuite/gdb.base/list-ambiguous0.c
+++ b/gdb/testsuite/gdb.base/list-ambiguous0.c
@@ -37,6 +37,6 @@ static int __attribute__ ((used)) ambiguous_var;
int
main (void)
-{
+{ /* main prologue */
return 0;
}
diff --git a/gdb/testsuite/gdb.base/list-before-start.exp b/gdb/testsuite/gdb.base/list-before-start.exp
new file mode 100644
index 0000000..5499257
--- /dev/null
+++ b/gdb/testsuite/gdb.base/list-before-start.exp
@@ -0,0 +1,36 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test the "list" command to print the location around main before the
+# program is started.
+
+standard_testfile list-ambiguous0.c
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} {
+ return -1
+}
+
+set fill "${decimal}\\s+\[^\n\r\]+"
+
+gdb_test_no_output "set listsize 10"
+
+gdb_test "list" \
+ [multi_line \
+ "${decimal}\\s+" \
+ "${decimal}\\s+int" \
+ "${decimal}\\s+main\[^\n\r\]+" \
+ "${decimal}\\s+\\{ /\\* main prologue \\*/" \
+ "${fill}" \
+ "${fill}" ]
diff --git a/gdb/testsuite/gdb.base/list-dot-nodebug.exp b/gdb/testsuite/gdb.base/list-dot-nodebug.exp
index c9d732e..b7359be 100644
--- a/gdb/testsuite/gdb.base/list-dot-nodebug.exp
+++ b/gdb/testsuite/gdb.base/list-dot-nodebug.exp
@@ -34,21 +34,36 @@ standard_testfile .c -extra.c
foreach_with_prefix debug {"none" "some"} {
- set flags "nodebug"
if {$debug == "some"} {
- set flags "debug"
- }
+ if {[prepare_for_testing_full "failed to prepare" \
+ [list ${testfile}-${debug} $linkflags \
+ $srcfile [list nodebug] \
+ $srcfile2 [list debug]]]} {
+ return -1
+ }
- if {[prepare_for_testing_full "failed to prepare" \
- [list ${testfile}-${debug} $linkflags \
- $srcfile [list nodebug] \
- $srcfile2 [list $debug]]]} {
- return -1
+ # We don't test "list ." before starting with some debug info
+ # because GDB will choose the symtab that has debuginfo, and
+ # print the copyright blurb. This test isn't interested (yet?)
+ # in checking if this default location choice is consistent.
+ } else {
+ set executable ${testfile}-none
+ if {[build_executable "failed to prepare" ${executable} \
+ [list $srcfile $srcfile2] $linkflags]} {
+ return -1
+ }
+
+ # Stripping is a backup in case the system has static libc debuginfo.
+ # We can continue the test even if it fails.
+ gdb_gnu_strip_debug $executable no-debuglink
+
+ clean_restart ${executable}
+
+ gdb_test "list ." \
+ "^Insufficient debug info for showing source lines at default location" \
+ "print before start"
}
- gdb_test "list ." \
- "^Insufficient debug info for showing source lines at default location" \
- "print before start"
if { ![runto bar] } {
return -1
diff --git a/gdb/testsuite/gdb.base/maint-info-inline-frames-and-blocks.c b/gdb/testsuite/gdb.base/maint-info-inline-frames-and-blocks.c
new file mode 100644
index 0000000..35b2064
--- /dev/null
+++ b/gdb/testsuite/gdb.base/maint-info-inline-frames-and-blocks.c
@@ -0,0 +1,57 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+static void inline_func_a (void);
+static void inline_func_b (void);
+static void normal_func (void);
+
+volatile int global_var = 0;
+
+static void __attribute__((noinline))
+normal_func (void)
+{
+ /* Do some work. */
+ ++global_var;
+ ++global_var;
+
+ /* Now the inline function. */
+ inline_func_a ();
+
+ /* Do some work. */
+ ++global_var; /* After inline function. */
+ ++global_var;
+}
+
+static inline void __attribute__((__always_inline__))
+inline_func_a (void)
+{
+ inline_func_b ();
+}
+
+static inline void __attribute__((__always_inline__))
+inline_func_b (void)
+{
+ ++global_var;
+ ++global_var;
+}
+
+int
+main ()
+{
+ normal_func ();
+ return 0;
+}
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
new file mode 100644
index 0000000..16be22a
--- /dev/null
+++ b/gdb/testsuite/gdb.base/maint-info-inline-frames-and-blocks.exp
@@ -0,0 +1,214 @@
+# Copyright (C) 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Check the 'maint info inline-frames' and 'maint info blocks'
+# commands.
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
+ {debug nopie}]} {
+ return -1
+}
+
+if {![runto normal_func]} {
+ return 0
+}
+
+# Make a pattern to match 'maint info blocks' output. ARGS is the
+# list of function names we expect to see. If the function name
+# starts with 'inline_func' then we expect to see an inline block,
+# otherwise blocks are not expected to be inline.
+proc make_blocks_result { args } {
+ set result \
+ [list \
+ "Blocks at $::hex:" \
+ " from objfile: \\\[\\(objfile \\*\\) $::hex\\\] [string_to_regexp $::binfile]" \
+ ""\
+ "\\\[\\(block \\*\\) $::hex\\\] $::hex\\.\\.$::hex" \
+ " entry pc: $::hex" \
+ " is global block" \
+ ".*" \
+ "\\\[\\(block \\*\\) $::hex\\\] $::hex\\.\\.$::hex" \
+ " entry pc: $::hex" \
+ " is static block" \
+ ".*" ]
+
+ foreach func $args {
+ lappend result \
+ "\\\[\\(block \\*\\) $::hex\\\] $::hex\\.\\.$::hex" \
+ " entry pc: $::hex"
+
+ if { [string range $func 0 10] eq "inline_func" } {
+ lappend result" inline function: $func"
+ } else {
+ lappend result" function: $func"
+ }
+
+ lappend result ".*"
+ }
+
+ return [multi_line {*}$result]
+}
+
+gdb_test "maint info blocks" [make_blocks_result normal_func] \
+ "maint info blocks in normal_func only"
+
+# Next forward until we find the call to inline_func_a(). The hope is
+# that when we see the 'inline_func_a()' line this will be the start of
+# the inlined function. This might not be the case on all
+# architectures if the compiler needs to perform some preamble.
+gdb_test_multiple "next" "next forward to inline_func_a" {
+ -re "^$decimal\\s+inline_func_a \\(\\);\r\n" {
+ # Consume the next prompt.
+ gdb_expect {
+ -re "^$gdb_prompt $" {}
+ }
+ pass $gdb_test_name
+ }
+
+ -re "^$decimal\\s+\[^\r\n\]+After inline function\[^\r\n\]+\r\n" {
+ # We've gone too far!
+ fail $gdb_test_name
+ }
+
+ -re "^$decimal\\s+\[^\r\n\]+\r\n" {
+ send_gdb "next\n"
+ exp_continue
+ }
+
+ -re "^\[^\r\n\]+\r\n" {
+ exp_continue
+ }
+}
+
+gdb_test "maint info blocks" [make_blocks_result normal_func \
+ inline_func_a inline_func_b] \
+ "maint info blocks when all blocks visible"
+
+# View the inline frame information. This should display that we are
+# at the start of inline_func_a() within normal_func().
+gdb_test "maint info inline-frames" \
+ [multi_line \
+ "^Cached inline state information for thread $decimal\\." \
+ "program counter = $hex" \
+ "skipped frames = 2" \
+ " inline_func_b" \
+ " inline_func_a" \
+ "> normal_func"] \
+ "check inline-frames state when in normal_func"
+
+# Step, we should now enter the inlined function.
+gdb_test "step" ".*" \
+ "step to enter inline_func"
+
+# And the inline-frames information should update.
+gdb_test "maint info inline-frames" \
+ [multi_line \
+ "^Cached inline state information for thread $decimal\\." \
+ "program counter = $hex" \
+ "skipped frames = 1" \
+ " inline_func_b" \
+ "> inline_func_a" \
+ " normal_func"] \
+ "check inline-frames state when just entered inline_func_a"
+
+# Record the current program counter.
+set pc [get_hexadecimal_valueof "\$pc" "UNKNOWN"]
+
+# Use the recorded $pc value to check inline frames.
+gdb_test "maint info inline-frames $pc" \
+ [multi_line \
+ "^program counter = $hex" \
+ "skipped frames = 2" \
+ " inline_func_b" \
+ " inline_func_a" \
+ "> normal_func"] \
+ "check inline-frames state at recorded \$pc while at the \$pc"
+
+# Step again, we should now enter inlined_func_b().
+gdb_test "step" ".*" \
+ "step into inline_func_b"
+
+gdb_test "maint info inline-frames" \
+ [multi_line \
+ "^Cached inline state information for thread $decimal\\." \
+ "program counter = $hex" \
+ "skipped frames = 0" \
+ "> inline_func_b" \
+ " inline_func_a" \
+ " normal_func"] \
+ "check inline-frames state when just entered inline_func_b"
+
+gdb_test "maint info blocks" [make_blocks_result normal_func \
+ inline_func_a inline_func_b] \
+ "maint info blocks when all blocks still visible"
+
+gdb_test "step" ".*" \
+ "step into the body of inline_func_b"
+
+# Now we are no longer at the start of the inlined function we should
+# no longer see normal_func() in the inline-frames information.
+gdb_test "maint info inline-frames" \
+ [multi_line \
+ "^Cached inline state information for thread $decimal\\." \
+ "program counter = $hex" \
+ "skipped frames = 0" \
+ "> inline_func_b"] \
+ "check inline-frames state when within inline_func_b"
+
+gdb_test "maint info blocks" [make_blocks_result normal_func \
+ inline_func_a inline_func_b] \
+ "maint info blocks within inline function, all blocks still visible"
+
+# Use the recorded $pc value to check inline frames.
+gdb_test "maint info inline-frames $pc" \
+ [multi_line \
+ "^program counter = $hex" \
+ "skipped frames = 2" \
+ " inline_func_b" \
+ " inline_func_a" \
+ "> normal_func"] \
+ "check inline-frames state at recorded \$pc"
+
+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
+
+# Use the recorded $pc value to check inline frames when the inferior
+# is not executing.
+gdb_test "maint info inline-frames $pc" \
+ [multi_line \
+ "^program counter = $hex" \
+ "skipped frames = 2" \
+ " inline_func_b" \
+ " inline_func_a" \
+ "> normal_func"] \
+ "check inline-frames state at recorded \$pc before execution starts"
+
+gdb_test "maint info blocks $pc" [make_blocks_result normal_func \
+ inline_func_a inline_func_b] \
+ "maint info blocks using stored \$pc, inferior not running"
+
+# Trying to read the $pc from the current thread should fail if the
+# inferior is not yet running.
+gdb_test "maint info inline-frames" \
+ "^no inferior thread" \
+ "check inline-frames state of current thread before execution starts"
+
+gdb_test "maint info blocks" "^no inferior thread" \
+ "maint info blocks with no \$pc and inferior not running"
diff --git a/gdb/testsuite/gdb.base/new-ui.exp b/gdb/testsuite/gdb.base/new-ui.exp
index 2dfcbf7..a56d213 100644
--- a/gdb/testsuite/gdb.base/new-ui.exp
+++ b/gdb/testsuite/gdb.base/new-ui.exp
@@ -184,9 +184,11 @@ proc_with_prefix do_test_invalid_args {} {
"new-ui with bad interpreter name"
# Test that the TUI cannot be used for a new UI.
- gdb_test "new-ui tui $extra_tty_name" \
- "interpreter 'tui' cannot be used with a new UI" \
- "new-ui with tui"
+ if [allow_tui_tests] {
+ gdb_test "new-ui tui $extra_tty_name" \
+ "interpreter 'tui' cannot be used with a new UI" \
+ "new-ui with tui"
+ }
# Test that we can continue working normally.
if ![runto_main] {
diff --git a/gdb/testsuite/gdb.base/opaque.exp b/gdb/testsuite/gdb.base/opaque.exp
index 1bd1918..d803714 100644
--- a/gdb/testsuite/gdb.base/opaque.exp
+++ b/gdb/testsuite/gdb.base/opaque.exp
@@ -66,7 +66,7 @@ if {[istarget "rs6000-*-aix*"] && !$gcc_compiled} {
setup_xfail_on_opaque_pointer
gdb_test "whatis foop" \
"type = struct foo \[*\]+" \
- "whatis on opaque struct pointer (statically)"
+ "whatis on opaque struct pointer, statically"
# Ensure that we know the form of the structure that foop points to.
@@ -122,7 +122,7 @@ if ![runto_main] {
setup_xfail_on_opaque_pointer
gdb_test "whatis foop" \
"type = struct foo \[*\]+" \
- "whatis on opaque struct pointer (dynamically)"
+ "whatis on opaque struct pointer, dynamically"
# Ensure that we know the form of the thing foop points to.
@@ -131,18 +131,18 @@ setup_xfail_on_opaque_pointer
if {!$gcc_compiled} { setup_xfail "rs6000-*-*" }
gdb_test "ptype foop" \
"type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\} \[*\]+" \
- "ptype on opaque struct pointer (dynamically) 1"
+ "ptype on opaque struct pointer, dynamically 1"
gdb_test "whatis afoo" \
"type = struct foo" \
- "whatis on opaque struct instance (dynamically) 1"
+ "whatis on opaque struct instance, dynamically 1"
# Ensure that we know the form of afoo, an instance of a struct foo.
gdb_test "ptype afoo" \
"type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\}" \
- "ptype on opaque struct instance (dynamically) 1"
+ "ptype on opaque struct instance, dynamically 1"
# Ensure that we know the form of an explicit struct foo.
@@ -150,7 +150,7 @@ gdb_test "ptype afoo" \
if {!$gcc_compiled} { setup_xfail "rs6000-*-*" }
gdb_test "ptype struct foo" \
"type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\}" \
- "ptype on opaque struct tagname (dynamically) 1"
+ "ptype on opaque struct tagname, dynamically 1"
# Now reload the symbols again so we forget about anything we might
@@ -170,7 +170,7 @@ if ![runto getfoo] {
setup_xfail_on_opaque_pointer
gdb_test "whatis foop" \
"type = struct foo \[*\]+" \
- "whatis on opaque struct pointer (dynamically) 1"
+ "whatis on opaque struct pointer, dynamically 1"
# Ensure that we know the form of the thing foop points to.
@@ -178,22 +178,22 @@ gdb_test "whatis foop" \
setup_xfail_on_opaque_pointer
gdb_test "ptype foop" \
"type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\} \[*\]+" \
- "ptype on opaque struct pointer (dynamically) 2"
+ "ptype on opaque struct pointer, dynamically 2"
gdb_test "whatis afoo" \
"type = struct foo" \
- "whatis on opaque struct instance (dynamically) 2"
+ "whatis on opaque struct instance, dynamically 2"
# Ensure that we know the form of afoo, an instance of a struct foo.
gdb_test "ptype afoo" \
"type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\}" \
- "ptype on opaque struct instance (dynamically) 2"
+ "ptype on opaque struct instance, dynamically 2"
# Ensure that we know the form of an explicit struct foo.
gdb_test "ptype struct foo" \
"type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\}" \
- "ptype on opaque struct tagname (dynamically) 2"
+ "ptype on opaque struct tagname, dynamically 2"
diff --git a/gdb/testsuite/gdb.base/overlays.exp b/gdb/testsuite/gdb.base/overlays.exp
index 2adde30..c8730ec 100644
--- a/gdb/testsuite/gdb.base/overlays.exp
+++ b/gdb/testsuite/gdb.base/overlays.exp
@@ -150,7 +150,7 @@ if {$data_overlays} {
}
# Verify that early-mapped overlays have been bumped out
-# by later-mapped overlays layed over in the same VMA range.
+# by later-mapped overlays laid over in the same VMA range.
send_gdb "overlay list\n"
gdb_expect {
diff --git a/gdb/testsuite/gdb.base/pending.exp b/gdb/testsuite/gdb.base/pending.exp
index 737b0c4..833e084 100644
--- a/gdb/testsuite/gdb.base/pending.exp
+++ b/gdb/testsuite/gdb.base/pending.exp
@@ -39,7 +39,7 @@ clean_restart
gdb_test_multiple "break pendfunc1" "set pending breakpoint" {
-re ".*Make breakpoint pending.*y or \\\[n\\\]. $" {
- gdb_test "y" "Breakpoint.*pendfunc1.*pending." "set pending breakpoint (without symbols)"
+ gdb_test "y" "Breakpoint.*pendfunc1.*pending." "set pending breakpoint, without symbols"
}
}
@@ -49,7 +49,7 @@ gdb_test "complete condition " "condition 1"
gdb_test "info break" \
"Num Type\[ \]+Disp Enb Address\[ \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendfunc1.*" \
-"single pending breakpoint info (without symbols)"
+"single pending breakpoint info, without symbols"
with_test_prefix "first load" {
gdb_load ${binfile}
@@ -170,7 +170,8 @@ gdb_test "info break" \
\[\t \]+stop only if k == 1.*
\[\t \]+print k.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp2_loc if x > 3.*" \
+\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp2_loc.*
+\\s+stop only if x > 3.*" \
"multiple pending breakpoints"
@@ -195,8 +196,10 @@ gdb_test "info break" \
\[\t \]+stop only if k == 1.*
\[\t \]+print k.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp2_loc if x > 3.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp3_loc.*ignore next 2 hits.*" \
+\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp2_loc.*
+\\s+stop only if x > 3.*
+\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp3_loc.*
+\\s+ignore next 2 hits.*" \
"multiple pending breakpoints 2"
#
@@ -267,3 +270,24 @@ gdb_test "info break" \
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.*
\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*imaginary.*" \
"verify pending breakpoint after restart"
+
+# Test GDB's parsing of pending breakpoint thread and condition.
+
+gdb_test_no_output "set breakpoint pending on"
+gdb_test "break foo if (unknown_var && another_unknown_var) thread 1" \
+ "Breakpoint $decimal \\(foo\\) pending\\."
+set bpnum [get_integer_valueof "\$bpnum" "*INVALID" \
+ "get number for foo breakpoint"]
+
+if {[gdb_protocol_is_remote]} {
+ set evals_re "(?: \\(\[^) \]+ evals\\))?"
+} else {
+ set evals_re ""
+}
+
+gdb_test "info breakpoints $bpnum" \
+ [multi_line \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
+ "\\s+stop only if \\(unknown_var && another_unknown_var\\)${evals_re}" \
+ "\\s+stop only in thread 1"] \
+ "check pending breakpoint on foo"
diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp
index 9132071a..40176c6 100644
--- a/gdb/testsuite/gdb.base/printcmds.exp
+++ b/gdb/testsuite/gdb.base/printcmds.exp
@@ -1186,7 +1186,7 @@ gdb_test_no_output "complete p -source"
gdb_file_cmd ${binfile}
-gdb_test "print \$pc" "No registers\\." "print \$pc (with file)"
+gdb_test {print $pc} [string_to_regexp "No registers."] {print $pc, with file}
gdb_test_no_output "set print sevenbit-strings"
gdb_test_no_output "set print address off"
diff --git a/gdb/testsuite/gdb.base/recurse.exp b/gdb/testsuite/gdb.base/recurse.exp
index f5f0760..01ba55a 100644
--- a/gdb/testsuite/gdb.base/recurse.exp
+++ b/gdb/testsuite/gdb.base/recurse.exp
@@ -52,15 +52,15 @@ proc recurse_tests {} {
# Continue inward for a few iterations
gdb_test "continue" "Breakpoint.* recurse \\(a=9\\).*" \
- "continue to recurse (a = 9)"
+ "continue to recurse, a = 9"
gdb_test "continue" "Breakpoint.* recurse \\(a=8\\).*" \
- "continue to recurse (a = 8)"
+ "continue to recurse, a = 8"
gdb_test "continue" "Breakpoint.* recurse \\(a=7\\).*" \
- "continue to recurse (a = 7)"
+ "continue to recurse, a = 7"
gdb_test "continue" "Breakpoint.* recurse \\(a=6\\).*" \
- "continue to recurse (a = 6)"
+ "continue to recurse, a = 6"
gdb_test "continue" "Breakpoint.* recurse \\(a=5\\).*" \
- "continue to recurse (a = 5)"
+ "continue to recurse, a = 5"
# Put a watchpoint on another instance of b
# First we need to step over the assignment of b, so it has a known
@@ -76,13 +76,13 @@ proc recurse_tests {} {
# Continue inward for a few iterations
gdb_test "continue" "Breakpoint.* recurse \\(a=4\\).*" \
- "continue to recurse (a = 4)"
+ "continue to recurse, a = 4"
gdb_test "continue" "Breakpoint.* recurse \\(a=3\\).*" \
- "continue to recurse (a = 3)"
+ "continue to recurse, a = 3"
gdb_test "continue" "Breakpoint.* recurse \\(a=2\\).*" \
- "continue to recurse (a = 2)"
+ "continue to recurse, a = 2"
gdb_test "continue" "Breakpoint.* recurse \\(a=1\\).*" \
- "continue to recurse (a = 1)"
+ "continue to recurse, a = 1"
# Continue until second set of b (second instance).
gdb_test "continue" \
diff --git a/gdb/testsuite/gdb.base/reggroups.exp b/gdb/testsuite/gdb.base/reggroups.exp
index f96153b..56c00e5 100644
--- a/gdb/testsuite/gdb.base/reggroups.exp
+++ b/gdb/testsuite/gdb.base/reggroups.exp
@@ -27,7 +27,7 @@ if {![runto_main]} {
return 0
}
-set invalid_register_re "Invalid register .*"
+set invalid_register_re "Invalid register \[^\r\n\]*"
# Fetch all reggroups from 'maint print reggroups'.
@@ -51,6 +51,7 @@ proc fetch_reggroups {test} {
}
}
+ verbose -log "found reggroups: $reggroups"
return $reggroups
}
@@ -78,21 +79,34 @@ proc fetch_reggroup_regs {reggroup test} {
# xmm0 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, ... }}
#
set regs {}
- gdb_test_multiple "info reg $reggroup" $test {
- -re "info reg $reggroup\r\n" {
+ set have_invalid_register_fail 0
+ set re_regname "\[0-9a-zA-Z_-\]+"
+ set re_hws "\[ \t\]+"
+ set re_hs "\[^\n\r\]+"
+ set re_eol "\r\n"
+ set re_lookahead_eol "(?=$re_eol)"
+ gdb_test_multiple "info reg $reggroup" $test -lbl {
+ -re "^info reg $reggroup" {
exp_continue
}
- -re "^(\[0-9a-zA-Z-\]+)\[ \t\]+(0x\[0-9a-f\]+)\[ \t\]+(\[^\n\r\]+)\r\n" {
+ -re "^${re_eol}($re_regname)$re_hws$::hex$re_hws${re_hs}$re_lookahead_eol" {
lappend regs $expect_out(1,string)
exp_continue
}
-re $invalid_register_re {
- fail "$test (unexpected invalid register response)"
+ set have_invalid_register_fail 1
+ exp_continue
}
- -re "$gdb_prompt $" {
- pass $test
+ -re -wrap "" {
+ if { $have_invalid_register_fail } {
+ fail "$test (unexpected invalid register response)"
+ } else {
+ pass $test
+ }
}
}
+
+ verbose -log "found regs in reggroup $reggroup: [join $regs]"
return $regs
}
diff --git a/gdb/testsuite/gdb.base/remote.exp b/gdb/testsuite/gdb.base/remote.exp
index 015cc56..52c4d27 100644
--- a/gdb/testsuite/gdb.base/remote.exp
+++ b/gdb/testsuite/gdb.base/remote.exp
@@ -167,7 +167,7 @@ set sizeof_random_data [get_sizeof "random_data" 48*1024]
clean_restart $binfile
#
-# Part THREE: Check the upload behavour
+# Part THREE: Check the upload behavior.
#
if {![runto_main]} {
return
diff --git a/gdb/testsuite/gdb.base/reset-catchpoint-cond-lib.c b/gdb/testsuite/gdb.base/reset-catchpoint-cond-lib.c
new file mode 100644
index 0000000..06f3c3d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/reset-catchpoint-cond-lib.c
@@ -0,0 +1,75 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <assert.h>
+#include <stdlib.h>
+
+/* This type is used by GDB. */
+struct lib_type
+{
+ int a;
+ int b;
+ int c;
+};
+
+/* Ensure the type above is used. */
+volatile struct lib_type global_lib_object = { 1, 2, 3 };
+
+/* This pointer is checked by GDB. */
+volatile void *opaque_ptr = 0;
+
+void
+lib_func_test_syscall (void)
+{
+ puts ("Inside library\n");
+ fflush (stdout);
+}
+
+static void
+sig_handler (int signo)
+{
+ /* Nothing. */
+}
+
+void
+lib_func_test_signal (void)
+{
+ signal (SIGUSR1, sig_handler);
+
+ kill (getpid (), SIGUSR1);
+}
+
+void
+lib_func_test_fork (void)
+{
+ pid_t pid = fork ();
+ assert (pid != -1);
+
+ if (pid == 0)
+ {
+ /* Child: just exit. */
+ exit (0);
+ }
+
+ /* Parent. */
+ waitpid (pid, NULL, 0);
+}
diff --git a/gdb/testsuite/gdb.base/reset-catchpoint-cond.c b/gdb/testsuite/gdb.base/reset-catchpoint-cond.c
new file mode 100644
index 0000000..0c1d5ea
--- /dev/null
+++ b/gdb/testsuite/gdb.base/reset-catchpoint-cond.c
@@ -0,0 +1,50 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+extern void lib_func_test_syscall (void);
+extern void lib_func_test_signal (void);
+extern void lib_func_test_fork (void);
+
+/* We use this to perform some filler work. */
+volatile int global_var = 0;
+
+/* Just somewhere for GDB to put a breakpoint. */
+void
+breakpt_before_exit (void)
+{
+ /* Nothing. */
+}
+
+int
+main (void)
+{
+#if defined TEST_SYSCALL
+ lib_func_test_syscall ();
+#elif defined TEST_SIGNAL
+ lib_func_test_signal ();
+#elif defined TEST_FORK
+ lib_func_test_fork ();
+#else
+# error compile with suitable -DTEST_xxx macro defined
+#endif
+
+ ++global_var;
+
+ breakpt_before_exit ();
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/reset-catchpoint-cond.exp b/gdb/testsuite/gdb.base/reset-catchpoint-cond.exp
new file mode 100644
index 0000000..e119c32
--- /dev/null
+++ b/gdb/testsuite/gdb.base/reset-catchpoint-cond.exp
@@ -0,0 +1,169 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test that the condition for a catchpoint is correctly reset after
+# shared libraries are unloaded, as happens when an inferior is
+# restarted.
+#
+# If this is not done then, when the catchpoint is hit on the second
+# run, we'll evaluate the parsed expression from the first run, which
+# might include references to types owned by the now deleted objfile
+# (for the shared library loaded in the first run).
+#
+# This scripts tests a number of different catchpoint types. Inside
+# GDB these are all sub-classes of the 'catchpoint' type, which is
+# where the fix for the above issue resides, so all catchpoint types
+# should work correctly.
+
+standard_testfile .c -lib.c
+
+set libfile $binfile-lib.so
+
+set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
+
+if {[build_executable "build shared library" $libfile $srcfile2 \
+ {debug shlib}] == -1} {
+ return
+}
+
+# Depending on whether or not libc debug info is installed, when we
+# hit a syscall catchpoint inside libc there might be a source line
+# included in the output.
+#
+# This regexp will match an optional line and can be added to the
+# expected catchpoint output to ignore the (possibly missing) source
+# line.
+set libc_src_line_re "(?:\r\n\[^\r\n\]+)?"
+
+# Check the Python bp_modified_list and then reset the list back to
+# empty. TESTNAME is just a string. BP_NUM is a list of breakpoint
+# numbers that are expected to appear (in the given order) in the
+# bp_modified_list.
+
+proc check_modified_bp_list { testname bp_num } {
+ if { [allow_python_tests] } {
+ set expected [join $bp_num ", "]
+
+ gdb_test "python print(bp_modified_list)" "\\\[$expected\\\]" \
+ $testname
+ gdb_test_no_output -nopass "python bp_modified_list=\[\]" \
+ "reset bp_modified_list after $testname"
+ }
+}
+
+# Build an executable and run tests on 'catch MODE'.
+
+proc run_test { mode } {
+ set exec_name ${::binfile}-${mode}
+
+ set macro TEST_[string toupper $mode]
+
+ if {[build_executable "build test executable" $exec_name $::srcfile \
+ [list debug shlib=$::libfile additional_flags=-D${macro}]] == -1} {
+ return
+ }
+
+ clean_restart $exec_name
+ gdb_load_shlib $::libfile
+
+ if {![runto_main]} {
+ return
+ }
+
+ if { $mode eq "syscall" } {
+ gdb_test "catch syscall write" \
+ "Catchpoint $::decimal \\(syscall 'write' \[^)\]+\\)"
+ set catch_re "call to syscall write"
+ } elseif { $mode eq "signal" } {
+ gdb_test "catch signal SIGUSR1" \
+ "Catchpoint $::decimal \\(signal SIGUSR1\\)"
+ set catch_re "signal SIGUSR1"
+ } elseif { $mode eq "fork" } {
+ gdb_test "catch fork" \
+ "Catchpoint $::decimal \\(fork\\)"
+ set catch_re "forked process $::decimal"
+ } else {
+ error "unknown mode $mode"
+ }
+ set cp_num [get_integer_valueof "\$bpnum" "*UNKNOWN*"]
+
+ gdb_breakpoint "breakpt_before_exit"
+
+ gdb_test "continue" \
+ "Catchpoint ${cp_num} \[^\r\n\]+$::libc_src_line_re"
+
+ if { [allow_python_tests] } {
+ gdb_test_no_output "source $::pyfile" "import python scripts"
+ check_modified_bp_list \
+ "check b/p modified observer has not yet triggered" {}
+ }
+
+ with_test_prefix "with false condition" {
+ gdb_test_no_output "condition $cp_num ((struct lib_type *) opaque_ptr) != 0" \
+ "set catchpoint condition"
+
+ check_modified_bp_list \
+ "catchpoint modified once by setting condition" \
+ [list $cp_num]
+
+ gdb_run_cmd
+ gdb_test "" [multi_line \
+ "Breakpoint $::decimal, main \\(\\) \[^\r\n\]+" \
+ "$::decimal\\s+\[^\r\n\]+"]
+
+ check_modified_bp_list "catchpoint modified twice at startup" \
+ [list $cp_num $cp_num "$::decimal"]
+
+ gdb_test "continue" \
+ [multi_line \
+ "Breakpoint $::decimal, breakpt_before_exit \\(\\) at \[^\r\n\]+" \
+ "$::decimal\\s+\[^\r\n\]+"] \
+ "continue to breakpt_before_exit"
+ }
+
+ # Check the bp_modified_list against '.*'. We don't care at this
+ # point what's in the list (nothing relevant has happened since we
+ # last checked), but this has the side effect of clearing the list.
+ check_modified_bp_list "clear bp modified list" { .* }
+
+ with_test_prefix "with true condition" {
+ gdb_test_no_output "condition $cp_num ((struct lib_type *) opaque_ptr) == 0" \
+ "set catchpoint condition"
+
+ check_modified_bp_list \
+ "catchpoint modified once by setting condition" \
+ [list $cp_num]
+
+ gdb_run_cmd
+ gdb_test "" [multi_line \
+ "Breakpoint $::decimal, main \\(\\) \[^\r\n\]+" \
+ "$::decimal\\s+\[^\r\n\]+"]
+
+ check_modified_bp_list "catchpoint modified twice at startup" \
+ [list $cp_num $cp_num "$::decimal"]
+
+ gdb_test "continue" \
+ "Catchpoint $cp_num \\($catch_re\\), \[^\r\n\]+$::libc_src_line_re" \
+ "continue until catchpoint hit"
+
+ check_modified_bp_list "catchpoint modified again when hit" \
+ [list $cp_num]
+ }
+}
+
+# Run the tests.
+foreach_with_prefix mode { syscall signal fork } {
+ run_test $mode
+}
diff --git a/gdb/testsuite/gdb.base/reset-catchpoint-cond.py b/gdb/testsuite/gdb.base/reset-catchpoint-cond.py
new file mode 100644
index 0000000..bf90ec8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/reset-catchpoint-cond.py
@@ -0,0 +1,23 @@
+# Copyright (C) 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+bp_modified_list = []
+
+
+def bp_modified(bp):
+ bp_modified_list.append(bp.number)
+
+
+gdb.events.breakpoint_modified.connect(bp_modified)
diff --git a/gdb/testsuite/gdb.base/return.exp b/gdb/testsuite/gdb.base/return.exp
index 29de995..23016f8 100644
--- a/gdb/testsuite/gdb.base/return.exp
+++ b/gdb/testsuite/gdb.base/return.exp
@@ -15,12 +15,12 @@
# This file was written by Jeff Law. (law@cs.utah.edu)
+set allow_float_test [allow_float_test]
+
if { [prepare_for_testing "failed to prepare" "return"] } {
return -1
}
-set allow_float_test [allow_float_test]
-
proc return_tests { } {
global gdb_prompt allow_float_test
diff --git a/gdb/testsuite/gdb.base/savedregs.exp b/gdb/testsuite/gdb.base/savedregs.exp
index ce3ab94..f20fd7c 100644
--- a/gdb/testsuite/gdb.base/savedregs.exp
+++ b/gdb/testsuite/gdb.base/savedregs.exp
@@ -57,7 +57,7 @@ proc process_saved_regs { current inner outer } {
# and for dummy frames won't have saved registers. If there's a
# problem, fail but capture the output anyway, hopefully later
# "info frame" requests for that same frame will at least fail in
- # a consistent manner (stops propogated fails).
+ # a consistent manner (stops propagated fails).
foreach func $inner {
set saved_regs($func) "error"
diff --git a/gdb/testsuite/gdb.base/scope-hw-watch-disable.exp b/gdb/testsuite/gdb.base/scope-hw-watch-disable.exp
index 6113770..29eb682 100644
--- a/gdb/testsuite/gdb.base/scope-hw-watch-disable.exp
+++ b/gdb/testsuite/gdb.base/scope-hw-watch-disable.exp
@@ -29,6 +29,15 @@ if {![runto_main]} {
return -1
}
+gdb_test_multiple "maint info break" "maint info break before" {
+ -re -wrap "watchpoint.*" {
+ fail $gdb_test_name
+ }
+ -re -wrap "" {
+ pass $gdb_test_name
+ }
+}
+
gdb_test "awatch a" \
"Can't set read/access watchpoint when hardware watchpoints are disabled." \
"unsuccessful attempt to create an access watchpoint"
@@ -36,5 +45,14 @@ gdb_test "rwatch b" \
"Can't set read/access watchpoint when hardware watchpoints are disabled." \
"unsuccessful attempt to create a read watchpoint"
+gdb_test_multiple "maint info break" "maint info break after" {
+ -re -wrap "watchpoint.*" {
+ fail $gdb_test_name
+ }
+ -re -wrap "" {
+ pass $gdb_test_name
+ }
+}
+
# The program continues until termination.
gdb_continue_to_end
diff --git a/gdb/testsuite/gdb.base/sepdebug.exp b/gdb/testsuite/gdb.base/sepdebug.exp
index ee9bea2..eb3515b 100644
--- a/gdb/testsuite/gdb.base/sepdebug.exp
+++ b/gdb/testsuite/gdb.base/sepdebug.exp
@@ -296,7 +296,7 @@ gdb_test "catch exec" "Catchpoint \[0-9\]+ \\(exec\\)" \
#
gdb_test_no_output "set breakpoint pending off"
-gdb_test "break 999" "No line 999 in the current file." \
+gdb_test "break 999" "^No compiled code for line 999 in the current file\\." \
"break on non-existent source line"
# Run to the desired default location. If not positioned here, the
diff --git a/gdb/testsuite/gdb.base/setshow.exp b/gdb/testsuite/gdb.base/setshow.exp
index 9eb44b3..9380331 100644
--- a/gdb/testsuite/gdb.base/setshow.exp
+++ b/gdb/testsuite/gdb.base/setshow.exp
@@ -67,12 +67,12 @@ proc_with_prefix test_setshow_annotate {} {
#test set annotate 1
gdb_test "set annotate 1" ".*post-prompt.*"
- gdb_test "show annotate" "Annotation_level is 1..*" "show annotate (1)"
+ gdb_test "show annotate" "Annotation_level is 1..*" "show annotate, 1"
#test annotation_level 1
gdb_test "info line 1" "Line 1 of .* is at address .* but contains no code.*:1:0:beg:0x.*" "annotation_level 1"
#test set annotate 0
gdb_test_no_output "set annotate 0" "set annotate 0"
- gdb_test "show annotate" "Annotation_level is 0..*" "show annotate (0)"
+ gdb_test "show annotate" "Annotation_level is 0..*" "show annotate, 0"
#test annotation_level 0
gdb_test "info line 1" "Line 1 of .* is at address .* but contains no code.*" "annotation_level 0"
}
@@ -121,13 +121,13 @@ proc_with_prefix test_setshow_check {} {
"_gdb_setting check range on"
#test show check range on
- gdb_test "show check range" "Range checking is \"on\"\..*" "show check range (on)"
+ gdb_test "show check range" "Range checking is \"on\"\..*" "show check range, on"
#test set check range off with trailing space
gdb_test_no_output "set check range off " "set check range off"
#test show check range off
- gdb_test "show check range" "Range checking is \"off\"\..*" "show check range (off)"
+ gdb_test "show check range" "Range checking is \"off\"\..*" "show check range, off"
gdb_test "p \$_gdb_setting(\"check range\")" " = \"off\"" \
"_gdb_setting check range off"
@@ -144,7 +144,7 @@ proc_with_prefix test_setshow_check {} {
# Test show check type on
gdb_test "show check type" "Strict type checking is on\..*" \
- "show check type (on)"
+ "show check type, on"
gdb_test "p \$_gdb_setting_str(\"check type\")" " = \"on\"" \
"_gdb_setting_str check type on"
gdb_test "p \$_gdb_setting(\"check type\")" " = 1" \
@@ -159,7 +159,7 @@ proc_with_prefix test_setshow_check {} {
# Test show check type off
gdb_test "show check type" "Strict type checking is off\..*" \
- "show check type (off)"
+ "show check type, off"
}
proc_with_prefix test_setshow_breakpoint_pending {} {
@@ -200,11 +200,11 @@ proc_with_prefix test_setshow_complaints {} {
#test set complaints 100
gdb_test_no_output "set complaints 100" "set complaints 100"
#test show complaints 100
- gdb_test "show complaints" "Max number of complaints about incorrect symbols is 100..*" "show complaints (100)"
+ gdb_test "show complaints" "Max number of complaints about incorrect symbols is 100..*" "show complaints, 100"
#test set complaints 0
gdb_test_no_output "set complaints 0" "set complaints 0"
#test show complaints 0
- gdb_test "show complaints" "Max number of complaints about incorrect symbols is 0..*" "show complaints (0)"
+ gdb_test "show complaints" "Max number of complaints about incorrect symbols is 0..*" "show complaints, 0"
}
proc_with_prefix test_setshow_confirm {} {
@@ -213,11 +213,11 @@ proc_with_prefix test_setshow_confirm {} {
#test set confirm off
gdb_test_no_output "set confirm off" "set confirm off"
#test show confirm off
- gdb_test "show confirm" "Whether to confirm potentially dangerous operations is off..*" "show confirm (off)"
+ gdb_test "show confirm" "Whether to confirm potentially dangerous operations is off..*" "show confirm, off"
#test set confirm on
gdb_test_no_output "set confirm on" "set confirm on"
#test show confirm on
- gdb_test "show confirm" "Whether to confirm potentially dangerous operations is on..*" "show confirm (on)"
+ gdb_test "show confirm" "Whether to confirm potentially dangerous operations is on..*" "show confirm, on"
}
proc_with_prefix test_setshow_editing {} {
@@ -331,7 +331,7 @@ proc_with_prefix test_setshow_history {} {
#test show history filename foobar.baz
gdb_test "show history filename" \
"The filename in which to record the command history is \"[string_to_regexp $PWD]/foobar.baz\"..*" \
- "show history filename (current_directory/foobar.baz)"
+ "show history filename, current_directory/foobar.baz"
#test set history save on
gdb_test_no_output "set history save on" "set history save on"
@@ -356,13 +356,13 @@ proc_with_prefix test_setshow_language {} {
gdb_test_no_output "set language asm"
#test show language asm
- gdb_test "show language" "The current source language is \"asm\"..*" "show language (asm)"
+ gdb_test "show language" "The current source language is \"asm\"..*" "show language, asm"
#test set language rust, with a trailing space
gdb_test_no_output "set language rust " "set language rust"
#test show language rust
- gdb_test "show language" "The current source language is \"rust\"..*" "show language (rust)"
+ gdb_test "show language" "The current source language is \"rust\"..*" "show language, rust"
#test completion for set language.
gdb_test "complete set language min" "set language minimal" \
@@ -372,7 +372,7 @@ proc_with_prefix test_setshow_language {} {
gdb_test_no_output "set language auto" "set language auto"
#test show language
- gdb_test "show language" "The current source language is \"auto.*\"..*" "show language (auto)"
+ gdb_test "show language" "The current source language is \"auto.*\"..*" "show language, auto"
}
proc_with_prefix test_setshow_listsize {} {
@@ -447,13 +447,13 @@ proc_with_prefix test_setshow_radix {} {
gdb_test "set radix 16" "Input and output radices now set to decimal 16, hex 10, octal 20..*"
#test show radix 16
- gdb_test "show radix" "Input and output radices set to decimal 16, hex 10, octal 20..*" "show radix (16)"
+ gdb_test "show radix" "Input and output radices set to decimal 16, hex 10, octal 20..*" "show radix, 16"
#test set radix 10
gdb_test "set radix" "Input and output radices now set to decimal 10, hex a, octal 12..*" "set radix 10"
#test show radix 10
- gdb_test "show radix" "Input and output radices set to decimal 10, hex a, octal 12..*" "show radix (10)"
+ gdb_test "show radix" "Input and output radices set to decimal 10, hex a, octal 12..*" "show radix, 10"
}
proc_with_prefix test_setshow_width {} {
@@ -492,13 +492,13 @@ proc_with_prefix test_setshow_verbose {} {
gdb_test_no_output "set verbose on" "set verbose on"
#test show verbose on
- gdb_test "show verbose" "Verbose printing of informational messages is on..*" "show verbose (on)"
+ gdb_test "show verbose" "Verbose printing of informational messages is on..*" "show verbose, on"
#test set verbose off
gdb_test_no_output "set verbose off" "set verbose off"
#test show verbose off
- gdb_test "show verbose" "Verbosity is off..*" "show verbose (off)"
+ gdb_test "show verbose" "Verbosity is off..*" "show verbose, off"
}
proc_with_prefix test_argument_preceded_by_space {} {
diff --git a/gdb/testsuite/gdb.base/setvar.exp b/gdb/testsuite/gdb.base/setvar.exp
index 9ac2402..416dcc6 100644
--- a/gdb/testsuite/gdb.base/setvar.exp
+++ b/gdb/testsuite/gdb.base/setvar.exp
@@ -390,13 +390,13 @@ set timeout $prev_timeout
if {[is_c_compiler_gcc]} {
gdb_test "print sef.field=sm1" ".*.\[0-9\]* = sm1"
- gdb_test "print sef.field" ".*.\[0-9\]* = sm1" "print sef.field (sm1)"
+ gdb_test "print sef.field" ".*.\[0-9\]* = sm1" "print sef.field, sm1"
gdb_test "print sef.field=s1" ".*.\[0-9\]* = s1"
- gdb_test "print sef.field" ".*.\[0-9\]* = s1" "print sef.field (s1)"
+ gdb_test "print sef.field" ".*.\[0-9\]* = s1" "print sef.field, s1"
gdb_test "print uef.field=u2" ".*.\[0-9\]* = u2"
- gdb_test "print uef.field" ".*.\[0-9\]* = u2" "print uef.field (u2)"
+ gdb_test "print uef.field" ".*.\[0-9\]* = u2" "print uef.field, u2"
gdb_test "print uef.field=u1" ".*.\[0-9\]* = u1"
- gdb_test "print uef.field" ".*.\[0-9\]* = u1" "print uef.field (u1)"
+ gdb_test "print uef.field" ".*.\[0-9\]* = u1" "print uef.field, u1"
# Test for truncation when assigning invalid values to bitfields.
gdb_test "print sef.field=7" \
diff --git a/gdb/testsuite/gdb.base/sigbpt.exp b/gdb/testsuite/gdb.base/sigbpt.exp
index 4855400..6f4616e 100644
--- a/gdb/testsuite/gdb.base/sigbpt.exp
+++ b/gdb/testsuite/gdb.base/sigbpt.exp
@@ -22,7 +22,7 @@
# This test is known to tickle the following problems: kernel letting
# the inferior execute both the system call, and the instruction
# following, when single-stepping a system call; kernel failing to
-# propogate the single-step state when single-stepping the sigreturn
+# propagate the single-step state when single-stepping the sigreturn
# system call, instead resuming the inferior at full speed; GDB
# doesn't know how to software single-step across a sigreturn
# instruction. Since the kernel problems can be "fixed" using
diff --git a/gdb/testsuite/gdb.base/signals.exp b/gdb/testsuite/gdb.base/signals.exp
index 38c63b5..e6bd35a 100644
--- a/gdb/testsuite/gdb.base/signals.exp
+++ b/gdb/testsuite/gdb.base/signals.exp
@@ -105,7 +105,7 @@ if {[runto_main]} {
"next to ++count #2"
sleep 2
- # ...call the function, which is immediatly interrupted
+ # ...call the function, which is immediately interrupted
gdb_test "p func1 ()" \
"Breakpoint \[0-9\]*, handler.*
diff --git a/gdb/testsuite/gdb.base/sigrepeat.c b/gdb/testsuite/gdb.base/sigrepeat.c
index 8717721..79fe648 100644
--- a/gdb/testsuite/gdb.base/sigrepeat.c
+++ b/gdb/testsuite/gdb.base/sigrepeat.c
@@ -59,7 +59,7 @@ handler (int sig)
while (1)
{
/* Wait until a signal has become pending, that way when this
- handler returns it will be immediatly delivered leading to
+ handler returns it will be immediately delivered leading to
back-to-back signals. */
sigset_t set;
sigemptyset (&set);
diff --git a/gdb/testsuite/gdb.base/skip.exp b/gdb/testsuite/gdb.base/skip.exp
index d3936bb..ccc7ca3 100644
--- a/gdb/testsuite/gdb.base/skip.exp
+++ b/gdb/testsuite/gdb.base/skip.exp
@@ -31,9 +31,9 @@ set srcfile1 skip1.c
# Right after we start gdb, there's no default file or function to skip.
-gdb_test "skip file" "No default file now." "skip file (no default file)"
+gdb_test "skip file" "No default file now." "skip file, no default file"
gdb_test "skip function" "No default function now."
-gdb_test "skip" "No default function now." "skip (no default function)"
+gdb_test "skip" "No default function now." "skip, no default function"
# Test elided args.
@@ -59,8 +59,8 @@ gdb_test "info skip" "Not skipping any files or functions\." "info skip empty"
# Create a skiplist entry for the current file and function.
-gdb_test "skip file" "File .*$srcfile will be skipped when stepping\." "skip file ($srcfile)"
-gdb_test "skip" "Function main will be skipped when stepping\." "skip (main)"
+gdb_test "skip file" "File .*$srcfile will be skipped when stepping\." "skip file, $srcfile"
+gdb_test "skip" "Function main will be skipped when stepping\." "skip, main"
# Create a skiplist entry for a specified file and function.
diff --git a/gdb/testsuite/gdb.base/solib-display.exp b/gdb/testsuite/gdb.base/solib-display.exp
index 5c27f29..c9c66f6 100644
--- a/gdb/testsuite/gdb.base/solib-display.exp
+++ b/gdb/testsuite/gdb.base/solib-display.exp
@@ -126,7 +126,7 @@ foreach libsepdebug {NO IN SEP} { with_test_prefix "$libsepdebug" {
"1: \\(int\\) a_global = 41" \
"warning: .*b_global.*" \
"3: \\(int\\) c_global = 43" \
- ] "after rerun (2)"
+ ] "after rerun, 2"
# Now verify that displays which are not in the shared library
# are not cleared permaturely.
diff --git a/gdb/testsuite/gdb.base/solib-search.exp b/gdb/testsuite/gdb.base/solib-search.exp
index 581046a..bf021c8 100644
--- a/gdb/testsuite/gdb.base/solib-search.exp
+++ b/gdb/testsuite/gdb.base/solib-search.exp
@@ -43,7 +43,11 @@ set right_binfile2_lib \
set binfile1_lib [standard_output_file ${libname1}.so]
set binfile2_lib [standard_output_file ${libname2}.so]
-set lib_flags [list debug ldflags=-Wl,-Bsymbolic]
+# When this test was written, GDB's ability to track down shared
+# libraries for a core file based on the build-id much poorer. As GDB
+# has improved we now need to disable build-ids in order for this test
+# to function as expected.
+set lib_flags [list debug no-build-id ldflags=-Wl,-Bsymbolic]
set wrong_lib_flags "$lib_flags additional_flags=-DARRAY_SIZE=1"
set right_lib_flags "$lib_flags additional_flags=-DARRAY_SIZE=8192 additional_flags=-DRIGHT"
@@ -108,9 +112,9 @@ proc test_backtrace { expect_fail } {
set total_expected 5
if { $expect_fail } {
- set testname "backtrace (with wrong libs)"
+ set testname "backtrace, with wrong libs"
} else {
- set testname "backtrace (with right libs)"
+ set testname "backtrace, with right libs"
}
# N.B. The order of the tests here is important.
# We need to count each function in the backtrace, and expect matches
@@ -137,7 +141,7 @@ proc test_backtrace { expect_fail } {
exp_continue
}
-re "\[\r\n\]$gdb_prompt $" {
- pass "$testname (data collection)"
+ pass "$testname, data collection"
}
}
diff --git a/gdb/testsuite/gdb.base/step-break.exp b/gdb/testsuite/gdb.base/step-break.exp
index da804e3..7dc0492 100644
--- a/gdb/testsuite/gdb.base/step-break.exp
+++ b/gdb/testsuite/gdb.base/step-break.exp
@@ -34,9 +34,9 @@ gdb_test "break $bp_location" \
gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, main \\(\\) at .*$srcfile:$bp_location.*set breakpoint here.*" \
"run until breakpoint set at a line number"
-gdb_test "next 2" ".*place2.*" "next 2 (1)"
-gdb_test "next 2" ".*place3.*" "next 2 (2)"
-gdb_test "next 2" ".*place2.*" "next 2 (3)"
-gdb_test "next 2" ".*place3.*" "next 2 (4)"
-gdb_test "next 2" ".*place2.*" "next 2 (5)"
-gdb_test "next 2" ".*place3.*" "next 2 (6)"
+gdb_test "next 2" ".*place2.*" "next 2, 1"
+gdb_test "next 2" ".*place3.*" "next 2, 2"
+gdb_test "next 2" ".*place2.*" "next 2, 3"
+gdb_test "next 2" ".*place3.*" "next 2, 4"
+gdb_test "next 2" ".*place2.*" "next 2, 5"
+gdb_test "next 2" ".*place3.*" "next 2, 6"
diff --git a/gdb/testsuite/gdb.base/step-into-other-file.c b/gdb/testsuite/gdb.base/step-into-other-file.c
new file mode 100644
index 0000000..5ec7c33
--- /dev/null
+++ b/gdb/testsuite/gdb.base/step-into-other-file.c
@@ -0,0 +1,31 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int var;
+
+int
+foo (void)
+{
+ var = 1;
+#include "step-into-other-file.h"
+}
+
+int
+main ()
+{
+ return foo ();
+}
diff --git a/gdb/testsuite/gdb.base/step-into-other-file.exp b/gdb/testsuite/gdb.base/step-into-other-file.exp
new file mode 100644
index 0000000..f0e8c3f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/step-into-other-file.exp
@@ -0,0 +1,36 @@
+# Copyright (C) 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Check that when stepping into another file, the file is shown.
+
+standard_testfile .c .h
+
+set flags {}
+lappend flags debug
+lappend_include_file flags $srcdir/$subdir/$srcfile2
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
+ $flags] == -1 } {
+ return -1
+}
+
+if ![runto_main] {
+ return -1
+}
+
+gdb_test step $srcfile:$decimal\r\n.*
+
+# Regression test for PR32011.
+gdb_test next $srcfile2:$decimal\r\n.*
diff --git a/gdb/testsuite/gdb.base/step-into-other-file.h b/gdb/testsuite/gdb.base/step-into-other-file.h
new file mode 100644
index 0000000..60b4816
--- /dev/null
+++ b/gdb/testsuite/gdb.base/step-into-other-file.h
@@ -0,0 +1,18 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ return 1;
diff --git a/gdb/testsuite/gdb.base/step-over-syscall.exp b/gdb/testsuite/gdb.base/step-over-syscall.exp
index 8cacc09..c40b20f 100644
--- a/gdb/testsuite/gdb.base/step-over-syscall.exp
+++ b/gdb/testsuite/gdb.base/step-over-syscall.exp
@@ -99,13 +99,13 @@ proc setup { syscall } {
gdb_test "break \*$syscall" "Breakpoint \[0-9\]* at .*"
gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, (.* in )?(__libc_)?$syscall \\(\\).*" \
- "continue to $syscall (1st time)"
+ "continue to $syscall, 1st time"
# Hit the breakpoint on $syscall for the first time. In this time,
# we will let PLT resolution done, and the number single steps we will
# do later will be reduced.
gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, (.* in )?(__libc_)?$syscall \\(\\).*" \
- "continue to $syscall (2nd time)"
+ "continue to $syscall, 2nd time"
# Hit the breakpoint on $syscall for the second time. In this time,
# the address of syscall insn and next insn of syscall are recorded.
@@ -236,7 +236,7 @@ proc step_over_syscall { syscall } {
}
gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, (.* in )?(__libc_)?$syscall \\(\\).*" \
- "continue to $syscall (3rd time)"
+ "continue to $syscall, 3rd time"
# Hit the breakpoint on $syscall for the third time. In this time, we'll set
# breakpoint on the syscall insn we recorded previously, and single step over it.
diff --git a/gdb/testsuite/gdb.base/store.exp b/gdb/testsuite/gdb.base/store.exp
index 9286253..2271156 100644
--- a/gdb/testsuite/gdb.base/store.exp
+++ b/gdb/testsuite/gdb.base/store.exp
@@ -196,7 +196,7 @@ proc check_field { t } {
gdb_test "continue" "register struct f_${t} u = f_${t};" \
"continue field ${t}"
- # Match either the return statement, or the line immediatly after
+ # Match either the return statement, or the line immediately after
# it. The compiler can end up merging the return statement into
# the return instruction.
gdb_test "next" "(return u;|\})" "next field ${t}"
diff --git a/gdb/testsuite/gdb.base/structs.exp b/gdb/testsuite/gdb.base/structs.exp
index 31b2bbe..7f1192d 100644
--- a/gdb/testsuite/gdb.base/structs.exp
+++ b/gdb/testsuite/gdb.base/structs.exp
@@ -296,7 +296,7 @@ proc test_struct_returns { n } {
# known, both failed to print a final "source and line" and misplaced
# the frame ("No frame").
- # The test is writen so that it only reports one FAIL/PASS for the
+ # The test is written so that it only reports one FAIL/PASS for the
# entire operation. The value returned is checked further down.
# "return_value_known", if non-zero, indicates that GDB knew where
# the return value was located.
diff --git a/gdb/testsuite/gdb.base/style-logging.exp b/gdb/testsuite/gdb.base/style-logging.exp
index 882418b..d866d36 100644
--- a/gdb/testsuite/gdb.base/style-logging.exp
+++ b/gdb/testsuite/gdb.base/style-logging.exp
@@ -41,7 +41,8 @@ with_ansi_styling_terminal {
set main_expr [style main function]
set base_file_expr [style ".*style\\.c" file]
- set file_expr "$base_file_expr:\[0-9\]"
+ set line_expr [style $decimal line-number]
+ set file_expr "$base_file_expr:$line_expr"
set arg_expr [style "arg." variable]
gdb_test "frame" \
"$main_expr.*$arg_expr.*$arg_expr.*$file_expr.*"
diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
index aff6545..d29b238 100644
--- a/gdb/testsuite/gdb.base/style.exp
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -99,7 +99,8 @@ proc run_style_tests { } {
set main_expr [limited_style main function]
set base_file_expr [limited_style ".*style\\.c" file]
- set file_expr "$base_file_expr:\[0-9\]+"
+ set line_expr [limited_style $decimal line-number]
+ set file_expr "$base_file_expr:$line_expr"
set arg_expr [limited_style "arg." variable]
# On some embedded targets that don't fully support argc/argv,
@@ -109,12 +110,12 @@ proc run_style_tests { } {
gdb_test "frame" \
[multi_line \
"#0\\s+$main_expr\\s+\\($arg_expr=$decimal,\\s+$arg_expr=$hex.*\\)\\s+at\\s+$file_expr" \
- "\[0-9\]+\\s+.*return.* break here .*"]
+ "$line_expr\\s+.*return.* break here .*"]
gdb_test "info breakpoints" "$main_expr at $file_expr.*"
gdb_test_no_output "set style sources off"
gdb_test "frame" \
- "\r\n\[^\033\]*break here.*" \
+ "\r\n$line_expr\[^\033\]*break here.*" \
"frame without sources styling"
gdb_test_no_output "set style sources on"
@@ -139,18 +140,18 @@ proc run_style_tests { } {
[multi_line \
"#0\\s+$main_expr\\s+\\($arg_expr=$decimal,\\s+$arg_expr=$hex\\)" \
"\\s+at\\s+$file_expr" \
- "\[0-9\]+\\s+.*return.* break here .*"]
+ "$line_expr\\s+.*return.* break here .*"]
set re1_styled \
[multi_line \
"#0\\s+$main_expr\\s+\\($arg_expr=$decimal,\\s+" \
"\\s+$arg_expr=$hex.*\\)" \
"\\s+at\\s+$file_expr" \
- "\[0-9\]+\\s+.*return.* break here .*"]
+ "$line_expr\\s+.*return.* break here .*"]
set re2_styled \
[multi_line \
"#0\\s+$main_expr\\s+\\($arg_expr=.*" \
"\\s+$arg_expr=$hex.*\\)\\s+at\\s+$file_expr" \
- "\[0-9\]+\\s+.*return.* break here .*"]
+ "$line_expr\\s+.*return.* break here .*"]
# The length of the line containing argv containing:
# - 4 leading spaces
diff --git a/gdb/testsuite/gdb.base/sym-file.exp b/gdb/testsuite/gdb.base/sym-file.exp
index 3e36e65..17650cb 100644
--- a/gdb/testsuite/gdb.base/sym-file.exp
+++ b/gdb/testsuite/gdb.base/sym-file.exp
@@ -67,134 +67,156 @@ if {[prepare_for_testing "failed to prepare" $binfile "$srcfile $srcfile2" $exe
gdb_load_shlib ${lib_so}
-if {![runto_main]} {
- return
-}
-
-# 1) Run to gdb_add_symbol_file in $srcfile for adding the library's
-# symbols.
-gdb_breakpoint gdb_add_symbol_file
-gdb_continue_to_breakpoint gdb_add_symbol_file
-
-# 2) Set a pending breakpoint at bar in $srcfile3.
-set result [gdb_breakpoint bar allow-pending]
-if {!$result} {
- return
-}
-
-# 3) Add the library's symbols using 'add-symbol-file'.
-set result [gdb_test "add-symbol-file ${lib_syms} addr" \
- "Reading symbols from .*${lib_syms}\\.\\.\\." \
- "add-symbol-file ${lib_basename}.so addr" \
- "add symbol table from file \".*${lib_basename}\\.so\"\
- at.*\\(y or n\\) " \
- "y"]
-if {$result != 0} {
- return
-}
-
-# 4) 'info files' must display $srcfile3.
-gdb_test "info files" \
- "^(?=(.*${lib_basename})).*" \
- "info files must display ${lib_basename}"
-
-# 5) Continue to bar in $srcfile3 to ensure that the breakpoint
-# was bound correctly after adding $shilb_name.
-set lnum_bar [gdb_get_line_number "break at bar" $srcfile3]
-gdb_continue_to_breakpoint bar ".*${lib_basename}\\.c:$lnum_bar.*"
-
-# 6) Set a breakpoint at foo in $srcfile3.
-set result [gdb_breakpoint foo]
-if {!$result} {
- return
-}
-
-# 7) Continue to foo in $srcfile3 to ensure that the breakpoint
-# was bound correctly.
-set lnum_foo [gdb_get_line_number "break at foo" $srcfile3]
-gdb_continue_to_breakpoint foo ".*${lib_basename}\\.c:$lnum_foo.*"
-
-# 8) Set a breakpoint at gdb_remove_symbol_file in $srcfile for
-# removing the library's symbols.
-set result [gdb_breakpoint gdb_remove_symbol_file]
-if {!$result} {
- return
-}
+proc do_test { remove_expr } {
+ global lib_basename lib_syms srcfile srcfile3
-# 9) Continue to gdb_remove_symbol_file in $srcfile.
-gdb_continue_to_breakpoint gdb_remove_symbol_file
-
-# 10) Remove the library's symbols using 'remove-symbol-file'.
-set result [gdb_test "remove-symbol-file -a addr" \
- ""\
- "remove-symbol-file -a addr" \
- "Remove symbol table from file \".*${lib_basename}\\.so\"\\?\
-.*\\(y or n\\) " \
- "y"]
-if {$result != 0} {
- return
-}
+ clean_restart $::binfile
-# 11) 'info files' must not display ${lib_basename}, anymore.
-gdb_test "info files" \
- "^(?!(.*${lib_basename})).*" \
- "info files must not display ${lib_basename}"
+ if {![runto_main]} {
+ return
+ }
-# 12) Check that the breakpoints at foo and bar are pending after
-# removing the library's symbols.
-gdb_test "info breakpoints 3" \
- ".*PENDING.*" \
- "breakpoint at foo is pending"
-
-gdb_test "info breakpoints 4" \
- ".*PENDING.*" \
- "breakpoint at bar is pending"
-
-# 13) Check that the execution can continue without error.
-set lnum_reload [gdb_get_line_number "reload lib here"]
-gdb_breakpoint $lnum_reload
-gdb_continue_to_breakpoint reload ".*${srcfile}:$lnum_reload.*"
-
-# 14) Regression test for a stale breakpoints bug. Check whether
-# unloading symbols manually without the program actually unloading
-# the library, when breakpoints are inserted doesn't leave stale
-# breakpoints behind.
-with_test_prefix "stale bkpts" {
- # Force breakpoints always inserted.
- gdb_test_no_output "set breakpoint always-inserted on"
-
- # Get past the library reload.
+ # 1) Run to gdb_add_symbol_file in $srcfile for adding the library's
+ # symbols.
+ gdb_breakpoint gdb_add_symbol_file
gdb_continue_to_breakpoint gdb_add_symbol_file
- # Load the library's symbols.
- gdb_test "add-symbol-file ${lib_syms} addr" \
- "Reading symbols from .*${lib_syms}\\.\\.\\." \
- "add-symbol-file ${lib_basename}.so addr" \
- "add symbol table from file \".*${lib_syms}\"\
+ # 2) Set a pending breakpoint at bar in $srcfile3.
+ set result [gdb_breakpoint bar allow-pending]
+ if {!$result} {
+ return
+ }
+
+ # 3) Add the library's symbols using 'add-symbol-file'.
+ set result [gdb_test "add-symbol-file ${lib_syms} addr" \
+ "Reading symbols from .*${lib_syms}\\.\\.\\." \
+ "add-symbol-file ${lib_basename}.so addr" \
+ "add symbol table from file \".*${lib_basename}\\.so\"\
+ at.*\\(y or n\\) " \
+ "y"]
+ if {$result != 0} {
+ return
+ }
+
+ # 4) 'info files' must display $srcfile3.
+ gdb_test "info files" \
+ "^(?=(.*${lib_basename})).*" \
+ "info files must display ${lib_basename}"
+
+ # 5) Continue to bar in $srcfile3 to ensure that the breakpoint
+ # was bound correctly after adding $shilb_name.
+ set lnum_bar [gdb_get_line_number "break at bar" $srcfile3]
+ gdb_continue_to_breakpoint bar ".*${lib_basename}\\.c:$lnum_bar.*"
+
+ # 6) Set a breakpoint at foo in $srcfile3.
+ set result [gdb_breakpoint foo]
+ if {!$result} {
+ return
+ }
+
+ # 7) Continue to foo in $srcfile3 to ensure that the breakpoint
+ # was bound correctly.
+ set lnum_foo [gdb_get_line_number "break at foo" $srcfile3]
+ gdb_continue_to_breakpoint foo ".*${lib_basename}\\.c:$lnum_foo.*"
+
+ # 8) Set a breakpoint at gdb_remove_symbol_file in $srcfile for
+ # removing the library's symbols.
+ set result [gdb_breakpoint gdb_remove_symbol_file]
+ if {!$result} {
+ return
+ }
+
+ # 9) Continue to gdb_remove_symbol_file in $srcfile.
+ gdb_continue_to_breakpoint gdb_remove_symbol_file
+
+ # 10) Remove the library's symbols using 'remove-symbol-file'.
+ set result [gdb_test "remove-symbol-file ${remove_expr}" \
+ ""\
+ "remove-symbol-file" \
+ "Remove symbol table from file \".*${lib_basename}\\.so\"\\?\
+.*\\(y or n\\) " \
+ "y"]
+ if {$result != 0} {
+ return
+ }
+
+ # 11) 'info files' must not display ${lib_basename}, anymore.
+ gdb_test "info files" \
+ "^(?!(.*${lib_basename})).*" \
+ "info files must not display ${lib_basename}"
+
+ # 12) Check that the breakpoints at foo and bar are pending after
+ # removing the library's symbols.
+ gdb_test "info breakpoints 3" \
+ ".*PENDING.*" \
+ "breakpoint at foo is pending"
+
+ gdb_test "info breakpoints 4" \
+ ".*PENDING.*" \
+ "breakpoint at bar is pending"
+
+ # 13) Check that the execution can continue without error.
+ set lnum_reload [gdb_get_line_number "reload lib here"]
+ gdb_breakpoint $lnum_reload
+ gdb_continue_to_breakpoint reload ".*${srcfile}:$lnum_reload.*"
+
+ # 14) Regression test for a stale breakpoints bug. Check whether
+ # unloading symbols manually without the program actually unloading
+ # the library, when breakpoints are inserted doesn't leave stale
+ # breakpoints behind.
+ with_test_prefix "stale bkpts" {
+ # Force breakpoints always inserted.
+ gdb_test_no_output "set breakpoint always-inserted on"
+
+ # Get past the library reload.
+ gdb_continue_to_breakpoint gdb_add_symbol_file
+
+ # Load the library's symbols.
+ gdb_test "add-symbol-file ${lib_syms} addr" \
+ "Reading symbols from .*${lib_syms}\\.\\.\\." \
+ "add-symbol-file ${lib_basename}.so addr" \
+ "add symbol table from file \".*${lib_syms}\"\
at.*\\(y or n\\) " \
- "y"
+ "y"
- # Set a breakpoint at baz, in the library.
- gdb_breakpoint baz
+ # Set a breakpoint at baz, in the library.
+ gdb_breakpoint baz
- gdb_test "info breakpoints 7" ".*y.*0x.*in baz.*" \
- "breakpoint at baz is resolved"
+ gdb_test "info breakpoints 7" ".*y.*0x.*in baz.*" \
+ "breakpoint at baz is resolved"
- # Unload symbols manually without the program actually unloading
- # the library.
- gdb_test "remove-symbol-file -a addr" \
- "" \
- "remove-symbol-file -a addr" \
- "Remove symbol table from file \".*${lib_basename}\\.so\"\\?\
+ # Unload symbols manually without the program actually unloading
+ # the library.
+ gdb_test "remove-symbol-file ${remove_expr}" \
+ "" \
+ "remove-symbol-file" \
+ "Remove symbol table from file \".*${lib_basename}\\.so\"\\?\
.*\\(y or n\\) " \
- "y"
+ "y"
+
+ gdb_test "info breakpoints 7" ".*PENDING.*" \
+ "breakpoint at baz is pending"
- gdb_test "info breakpoints 7" ".*PENDING.*" \
- "breakpoint at baz is pending"
+ # Check that execution can continue without error. If GDB leaves
+ # breakpoints behind, we'll get back a spurious SIGTRAP.
+ set lnum_end [gdb_get_line_number "end here"]
+ gdb_breakpoint $lnum_end
+ gdb_continue_to_breakpoint "end here" ".*end here.*"
+ }
+}
- # Check that execution can continue without error. If GDB leaves
- # breakpoints behind, we'll get back a spurious SIGTRAP.
- set lnum_end [gdb_get_line_number "end here"]
- gdb_breakpoint $lnum_end
- gdb_continue_to_breakpoint "end here" ".*end here.*"
+foreach remove_expr [list addr bar "bar + 0x10" "${lib_syms}" ] {
+ # Don't use full filenames in the test prefix. Also, add '-a' to
+ # all the REMOVE_EXPR values which are addresses rather than
+ # filenames.
+ set prefix $remove_expr
+ if { $prefix == $lib_syms } {
+ set prefix [file tail $prefix]
+ } else {
+ set remove_expr "-a $remove_expr"
+ }
+
+ with_test_prefix "remove_expr=$prefix" {
+ do_test $remove_expr
+ }
}
diff --git a/gdb/testsuite/gdb.base/sysroot-debug-lookup.exp b/gdb/testsuite/gdb.base/sysroot-debug-lookup.exp
index 5f17315..80cad95 100644
--- a/gdb/testsuite/gdb.base/sysroot-debug-lookup.exp
+++ b/gdb/testsuite/gdb.base/sysroot-debug-lookup.exp
@@ -78,9 +78,8 @@ proc_with_prefix lookup_via_build_id {} {
gdb_assert { $::gdb_file_cmd_debug_info eq "debug" } \
"ensure debug information was found"
- if { $sysroot_prefix eq "" } {
- set lookup_filename $debug_filename
- } else {
+ if { $sysroot_prefix eq "target:"
+ && [target_info gdb_protocol] == "extended-remote"} {
# Only when using the extended-remote board will we have
# started a remote target by this point. In this case GDB
# will see the 'target:' prefix as remote, and so the
@@ -89,11 +88,9 @@ proc_with_prefix lookup_via_build_id {} {
# In all other cases we will still be using the default,
# initial target, in which case GDB considers the
# 'target:' prefix to indicate the local filesystem.
- if {[target_info gdb_protocol] == "extended-remote"} {
- set lookup_filename $sysroot_prefix$debug_symlink
- } else {
- set lookup_filename $debug_symlink
- }
+ set lookup_filename $sysroot_prefix$debug_symlink
+ } else {
+ set lookup_filename $debug_filename
}
set re [string_to_regexp "Reading symbols from $lookup_filename..."]
gdb_assert {[regexp $re $::gdb_file_cmd_msg]} \
@@ -174,24 +171,9 @@ proc_with_prefix lookup_via_debuglink {} {
# in the sysroot.
gdb_file_cmd ${sysroot_prefix}$exec_in_sysroot
- # Giving a sysroot a 'target:' prefix doesn't seem to work as
- # might be expected for debug-link based lookups. For this
- # style of lookup GDB only seems to care if the original file
- # itself had a 'target:' prefix. The 'target:' prefix on the
- # sysroot just seems to cause GDB to bail on looking up via
- # the 'target:' prefixed sysroot.
- #
- # Bug PR gdb/30866 seems to be the (or a) relevant bug for
- # this problem.
- if { $sysroot_prefix ne "" } {
- setup_kfail "*-*-*" 31804
- }
gdb_assert { $::gdb_file_cmd_debug_info eq "debug" } \
"ensure debug information was found"
- if { $sysroot_prefix ne "" } {
- setup_kfail "*-*-*" 31804
- }
set re [string_to_regexp "Reading symbols from ${sysroot_prefix}$debug_symlink..."]
gdb_assert {[regexp $re $::gdb_file_cmd_msg]} \
"debug symbols read from correct file"
diff --git a/gdb/testsuite/gdb.base/testenv.exp b/gdb/testsuite/gdb.base/testenv.exp
index 847647e..908918a 100644
--- a/gdb/testsuite/gdb.base/testenv.exp
+++ b/gdb/testsuite/gdb.base/testenv.exp
@@ -68,7 +68,7 @@ proc find_env {varname} {
}
-re "$gdb_prompt $" {
# If this fails, bail out, otherwise we get stuck in
- # an infinite loop. The caller will end up emiting a
+ # an infinite loop. The caller will end up emitting a
# FAIL.
return "<fail>"
}
diff --git a/gdb/testsuite/gdb.base/vla-optimized-out.exp b/gdb/testsuite/gdb.base/vla-optimized-out.exp
index a0762d5..b57e474 100644
--- a/gdb/testsuite/gdb.base/vla-optimized-out.exp
+++ b/gdb/testsuite/gdb.base/vla-optimized-out.exp
@@ -57,15 +57,15 @@ proc vla_optimized_out {exe_suffix options} {
# that case to reply with 'no such vector element'.
gdb_test "p a\[0\]" \
"(= <optimized out>|no such vector element)" \
- "print out of range element of vla (0)"
+ "print out of range element of vla, 0"
gdb_test "p a\[6\]" \
"no such vector element" \
- "print out of range element of vla (6)"
+ "print out of range element of vla, 6"
gdb_test "p a\[0xffffffff\]" \
"no such vector element" \
- "print out of range element of vla (0xffffffff)"
+ "print out of range element of vla, 0xffffffff"
}
set o1_sizeof_result "6"
diff --git a/gdb/testsuite/gdb.base/vla-ptr.exp b/gdb/testsuite/gdb.base/vla-ptr.exp
index a784c18..df1b8f0 100644
--- a/gdb/testsuite/gdb.base/vla-ptr.exp
+++ b/gdb/testsuite/gdb.base/vla-ptr.exp
@@ -29,13 +29,13 @@ set sizeof_int [get_sizeof "int" 4]
# Check that VLA passed to function (pointer) points to the first element.
gdb_breakpoint [gdb_get_line_number "foo_bp"]
gdb_continue_to_breakpoint "foo_bp"
-gdb_test "print vla_ptr" "\\\(int \\\*\\\) $hex" "print vla_ptr (foo)"
-gdb_test "print *vla_ptr" " = 2" "print *vla_ptr (foo)"
+gdb_test "print vla_ptr" "\\\(int \\\*\\\) $hex" "print vla_ptr, foo"
+gdb_test "print *vla_ptr" " = 2" "print *vla_ptr, foo"
gdb_breakpoint [gdb_get_line_number "bar_bp"]
gdb_continue_to_breakpoint "bar_bp"
-gdb_test "print vla_ptr" "\\\(int \\\*\\\) $hex" "print vla_ptr (bar)"
-gdb_test "print *vla_ptr" " = 2" "print *vla_ptr (bar)"
+gdb_test "print vla_ptr" "\\\(int \\\*\\\) $hex" "print vla_ptr, bar"
+gdb_test "print *vla_ptr" " = 2" "print *vla_ptr, bar"
gdb_breakpoint [gdb_get_line_number "vla_func_bp"]
gdb_continue_to_breakpoint "vla_func_bp"
diff --git a/gdb/testsuite/gdb.base/vla-sideeffect.exp b/gdb/testsuite/gdb.base/vla-sideeffect.exp
index e17037d..8215ec2 100644
--- a/gdb/testsuite/gdb.base/vla-sideeffect.exp
+++ b/gdb/testsuite/gdb.base/vla-sideeffect.exp
@@ -52,30 +52,30 @@ gdb_test "print vla1\[0\]" " = 10" \
gdb_test "print sizeof (vla2\[i++\])" " = ${sizeof_vla}"
gdb_test "print i" " = 1" \
- "print i - sizeof with side effects (1)"
+ "print i - sizeof with side effects, 1"
gdb_test "print sizeof (vla2\[i++ + sizeof(j++)\])" " = ${sizeof_vla}"
gdb_test "print i" " = 2" \
- "print i - sizeof with side effects (2)"
+ "print i - sizeof with side effects, 2"
gdb_test "print j" " = 0" \
"print j - sizeof with no side effects"
gdb_test "ptype vla2\[i++\]" "type = int \\\[10\\\]"
gdb_test "print i" " = 2" \
- "print i - ptype with side effects (1)"
+ "print i - ptype with side effects, 1"
gdb_test "ptype vla2\[i++ + sizeof(j++)\]" "type = int \\\[10\\\]"
gdb_test "print i" " = 2" \
- "print i - ptype with side effects (2)"
+ "print i - ptype with side effects, 2"
gdb_test "print j" " = 0" \
"print j - ptype with no side effects"
gdb_test "whatis vla2\[i++\]" "type = int \\\[10\\\]"
gdb_test "print i" " = 2" \
- "print i - whatis with side effects (1)"
+ "print i - whatis with side effects, 1"
gdb_test "whatis vla2\[i++ + sizeof(j++)\]" "type = int \\\[10\\\]"
gdb_test "print i" " = 2" \
- "print i - whatis with side effects (2)"
+ "print i - whatis with side effects, 2"
gdb_test "print j" " = 0" \
"print j - whatis with no side effects"
diff --git a/gdb/testsuite/gdb.base/watch-vfork.exp b/gdb/testsuite/gdb.base/watch-vfork.exp
index 617a975..f7e268f 100644
--- a/gdb/testsuite/gdb.base/watch-vfork.exp
+++ b/gdb/testsuite/gdb.base/watch-vfork.exp
@@ -37,11 +37,11 @@ proc test_watchpoint_across_vfork { hw teststr } {
gdb_test "watch global" \
"atchpoint .*: global" \
- "Watchpoint on global variable ($teststr)"
+ "Watchpoint on global variable, $teststr"
gdb_test "continue" \
"atchpoint .*: global.*" \
- "Watchpoint triggers after vfork ($teststr)"
+ "Watchpoint triggers after vfork, $teststr"
}
if { [allow_hw_watchpoint_tests] } {
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 30fa12e..154514f 100644
--- a/gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.exp
+++ b/gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.exp
@@ -62,7 +62,7 @@
#
# If the target has non-continuable watchpoints, while GDB thinks it
# has continuable watchpoints, GDB will see a watchpoint trigger,
-# notice no value changed, and immediatly continue the target. Now,
+# notice no value changed, and immediately continue the target. Now,
# either the target manages to step-over the watchpoint transparently,
# and GDB thus fails to present to value change to the user, or, the
# watchpoint will keep re-triggering, with the program never making
diff --git a/gdb/testsuite/gdb.base/wchar.exp b/gdb/testsuite/gdb.base/wchar.exp
index a4127fc..0fc97cf 100644
--- a/gdb/testsuite/gdb.base/wchar.exp
+++ b/gdb/testsuite/gdb.base/wchar.exp
@@ -60,15 +60,15 @@ gdb_test "print repeat_p" \
gdb_test_no_output "set print null on"
gdb_test "print repeat" "= L\"A\", '$cent' <repeats 21 times>, \"B\"" \
- "print repeat (print null on)"
+ "print repeat, print null on"
gdb_test_no_output "set print elements 3"
gdb_test "print repeat" "= L\"A$cent$cent\"\.\.\." \
- "print repeat (print elements 3)"
+ "print repeat, print elements 3"
gdb_test "print repeat_p" "= $hex L\"A$cent$cent\"\.\.\." \
- "print repeat_p (print elements 3)"
+ "print repeat_p, print elements 3"
# From PR cli/14977, but here because it requires wchar_t.
gdb_test "printf \"%ls\\n\", 0" "\\(null\\)"
diff --git a/gdb/testsuite/gdb.base/whatis-ptype-typedefs.exp b/gdb/testsuite/gdb.base/whatis-ptype-typedefs.exp
index eb575b3..7088299 100644
--- a/gdb/testsuite/gdb.base/whatis-ptype-typedefs.exp
+++ b/gdb/testsuite/gdb.base/whatis-ptype-typedefs.exp
@@ -55,7 +55,7 @@ proc prepare {lang} {
return 1
}
-# The following list is layed out as a table. It is composed by
+# The following list is laid out as a table. It is composed by
# sub-lists (lines), with each line representing one whatis/ptype
# test. The sub-list (line) elements (columns) are (in order):
#
@@ -271,8 +271,11 @@ proc run_tests {lang} {
if {([string match "v_*" $to]
|| (![string match "v_*" $from] && ![string match "*method" $from])
|| [string match "*method" $to])} {
- gdb_test "whatis ($to) $from" "syntax error.*" "whatis ($to) $from (syntax)"
- gdb_test "ptype ($to) $from" "syntax error.*" "ptype ($to) $from (syntax)"
+ set cmd "whatis ($to) $from"
+ gdb_test $cmd "syntax error.*" "$cmd, syntax"
+
+ set cmd "ptype ($to) $from"
+ gdb_test $cmd "syntax error.*" "$cmd, syntax"
} elseif {([string match "*float*" $from] && [string match "*array*" $to])
|| (!$float_ptr_same_size
&& ([string match "float*" $to] && [string match "*array*" $from]
@@ -289,8 +292,11 @@ proc run_tests {lang} {
|| ([string match "*ftype2" $to] && [string match "*method" $from])
|| ([string match "*method_ptr*" $to] && [string match "*method" $from])
|| ([string match "*method_ptr*" $to] && [string match "*array*" $from])} {
- gdb_test "whatis ($to) $from" "Invalid cast." "whatis ($to) $from (invalid)"
- gdb_test "ptype ($to) $from" "Invalid cast." "ptype ($to) $from (invalid)"
+ set cmd "whatis ($to) $from"
+ gdb_test $cmd "Invalid cast." "$cmd, invalid"
+
+ set cmd "ptype ($to) $from"
+ gdb_test $cmd "Invalid cast." "$cmd, invalid"
} else {
gdb_test "whatis ($to) $from" "type = [string_to_regexp $to]"
gdb_test "ptype ($to) $from" "type = $ptype"
diff --git a/gdb/testsuite/gdb.base/wrap-line.exp b/gdb/testsuite/gdb.base/wrap-line.exp
index b0931a3..323cd6c 100644
--- a/gdb/testsuite/gdb.base/wrap-line.exp
+++ b/gdb/testsuite/gdb.base/wrap-line.exp
@@ -19,8 +19,10 @@
# build == host.
require {!is_remote host}
-# Test both ansi (no auto-wrap) and xterm (auto-wrap).
-set terms {ansi xterm}
+# Test both ansi (no auto-wrap) and xterm (auto-wrap). Also test dumb, which
+# shows the effective behaviour on stub-termcap systems, regardless of the
+# TERM setting.
+set terms {ansi xterm dumb}
# Fill line, assuming we start after the gdb prompt.
proc fill_line { width } {
@@ -44,9 +46,11 @@ proc get_screen_width { } {
upvar gdb_width gdb_width
upvar readline_width readline_width
upvar env_width env_width
+ upvar wrap_mode wrap_mode
set gdb_width 0
set readline_width 0
set env_width 0
+ set wrap_mode ""
set re1 "Number of characters gdb thinks are in a line is ($::decimal)\[^\r\n\]*\\."
set re2 \
"Number of characters readline reports are in a line is ($::decimal)\[^\r\n\]*\\."
@@ -54,6 +58,7 @@ proc get_screen_width { } {
"Number of characters curses thinks are in a line is $::decimal\\."
set re4 \
"Number of characters environment thinks are in a line is ($::decimal) \\(COLUMNS\\)."
+ set re5 [string cat "Readline wrapping mode: (\[^\r\n]*\)\\."]
set cmd "maint info screen"
set re \
[multi_line \
@@ -61,12 +66,14 @@ proc get_screen_width { } {
$re2 \
"(?:$re3" \
")?$re4" \
- .*]
+ .* \
+ $re5]
gdb_test_multiple $cmd "" {
-re -wrap $re {
set gdb_width $expect_out(1,string)
set readline_width $expect_out(2,string)
set env_width $expect_out(3,string)
+ set wrap_mode $expect_out(4,string)
pass $gdb_test_name
}
}
@@ -79,10 +86,16 @@ proc test_wrap { width_auto_detected } {
get_screen_width
- if { $::term == "xterm" } {
+ set wrap_mode_terminal "terminal (terminal is auto wrap capable)"
+ set wrap_mode_readline \
+ "readline (terminal is not auto wrap capable, last column reserved)"
+ set have_wrap 1
+ if { $wrap_mode == $wrap_mode_terminal } {
gdb_assert { $gdb_width == $readline_width }
- } else {
+ } elseif { $wrap_mode == $wrap_mode_readline } {
gdb_assert { $gdb_width == [expr $readline_width + 1] }
+ } else {
+ set have_wrap 0
}
gdb_assert { $gdb_width == $env_width } "width"
@@ -113,7 +126,10 @@ proc test_wrap { width_auto_detected } {
gdb_test_multiple "" "wrap" {
-re $re {
- pass $gdb_test_name
+ gdb_assert {$have_wrap} $gdb_test_name
+ }
+ -re "\r<.*" {
+ gdb_assert {!$have_wrap} $gdb_test_name
}
}
diff --git a/gdb/testsuite/gdb.arch/i386-mpx-simple_segv.c b/gdb/testsuite/gdb.btrace/event-tracing-gap.c
index 6843317..b04f74d 100644
--- a/gdb/testsuite/gdb.arch/i386-mpx-simple_segv.c
+++ b/gdb/testsuite/gdb.btrace/event-tracing-gap.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 2015-2024 Free Software Foundation, Inc.
+/* This testcase is part of GDB, the GNU debugger.
- Contributed by Intel Corp. <walfred.tedeschi@intel.com>
+ Copyright 2024 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,22 +15,18 @@
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 OUR_SIZE 5
-
-void
-upper (int * p, int len)
+static int
+square (int num)
{
- int value;
- len++; /* b0-size-test. */
- value = *(p + len);
+ return num * num; /* bp1. */
}
int
main (void)
{
- int a = 0; /* Dummy variable for debugging purposes. */
- int sx[OUR_SIZE];
- a++; /* register-eval. */
- upper (sx, OUR_SIZE + 2);
- return sx[1];
+ int a = 2;
+ int ans = 0;
+
+ ans = square (a);
+ return 0; /* bp2. */
}
diff --git a/gdb/testsuite/gdb.btrace/event-tracing-gap.exp b/gdb/testsuite/gdb.btrace/event-tracing-gap.exp
new file mode 100644
index 0000000..d33e8e8
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/event-tracing-gap.exp
@@ -0,0 +1,75 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2024 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test event tracing with gaps.
+
+require allow_btrace_pt_event_trace_tests
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} {
+ return -1
+}
+
+if {![runto_main]} {
+ return -1
+}
+
+gdb_test_no_output "set record btrace pt event-tracing on"
+gdb_test_no_output "record btrace pt"
+
+set bp_1 [gdb_get_line_number "bp1"]
+set bp_2 [gdb_get_line_number "bp2"]
+gdb_breakpoint $bp_1
+gdb_breakpoint $bp_2
+
+gdb_test "next"
+
+# Inferior calls and return commands will create gaps in the recording.
+gdb_test "call square (3)" [multi_line \
+ "" \
+ "Breakpoint $decimal, square \\(num=3\\) at \[^\r\n\]+:$bp_1" \
+ "$decimal.*bp1.*" \
+ "The program being debugged stopped while in a function called from GDB\\." \
+ "Evaluation of the expression containing the function" \
+ "\\(square\\) will be abandoned\\." \
+ "When the function is done executing, GDB will silently stop\\."]
+
+gdb_test "return 9" "0.*main.*" \
+ "return" \
+ "Make.*return now\\? \\(y or n\\) " "y"
+
+gdb_continue_to_breakpoint "break at bp_1" ".*$srcfile:$bp_1.*"
+gdb_continue_to_breakpoint "break at bp_2" ".*$srcfile:$bp_2.*"
+
+# We should have 2 gaps and events for each breakpoint we hit.
+# Note that due to the asynchronous nature of certain events, we use
+# gdb_test_sequence and check only for events that we can control.
+gdb_test_sequence "record function-call-history" "function-call-history" {
+ "\[0-9\]+\tmain"
+ "\\\[iret(: ip = $hex)?\\\]"
+ "\[0-9\]+\t\\\[non-contiguous\\\]"
+ "\[0-9\]+\tsquare"
+ "\\\[interrupt: vector = 0x3 \\\(#bp\\\)(, ip = 0x\[0-9a-fA-F\]+)?\\\]"
+ "\\\[iret(: ip = $hex)?\\\]"
+ "\[0-9\]+\t\\\[non-contiguous\\\]"
+ "\[0-9\]+\tmain"
+ "\[0-9\]+\tsquare"
+ "\\\[interrupt: vector = 0x3 \\\(#bp\\\)(, ip = 0x\[0-9a-fA-F\]+)?\\\]"
+ "\\\[iret(: ip = $hex)?\\\]"
+ "\[0-9\]+\tmain"
+}
diff --git a/gdb/testsuite/gdb.btrace/event-tracing.exp b/gdb/testsuite/gdb.btrace/event-tracing.exp
new file mode 100644
index 0000000..1a5eee0
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/event-tracing.exp
@@ -0,0 +1,52 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2024 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test basic Intel PT event tracing
+
+require allow_btrace_pt_event_trace_tests
+
+standard_testfile null-deref.c
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} {
+ return -1
+}
+
+if {![runto_main]} {
+ return -1
+}
+
+gdb_test_no_output "set record btrace pt event-tracing on"
+gdb_test_no_output "record btrace pt"
+
+gdb_test "continue" "Program received signal SIGSEGV, Segmentation fault.*"
+
+# Test printing of at least one INTERRUPT and one IRET event.
+# This uses test_sequence to avoid random events failing the tests.
+gdb_test_sequence "record function-call-history" "function-call-history" {
+ "\[0-9\]+\tmain"
+ "\t \\\[iret(: ip = $hex)?\\\]"
+ "\t \\\[interrupt: vector = 0xe \\\(#pf\\\)(, cr2 = 0x0)?(, ip = 0x\[0-9a-fA-F\]+)?\\\]"
+}
+
+# Test the instruction-history. Assembly can differ between compilers. To
+# avoid creating a .S file for this test we just check the event at the end.
+gdb_test "record instruction-history" \
+ "$decimal\t \\\[interrupt: vector = 0xe \\\(#pf\\\)(, cr2 = 0x0)?(, ip = $hex)?\\\]"
+
+# Test reverse stepping and replay stepping
+gdb_test "reverse-stepi" "\\\[interrupt: vector = 0xe \\\(#pf\\\)(, cr2 = 0x0)?(, ip = $hex)?\\\].*"
+gdb_test "stepi" "\\\[interrupt: vector = 0xe \\\(#pf\\\)(, cr2 = 0x0)?(, ip = $hex)?\\\].*"
diff --git a/gdb/testsuite/gdb.btrace/i386-ptwrite.S b/gdb/testsuite/gdb.btrace/i386-ptwrite.S
new file mode 100644
index 0000000..5c649cf
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/i386-ptwrite.S
@@ -0,0 +1,550 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+ This file has been generated using gcc version 10.3.1 20210422
+ (Red Hat 10.3.1-1):
+ gcc -S -dA -g -m32 -mptwrite ptwrite.c -o i386-ptwrite.S. */
+
+
+ .file "ptwrite.c"
+ .text
+.Ltext0:
+ .globl ptwrite1
+ .type ptwrite1, @function
+ptwrite1:
+.LFB4021:
+ .file 1 "ptwrite.c"
+ # ptwrite.c:22:1
+ .loc 1 22 1
+ .cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ subl $16, %esp
+ # ptwrite.c:23:3
+ .loc 1 23 3
+ movl 8(%ebp), %eax
+ movl %eax, -4(%ebp)
+.LBB6:
+.LBB7:
+ .file 2 "/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h"
+ # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:307:3
+ .loc 2 307 3
+ movl -4(%ebp), %eax
+ ptwrite %eax
+ # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:308:1
+ .loc 2 308 1
+ nop
+.LBE7:
+.LBE6:
+ # ptwrite.c:24:1
+ .loc 1 24 1
+ nop
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+# SUCC: EXIT [always]
+ ret
+ .cfi_endproc
+.LFE4021:
+ .size ptwrite1, .-ptwrite1
+ .globl ptwrite2
+ .type ptwrite2, @function
+ptwrite2:
+.LFB4022:
+ # ptwrite.c:28:1
+ .loc 1 28 1
+ .cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ subl $16, %esp
+ # ptwrite.c:29:3
+ .loc 1 29 3
+ movl 8(%ebp), %eax
+ movl %eax, -4(%ebp)
+.LBB8:
+.LBB9:
+ # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:307:3
+ .loc 2 307 3
+ movl -4(%ebp), %eax
+ ptwrite %eax
+ # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:308:1
+ .loc 2 308 1
+ nop
+.LBE9:
+.LBE8:
+ # ptwrite.c:30:1
+ .loc 1 30 1
+ nop
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+# SUCC: EXIT [always]
+ ret
+ .cfi_endproc
+.LFE4022:
+ .size ptwrite2, .-ptwrite2
+ .globl main
+ .type main, @function
+main:
+.LFB4023:
+ # ptwrite.c:34:1
+ .loc 1 34 1
+ .cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ # ptwrite.c:35:3
+ .loc 1 35 3
+ pushl $66
+ call ptwrite1
+ addl $4, %esp
+ # ptwrite.c:36:3
+ .loc 1 36 3
+ pushl $67
+ call ptwrite2
+ addl $4, %esp
+ # ptwrite.c:38:10
+ .loc 1 38 10
+ movl $0, %eax
+ # ptwrite.c:39:1
+ .loc 1 39 1
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+# SUCC: EXIT [always]
+ ret
+ .cfi_endproc
+.LFE4023:
+ .size main, .-main
+.Letext0:
+ .section .debug_info,"",@progbits
+.Ldebug_info0:
+ .long 0x129 # Length of Compilation Unit Info
+ .value 0x4 # DWARF version number
+ .long .Ldebug_abbrev0 # Offset Into Abbrev. Section
+ .byte 0x4 # Pointer Size (in bytes)
+ .uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit)
+ .long .LASF15 # DW_AT_producer: "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -m32 -mptwrite -mtune=generic -march=i686 -g"
+ .byte 0xc # DW_AT_language
+ .long .LASF16 # DW_AT_name: "ptwrite.c"
+ .long .LASF17 # DW_AT_comp_dir: "gdb/gdb/testsuite/gdb.btrace"
+ .long .Ltext0 # DW_AT_low_pc
+ .long .Letext0-.Ltext0 # DW_AT_high_pc
+ .long .Ldebug_line0 # DW_AT_stmt_list
+ .uleb128 0x2 # (DIE (0x25) DW_TAG_base_type)
+ .byte 0x4 # DW_AT_byte_size
+ .byte 0x5 # DW_AT_encoding
+ .ascii "int\0" # DW_AT_name
+ .uleb128 0x3 # (DIE (0x2c) DW_TAG_base_type)
+ .byte 0x2 # DW_AT_byte_size
+ .byte 0x5 # DW_AT_encoding
+ .long .LASF0 # DW_AT_name: "short int"
+ .uleb128 0x3 # (DIE (0x33) DW_TAG_base_type)
+ .byte 0x1 # DW_AT_byte_size
+ .byte 0x6 # DW_AT_encoding
+ .long .LASF1 # DW_AT_name: "char"
+ .uleb128 0x3 # (DIE (0x3a) DW_TAG_base_type)
+ .byte 0x8 # DW_AT_byte_size
+ .byte 0x5 # DW_AT_encoding
+ .long .LASF2 # DW_AT_name: "long long int"
+ .uleb128 0x3 # (DIE (0x41) DW_TAG_base_type)
+ .byte 0x4 # DW_AT_byte_size
+ .byte 0x4 # DW_AT_encoding
+ .long .LASF3 # DW_AT_name: "float"
+ .uleb128 0x3 # (DIE (0x48) DW_TAG_base_type)
+ .byte 0x4 # DW_AT_byte_size
+ .byte 0x7 # DW_AT_encoding
+ .long .LASF4 # DW_AT_name: "unsigned int"
+ .uleb128 0x3 # (DIE (0x4f) DW_TAG_base_type)
+ .byte 0x4 # DW_AT_byte_size
+ .byte 0x5 # DW_AT_encoding
+ .long .LASF5 # DW_AT_name: "long int"
+ .uleb128 0x3 # (DIE (0x56) DW_TAG_base_type)
+ .byte 0x1 # DW_AT_byte_size
+ .byte 0x8 # DW_AT_encoding
+ .long .LASF6 # DW_AT_name: "unsigned char"
+ .uleb128 0x3 # (DIE (0x5d) DW_TAG_base_type)
+ .byte 0x2 # DW_AT_byte_size
+ .byte 0x7 # DW_AT_encoding
+ .long .LASF7 # DW_AT_name: "short unsigned int"
+ .uleb128 0x3 # (DIE (0x64) DW_TAG_base_type)
+ .byte 0x4 # DW_AT_byte_size
+ .byte 0x7 # DW_AT_encoding
+ .long .LASF8 # DW_AT_name: "long unsigned int"
+ .uleb128 0x3 # (DIE (0x6b) DW_TAG_base_type)
+ .byte 0x1 # DW_AT_byte_size
+ .byte 0x6 # DW_AT_encoding
+ .long .LASF9 # DW_AT_name: "signed char"
+ .uleb128 0x3 # (DIE (0x72) DW_TAG_base_type)
+ .byte 0x8 # DW_AT_byte_size
+ .byte 0x7 # DW_AT_encoding
+ .long .LASF10 # DW_AT_name: "long long unsigned int"
+ .uleb128 0x3 # (DIE (0x79) DW_TAG_base_type)
+ .byte 0x8 # DW_AT_byte_size
+ .byte 0x4 # DW_AT_encoding
+ .long .LASF11 # DW_AT_name: "double"
+ .uleb128 0x4 # (DIE (0x80) DW_TAG_subprogram)
+ # DW_AT_external
+ .long .LASF18 # DW_AT_name: "main"
+ .byte 0x1 # DW_AT_decl_file (ptwrite.c)
+ .byte 0x21 # DW_AT_decl_line
+ .byte 0x1 # DW_AT_decl_column
+ # DW_AT_prototyped
+ .long 0x25 # DW_AT_type
+ .long .LFB4023 # DW_AT_low_pc
+ .long .LFE4023-.LFB4023 # DW_AT_high_pc
+ .uleb128 0x1 # DW_AT_frame_base
+ .byte 0x9c # DW_OP_call_frame_cfa
+ # DW_AT_GNU_all_tail_call_sites
+ .uleb128 0x5 # (DIE (0x96) DW_TAG_subprogram)
+ # DW_AT_external
+ .long .LASF12 # DW_AT_name: "ptwrite2"
+ .byte 0x1 # DW_AT_decl_file (ptwrite.c)
+ .byte 0x1b # DW_AT_decl_line
+ .byte 0x1 # DW_AT_decl_column
+ # DW_AT_prototyped
+ .long .LFB4022 # DW_AT_low_pc
+ .long .LFE4022-.LFB4022 # DW_AT_high_pc
+ .uleb128 0x1 # DW_AT_frame_base
+ .byte 0x9c # DW_OP_call_frame_cfa
+ # DW_AT_GNU_all_call_sites
+ .long 0xd5 # DW_AT_sibling
+ .uleb128 0x6 # (DIE (0xac) DW_TAG_formal_parameter)
+ .long .LASF14 # DW_AT_name: "value"
+ .byte 0x1 # DW_AT_decl_file (ptwrite.c)
+ .byte 0x1b # DW_AT_decl_line
+ .byte 0xf # DW_AT_decl_column
+ .long 0x25 # DW_AT_type
+ .uleb128 0x2 # DW_AT_location
+ .byte 0x91 # DW_OP_fbreg
+ .sleb128 0
+ .uleb128 0x7 # (DIE (0xbb) DW_TAG_inlined_subroutine)
+ .long 0x114 # DW_AT_abstract_origin
+ .long .LBB8 # DW_AT_low_pc
+ .long .LBE8-.LBB8 # DW_AT_high_pc
+ .byte 0x1 # DW_AT_call_file (ptwrite.c)
+ .byte 0x1d # DW_AT_call_line
+ .byte 0x3 # DW_AT_call_column
+ .uleb128 0x8 # (DIE (0xcb) DW_TAG_formal_parameter)
+ .long 0x11e # DW_AT_abstract_origin
+ .uleb128 0x2 # DW_AT_location
+ .byte 0x91 # DW_OP_fbreg
+ .sleb128 -12
+ .byte 0 # end of children of DIE 0xbb
+ .byte 0 # end of children of DIE 0x96
+ .uleb128 0x5 # (DIE (0xd5) DW_TAG_subprogram)
+ # DW_AT_external
+ .long .LASF13 # DW_AT_name: "ptwrite1"
+ .byte 0x1 # DW_AT_decl_file (ptwrite.c)
+ .byte 0x15 # DW_AT_decl_line
+ .byte 0x1 # DW_AT_decl_column
+ # DW_AT_prototyped
+ .long .LFB4021 # DW_AT_low_pc
+ .long .LFE4021-.LFB4021 # DW_AT_high_pc
+ .uleb128 0x1 # DW_AT_frame_base
+ .byte 0x9c # DW_OP_call_frame_cfa
+ # DW_AT_GNU_all_call_sites
+ .long 0x114 # DW_AT_sibling
+ .uleb128 0x6 # (DIE (0xeb) DW_TAG_formal_parameter)
+ .long .LASF14 # DW_AT_name: "value"
+ .byte 0x1 # DW_AT_decl_file (ptwrite.c)
+ .byte 0x15 # DW_AT_decl_line
+ .byte 0xf # DW_AT_decl_column
+ .long 0x25 # DW_AT_type
+ .uleb128 0x2 # DW_AT_location
+ .byte 0x91 # DW_OP_fbreg
+ .sleb128 0
+ .uleb128 0x7 # (DIE (0xfa) DW_TAG_inlined_subroutine)
+ .long 0x114 # DW_AT_abstract_origin
+ .long .LBB6 # DW_AT_low_pc
+ .long .LBE6-.LBB6 # DW_AT_high_pc
+ .byte 0x1 # DW_AT_call_file (ptwrite.c)
+ .byte 0x17 # DW_AT_call_line
+ .byte 0x3 # DW_AT_call_column
+ .uleb128 0x8 # (DIE (0x10a) DW_TAG_formal_parameter)
+ .long 0x11e # DW_AT_abstract_origin
+ .uleb128 0x2 # DW_AT_location
+ .byte 0x91 # DW_OP_fbreg
+ .sleb128 -12
+ .byte 0 # end of children of DIE 0xfa
+ .byte 0 # end of children of DIE 0xd5
+ .uleb128 0x9 # (DIE (0x114) DW_TAG_subprogram)
+ # DW_AT_external
+ .long .LASF19 # DW_AT_name: "_ptwrite32"
+ .byte 0x2 # DW_AT_decl_file (/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h)
+ .value 0x131 # DW_AT_decl_line
+ .byte 0x1 # DW_AT_decl_column
+ # DW_AT_prototyped
+ .byte 0x3 # DW_AT_inline
+ # DW_AT_artificial
+ .uleb128 0xa # (DIE (0x11e) DW_TAG_formal_parameter)
+ .ascii "__B\0" # DW_AT_name
+ .byte 0x2 # DW_AT_decl_file (/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h)
+ .value 0x131 # DW_AT_decl_line
+ .byte 0x16 # DW_AT_decl_column
+ .long 0x48 # DW_AT_type
+ .byte 0 # end of children of DIE 0x114
+ .byte 0 # end of children of DIE 0xb
+ .section .debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+ .uleb128 0x1 # (abbrev code)
+ .uleb128 0x11 # (TAG: DW_TAG_compile_unit)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x25 # (DW_AT_producer)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x13 # (DW_AT_language)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x1b # (DW_AT_comp_dir)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x11 # (DW_AT_low_pc)
+ .uleb128 0x1 # (DW_FORM_addr)
+ .uleb128 0x12 # (DW_AT_high_pc)
+ .uleb128 0x6 # (DW_FORM_data4)
+ .uleb128 0x10 # (DW_AT_stmt_list)
+ .uleb128 0x17 # (DW_FORM_sec_offset)
+ .byte 0
+ .byte 0
+ .uleb128 0x2 # (abbrev code)
+ .uleb128 0x24 # (TAG: DW_TAG_base_type)
+ .byte 0 # DW_children_no
+ .uleb128 0xb # (DW_AT_byte_size)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3e # (DW_AT_encoding)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0x8 # (DW_FORM_string)
+ .byte 0
+ .byte 0
+ .uleb128 0x3 # (abbrev code)
+ .uleb128 0x24 # (TAG: DW_TAG_base_type)
+ .byte 0 # DW_children_no
+ .uleb128 0xb # (DW_AT_byte_size)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3e # (DW_AT_encoding)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .byte 0
+ .byte 0
+ .uleb128 0x4 # (abbrev code)
+ .uleb128 0x2e # (TAG: DW_TAG_subprogram)
+ .byte 0 # DW_children_no
+ .uleb128 0x3f # (DW_AT_external)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x39 # (DW_AT_decl_column)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x27 # (DW_AT_prototyped)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x11 # (DW_AT_low_pc)
+ .uleb128 0x1 # (DW_FORM_addr)
+ .uleb128 0x12 # (DW_AT_high_pc)
+ .uleb128 0x6 # (DW_FORM_data4)
+ .uleb128 0x40 # (DW_AT_frame_base)
+ .uleb128 0x18 # (DW_FORM_exprloc)
+ .uleb128 0x2116 # (DW_AT_GNU_all_tail_call_sites)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .byte 0
+ .byte 0
+ .uleb128 0x5 # (abbrev code)
+ .uleb128 0x2e # (TAG: DW_TAG_subprogram)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x3f # (DW_AT_external)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x39 # (DW_AT_decl_column)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x27 # (DW_AT_prototyped)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x11 # (DW_AT_low_pc)
+ .uleb128 0x1 # (DW_FORM_addr)
+ .uleb128 0x12 # (DW_AT_high_pc)
+ .uleb128 0x6 # (DW_FORM_data4)
+ .uleb128 0x40 # (DW_AT_frame_base)
+ .uleb128 0x18 # (DW_FORM_exprloc)
+ .uleb128 0x2117 # (DW_AT_GNU_all_call_sites)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x1 # (DW_AT_sibling)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .byte 0
+ .byte 0
+ .uleb128 0x6 # (abbrev code)
+ .uleb128 0x5 # (TAG: DW_TAG_formal_parameter)
+ .byte 0 # DW_children_no
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x39 # (DW_AT_decl_column)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x2 # (DW_AT_location)
+ .uleb128 0x18 # (DW_FORM_exprloc)
+ .byte 0
+ .byte 0
+ .uleb128 0x7 # (abbrev code)
+ .uleb128 0x1d # (TAG: DW_TAG_inlined_subroutine)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x31 # (DW_AT_abstract_origin)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x11 # (DW_AT_low_pc)
+ .uleb128 0x1 # (DW_FORM_addr)
+ .uleb128 0x12 # (DW_AT_high_pc)
+ .uleb128 0x6 # (DW_FORM_data4)
+ .uleb128 0x58 # (DW_AT_call_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x59 # (DW_AT_call_line)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x57 # (DW_AT_call_column)
+ .uleb128 0xb # (DW_FORM_data1)
+ .byte 0
+ .byte 0
+ .uleb128 0x8 # (abbrev code)
+ .uleb128 0x5 # (TAG: DW_TAG_formal_parameter)
+ .byte 0 # DW_children_no
+ .uleb128 0x31 # (DW_AT_abstract_origin)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x2 # (DW_AT_location)
+ .uleb128 0x18 # (DW_FORM_exprloc)
+ .byte 0
+ .byte 0
+ .uleb128 0x9 # (abbrev code)
+ .uleb128 0x2e # (TAG: DW_TAG_subprogram)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x3f # (DW_AT_external)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0x5 # (DW_FORM_data2)
+ .uleb128 0x39 # (DW_AT_decl_column)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x27 # (DW_AT_prototyped)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x20 # (DW_AT_inline)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x34 # (DW_AT_artificial)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .byte 0
+ .byte 0
+ .uleb128 0xa # (abbrev code)
+ .uleb128 0x5 # (TAG: DW_TAG_formal_parameter)
+ .byte 0 # DW_children_no
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0x8 # (DW_FORM_string)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0x5 # (DW_FORM_data2)
+ .uleb128 0x39 # (DW_AT_decl_column)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .byte 0
+ .byte 0
+ .byte 0
+ .section .debug_aranges,"",@progbits
+ .long 0x1c # Length of Address Ranges Info
+ .value 0x2 # DWARF aranges version
+ .long .Ldebug_info0 # Offset of Compilation Unit Info
+ .byte 0x4 # Size of Address
+ .byte 0 # Size of Segment Descriptor
+ .value 0 # Pad to 8 byte boundary
+ .value 0
+ .long .Ltext0 # Address
+ .long .Letext0-.Ltext0 # Length
+ .long 0
+ .long 0
+ .section .debug_line,"",@progbits
+.Ldebug_line0:
+ .section .debug_str,"MS",@progbits,1
+.LASF2:
+ .string "long long int"
+.LASF14:
+ .string "value"
+.LASF19:
+ .string "_ptwrite32"
+.LASF4:
+ .string "unsigned int"
+.LASF17:
+ .string "gdb/gdb/testsuite/gdb.btrace"
+.LASF18:
+ .string "main"
+.LASF16:
+ .string "ptwrite.c"
+.LASF8:
+ .string "long unsigned int"
+.LASF10:
+ .string "long long unsigned int"
+.LASF13:
+ .string "ptwrite1"
+.LASF12:
+ .string "ptwrite2"
+.LASF6:
+ .string "unsigned char"
+.LASF1:
+ .string "char"
+.LASF5:
+ .string "long int"
+.LASF15:
+ .string "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -m32 -mptwrite -mtune=generic -march=i686 -g"
+.LASF11:
+ .string "double"
+.LASF7:
+ .string "short unsigned int"
+.LASF9:
+ .string "signed char"
+.LASF3:
+ .string "float"
+.LASF0:
+ .string "short int"
+ .ident "GCC: (GNU) 10.3.1 20210422 (Red Hat 10.3.1-1)"
+ .section .note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.btrace/multi-thread-step.exp b/gdb/testsuite/gdb.btrace/multi-thread-step.exp
index 154db9a..cd20e8a 100644
--- a/gdb/testsuite/gdb.btrace/multi-thread-step.exp
+++ b/gdb/testsuite/gdb.btrace/multi-thread-step.exp
@@ -111,14 +111,14 @@ proc test_cont {} {
with_test_prefix "cont" {
gdb_test "thread 1" ".*"
with_test_prefix "thread 1" {
- gdb_test "continue" "No more reverse-execution history.*"
+ gdb_test "continue" "Reached end of recorded history.*"
check_not_replaying 1
check_replay_insn 2 2
}
gdb_test "thread 2" ".*"
with_test_prefix "thread 2" {
- gdb_test "continue" "No more reverse-execution history.*"
+ gdb_test "continue" "Reached end of recorded history.*"
check_not_replaying 1
check_not_replaying 2
@@ -128,7 +128,7 @@ proc test_cont {} {
proc test_cont_all {} {
with_test_prefix "cont-all" {
- gdb_test "continue" "No more reverse-execution history.*"
+ gdb_test "continue" "Reached end of recorded history.*"
# this works because we're lock-stepping threads that executed exactly
# the same code starting from the same instruction.
diff --git a/gdb/testsuite/gdb.btrace/nohist.exp b/gdb/testsuite/gdb.btrace/nohist.exp
index d719091..ac6a41c 100644
--- a/gdb/testsuite/gdb.btrace/nohist.exp
+++ b/gdb/testsuite/gdb.btrace/nohist.exp
@@ -42,7 +42,7 @@ with_test_prefix "forward" {
check_not_replaying
}
-gdb_test "reverse-continue" "No more reverse-execution history\.\r\n.*"
+gdb_test "reverse-continue" "Reached end of recorded history; stopping.*"
with_test_prefix "backward" {
check_not_replaying
diff --git a/gdb/testsuite/gdb.btrace/non-stop.exp b/gdb/testsuite/gdb.btrace/non-stop.exp
index 62c940e..8397c20 100644
--- a/gdb/testsuite/gdb.btrace/non-stop.exp
+++ b/gdb/testsuite/gdb.btrace/non-stop.exp
@@ -79,14 +79,26 @@ proc gdb_cont_to_bp_line { line threads nthreads } {
$nthreads
}
-proc gdb_cont_to_no_history { threads cmd nthreads } {
+proc gdb_cont_to_no_history_backward { threads cmd nthreads } {
gdb_cont_to $threads $cmd \
- [multi_line \
- "No more reverse-execution history\." \
- "\[^\\\r\\\n\]*" \
- "\[^\\\r\\\n\]*" \
- ] \
- $nthreads
+ [multi_line \
+ "Reached end of recorded history; stopping\." \
+ "Backward execution from here not possible\." \
+ "\[^\\\r\\\n\]*" \
+ "\[^\\\r\\\n\]*" \
+ ] \
+ $nthreads
+}
+
+proc gdb_cont_to_no_history_forward { threads cmd nthreads } {
+ gdb_cont_to $threads $cmd \
+ [multi_line \
+ "Reached end of recorded history; stopping\." \
+ "Following forward execution will be added to history\." \
+ "\[^\\\r\\\n\]*" \
+ "\[^\\\r\\\n\]*" \
+ ] \
+ $nthreads
}
# trace the code between the two breakpoints
@@ -176,14 +188,14 @@ with_test_prefix "reverse-step" {
with_test_prefix "continue" {
with_test_prefix "thread 1" {
with_test_prefix "continue" {
- gdb_cont_to_no_history 1 "continue" 1
+ gdb_cont_to_no_history_forward 1 "continue" 1
gdb_test "thread apply 1 info record" \
".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*"
gdb_test "thread apply 2 info record" \
".*Replay in progress\. At instruction 5\."
}
with_test_prefix "reverse-continue" {
- gdb_cont_to_no_history 1 "reverse-continue" 1
+ gdb_cont_to_no_history_backward 1 "reverse-continue" 1
gdb_test "thread apply 1 info record" \
".*Replay in progress\. At instruction 1\."
gdb_test "thread apply 2 info record" \
@@ -193,14 +205,14 @@ with_test_prefix "continue" {
with_test_prefix "thread 2" {
with_test_prefix "continue" {
- gdb_cont_to_no_history 2 "continue" 1
+ gdb_cont_to_no_history_forward 2 "continue" 1
gdb_test "thread apply 1 info record" \
".*Replay in progress\. At instruction 1\."
gdb_test "thread apply 2 info record" \
".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*"
}
with_test_prefix "reverse-continue" {
- gdb_cont_to_no_history 2 "reverse-continue" 1
+ gdb_cont_to_no_history_backward 2 "reverse-continue" 1
gdb_test "thread apply 1 info record" \
".*Replay in progress\. At instruction 1\."
gdb_test "thread apply 2 info record" \
@@ -215,8 +227,8 @@ with_test_prefix "no progress" {
gdb_test "thread apply 1 record goto end" ".*"
gdb_test "thread apply 2 record goto begin" ".*"
- gdb_cont_to_no_history 1 "continue" 1
- gdb_cont_to_no_history 1 "step" 1
+ gdb_cont_to_no_history_forward 1 "continue" 1
+ gdb_cont_to_no_history_forward 1 "step" 1
gdb_test "thread apply 1 info record" \
".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*"
gdb_test "thread apply 2 info record" \
@@ -227,8 +239,8 @@ with_test_prefix "no progress" {
gdb_test "thread apply 1 record goto begin" ".*"
gdb_test "thread apply 2 record goto end" ".*"
- gdb_cont_to_no_history 2 "continue" 1
- gdb_cont_to_no_history 2 "step" 1
+ gdb_cont_to_no_history_forward 2 "continue" 1
+ gdb_cont_to_no_history_forward 2 "step" 1
gdb_test "thread apply 1 info record" \
".*Replay in progress\. At instruction 1\."
gdb_test "thread apply 2 info record" \
@@ -238,7 +250,7 @@ with_test_prefix "no progress" {
with_test_prefix "all" {
gdb_test "thread apply all record goto begin" ".*"
- gdb_cont_to_no_history all "continue" 2
+ gdb_cont_to_no_history_forward all "continue" 2
gdb_test "thread apply 1 info record" \
".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*"
gdb_test "thread apply 2 info record" \
diff --git a/gdb/testsuite/gdb.btrace/null-deref.c b/gdb/testsuite/gdb.btrace/null-deref.c
new file mode 100644
index 0000000..f0de31f
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/null-deref.c
@@ -0,0 +1,26 @@
+/* Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+
+int
+main ()
+{
+ int a = 34;
+ int *b = NULL;
+
+ a = *b; /* BP1. */
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.btrace/ptwrite.c b/gdb/testsuite/gdb.btrace/ptwrite.c
new file mode 100644
index 0000000..e10b885
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/ptwrite.c
@@ -0,0 +1,39 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <immintrin.h>
+
+void
+ptwrite1 (int value)
+{
+ _ptwrite32 (value);
+}
+
+void
+ptwrite2 (int value)
+{
+ _ptwrite32 (value);
+}
+
+int
+main (void)
+{
+ ptwrite1 (0x42);
+ ptwrite2 (0x43);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.btrace/ptwrite.exp b/gdb/testsuite/gdb.btrace/ptwrite.exp
new file mode 100644
index 0000000..0970d31
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/ptwrite.exp
@@ -0,0 +1,201 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2024 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+load_lib gdb-python.exp
+
+require allow_btrace_ptw_tests allow_python_tests
+
+set opts {}
+
+if [info exists COMPILE] {
+ # make check RUNTESTFLAGS="gdb.btrace/ptwrite.exp COMPILE=1"
+ standard_testfile ptwrite.c
+ lappend opts debug additional_flags=-mptwrite
+} elseif {[istarget "i?86-*-*"] || [istarget "x86_64-*-*"]} {
+ if {[is_amd64_regs_target]} {
+ standard_testfile x86_64-ptwrite.S
+ } else {
+ standard_testfile i386-ptwrite.S
+ }
+} else {
+ unsupported "target architecture not supported"
+ return -1
+}
+
+if [prepare_for_testing "failed to prepare" $testfile $srcfile $opts] {
+ return -1
+}
+
+if { ![runto_main] } {
+ untested "failed to run to main"
+ return -1
+}
+
+### 1. Default testrun
+
+# Setup recording
+gdb_test_no_output "set record instruction-history-size unlimited"
+gdb_test_no_output "record btrace pt"
+gdb_test "next 2" ".*"
+
+with_test_prefix "Default" {
+ # Test record instruction-history
+ gdb_test "record instruction-history 1" [multi_line \
+ ".*\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ "\[0-9\]+\t \\\[0x42\\\]" \
+ ".*\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ "\[0-9\]+\t \\\[0x43\\\].*" \
+ ]
+
+ gdb_test "record instruction-history /a 1" [multi_line \
+ ".*\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ ".*\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+.*" \
+ ]
+
+ # Test function call history
+ gdb_test "record function-call-history 1,4" [multi_line \
+ "1\tmain" \
+ "2\tptwrite1" \
+ "\t \\\[0x42\\\]" \
+ "3\tmain" \
+ "4\tptwrite2" \
+ "\t \\\[0x43\\\]" \
+ ]
+
+ gdb_test "record function-call-history /a 1,4" [multi_line \
+ "1\tmain" \
+ "2\tptwrite1" \
+ "3\tmain" \
+ "4\tptwrite2" \
+ ]
+}
+
+# Test payload printing during stepping
+with_test_prefix "Stepping" {
+ gdb_test "record goto 10" "Can't go to an auxiliary instruction\."
+ gdb_test "record goto 9" ".*ptwrite.* at .*"
+ gdb_test "stepi" ".*\\\[0x42\\\].*"
+ gdb_test "reverse-stepi" ".*\\\[0x42\\\].*"
+ gdb_test "continue" [multi_line \
+ ".*\\\[0x42\\\]" \
+ "\\\[0x43\\\].*" \
+ ]
+ gdb_test "reverse-continue" [multi_line \
+ ".*\\\[0x43\\\]" \
+ "\\\[0x42\\\].*" \
+ ]
+}
+
+# Test auxiliary type in python
+gdb_test_multiline "auxiliary type in python" \
+ "python" "" \
+ "h = gdb.current_recording().instruction_history" "" \
+ "for insn in h:" "" \
+ " if hasattr(insn, 'decoded'):" "" \
+ " print(insn.decoded.decode())" "" \
+ " elif hasattr(insn, 'data'):" "" \
+ " print(insn.data)" "" \
+ "end" \
+ [multi_line \
+ ".*mov -0x4\\\(%(e|r)bp\\\),%(e|r)ax" \
+ "ptwrite %eax" \
+ "0x42" \
+ "nop.*" \
+ "mov -0x4\\\(%(e|r)bp\\\),%(e|r)ax" \
+ "ptwrite %eax" \
+ "0x43" \
+ "nop.*"
+ ]
+
+
+### 2. Test filter registration
+### 2.1 Custom filter
+with_test_prefix "Custom" {
+ gdb_test_multiline "register filter in python" \
+ "python" "" \
+ "def my_filter(payload, ip):" "" \
+ " if payload == 66:" "" \
+ " return \"payload: {0}, ip: {1:#x}\".format(payload, ip)" "" \
+ " else:" "" \
+ " return None" "" \
+ "def factory(thread): return my_filter" "" \
+ "import gdb.ptwrite" "" \
+ "gdb.ptwrite.register_filter_factory(factory)" "" \
+ "end" ""
+
+ gdb_test "record instruction-history 1" [multi_line \
+ ".*\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ "\[0-9\]+\t \\\[payload: 66, ip: $hex\\\]" \
+ ".*\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ "\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:.*" \
+ ]
+}
+
+### 2.2 None as filter. This resets the default behaviour.
+with_test_prefix "None" {
+ gdb_test_multiline "register filter in python" \
+ "python" "" \
+ "import gdb.ptwrite" "" \
+ "gdb.ptwrite.register_filter_factory(None)" "" \
+ "end" ""
+
+ gdb_test "record instruction-history 1" [multi_line \
+ ".*\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ "\[0-9\]+\t \\\[0x42\\\]" \
+ ".*\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ "\[0-9\]+\t \\\[0x43\\\].*" \
+ ]
+}
+
+### 2.3 Lambdas as filter
+with_test_prefix "Lambdas" {
+ gdb_test_multiline "register filter in python" \
+ "python" "" \
+ "import gdb.ptwrite" "" \
+ "lambda_filter = lambda payload, ip: \"{}\".format(payload + 2)" "" \
+ "gdb.ptwrite.register_filter_factory(lambda thread : lambda_filter)" "" \
+ "end" ""
+
+ gdb_test "record instruction-history 1" [multi_line \
+ ".*\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ "\[0-9\]+\t \\\[68\\\]" \
+ ".*\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ "\[0-9\]+\t \\\[69\\\].*" \
+ ] "Lambdas: record instruction-history 1"
+}
+
+### 2.4 Functors as filter
+with_test_prefix "Functors" {
+ gdb_test_multiline "register filter in python" \
+ "python" "" \
+ "import gdb.ptwrite" "" \
+ "class foobar(object):" "" \
+ " def __init__(self):" "" \
+ " self.variable = 0" "" \
+ " def __call__(self, payload, ip):" "" \
+ " self.variable += 1" "" \
+ " return \"{}, {}\".format(self.variable, payload)" "" \
+ "gdb.ptwrite.register_filter_factory(lambda thread : foobar())" "" \
+ "end" ""
+
+ gdb_test "record instruction-history 1" [multi_line \
+ ".*\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ "\[0-9\]+\t \\\[1, 66\\\]" \
+ ".*\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ "\[0-9\]+\t \\\[2, 67\\\].*" \
+ ] "Functors: record instruction-history 1"
+}
diff --git a/gdb/testsuite/gdb.btrace/stepi.exp b/gdb/testsuite/gdb.btrace/stepi.exp
index a70a5ad..689bc79 100644
--- a/gdb/testsuite/gdb.btrace/stepi.exp
+++ b/gdb/testsuite/gdb.btrace/stepi.exp
@@ -100,7 +100,7 @@ with_test_prefix "reverse-nexti.1" {
# we can't reverse-nexti any further
with_test_prefix "reverse-nexti.2" {
gdb_test "reverse-nexti" \
- "No more reverse-execution history\.\r\n.*main\.2.*" \
+ "Reached end of recorded history; stopping\.\r\n.*main\.2.*" \
"reverse-nexti.2"
check_replay_at 1
}
@@ -140,20 +140,20 @@ with_test_prefix "goto begin" {
with_test_prefix "reverse-stepi" {
gdb_test "reverse-stepi" \
- "No more reverse-execution history\.\r\n.*main\.2.*" \
+ "Reached end of recorded history; stopping\.\r\n.*main\.2.*" \
"reverse-stepi.1"
gdb_test "reverse-stepi" \
- "No more reverse-execution history\.\r\n.*main\.2.*" \
+ "Reached end of recorded history; stopping\.\r\n.*main\.2.*" \
"reverse-stepi.2"
check_replay_at 1
}
with_test_prefix "reverse-nexti" {
gdb_test "reverse-nexti" \
- "No more reverse-execution history\.\r\n.*main\.2.*" \
+ "Reached end of recorded history; stopping\.\r\n.*main\.2.*" \
"reverse-nexti.1"
gdb_test "reverse-nexti" \
- "No more reverse-execution history\.\r\n.*main\.2.*" \
+ "Reached end of recorded history; stopping\.\r\n.*main\.2.*" \
"reverse-nexti.2"
check_replay_at 1
}
@@ -169,10 +169,10 @@ with_test_prefix "goto begin" {
with_test_prefix "reverse-stepi" {
gdb_test "reverse-stepi" ".*main\.2.*" "reverse-stepi.1"
gdb_test "reverse-stepi" \
- "No more reverse-execution history\.\r\n.*main\.2.*" \
+ "Reached end of recorded history; stopping\.\r\n.*main\.2.*" \
"reverse-stepi.2"
gdb_test "reverse-stepi" \
- "No more reverse-execution history\.\r\n.*main\.2.*" \
+ "Reached end of recorded history; stopping\.\r\n.*main\.2.*" \
"reverse-stepi.3"
check_replay_at 1
}
diff --git a/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S b/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S
new file mode 100644
index 0000000..be4d204
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S
@@ -0,0 +1,544 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+ This file has been generated using gcc version 10.3.1 20210422
+ (Red Hat 10.3.1-1):
+ gcc -S -dA -g -mptwrite ptwrite.c -o x86_64-ptwrite.S. */
+
+ .file "ptwrite.c"
+ .text
+.Ltext0:
+ .globl ptwrite1
+ .type ptwrite1, @function
+ptwrite1:
+.LFB4096:
+ .file 1 "ptwrite.c"
+ # ptwrite.c:22:1
+ .loc 1 22 1
+ .cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ movl %edi, -20(%rbp)
+ # ptwrite.c:23:3
+ .loc 1 23 3
+ movl -20(%rbp), %eax
+ movl %eax, -4(%rbp)
+.LBB6:
+.LBB7:
+ .file 2 "/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h"
+ # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:307:3
+ .loc 2 307 3
+ movl -4(%rbp), %eax
+ ptwrite %eax
+ # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:308:1
+ .loc 2 308 1
+ nop
+.LBE7:
+.LBE6:
+ # ptwrite.c:24:1
+ .loc 1 24 1
+ nop
+ popq %rbp
+ .cfi_def_cfa 7, 8
+# SUCC: EXIT [always]
+ ret
+ .cfi_endproc
+.LFE4096:
+ .size ptwrite1, .-ptwrite1
+ .globl ptwrite2
+ .type ptwrite2, @function
+ptwrite2:
+.LFB4097:
+ # ptwrite.c:28:1
+ .loc 1 28 1
+ .cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ movl %edi, -20(%rbp)
+ # ptwrite.c:29:3
+ .loc 1 29 3
+ movl -20(%rbp), %eax
+ movl %eax, -4(%rbp)
+.LBB8:
+.LBB9:
+ # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:307:3
+ .loc 2 307 3
+ movl -4(%rbp), %eax
+ ptwrite %eax
+ # /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:308:1
+ .loc 2 308 1
+ nop
+.LBE9:
+.LBE8:
+ # ptwrite.c:30:1
+ .loc 1 30 1
+ nop
+ popq %rbp
+ .cfi_def_cfa 7, 8
+# SUCC: EXIT [always]
+ ret
+ .cfi_endproc
+.LFE4097:
+ .size ptwrite2, .-ptwrite2
+ .globl main
+ .type main, @function
+main:
+.LFB4098:
+ # ptwrite.c:34:1
+ .loc 1 34 1
+ .cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ # ptwrite.c:35:3
+ .loc 1 35 3
+ movl $66, %edi
+ call ptwrite1
+ # ptwrite.c:36:3
+ .loc 1 36 3
+ movl $67, %edi
+ call ptwrite2
+ # ptwrite.c:38:10
+ .loc 1 38 10
+ movl $0, %eax
+ # ptwrite.c:39:1
+ .loc 1 39 1
+ popq %rbp
+ .cfi_def_cfa 7, 8
+# SUCC: EXIT [always]
+ ret
+ .cfi_endproc
+.LFE4098:
+ .size main, .-main
+.Letext0:
+ .section .debug_info,"",@progbits
+.Ldebug_info0:
+ .long 0x159 # Length of Compilation Unit Info
+ .value 0x4 # DWARF version number
+ .long .Ldebug_abbrev0 # Offset Into Abbrev. Section
+ .byte 0x8 # Pointer Size (in bytes)
+ .uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit)
+ .long .LASF15 # DW_AT_producer: "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -mptwrite -mtune=generic -march=x86-64 -g"
+ .byte 0xc # DW_AT_language
+ .long .LASF16 # DW_AT_name: "ptwrite.c"
+ .long .LASF17 # DW_AT_comp_dir: "gdb/gdb/testsuite/gdb.btrace"
+ .quad .Ltext0 # DW_AT_low_pc
+ .quad .Letext0-.Ltext0 # DW_AT_high_pc
+ .long .Ldebug_line0 # DW_AT_stmt_list
+ .uleb128 0x2 # (DIE (0x2d) DW_TAG_base_type)
+ .byte 0x4 # DW_AT_byte_size
+ .byte 0x5 # DW_AT_encoding
+ .ascii "int\0" # DW_AT_name
+ .uleb128 0x3 # (DIE (0x34) DW_TAG_base_type)
+ .byte 0x2 # DW_AT_byte_size
+ .byte 0x5 # DW_AT_encoding
+ .long .LASF0 # DW_AT_name: "short int"
+ .uleb128 0x3 # (DIE (0x3b) DW_TAG_base_type)
+ .byte 0x1 # DW_AT_byte_size
+ .byte 0x6 # DW_AT_encoding
+ .long .LASF1 # DW_AT_name: "char"
+ .uleb128 0x3 # (DIE (0x42) DW_TAG_base_type)
+ .byte 0x8 # DW_AT_byte_size
+ .byte 0x5 # DW_AT_encoding
+ .long .LASF2 # DW_AT_name: "long long int"
+ .uleb128 0x3 # (DIE (0x49) DW_TAG_base_type)
+ .byte 0x4 # DW_AT_byte_size
+ .byte 0x4 # DW_AT_encoding
+ .long .LASF3 # DW_AT_name: "float"
+ .uleb128 0x3 # (DIE (0x50) DW_TAG_base_type)
+ .byte 0x8 # DW_AT_byte_size
+ .byte 0x7 # DW_AT_encoding
+ .long .LASF4 # DW_AT_name: "long unsigned int"
+ .uleb128 0x3 # (DIE (0x57) DW_TAG_base_type)
+ .byte 0x8 # DW_AT_byte_size
+ .byte 0x5 # DW_AT_encoding
+ .long .LASF5 # DW_AT_name: "long int"
+ .uleb128 0x3 # (DIE (0x5e) DW_TAG_base_type)
+ .byte 0x1 # DW_AT_byte_size
+ .byte 0x8 # DW_AT_encoding
+ .long .LASF6 # DW_AT_name: "unsigned char"
+ .uleb128 0x3 # (DIE (0x65) DW_TAG_base_type)
+ .byte 0x2 # DW_AT_byte_size
+ .byte 0x7 # DW_AT_encoding
+ .long .LASF7 # DW_AT_name: "short unsigned int"
+ .uleb128 0x3 # (DIE (0x6c) DW_TAG_base_type)
+ .byte 0x4 # DW_AT_byte_size
+ .byte 0x7 # DW_AT_encoding
+ .long .LASF8 # DW_AT_name: "unsigned int"
+ .uleb128 0x3 # (DIE (0x73) DW_TAG_base_type)
+ .byte 0x1 # DW_AT_byte_size
+ .byte 0x6 # DW_AT_encoding
+ .long .LASF9 # DW_AT_name: "signed char"
+ .uleb128 0x3 # (DIE (0x7a) DW_TAG_base_type)
+ .byte 0x8 # DW_AT_byte_size
+ .byte 0x7 # DW_AT_encoding
+ .long .LASF10 # DW_AT_name: "long long unsigned int"
+ .uleb128 0x3 # (DIE (0x81) DW_TAG_base_type)
+ .byte 0x8 # DW_AT_byte_size
+ .byte 0x4 # DW_AT_encoding
+ .long .LASF11 # DW_AT_name: "double"
+ .uleb128 0x4 # (DIE (0x88) DW_TAG_subprogram)
+ # DW_AT_external
+ .long .LASF18 # DW_AT_name: "main"
+ .byte 0x1 # DW_AT_decl_file (ptwrite.c)
+ .byte 0x21 # DW_AT_decl_line
+ .byte 0x1 # DW_AT_decl_column
+ # DW_AT_prototyped
+ .long 0x2d # DW_AT_type
+ .quad .LFB4098 # DW_AT_low_pc
+ .quad .LFE4098-.LFB4098 # DW_AT_high_pc
+ .uleb128 0x1 # DW_AT_frame_base
+ .byte 0x9c # DW_OP_call_frame_cfa
+ # DW_AT_GNU_all_tail_call_sites
+ .uleb128 0x5 # (DIE (0xa6) DW_TAG_subprogram)
+ # DW_AT_external
+ .long .LASF12 # DW_AT_name: "ptwrite2"
+ .byte 0x1 # DW_AT_decl_file (ptwrite.c)
+ .byte 0x1b # DW_AT_decl_line
+ .byte 0x1 # DW_AT_decl_column
+ # DW_AT_prototyped
+ .quad .LFB4097 # DW_AT_low_pc
+ .quad .LFE4097-.LFB4097 # DW_AT_high_pc
+ .uleb128 0x1 # DW_AT_frame_base
+ .byte 0x9c # DW_OP_call_frame_cfa
+ # DW_AT_GNU_all_call_sites
+ .long 0xf5 # DW_AT_sibling
+ .uleb128 0x6 # (DIE (0xc4) DW_TAG_formal_parameter)
+ .long .LASF14 # DW_AT_name: "value"
+ .byte 0x1 # DW_AT_decl_file (ptwrite.c)
+ .byte 0x1b # DW_AT_decl_line
+ .byte 0xf # DW_AT_decl_column
+ .long 0x2d # DW_AT_type
+ .uleb128 0x2 # DW_AT_location
+ .byte 0x91 # DW_OP_fbreg
+ .sleb128 -36
+ .uleb128 0x7 # (DIE (0xd3) DW_TAG_inlined_subroutine)
+ .long 0x144 # DW_AT_abstract_origin
+ .quad .LBB8 # DW_AT_low_pc
+ .quad .LBE8-.LBB8 # DW_AT_high_pc
+ .byte 0x1 # DW_AT_call_file (ptwrite.c)
+ .byte 0x1d # DW_AT_call_line
+ .byte 0x3 # DW_AT_call_column
+ .uleb128 0x8 # (DIE (0xeb) DW_TAG_formal_parameter)
+ .long 0x14e # DW_AT_abstract_origin
+ .uleb128 0x2 # DW_AT_location
+ .byte 0x91 # DW_OP_fbreg
+ .sleb128 -20
+ .byte 0 # end of children of DIE 0xd3
+ .byte 0 # end of children of DIE 0xa6
+ .uleb128 0x5 # (DIE (0xf5) DW_TAG_subprogram)
+ # DW_AT_external
+ .long .LASF13 # DW_AT_name: "ptwrite1"
+ .byte 0x1 # DW_AT_decl_file (ptwrite.c)
+ .byte 0x15 # DW_AT_decl_line
+ .byte 0x1 # DW_AT_decl_column
+ # DW_AT_prototyped
+ .quad .LFB4096 # DW_AT_low_pc
+ .quad .LFE4096-.LFB4096 # DW_AT_high_pc
+ .uleb128 0x1 # DW_AT_frame_base
+ .byte 0x9c # DW_OP_call_frame_cfa
+ # DW_AT_GNU_all_call_sites
+ .long 0x144 # DW_AT_sibling
+ .uleb128 0x6 # (DIE (0x113) DW_TAG_formal_parameter)
+ .long .LASF14 # DW_AT_name: "value"
+ .byte 0x1 # DW_AT_decl_file (ptwrite.c)
+ .byte 0x15 # DW_AT_decl_line
+ .byte 0xf # DW_AT_decl_column
+ .long 0x2d # DW_AT_type
+ .uleb128 0x2 # DW_AT_location
+ .byte 0x91 # DW_OP_fbreg
+ .sleb128 -36
+ .uleb128 0x7 # (DIE (0x122) DW_TAG_inlined_subroutine)
+ .long 0x144 # DW_AT_abstract_origin
+ .quad .LBB6 # DW_AT_low_pc
+ .quad .LBE6-.LBB6 # DW_AT_high_pc
+ .byte 0x1 # DW_AT_call_file (ptwrite.c)
+ .byte 0x17 # DW_AT_call_line
+ .byte 0x3 # DW_AT_call_column
+ .uleb128 0x8 # (DIE (0x13a) DW_TAG_formal_parameter)
+ .long 0x14e # DW_AT_abstract_origin
+ .uleb128 0x2 # DW_AT_location
+ .byte 0x91 # DW_OP_fbreg
+ .sleb128 -20
+ .byte 0 # end of children of DIE 0x122
+ .byte 0 # end of children of DIE 0xf5
+ .uleb128 0x9 # (DIE (0x144) DW_TAG_subprogram)
+ # DW_AT_external
+ .long .LASF19 # DW_AT_name: "_ptwrite32"
+ .byte 0x2 # DW_AT_decl_file (/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h)
+ .value 0x131 # DW_AT_decl_line
+ .byte 0x1 # DW_AT_decl_column
+ # DW_AT_prototyped
+ .byte 0x3 # DW_AT_inline
+ # DW_AT_artificial
+ .uleb128 0xa # (DIE (0x14e) DW_TAG_formal_parameter)
+ .ascii "__B\0" # DW_AT_name
+ .byte 0x2 # DW_AT_decl_file (/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h)
+ .value 0x131 # DW_AT_decl_line
+ .byte 0x16 # DW_AT_decl_column
+ .long 0x6c # DW_AT_type
+ .byte 0 # end of children of DIE 0x144
+ .byte 0 # end of children of DIE 0xb
+ .section .debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+ .uleb128 0x1 # (abbrev code)
+ .uleb128 0x11 # (TAG: DW_TAG_compile_unit)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x25 # (DW_AT_producer)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x13 # (DW_AT_language)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x1b # (DW_AT_comp_dir)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x11 # (DW_AT_low_pc)
+ .uleb128 0x1 # (DW_FORM_addr)
+ .uleb128 0x12 # (DW_AT_high_pc)
+ .uleb128 0x7 # (DW_FORM_data8)
+ .uleb128 0x10 # (DW_AT_stmt_list)
+ .uleb128 0x17 # (DW_FORM_sec_offset)
+ .byte 0
+ .byte 0
+ .uleb128 0x2 # (abbrev code)
+ .uleb128 0x24 # (TAG: DW_TAG_base_type)
+ .byte 0 # DW_children_no
+ .uleb128 0xb # (DW_AT_byte_size)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3e # (DW_AT_encoding)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0x8 # (DW_FORM_string)
+ .byte 0
+ .byte 0
+ .uleb128 0x3 # (abbrev code)
+ .uleb128 0x24 # (TAG: DW_TAG_base_type)
+ .byte 0 # DW_children_no
+ .uleb128 0xb # (DW_AT_byte_size)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3e # (DW_AT_encoding)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .byte 0
+ .byte 0
+ .uleb128 0x4 # (abbrev code)
+ .uleb128 0x2e # (TAG: DW_TAG_subprogram)
+ .byte 0 # DW_children_no
+ .uleb128 0x3f # (DW_AT_external)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x39 # (DW_AT_decl_column)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x27 # (DW_AT_prototyped)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x11 # (DW_AT_low_pc)
+ .uleb128 0x1 # (DW_FORM_addr)
+ .uleb128 0x12 # (DW_AT_high_pc)
+ .uleb128 0x7 # (DW_FORM_data8)
+ .uleb128 0x40 # (DW_AT_frame_base)
+ .uleb128 0x18 # (DW_FORM_exprloc)
+ .uleb128 0x2116 # (DW_AT_GNU_all_tail_call_sites)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .byte 0
+ .byte 0
+ .uleb128 0x5 # (abbrev code)
+ .uleb128 0x2e # (TAG: DW_TAG_subprogram)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x3f # (DW_AT_external)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x39 # (DW_AT_decl_column)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x27 # (DW_AT_prototyped)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x11 # (DW_AT_low_pc)
+ .uleb128 0x1 # (DW_FORM_addr)
+ .uleb128 0x12 # (DW_AT_high_pc)
+ .uleb128 0x7 # (DW_FORM_data8)
+ .uleb128 0x40 # (DW_AT_frame_base)
+ .uleb128 0x18 # (DW_FORM_exprloc)
+ .uleb128 0x2117 # (DW_AT_GNU_all_call_sites)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x1 # (DW_AT_sibling)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .byte 0
+ .byte 0
+ .uleb128 0x6 # (abbrev code)
+ .uleb128 0x5 # (TAG: DW_TAG_formal_parameter)
+ .byte 0 # DW_children_no
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x39 # (DW_AT_decl_column)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x2 # (DW_AT_location)
+ .uleb128 0x18 # (DW_FORM_exprloc)
+ .byte 0
+ .byte 0
+ .uleb128 0x7 # (abbrev code)
+ .uleb128 0x1d # (TAG: DW_TAG_inlined_subroutine)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x31 # (DW_AT_abstract_origin)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x11 # (DW_AT_low_pc)
+ .uleb128 0x1 # (DW_FORM_addr)
+ .uleb128 0x12 # (DW_AT_high_pc)
+ .uleb128 0x7 # (DW_FORM_data8)
+ .uleb128 0x58 # (DW_AT_call_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x59 # (DW_AT_call_line)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x57 # (DW_AT_call_column)
+ .uleb128 0xb # (DW_FORM_data1)
+ .byte 0
+ .byte 0
+ .uleb128 0x8 # (abbrev code)
+ .uleb128 0x5 # (TAG: DW_TAG_formal_parameter)
+ .byte 0 # DW_children_no
+ .uleb128 0x31 # (DW_AT_abstract_origin)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x2 # (DW_AT_location)
+ .uleb128 0x18 # (DW_FORM_exprloc)
+ .byte 0
+ .byte 0
+ .uleb128 0x9 # (abbrev code)
+ .uleb128 0x2e # (TAG: DW_TAG_subprogram)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x3f # (DW_AT_external)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0x5 # (DW_FORM_data2)
+ .uleb128 0x39 # (DW_AT_decl_column)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x27 # (DW_AT_prototyped)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x20 # (DW_AT_inline)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x34 # (DW_AT_artificial)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .byte 0
+ .byte 0
+ .uleb128 0xa # (abbrev code)
+ .uleb128 0x5 # (TAG: DW_TAG_formal_parameter)
+ .byte 0 # DW_children_no
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0x8 # (DW_FORM_string)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0x5 # (DW_FORM_data2)
+ .uleb128 0x39 # (DW_AT_decl_column)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .byte 0
+ .byte 0
+ .byte 0
+ .section .debug_aranges,"",@progbits
+ .long 0x2c # Length of Address Ranges Info
+ .value 0x2 # DWARF aranges version
+ .long .Ldebug_info0 # Offset of Compilation Unit Info
+ .byte 0x8 # Size of Address
+ .byte 0 # Size of Segment Descriptor
+ .value 0 # Pad to 16 byte boundary
+ .value 0
+ .quad .Ltext0 # Address
+ .quad .Letext0-.Ltext0 # Length
+ .quad 0
+ .quad 0
+ .section .debug_line,"",@progbits
+.Ldebug_line0:
+ .section .debug_str,"MS",@progbits,1
+.LASF2:
+ .string "long long int"
+.LASF14:
+ .string "value"
+.LASF19:
+ .string "_ptwrite32"
+.LASF8:
+ .string "unsigned int"
+.LASF17:
+ .string "gdb/gdb/testsuite/gdb.btrace"
+.LASF18:
+ .string "main"
+.LASF16:
+ .string "ptwrite.c"
+.LASF4:
+ .string "long unsigned int"
+.LASF10:
+ .string "long long unsigned int"
+.LASF15:
+ .string "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -mptwrite -mtune=generic -march=x86-64 -g"
+.LASF13:
+ .string "ptwrite1"
+.LASF12:
+ .string "ptwrite2"
+.LASF6:
+ .string "unsigned char"
+.LASF1:
+ .string "char"
+.LASF5:
+ .string "long int"
+.LASF11:
+ .string "double"
+.LASF7:
+ .string "short unsigned int"
+.LASF9:
+ .string "signed char"
+.LASF3:
+ .string "float"
+.LASF0:
+ .string "short int"
+ .ident "GCC: (GNU) 10.3.1 20210422 (Red Hat 10.3.1-1)"
+ .section .note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.compile/compile.exp b/gdb/testsuite/gdb.compile/compile.exp
index cd59633..2c2e321 100644
--- a/gdb/testsuite/gdb.compile/compile.exp
+++ b/gdb/testsuite/gdb.compile/compile.exp
@@ -66,7 +66,7 @@ if {[skip_compile_feature_untested]} {
gdb_test_no_output "compile -- f = 10" \
"test abbreviations and code delimiter"
-gdb_test "compile f = 10;" ".*= 10;: No such file.*" \
+gdb_test "compile f = 10;" "^Junk after filename \"=\": 10;" \
"Test abbreviations and code collision"
gdb_test_no_output "compile -r -- void _gdb_expr(){int i = 5;}" \
diff --git a/gdb/testsuite/gdb.cp/anon-ns.exp b/gdb/testsuite/gdb.cp/anon-ns.exp
index c01a3ab..2b2376d 100644
--- a/gdb/testsuite/gdb.cp/anon-ns.exp
+++ b/gdb/testsuite/gdb.cp/anon-ns.exp
@@ -55,12 +55,10 @@ foreach test $methods {
gdb_test "list $test" $result
gdb_test "list '$test'" $result
- if {[gdb_breakpoint $test]} {
- pass "break $test"
- }
- if {[gdb_breakpoint '$test']} {
- pass "break '$test'"
- }
+ gdb_assert { [gdb_breakpoint $test no-message] } \
+ "break $test, unquoted"
+ gdb_assert { [gdb_breakpoint '$test' no-message] } \
+ "break $test, single-quoted"
}
# PR c++/17976
diff --git a/gdb/testsuite/gdb.cp/breakpoint-shlib-func.exp b/gdb/testsuite/gdb.cp/breakpoint-shlib-func.exp
index 9924d9b..085020f 100644
--- a/gdb/testsuite/gdb.cp/breakpoint-shlib-func.exp
+++ b/gdb/testsuite/gdb.cp/breakpoint-shlib-func.exp
@@ -47,18 +47,9 @@ gdb_load_shlib $libobj
gdb_test "break foo" "Breakpoint $decimal at $hex"
gdb_test "info breakpoints" "<foo\\(\\)@plt>"
-# This is used as an override for delete_breakpoints when we don't
-# want functions in gdb.exp to delete breakpoints behind the scenes
-# for us.
-proc do_not_delete_breakpoints {} {
- # Just do nothing.
-}
-
# Runto main, but don't delete all the breakpoints.
-with_override delete_breakpoints do_not_delete_breakpoints {
- if {![runto_main]} {
- return -1
- }
+if {![runto_main no-delete-breakpoints]} {
+ return -1
}
# The breakpoint should now be showing in `foo` for real.
diff --git a/gdb/testsuite/gdb.cp/classes.exp b/gdb/testsuite/gdb.cp/classes.exp
index 97dca29..4d29bf5 100644
--- a/gdb/testsuite/gdb.cp/classes.exp
+++ b/gdb/testsuite/gdb.cp/classes.exp
@@ -502,7 +502,7 @@ proc test_enums {} {
gdb_test "print obj_with_enum" \
"\\$\[0-9\]+ = \{priv_enum = (ClassWithEnum::)?green, x = 0\}" \
- "print obj_with_enum (2)"
+ "print obj_with_enum, 2"
# print the enum member
diff --git a/gdb/testsuite/gdb.cp/exception.exp b/gdb/testsuite/gdb.cp/exception.exp
index 0cc97fe..5489d0c 100644
--- a/gdb/testsuite/gdb.cp/exception.exp
+++ b/gdb/testsuite/gdb.cp/exception.exp
@@ -86,7 +86,7 @@ if { !$ok } {
return
}
-set name "info breakpoints (after inferior run)"
+set name "info breakpoints, after inferior run"
gdb_test_multiple "info breakpoints" $name {
-re "$re_head${ws}$re_2_bp${ws}$re_3_bp${ws}$re_4_bp\r\n$gdb_prompt $" {
pass $name
diff --git a/gdb/testsuite/gdb.cp/m-static.exp b/gdb/testsuite/gdb.cp/m-static.exp
index 45bc090..3d59a48 100644
--- a/gdb/testsuite/gdb.cp/m-static.exp
+++ b/gdb/testsuite/gdb.cp/m-static.exp
@@ -71,11 +71,18 @@ if { [is_aarch32_target] } {
gdb_test "print test5.single_constructor" \
{ = {single_constructor \*\(single_constructor \* const\)} 0x[0-9a-f]+ <single_constructor::single_constructor\(\)>} \
"simple object instance, print constructor"
- gdb_test "ptype test5.single_constructor" \
- {type = class single_constructor {\r\n public:\r\n single_constructor\(void\);\r\n ~single_constructor\(\);\r\n} \*\(single_constructor \* const\)} \
+
+ set re \
+ [multi_line_string_to_regexp \
+ "type = class single_constructor {" \
+ "" \
+ " public:" \
+ " single_constructor(void);" \
+ " ~single_constructor(void);" \
+ "} *(single_constructor * const)"]
+ gdb_test "ptype test5.single_constructor" $re \
"simple object instance, ptype constructor"
- gdb_test "ptype single_constructor::single_constructor" \
- {type = class single_constructor {\r\n public:\r\n single_constructor\(void\);\r\n ~single_constructor\(\);\r\n} \*\(single_constructor \* const\)} \
+ gdb_test "ptype single_constructor::single_constructor" $re \
"simple object class, ptype constructor"
gdb_test "print test1.~gnu_obj_1" \
@@ -168,12 +175,12 @@ if {[test_compiler_info {gcc-[0-3]-*}]
# and DW_AT_MIPS_linkage_name = _ZN9gnu_obj_47nowhereE .
setup_xfail *-*-*
}
-gdb_test "print test4.nowhere" "<optimized out>" "static const int initialized nowhere (print field)"
+gdb_test "print test4.nowhere" "<optimized out>" "static const int initialized nowhere, print field"
gdb_test "ptype test4.nowhere" "type = const int"
gdb_test "print test4.nowhere.nowhere" "Attempt to extract a component of a value that is not a structure."
# Same, but print the whole struct.
-gdb_test "print test4" "static nowhere = <optimized out>.*" "static const int initialized nowhere (whole struct)"
+gdb_test "print test4" "static nowhere = <optimized out>.*" "static const int initialized nowhere, whole struct"
# static const initialized in the class definition, PR gdb/11702.
if { $non_dwarf } { setup_xfail *-*-* }
diff --git a/gdb/testsuite/gdb.cp/member-ptr.exp b/gdb/testsuite/gdb.cp/member-ptr.exp
index 838fe96..d02a1ea 100644
--- a/gdb/testsuite/gdb.cp/member-ptr.exp
+++ b/gdb/testsuite/gdb.cp/member-ptr.exp
@@ -43,7 +43,7 @@ gdb_continue_to_breakpoint "continue to pmi = NULL"
# ptype on pointer to data member
-set name "ptype pmi (A::j)"
+set name "ptype pmi, A::j"
gdb_test_multiple "ptype pmi" $name {
-re "type = int A::\\*\r\n$gdb_prompt $" {
pass $name
@@ -52,7 +52,7 @@ gdb_test_multiple "ptype pmi" $name {
# print pointer to data member
-set name "print pmi (A::j) "
+set name "print pmi, A::j"
gdb_test_multiple "print pmi" $name {
-re "$vhn = &A::j\r\n$gdb_prompt $" {
pass $name
@@ -77,7 +77,7 @@ gdb_test_multiple "print pmi" $name {
# print dereferenced pointer to data member
-set name "print a.*pmi (A::j)"
+set name "print a.*pmi, A::j"
gdb_test_multiple "print a.*pmi" $name {
-re "$vhn = 121\r\n$gdb_prompt $" {
pass $name
@@ -97,7 +97,7 @@ gdb_test_multiple "print a.*pmi" $name {
# print dereferenced pointer to data member
# this time, dereferenced through a pointer
-set name "print a_p->*pmi (A::j)"
+set name "print a_p->*pmi, A::j"
gdb_test_multiple "print a_p->*pmi" $name {
-re "$vhn = 121\r\n$gdb_prompt $" {
pass $name
@@ -133,7 +133,7 @@ gdb_test_multiple "set var pmi = &A::jj" $name {
# print the pointer again
-set name "print pmi (A::jj)"
+set name "print pmi, A::jj"
gdb_test_multiple "print pmi" $name {
-re "$vhn = &A::jj\r\n$gdb_prompt $" {
pass $name
@@ -150,7 +150,7 @@ gdb_test_multiple "print pmi" $name {
# print dereferenced pointer to data member again
-set name "print a.*pmi (A::jj)"
+set name "print a.*pmi, A::jj"
gdb_test_multiple "print a.*pmi" $name {
-re "$vhn = 1331\r\n$gdb_prompt $" {
pass $name
@@ -181,7 +181,7 @@ gdb_test_multiple "set var pmi = &A::j" $name {
# print dereferenced pointer to data member yet again (extra check, why not)
-set name "print a.*pmi (A::j) (again)"
+set name "print a.*pmi, A::j, again"
gdb_test_multiple "print a.*pmi" $name {
-re "$vhn = 121\r\n$gdb_prompt $" {
pass $name
@@ -209,7 +209,7 @@ gdb_test_multiple "print a.*pmi = 33" $name {
# Now check that the data really was changed
-set name "print a.*pmi (A::j) (33)"
+set name "print a.*pmi, A::j, 33"
gdb_test_multiple "print a.*pmi" $name {
-re "$vhn = 33\r\n$gdb_prompt $" {
pass $name
@@ -223,7 +223,7 @@ gdb_test_multiple "print a.*pmi" $name {
# Double-check by printing a.
-set name "print a (j = 33)"
+set name "print a, j = 33"
gdb_test_multiple "print a" $name {
-re "$vhn = \{c = 120 'x', j = 33, jj = 1331, (static|static int) s = 10, (_vptr.A|_vptr\\$) = ($hex|$hex <A virtual table>)\}\r\n$gdb_prompt $" {
pass $name
@@ -257,7 +257,7 @@ gdb_test_multiple "print a_p->*pmi = 44" $name {
# Check that the data really was changed
-set name "print a_p->*pmi (44)"
+set name "print a_p->*pmi, 44"
gdb_test_multiple "print a_p->*pmi" $name {
-re "$vhn = 44\r\n$gdb_prompt $" {
pass $name
@@ -271,7 +271,7 @@ gdb_test_multiple "print a_p->*pmi" $name {
# Double-check by printing a.
-set name "print a (j = 44)"
+set name "print a, j = 44"
gdb_test_multiple "print a" $name {
-re "$vhn = \{c = 120 'x', j = 44, jj = 1331, (static|static int) s = 10, (_vptr.A|_vptr\\$) = ($hex|$hex <A virtual table>)\}\r\n$gdb_prompt $" {
pass $name
diff --git a/gdb/testsuite/gdb.cp/meth-typedefs.exp b/gdb/testsuite/gdb.cp/meth-typedefs.exp
index a1829a1..149f44c 100644
--- a/gdb/testsuite/gdb.cp/meth-typedefs.exp
+++ b/gdb/testsuite/gdb.cp/meth-typedefs.exp
@@ -152,12 +152,10 @@ foreach test $methods {
gdb_test "list -qualified $func" $result
gdb_test "list -qualified '$func'" $result
- if {[gdb_breakpoint "-qualified $func"]} {
- pass "break -qualified $func"
- }
- if {[gdb_breakpoint "-qualified '$func'"]} {
- pass "break -qualified '$func'"
- }
+ gdb_assert { [gdb_breakpoint "-qualified $func" no-message] } \
+ "break -qualified $func, unquoted"
+ gdb_assert { [gdb_breakpoint "-qualified '$func'" no-message] } \
+ "break -qualified $func, single-quoted"
}
# The tests above use -qualified to explicitly pick the one "test"
diff --git a/gdb/testsuite/gdb.cp/method2.exp b/gdb/testsuite/gdb.cp/method2.exp
index 9aa9bf0..0a07ff3 100644
--- a/gdb/testsuite/gdb.cp/method2.exp
+++ b/gdb/testsuite/gdb.cp/method2.exp
@@ -50,11 +50,11 @@ proc test_break { lang } {
incr idx
}
set expect [join $menu_items {.*[\r\n]*}]
- gdb_test_multiple "break A::method" "breaking in method ($lang)" {
+ gdb_test_multiple "break A::method" "breaking in method, $lang" {
-re $expect {
gdb_test "0" \
"canceled" \
- "breaking in method ($lang)"
+ $gdb_test_name
}
}
}
diff --git a/gdb/testsuite/gdb.cp/misc.exp b/gdb/testsuite/gdb.cp/misc.exp
index bcb20f8..3f5532e 100644
--- a/gdb/testsuite/gdb.cp/misc.exp
+++ b/gdb/testsuite/gdb.cp/misc.exp
@@ -51,10 +51,10 @@ proc test_expr { args } {
}
set last_ent [expr [llength $args] - 1]
set testname [lindex $args $last_ent]
- gdb_test_no_output [lindex $args 0] "$testname (setup)"
+ gdb_test_no_output [lindex $args 0] "$testname, setup"
for {set x 1} {$x < $last_ent} {set x [expr $x + 2]} {
- gdb_test [lindex $args $x] [lindex $args [expr $x + 1]] "$testname ([lindex $args $x])"
+ gdb_test [lindex $args $x] [lindex $args [expr $x + 1]] "$testname, [lindex $args $x]"
}
}
diff --git a/gdb/testsuite/gdb.cp/nested-types.exp b/gdb/testsuite/gdb.cp/nested-types.exp
index 5621fff..294358c 100644
--- a/gdb/testsuite/gdb.cp/nested-types.exp
+++ b/gdb/testsuite/gdb.cp/nested-types.exp
@@ -269,7 +269,7 @@ proc test_nested_limit {limit log} {
}
gdb_test "show print type nested-type-limit" \
"Will print $lstr nested types defined in a class" \
- "show print type nested-type-limit ($limit)"
+ "show print type nested-type-limit, $limit"
} else {
send_log "Tree to $limit levels:\n"
}
@@ -283,7 +283,7 @@ proc test_nested_limit {limit log} {
# the outermost node.
set result [lindex $result 0]
lassign $result type access key name children
- cp_test_ptype_class $name "ptype $name (limit = $limit)" $key \
+ cp_test_ptype_class $name "ptype $name, limit = $limit" $key \
$name $children
}
}
diff --git a/gdb/testsuite/gdb.cp/ovldbreak.exp b/gdb/testsuite/gdb.cp/ovldbreak.exp
index 882a83b..99d0a38 100644
--- a/gdb/testsuite/gdb.cp/ovldbreak.exp
+++ b/gdb/testsuite/gdb.cp/ovldbreak.exp
@@ -248,7 +248,7 @@ foreach ovld $overloads {
append bptable [format "\r\n\[0-9\]+\[\t \]+breakpoint\[\t \]+keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(%s\\) at.*$srcfile:%d" $ovld \
$line($type_map("$ovld"))]
}
-gdb_test "info break" $bptable "breakpoint info (after setting one-by-one)"
+gdb_test "info break" $bptable "breakpoint info, after setting one-by-one"
# Test choice "cancel".
# This is copy-and-paste from set_bp_overloaded.
@@ -288,7 +288,7 @@ gdb_expect {
}
}
-gdb_test "info break" $bptable "breakpoint info (after cancel)"
+gdb_test "info break" $bptable "breakpoint info, after cancel"
# Test that if the user selects multiple entries from the option list,
# GDB creates one breakpoint per entry.
@@ -325,7 +325,7 @@ gdb_expect {
}
}
-gdb_test "info breakpoints" "No breakpoints, watchpoints, tracepoints, or catchpoints." "breakpoint info (after delete)"
+gdb_test "info breakpoints" "No breakpoints, watchpoints, tracepoints, or catchpoints." "breakpoint info, after delete"
@@ -375,7 +375,7 @@ foreach ovld {void char signed_char unsigned_char short_int \
$types($ovld) $line($ovld)]
}
-gdb_test "info break" $bptable "breakpoint info (after setting on all)"
+gdb_test "info break" $bptable "breakpoint info, after setting on all"
# Run through each breakpoint.
proc continue_to_bp_overloaded {bpnumber might_fail line argtype argument} {
diff --git a/gdb/testsuite/gdb.cp/pass-by-ref-2.exp b/gdb/testsuite/gdb.cp/pass-by-ref-2.exp
index 3c7b19a..00141d8 100644
--- a/gdb/testsuite/gdb.cp/pass-by-ref-2.exp
+++ b/gdb/testsuite/gdb.cp/pass-by-ref-2.exp
@@ -72,22 +72,22 @@ gdb_test "print cbvDtorDel (*dtorDel)" \
# Test that GDB calls the correct copy ctor
gdb_test "print cbvFourCCtor (fourCctor_c0v0)" "13" \
- "call cbvFourCCtor (c0v0)"
+ "call cbvFourCCtor, c0v0"
gdb_test "print fourCctor_c0v0.x" "2" \
"cbv argument 'twoCctor_c0v0' should not change"
gdb_test "print cbvFourCCtor (fourCctor_c1v0)" "14" \
- "call cbvFourCCtor (c1v0)"
+ "call cbvFourCCtor, c1v0"
gdb_test "print fourCctor_c1v0.x" "2" \
"cbv argument 'twoCctor_c1v0' should not change"
gdb_test "print cbvFourCCtor (fourCctor_c0v1)" "15" \
- "call cbvFourCCtor (c0v1)"
+ "call cbvFourCCtor, c0v1"
gdb_test "print fourCctor_c0v1.x" "2" \
"cbv argument 'twoCctor_c0v1' should not change"
gdb_test "print cbvFourCCtor (fourCctor_c1v1)" "16" \
- "call cbvFourCCtor (c1v1)"
+ "call cbvFourCCtor, c1v1"
gdb_test "print fourCctor_c1v1.x" "2" \
"cbv argument 'twoCctor_c1v1' should not change"
diff --git a/gdb/testsuite/gdb.cp/pass-by-ref.exp b/gdb/testsuite/gdb.cp/pass-by-ref.exp
index 7b2a619..a1f1df4 100644
--- a/gdb/testsuite/gdb.cp/pass-by-ref.exp
+++ b/gdb/testsuite/gdb.cp/pass-by-ref.exp
@@ -396,12 +396,12 @@ proc test_for_class { prefix states cbvfun data_field length} {
gdb_test "print ${cbvfun}<$name> (${name}_var)" " = $expected" \
"call '$cbvfun'"
gdb_test "print ${name}_var.${data_field}\[0\]" " = $ORIGINAL" \
- "cbv argument should not change (item 0)"
+ "cbv argument should not change, item 0"
if {$length > 1} {
set last_index [expr $length - 1]
gdb_test "print ${name}_var.${data_field}\[$last_index\]" \
" = $ORIGINAL" \
- "cbv argument should not change (item $last_index)"
+ "cbv argument should not change, item $last_index"
}
if {$dtor == "explicit"} {
if {$cctor == "defaultedIn"
diff --git a/gdb/testsuite/gdb.cp/rtti.exp b/gdb/testsuite/gdb.cp/rtti.exp
index 9651691..5caf4d1 100644
--- a/gdb/testsuite/gdb.cp/rtti.exp
+++ b/gdb/testsuite/gdb.cp/rtti.exp
@@ -73,7 +73,7 @@ gdb_test_multiple "print *e1" "print *e1" {
# NOTE: carlton/2004-01-14: This test with an "<incomplete type>"
# message because, within rtt1.cc, GDB has no way of knowing that the
-# class is called 'n2::D2' instead of just 'D2'. This is an artifical
+# class is called 'n2::D2' instead of just 'D2'. This is an artificial
# test case, though: if we were using these classes in a more
# substantial way, G++ would emit more debug info. As is, I don't
# think there's anything that GDB can do about this case until G++
diff --git a/gdb/testsuite/gdb.cp/step-and-next-inline.exp b/gdb/testsuite/gdb.cp/step-and-next-inline.exp
index 446cd82..af1719d 100644
--- a/gdb/testsuite/gdb.cp/step-and-next-inline.exp
+++ b/gdb/testsuite/gdb.cp/step-and-next-inline.exp
@@ -26,7 +26,7 @@ proc do_test { use_header } {
if { $use_header } {
# This test will not pass due to poor debug information
- # generated by GCC (at least upto 10.x). See
+ # generated by GCC (at least up to 10.x). See
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94474
return
}
diff --git a/gdb/testsuite/gdb.cp/templates.exp b/gdb/testsuite/gdb.cp/templates.exp
index 52129d8..8dd0cdc 100644
--- a/gdb/testsuite/gdb.cp/templates.exp
+++ b/gdb/testsuite/gdb.cp/templates.exp
@@ -641,7 +641,8 @@ foreach t [list "int" "char" "Empty<int>"] {
gdb_test "break Foozle::fogey<$t>" "Breakpoint.*at.* \\(3 locations\\)"
foreach u [list "int" "char" "Empty<int>"] {
gdb_breakpoint "Foozle<$t>::fogey<$u>" message
- gdb_breakpoint "Foozle<$t>::fogey<$u> ($u)" message
+ gdb_assert { [gdb_breakpoint "Foozle<$t>::fogey<$u> ($u)" no-message] } \
+ "break Foozle<$t>::fogey<$u> ($u), success"
}
}
@@ -667,10 +668,14 @@ foreach t [list "Empty" "Foozle"] {
# Try a specific instance, both with and without whitespace
# after the template-template parameter.
- gdb_breakpoint "operator< <$tt> ($tt&, $tt&)" message
- gdb_breakpoint "operator< <$tt > ($tt&, $tt&)" message
- gdb_breakpoint "operator<< <$tt> ($tt&, $tt&)" message
- gdb_breakpoint "operator<< <$tt > ($tt&, $tt&)" message
+ set loc "operator< <$tt> ($tt&, $tt&)"
+ gdb_assert { [gdb_breakpoint $loc no-message] } "break $loc, success"
+ set loc "operator< <$tt > ($tt&, $tt&)"
+ gdb_assert { [gdb_breakpoint $loc no-message] } "break $loc, success"
+ set loc "operator<< <$tt> ($tt&, $tt&)"
+ gdb_assert { [gdb_breakpoint $loc no-message] } "break $loc, success"
+ set loc "operator<< <$tt > ($tt&, $tt&)"
+ gdb_assert { [gdb_breakpoint $loc no-message] } "break $loc, success"
}
# Test that "-qualified" finds no matching locations.
diff --git a/gdb/testsuite/gdb.cp/virtfunc.exp b/gdb/testsuite/gdb.cp/virtfunc.exp
index 9add69e..636497e 100644
--- a/gdb/testsuite/gdb.cp/virtfunc.exp
+++ b/gdb/testsuite/gdb.cp/virtfunc.exp
@@ -197,7 +197,7 @@ proc test_virtual_calls {} {
# wrong value "202"
# gcc 2.95.3 -gdwarf-2
# gcc 2.95.3 -gstabs+
- # attempt to take addres of value not located in memory
+ # attempt to take address of value not located in memory
# gcc 3.3.2 -gdwarf-2
# gcc 3.3.2 -gstabs+
#
diff --git a/gdb/testsuite/gdb.dap/catch-exception.exp b/gdb/testsuite/gdb.dap/catch-exception.exp
index 166b862..a1ced06 100644
--- a/gdb/testsuite/gdb.dap/catch-exception.exp
+++ b/gdb/testsuite/gdb.dap/catch-exception.exp
@@ -57,6 +57,12 @@ foreach spec $bps {
gdb_assert {[dict get $spec source path] != "null"} \
"breakpoint $i path"
}
+
+ # Breakpoint should be unverified and pending.
+ gdb_assert {[dict get $spec verified] == "false"} \
+ "catchpoint $i is unverified"
+ gdb_assert {[dict get $spec reason] == "pending"} \
+ "catchpoint $i is pending"
}
incr i
}
diff --git a/gdb/testsuite/gdb.dap/cxx-exception.exp b/gdb/testsuite/gdb.dap/cxx-exception.exp
index b54b11a..1332043 100644
--- a/gdb/testsuite/gdb.dap/cxx-exception.exp
+++ b/gdb/testsuite/gdb.dap/cxx-exception.exp
@@ -37,6 +37,16 @@ set bps [dict get [lindex $obj 0] body breakpoints]
# breakpoints.
gdb_assert {[llength $bps] == 3} "three breakpoints"
+# Each breakpoint should be unverified and pending.
+foreach bp $bps {
+ with_test_prefix [dict get $bp id] {
+ gdb_assert {[dict get $bp verified] == "false"} \
+ "catchpoint is unverified"
+ gdb_assert {[dict get $bp reason] == "pending"} \
+ "catchpoint is pending"
+ }
+}
+
dap_check_request_and_response "configurationDone" configurationDone
if {[dap_launch $testfile] == ""} {
diff --git a/gdb/testsuite/gdb.dap/global.c b/gdb/testsuite/gdb.dap/global.c
new file mode 100644
index 0000000..d3b7085
--- /dev/null
+++ b/gdb/testsuite/gdb.dap/global.c
@@ -0,0 +1,31 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+static struct {
+ int x;
+ struct {
+ int x2;
+ } y;
+} global;
+
+int
+main ()
+{
+ global.x = 23;
+ global.y.x2 = 47;
+ return 0; /* BREAK */
+}
diff --git a/gdb/testsuite/gdb.dap/global.exp b/gdb/testsuite/gdb.dap/global.exp
new file mode 100644
index 0000000..79f7f2f
--- /dev/null
+++ b/gdb/testsuite/gdb.dap/global.exp
@@ -0,0 +1,72 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+require allow_dap_tests
+
+load_lib dap-support.exp
+
+standard_testfile
+
+if {[build_executable ${testfile}.exp $testfile $srcfile] == -1} {
+ return
+}
+
+if {[dap_initialize] == ""} {
+ return
+}
+
+set line [gdb_get_line_number "BREAK"]
+set obj [dap_check_request_and_response "set breakpoint by line number" \
+ setBreakpoints \
+ [format {o source [o path [%s]] breakpoints [a [o line [i %d]]]} \
+ [list s $srcfile] $line]]
+set line_bpno [dap_get_breakpoint_number $obj]
+
+dap_check_request_and_response "configurationDone" configurationDone
+
+if {[dap_launch $testfile] == ""} {
+ return
+}
+dap_wait_for_event_and_check "inferior started" thread "body reason" started
+
+dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
+ "body reason" breakpoint \
+ "body hitBreakpointIds" $line_bpno
+
+set bt [lindex [dap_check_request_and_response "backtrace" stackTrace \
+ {o threadId [i 1]}] \
+ 0]
+set frame_id [dict get [lindex [dict get $bt body stackFrames] 0] id]
+
+set scopes [dap_check_request_and_response "get scopes" scopes \
+ [format {o frameId [i %d]} $frame_id]]
+set scopes [dict get [lindex $scopes 0] body scopes]
+
+gdb_assert {[llength $scopes] == 2} "two scopes"
+
+lassign $scopes reg_scope global_scope
+
+gdb_assert {[dict get $global_scope name] == "Globals"} "scope is globals"
+
+gdb_assert {[dict get $global_scope namedVariables] == 1} "one var in globals"
+
+set num [dict get $global_scope variablesReference]
+set refs [lindex [dap_check_request_and_response "fetch variables" \
+ "variables" \
+ [format {o variablesReference [i %d] count [i 1]} \
+ $num]] \
+ 0]
+
+dap_shutdown
diff --git a/gdb/testsuite/gdb.dap/insn-bp.exp b/gdb/testsuite/gdb.dap/insn-bp.exp
new file mode 100644
index 0000000..4a4c144
--- /dev/null
+++ b/gdb/testsuite/gdb.dap/insn-bp.exp
@@ -0,0 +1,100 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test instruction breakpoint resolution.
+
+require allow_dap_tests
+
+load_lib dap-support.exp
+
+standard_testfile basic-dap.c
+
+if {[build_executable ${testfile}.exp $testfile $srcfile] == -1} {
+ return
+}
+
+# Get the address of a function. Make sure the inferior is running
+# first -- on the ARM builder, the function address changed during
+# startup, and we want to find the final relocated address.
+clean_restart $testfile
+if {![runto_main]} {
+ return
+}
+set addr [get_var_address address_breakpoint_here]
+gdb_exit
+
+if {[dap_initialize] == ""} {
+ return
+}
+
+set obj [dap_check_request_and_response "set breakpoint on main" \
+ setFunctionBreakpoints \
+ {o breakpoints [a [o name [s main]]]}]
+set fn_bpno [dap_get_breakpoint_number $obj]
+
+set obj [dap_check_request_and_response "set breakpoint by address" \
+ setInstructionBreakpoints \
+ [format {o breakpoints [a [o instructionReference [s %s]]]} \
+ $addr]]
+set bpno [dap_get_breakpoint_number $obj]
+
+set bp [lindex [dict get [lindex $obj 0] body breakpoints] 0]
+gdb_assert {[dict get $bp verified] == "false"} \
+ "breakpoint is not verified"
+
+dap_check_request_and_response "configurationDone" configurationDone
+
+if {[dap_launch $testfile] == ""} {
+ return
+}
+
+# The event we're looking for should occur during startup, but we want
+# to leave open the possibility that it occurs when waiting for the
+# stopped event. So, keep both event lists around and search them
+# once below.
+lassign [dap_wait_for_event_and_check "inferior started" \
+ thread "body reason" started] \
+ unused objs1
+lassign [dap_wait_for_event_and_check "stopped at breakpoint" stopped \
+ "body reason" breakpoint \
+ "body hitBreakpointIds" $fn_bpno] unused objs2
+
+set found_bp_event 0
+foreach obj [concat $objs1 $objs2] {
+ if { [dict get $obj "type"] != "event" } {
+ continue
+ }
+
+ if { [dict get $obj "event"] != "breakpoint" } {
+ continue
+ }
+
+ set body [dict get $obj "body"]
+
+ if { [dict get $body "reason"] != "changed" } {
+ continue
+ }
+
+ set breakpoint [dict get $body breakpoint]
+ if {[dict get $breakpoint id] == $bpno} {
+ gdb_assert {[dict get $breakpoint source name] == "basic-dap.c"} \
+ "breakpoint modification event has source"
+ set found_bp_event 1
+ }
+}
+
+gdb_assert {$found_bp_event} "found the breakpoint event"
+
+dap_shutdown
diff --git a/gdb/testsuite/gdb.dap/memory.exp b/gdb/testsuite/gdb.dap/memory.exp
index 7082706..c4e4fb3 100644
--- a/gdb/testsuite/gdb.dap/memory.exp
+++ b/gdb/testsuite/gdb.dap/memory.exp
@@ -25,11 +25,12 @@ if {[build_executable ${testfile}.exp $testfile] == -1} {
return
}
-save_vars { env(ASAN_OPTIONS) } {
+save_vars { env(ASAN_OPTIONS) env(TSAN_OPTIONS) } {
# The request readMemory with count 18446744073709551615 triggers address
# sanitizer. Suppress the error, leaving us with just this warning:
# WARNING: AddressSanitizer failed to allocate 0xffffffffffffffff bytes
set_sanitizer ASAN_OPTIONS allocator_may_return_null 1
+ set_sanitizer TSAN_OPTIONS allocator_may_return_null 1
if {[dap_initialize] == ""} {
return
diff --git a/gdb/testsuite/gdb.dap/rust-slices.exp b/gdb/testsuite/gdb.dap/rust-slices.exp
index d3bd305..4af8c11 100644
--- a/gdb/testsuite/gdb.dap/rust-slices.exp
+++ b/gdb/testsuite/gdb.dap/rust-slices.exp
@@ -59,9 +59,9 @@ set scopes [dap_check_request_and_response "get scopes" scopes \
[format {o frameId [i %d]} $frame_id]]
set scopes [dict get [lindex $scopes 0] body scopes]
-# There are three scopes because an artificial symbol ends up in the
-# DWARF. See https://github.com/rust-lang/rust/issues/125126.
-gdb_assert {[llength $scopes] == 3} "three scopes"
+# There may be three scopes instead of two if an artificial symbol ends up in
+# the DWARF. See https://github.com/rust-lang/rust/issues/125126.
+gdb_assert { [llength $scopes] == 2 || [llength $scopes] == 3 } "two scopes"
lassign $scopes scope ignore
gdb_assert {[dict get $scope name] == "Locals"} "scope is locals"
diff --git a/gdb/testsuite/gdb.dap/step-out.exp b/gdb/testsuite/gdb.dap/step-out.exp
index 31c50bb..193264f 100644
--- a/gdb/testsuite/gdb.dap/step-out.exp
+++ b/gdb/testsuite/gdb.dap/step-out.exp
@@ -59,15 +59,21 @@ set scopes [dap_check_request_and_response "get scopes" scopes \
[format {o frameId [i %d]} $frame_id]]
set scopes [dict get [lindex $scopes 0] body scopes]
-gdb_assert {[llength $scopes] == 2} "two scopes"
+gdb_assert {[llength $scopes] == 3} "three scopes"
-lassign $scopes scope reg_scope
+lassign $scopes scope reg_scope return_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] == 2} "two vars in scope"
+gdb_assert {[dict get $scope namedVariables] == 1} "one var in scope"
-set num [dict get $scope variablesReference]
+gdb_assert {[dict get $return_scope name] == "Return"} "scope is return"
+gdb_assert {[dict get $return_scope presentationHint] == "returnValue"} \
+ "returnValue presentation hint"
+gdb_assert {[dict get $return_scope namedVariables] == 1} \
+ "one var in return scope"
+
+set num [dict get $return_scope variablesReference]
set refs [lindex [dap_check_request_and_response "fetch arguments" \
"variables" \
[format {o variablesReference [i %d]} $num]] \
diff --git a/gdb/testsuite/gdb.debuginfod/corefile-mapped-file-1.c b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file-1.c
new file mode 100644
index 0000000..dd6b3f1
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file-1.c
@@ -0,0 +1,24 @@
+/* Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* This is in the shared library. */
+extern int foo (void);
+
+int
+main (void)
+{
+ int res = foo ();
+ return res;
+}
diff --git a/gdb/testsuite/gdb.debuginfod/corefile-mapped-file-2.c b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file-2.c
new file mode 100644
index 0000000..ccf35b7
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file-2.c
@@ -0,0 +1,22 @@
+/* Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+volatile int *library_ptr = (int *) POINTER_VALUE;
+
+int
+foo (void)
+{
+ return *library_ptr;
+}
diff --git a/gdb/testsuite/gdb.debuginfod/corefile-mapped-file-3.c b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file-3.c
new file mode 100644
index 0000000..98ed952
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file-3.c
@@ -0,0 +1,44 @@
+/* Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+volatile void* library_base_address = 0;
+volatile int *ptr = 0;
+
+int
+main ()
+{
+ struct stat buf;
+ int res;
+
+ int fd = open (SHLIB_FILENAME, O_RDONLY);
+ assert (fd != -1);
+
+ res = fstat (fd, &buf);
+ assert (res == 0);
+
+ library_base_address
+ = mmap (NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+
+ res = *ptr; /* Undefined behaviour here. */
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp
new file mode 100644
index 0000000..cf96b41
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/corefile-mapped-file.exp
@@ -0,0 +1,380 @@
+# Copyright 2024 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+# This test checks GDB's ability to use build-ids when setting up file backed
+# mappings as part of reading a core-file.
+#
+# A core-file contains a list of the files that were mapped into the process
+# at the time of the core-file creation. If the file was mapped read-only
+# then the file contents will not be present in the core-file, but instead GDB
+# is expected to open the mapped file and read the contents from there if
+# needed. And this is what GDB does.
+#
+# GDB (via the BFD library) will also spot if a mapped looks like a valid ELF
+# and contains a build-id, this build-id is passed back to GDB so that GDB can
+# validate the on-disk file it finds matches the file that was mapped when the
+# core-file was created.
+#
+# In addition, if the on-disk file is found to have a non-matching build-id
+# then GDB can use debuginfod to (try) and download a suitable file.
+#
+# This test is about checking that this file backed mapping mechanism works
+# correctly; that GDB will spot when the build-ids fail to match and will
+# refuse to load an incorrect file. Additionally we check that the correct
+# file can be downloaded from debuginfod.
+#
+# The test is rather contrived though. Instead of relying on having a shared
+# library mapped at the time of crash we mmap a shared library into the
+# process and then check this mapping within the test.
+#
+# The problem with using a normal shared library load for this test is that
+# the shared library list is processed as part of a separate step when opening
+# the core file. Right now this separate step doesn't check the build-ids
+# correctly, so GDB will potentially open the wrong shared library file. The
+# sections of this incorrect shared library are then added to GDB's list of
+# target sections, and are used to satisfy memory reads, which can give the
+# wrong results.
+#
+# 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
+# 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
+# part of this test actually uses debuginfod, everything up to that point is
+# pretty generic.
+
+require {!is_remote host}
+require {!is_remote target}
+
+load_lib debuginfod-support.exp
+
+require allow_shlib_tests
+
+standard_testfile -1.c -2.c -3.c
+
+# Compile an executable that loads the shared library as an actual
+# 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"]
+
+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 ] \
+ $srcfile { debug }]] != 0} {
+ return
+}
+
+if {![runto_main]} {
+ return
+}
+
+if { [is_address_zero_readable] } {
+ return
+}
+
+set ptr_address [get_hexadecimal_valueof "&library_ptr" "unknown"]
+
+set ptr_offset "unknown"
+gdb_test_multiple "info proc mappings" "" {
+ -re "^($hex)\\s+($hex)\\s+$hex\\s+($hex)\[^\r\n\]+$library_filename\\s*\r\n" {
+ set low_addr $expect_out(1,string)
+ set high_addr $expect_out(2,string)
+ set file_offset $expect_out(3,string)
+
+ if {[expr $ptr_address >= $low_addr] && [expr $ptr_address < $high_addr]} {
+ set mapping_offset [expr $ptr_address - $low_addr]
+ set ptr_offset [format 0x%x [expr $file_offset + $mapping_offset]]
+ }
+
+ exp_continue
+ }
+
+ -re "^$gdb_prompt $" {
+ }
+
+ -re "(^\[^\r\n\]*)\r\n" {
+ set tmp $expect_out(1,string)
+ exp_continue
+ }
+}
+
+gdb_assert { $ptr_offset ne "unknown" } \
+ "found pointer offset"
+
+set ptr_size [get_integer_valueof "sizeof (library_ptr)" "unknown"]
+set ptr_format_char ""
+if { $ptr_size == 2 } {
+ set ptr_format_char "b"
+} elseif { $ptr_size == 4 } {
+ set ptr_format_char "w"
+} elseif { $ptr_size == 8 } {
+ set ptr_format_char "g"
+}
+if { $ptr_format_char eq "" } {
+ untested "could not figure out size of library_ptr variable"
+ return
+}
+
+# Helper proc to read a value from inferior memory. Reads at address held in
+# global PTR_ADDRESS, and use PTR_FORMAT_CHAR for the size of the read.
+proc read_ptr_value { } {
+ set value ""
+ gdb_test_multiple "x/1${::ptr_format_char}x ${::ptr_address}" "" {
+ -re -wrap "^${::hex}(?:\\s+<\[^>\]+>)?:\\s+($::hex)" {
+ set value $expect_out(1,string)
+ }
+ -re -wrap "^${::hex}(?:\\s+<\[^>\]+>)?:\\s+Cannot access memory at address ${::hex}" {
+ set value "unavailable"
+ }
+ }
+ return $value
+}
+
+set ptr_expected_value [read_ptr_value]
+if { $ptr_expected_value eq "" } {
+ untested "could not find expected value for library_ptr"
+ return
+}
+
+# Now compile a second executable. This one doesn't load the shared
+# library as an actual shared library, but instead mmaps the library
+# into the executable.
+#
+# 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 \
+ $srcfile3 $opts] != 0} {
+ return
+}
+
+if {![runto_main]} {
+ return
+}
+
+gdb_breakpoint [gdb_get_line_number "Undefined behaviour here" $srcfile3]
+gdb_continue_to_breakpoint "run to breakpoint"
+
+set library_base_address \
+ [get_hexadecimal_valueof "library_base_address" "unknown"]
+set ptr_address [format 0x%x [expr $library_base_address + $ptr_offset]]
+
+set ptr_value [read_ptr_value]
+gdb_assert { $ptr_value == $ptr_expected_value } \
+ "check value of pointer variable"
+
+# Now rerun the second executable outside of GDB. The executable should crash
+# and generate a corefile.
+set corefile [core_find $binfile]
+if {$corefile eq ""} {
+ untested "could not generate core file"
+ return
+}
+
+# Load a core file from the global COREFILE. Use TESTNAME as the name
+# of the test.
+#
+# If LINE_RE is not the empty string then this is a regexp for a line
+# that we expect to see in the output when loading the core file, if
+# the line is not present then this test will fail.
+#
+# Any lines beginning with 'warning: ' will cause this test to fail.
+#
+# A couple of other standard lines that are produced when loading a
+# core file are also checked for, just to make sure the core file
+# loading has progressed as expected.
+proc load_core_file { testname { line_re "" } } {
+ set code {}
+
+ if { $line_re ne "" } {
+ append code {
+ -re "^$line_re\r\n" {
+ set saw_expected_line true
+ exp_continue
+ }
+ }
+ set saw_expected_line false
+ } else {
+ set saw_expected_line true
+ }
+
+ set saw_unknown_warning false
+ set saw_generated_by_line false
+ set saw_prog_terminated_line false
+
+ append code {
+ -re "^warning: \[^\r\n\]+\r\n" {
+ set saw_unknown_warning true
+ exp_continue
+ }
+
+ -re "^Core was generated by \[^\r\n\]+\r\n" {
+ set saw_generated_by_line true
+ exp_continue
+ }
+
+ -re "^Program terminated with signal SIGSEGV, Segmentation fault\\.\r\n" {
+ set saw_prog_terminated_line true
+ exp_continue
+ }
+
+ -re "^$::gdb_prompt $" {
+ gdb_assert {$saw_generated_by_line \
+ && $saw_prog_terminated_line \
+ && $saw_expected_line \
+ && !$saw_unknown_warning} \
+ $gdb_test_name
+ }
+
+ -re "^\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+ }
+
+ set res [catch { return [gdb_test_multiple "core-file $::corefile" \
+ "$testname" $code] } string]
+
+ if {$res == 1} {
+ global errorInfo errorCode
+ return -code error -errorinfo $errorInfo -errorcode $errorCode $string
+ } elseif {$res == 2} {
+ return $string
+ } else {
+ # 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"
+ return -1
+ }
+}
+
+# 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
+
+load_core_file "load core file"
+
+set library_base_address [get_hexadecimal_valueof "library_base_address" \
+ "unknown" "get library_base_address in core-file"]
+set ptr_address [format 0x%x [expr $library_base_address + $ptr_offset]]
+
+set ptr_value [read_ptr_value]
+gdb_assert { $ptr_value == $ptr_expected_value } \
+ "check value of pointer variable from core-file"
+
+# Now move the shared library file away and restart GDB. This time when we
+# load the core-file we should see a warning that GDB has failed to map in the
+# library file. An attempt to read the variable from the library file should
+# fail / give a warning.
+set library_backup_filename [standard_output_file "libfoo.so.backup"]
+remote_exec build "mv \"$library_filename\" \"$library_backup_filename\""
+
+clean_restart $binfile
+
+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"
+
+set ptr_value [read_ptr_value]
+gdb_assert { $ptr_value eq "unavailable" } \
+ "check value of pointer is unavailable with library file missing"
+
+# Now symlink the .build-id/xx/xxx...xxx filename within the debug
+# directory to library we just moved aside. Restart GDB and setup the
+# debug-file-directory before loading the core file.
+#
+# GDB should lookup the file to map via the build-id link in the
+# .build-id/ directory.
+set debugdir [standard_output_file "debugdir"]
+set build_id_filename \
+ $debugdir/[build_id_debug_filename_get $library_backup_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
+
+gdb_test_no_output "set debug-file-directory $debugdir" \
+ "set debug-file-directory"
+
+load_core_file "load corefile, lookup in debug-file-directory"
+
+set ptr_value [read_ptr_value]
+gdb_assert { $ptr_value == $ptr_expected_value } \
+ "check value of pointer variable from core-file, lookup in debug-file-directory"
+
+# Build a new version of the shared library, keep the library the same size,
+# but change the contents so the build-id changes. Then restart GDB and load
+# the core-file again. GDB should spot that the build-id for the shared
+# library is not as expected, and should refuse to map in the shared library.
+if {[build_executable "build second version of shared library" \
+ $library_filename $srcfile2 \
+ { debug shlib build-id \
+ additional_flags=-DPOINTER_VALUE=0x11223344 }] != 0} {
+ return
+}
+
+clean_restart $binfile
+
+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"
+
+set ptr_value [read_ptr_value]
+gdb_assert { $ptr_value eq "unavailable" } \
+ "check value of pointer is unavailable with wrong library in place"
+
+# Setup a debuginfod server which can serve the original shared library file.
+# Then restart GDB and load the core-file. GDB should download the original
+# shared library from debuginfod and use that to provide the file backed
+# mapping.
+if {![allow_debuginfod_tests]} {
+ untested "skippig debuginfod parts of this test"
+ return
+}
+
+set server_dir [standard_output_file "debuginfod.server"]
+file mkdir $server_dir
+file rename -force $library_backup_filename $server_dir
+
+prepare_for_debuginfod cache db
+
+set url [start_debuginfod $db $server_dir]
+if { $url eq "" } {
+ unresolved "failed to start debuginfod server"
+ return
+}
+
+with_debuginfod_env $cache {
+ setenv DEBUGINFOD_URLS $url
+
+ clean_restart
+ gdb_test_no_output "set debuginfod enabled on" \
+ "enabled debuginfod for initial test"
+ gdb_load $binfile
+
+ load_core_file "load corefile, download library from debuginfod" \
+ "Downloading\[^\r\n\]* executable for [string_to_regexp $library_filename]\\.\\.\\."
+
+ set ptr_value [read_ptr_value]
+ gdb_assert { $ptr_value == $ptr_expected_value } \
+ "check value of pointer variable after downloading library file"
+}
+
+stop_debuginfod
diff --git a/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp b/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
index 401af0d..450d890 100644
--- a/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
+++ b/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
@@ -195,12 +195,6 @@ proc test_urls {urls pattern_re test} {
$test
}
-# Used as a replacement for delete_breakpoints while calling
-# runto_main in one case where we don't want to delete all the
-# breakpoints.
-proc disable_delete_breakpoints {} {
-}
-
# Uses the global variables DEBUGDIR and DB which are setup elsewhere
# in this script.
#
@@ -234,14 +228,15 @@ proc_with_prefix local_url { } {
# the contents of DW_AT_comp_dir and DW_AT_name.
gdb_test "set cwd $debugdir" "" "file [file tail $binfile] cwd"
gdb_breakpoint $lineno
- with_override delete_breakpoints disable_delete_breakpoints {
- if {![runto_main]} {
- return
- }
- gdb_continue_to_breakpoint "runto breakpoint in main" \
- ".* Breakpoint here\\. .*"
+
+ # Run to main, but don't delete all breakpoints.
+ if {![runto_main no-delete-breakpoints]} {
+ return
}
+ gdb_continue_to_breakpoint "runto breakpoint in main" \
+ ".* Breakpoint here\\. .*"
+
# GDB should now find the executable file.
set enable_debuginfod_question \
"Enable debuginfod for this session. \\(y or \\\[n\\\]\\) "
diff --git a/gdb/testsuite/gdb.debuginfod/solib-with-soname-1.c b/gdb/testsuite/gdb.debuginfod/solib-with-soname-1.c
new file mode 100644
index 0000000..30e9267
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/solib-with-soname-1.c
@@ -0,0 +1,39 @@
+/* Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+
+/* It is important that these two variables have names of the same length
+ so that the debug information in the two library versions is laid out
+ the same. If they differ then the .dynamic section might move, which
+ will trigger a different check within GDB than the one we actually want
+ to check. */
+
+#if LIB_VERSION == 1
+volatile int *library_1_var = (volatile int *) 0x12345678;
+#elif LIB_VERSION == 2
+volatile int *library_2_var = (volatile int *) 0x11223344;
+#else
+# error Unknown library version
+#endif
+
+int
+foo (void)
+{
+ /* This should trigger a core dump. */
+ abort ();
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.debuginfod/solib-with-soname-2.c b/gdb/testsuite/gdb.debuginfod/solib-with-soname-2.c
new file mode 100644
index 0000000..a51d48e
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/solib-with-soname-2.c
@@ -0,0 +1,41 @@
+/* Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stddef.h>
+
+/* This is in the shared library. */
+extern int foo (void);
+
+/* This is updated by the .exp file. */
+char *libname = "libfoo_2.so";
+
+int
+main (void)
+{
+ void *handle;
+ int res, tmp;
+
+ handle = dlopen (libname, RTLD_LAZY);
+ assert (handle != NULL);
+
+ res = foo ();
+
+ tmp = dlclose (handle);
+ assert (tmp == 0);
+
+ return res;
+}
diff --git a/gdb/testsuite/gdb.debuginfod/solib-with-soname.exp b/gdb/testsuite/gdb.debuginfod/solib-with-soname.exp
new file mode 100644
index 0000000..9ef1204
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/solib-with-soname.exp
@@ -0,0 +1,290 @@
+# Copyright 2024 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+# This test exercises GDB's ability to validate build-ids when loading
+# shared libraries for a core file.
+#
+# The test creates two "versions" of a shared library, sets up a
+# symlink to point to one version of the library, and creates a core file.
+#
+# We then try re-loading the core file and executable and check that
+# GDB is able to correctly load the shared library. To confuse things
+# we retarget the library symlink at the other version of the library.
+#
+# After that we repeat the test, but this time deleting the symlink
+# completely.
+#
+# Then we remove the version of the library completely, at this point
+# we do expect GDB to give a warning about being unable to load the library.
+#
+# And finally, we setup debuginfod and have it serve the missing
+# library file, GDB should correctly download the library file.
+#
+# Despite this test living in the gdb.debuginfod/ directory, only the last
+# part of this test actually uses debuginfod, everything up to that point is
+# pretty generic.
+
+load_lib debuginfod-support.exp
+
+require allow_shlib_tests
+require {istarget "*-linux*"}
+require {!is_remote host}
+require {!using_fission}
+
+standard_testfile -1.c -2.c
+
+# Build two similar, but slightly different versions of the shared
+# library. Both libraries have DT_SONAME set to the generic
+# libfoo.so, we'll create a symlink with that name later.
+set library_1_filename [standard_output_file "libfoo_1.so"]
+set library_2_filename [standard_output_file "libfoo_2.so"]
+
+# The generic name for the library.
+set library_filename [standard_output_file "libfoo.so"]
+
+# When compiling a shared library the -Wl,-soname,NAME option is
+# automatically added based on the final name of the library. We want
+# to compile libfoo_1.so, but set the soname to libfoo.so. To achieve
+# this we first compile into libfoo.so, and then rename the library to
+# libfoo_1.so.
+if {[build_executable "build libfoo_1.so" $library_filename \
+ $srcfile \
+ { debug shlib build-id \
+ additional_flags=-DLIB_VERSION=1 }] == -1} {
+ return
+}
+remote_exec build "mv ${library_filename} ${library_1_filename}"
+
+# See the comment above, but this time we rename to libfoo_2.so.
+if {[build_executable "build libfoo_2.so" $library_filename \
+ $srcfile \
+ { debug shlib build-id \
+ additional_flags=-DLIB_VERSION=2 }] == -1} {
+ return
+}
+remote_exec build "mv ${library_filename} ${library_2_filename}"
+
+# Create libfoo.so symlink to the libfoo_1.so library. If this
+# symlink creation fails then we assume we can't create symlinks on
+# this host. If this succeeds then later symlink creation is required
+# to succeed, and will trigger an FAIL if it doesn't.
+set status \
+ [remote_exec build \
+ "ln -sf ${library_1_filename} ${library_filename}"]
+if {[lindex $status 0] != 0} {
+ unsupported "host does not support symbolic links"
+ return
+}
+
+# Build the executable. This links against libfoo.so, which is
+# poining 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 } {
+ return
+}
+
+# If the board file is automatically splitting the debug information
+# into a separate file (e.g. the cc-with-gnu-debuglink.exp board) then
+# this test isn't going to work.
+clean_restart
+gdb_file_cmd $binfile
+if {$gdb_file_cmd_debug_info ne "debug"} {
+ unsupported "failed to find debug information"
+ return
+}
+if {[regexp "${testfile}.debug" $gdb_file_cmd_msg]} {
+ unsupported "debug information has been split to a separate file"
+ return
+}
+
+# Run BINFILE which will generate a corefile.
+set corefile [core_find $binfile]
+if {$corefile eq ""} {
+ untested "could not generate core file"
+ return
+}
+
+# Helper proc to load global BINFILE and then load global COREFILE.
+#
+# If EXPECT_WARNING is true then we require a warning about being
+# unable to load the shared library symbols, otherwise, EXPECT_WARNING
+# is false and we require no warning.
+#
+# If EXPECT_DOWNLOAD is true then we require a line indicating that
+# the shared library is being downloaded from debuginfod, otherwise
+# the shared library should not be downloaded.
+#
+# If DEBUGDIR is not the empty string then 'debug-file-directory' is
+# set to the value of DEBUGDIR.
+proc load_exec_and_core_file { expect_warning expect_download testname \
+ {debugdir ""} } {
+ with_test_prefix $testname {
+ clean_restart $::binfile
+
+ if { $debugdir ne "" } {
+ gdb_test_no_output "set debug-file-directory $debugdir" \
+ "set debug directory"
+ }
+
+ set saw_warning false
+ set saw_download false
+ set saw_generated false
+ set saw_terminated false
+
+ gdb_test_multiple "core-file $::corefile" "load core file" {
+ -re "^Core was generated by \[^\r\n\]+\r\n" {
+ set saw_generated true
+ exp_continue
+ }
+ -re "^Program terminated with signal \[^\r\n\]+\r\n" {
+ set saw_terminated true
+ exp_continue
+ }
+ -re "^warning: Can't open file \[^\r\n\]+ during file-backed mapping note processing\r\n" {
+ # Ignore warnings from the file backed mapping phase.
+ exp_continue
+ }
+ -re "^warning: Could not load shared library symbols for \[^\r\n\]+/libfoo\\.so\\.\r\n" {
+ set saw_warning true
+ exp_continue
+ }
+ -re "^Downloading executable for \[^\r\n\]+/libfoo_1\\.so\\.\\.\\.\r\n" {
+ set saw_download true
+ exp_continue
+ }
+ -re "^$::gdb_prompt $" {
+ gdb_assert { $saw_generated && $saw_terminated \
+ && $saw_warning == $expect_warning \
+ && $saw_download == $expect_download } \
+ $gdb_test_name
+ }
+ -re "^\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+ }
+
+ # If we don't expect a warning then debug symbols from the
+ # shared library should be available. Confirm we can read a
+ # variable from the shared library. If we do expect a warning
+ # then the shared library debug symbols have not loaded, and
+ # the library variable should not be available.
+ if { !$expect_warning } {
+ gdb_test "print/x library_1_var" " = 0x12345678" \
+ "check library_1_var can be read"
+ } else {
+ gdb_test "print/x library_1_var" \
+ "^No symbol \"library_1_var\" in current context\\." \
+ "check library_1_var cannot be read"
+ }
+ }
+}
+
+# Initial test, just load the executable and core file. At this point
+# everything should load fine as everything is where we expect to find
+# it.
+load_exec_and_core_file false false \
+ "load core file, all libraries as expected"
+
+# Update libfoo.so symlink to point at the second library then reload
+# the core file. GDB should spot that the symlink points to the wrong
+# file, but should be able to figure out the correct file to load as
+# the right file will be in the mapped file list.
+set status [remote_exec build \
+ "ln -sf ${library_2_filename} ${library_filename}"]
+gdb_assert { [lindex $status 0] == 0 } \
+ "update library symlink to point to the wrong file"
+
+load_exec_and_core_file false false \
+ "load core file, symlink points to wrong file"
+
+# Remove libfoo.so symlink and reload the core file. As in the
+# previous test GDB should be able to figure out the correct file to
+# load as the correct file will still appear in the mapped file list.
+set status [remote_exec build "rm -f ${library_filename}"]
+gdb_assert { [lindex $status 0] == 0 } "remove library symlink"
+
+load_exec_and_core_file false false \
+ "load core file, symlink removed"
+
+# Remove LIBRARY_1_FILENAME. We'll now see a warning that the mapped
+# file can't be loaded (we ignore that warning), and we'll see a
+# warning that the shared library can't be loaded.
+set library_1_backup_filename ${library_1_filename}.backup
+set status \
+ [remote_exec build \
+ "mv ${library_1_filename} ${library_1_backup_filename}"]
+gdb_assert { [lindex $status 0] == 0 } \
+ "remove libfoo_1.so"
+
+load_exec_and_core_file true false \
+ "load core file, libfoo_1.so removed"
+
+# Symlink the .build-id/xx/xxx...xxx filename within the debug
+# directory to LIBRARY_1_BACKUP_FILENAME, now when we restart GDB it
+# should find the missing library within the debug directory.
+set debugdir [standard_output_file "debugdir"]
+set build_id_filename \
+ $debugdir/[build_id_debug_filename_get $library_1_backup_filename ""]
+set status \
+ [remote_exec build \
+ "mkdir -p [file dirname $build_id_filename]"]
+gdb_assert { [lindex $status 0] == 0 } \
+ "create sub-directory within the debug directory"
+set status \
+ [remote_exec build \
+ "ln -sf $library_1_backup_filename $build_id_filename"]
+gdb_assert { [lindex $status 0] == 0 } \
+ "create symlink within the debug directory "
+
+load_exec_and_core_file false false \
+ "load core file, find libfoo_1.so through debug-file-directory" \
+ $debugdir
+
+# Setup a debuginfod server which can serve the original shared
+# library file.
+if {![allow_debuginfod_tests]} {
+ untested "skippig debuginfod parts of this test"
+ return
+}
+
+set server_dir [standard_output_file "debuginfod.server"]
+file mkdir $server_dir
+file rename -force $library_1_backup_filename $server_dir
+
+prepare_for_debuginfod cache db
+
+set url [start_debuginfod $db $server_dir]
+if { $url eq "" } {
+ unresolved "failed to start debuginfod server"
+ return
+}
+
+with_debuginfod_env $cache {
+ setenv DEBUGINFOD_URLS $url
+
+ save_vars { GDBFLAGS } {
+ append GDBFLAGS " -ex \"set debuginfod enabled on\""
+
+ # Reload the executable and core file. GDB should download
+ # the file libfoo_1.so using debuginfod during the mapped file
+ # phase, but should then reuse that download during the shared
+ # library phase.
+ load_exec_and_core_file false true \
+ "load core file, use debuginfod"
+ }
+}
+
+stop_debuginfod
diff --git a/gdb/testsuite/gdb.dwarf2/backward-spec-inter-cu.exp b/gdb/testsuite/gdb.dwarf2/backward-spec-inter-cu.exp
index 59b3db5..2f41db9 100644
--- a/gdb/testsuite/gdb.dwarf2/backward-spec-inter-cu.exp
+++ b/gdb/testsuite/gdb.dwarf2/backward-spec-inter-cu.exp
@@ -98,6 +98,7 @@ foreach_with_prefix worker_threads $worker_threads_list {
gdb_load $binfile
- gdb_test "maint print objfiles" "$eol$ws+qualified:$ws+ns::v$eol.*" \
+ 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/count.exp b/gdb/testsuite/gdb.dwarf2/count.exp
index 52deb19..096e093 100644
--- a/gdb/testsuite/gdb.dwarf2/count.exp
+++ b/gdb/testsuite/gdb.dwarf2/count.exp
@@ -124,25 +124,11 @@ Dwarf::assemble $asm_file {
}
}
-if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile}1.o \
- object {nodebug}] != "" } {
+if { [prepare_for_testing "failed to prepare" $testfile \
+ [list $srcfile $asm_file] {nodebug}] } {
return -1
}
-if { [gdb_compile $asm_file ${binfile}2.o object {nodebug}] != "" } {
- return -1
-}
-
-if { [gdb_compile [list ${binfile}1.o ${binfile}2.o] \
- "${binfile}" executable {}] != "" } {
- return -1
-}
-
-save_vars { GDBFLAGS } {
- set GDBFLAGS [concat $GDBFLAGS " -readnow"]
- clean_restart ${testfile}
-}
-
if ![runto_main] {
return -1
}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-anon-mptr.exp b/gdb/testsuite/gdb.dwarf2/dw2-anon-mptr.exp
index 5935ba6..fa98e41 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-anon-mptr.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-anon-mptr.exp
@@ -36,5 +36,19 @@ gdb_test "show cp-abi" {The currently selected C\+\+ ABI is "gnu-v3".*}
gdb_load $binfile
+set re_address_class "@\[^\r\n\]+"
+
+set re_class_ptr_const \
+ [string cat \
+ [string_to_regexp "class {...} * const"] "( $re_address_class)?"]
+
gdb_test "ptype crash" \
- "type = class crash {\[\r\n \t\]*public:\[\r\n \t\]*crash\\(int \\(class {\\.\\.\\.}::\\*\\)\\(class {\\.\\.\\.} \\* const\\)\\);\[\r\n \t\]*}"
+ [multi_line \
+ "type = class crash {" \
+ "" \
+ " public:" \
+ [string cat \
+ [string_to_regexp " crash(int (class {...}::*)("] \
+ $re_class_ptr_const \
+ [string_to_regexp "));"]] \
+ "}"]
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-bad-parameter-type.exp b/gdb/testsuite/gdb.dwarf2/dw2-bad-parameter-type.exp
index 547ab81..d6b8d2e 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-bad-parameter-type.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-bad-parameter-type.exp
@@ -28,7 +28,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" object {}] != "
clean_restart $executable
# The first access (as we do not use -readnow) prints some:
-# Dwarf Error: Cannot find DIE at 0x0 referenced from DIE at 0x29 [in module ...]
+# DWARF Error: Cannot find DIE at 0x0 referenced from DIE at 0x29 [in module ...]
with_test_prefix "first" {
gdb_test "ptype f"
}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-error.exp b/gdb/testsuite/gdb.dwarf2/dw2-error.exp
index 8081e7f..526b394 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-error.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-error.exp
@@ -37,7 +37,7 @@ set host_binfile [gdb_remote_download host $binfile]
# First test that reading symbols fails.
gdb_test "file $host_binfile" \
- {Reading symbols.*Dwarf Error: wrong version in compilation unit header \(is 153, should be 2, 3, 4 or 5\).*} \
+ {Reading symbols.*DWARF Error: wrong version in compilation unit header \(is 153, should be 2, 3, 4 or 5\).*} \
"file $testfile"
# We can't use proc readnow, because the PR makes it return 0.
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c
index 58b97ca..2789e6a 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c
+++ b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c
@@ -46,11 +46,5 @@ int8_t pck__fp1_range_var = 16;
int
main (void)
{
- pck__fp1_var++;
- pck__fp1_var2++;
- pck__fp2_var++;
- pck__fp3_var++;
- pck__fp1_range_var++;
-
return 0;
}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inter-cu-error-2.exp b/gdb/testsuite/gdb.dwarf2/dw2-inter-cu-error-2.exp
new file mode 100644
index 0000000..585fd54
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-inter-cu-error-2.exp
@@ -0,0 +1,51 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Check that GDB doesn't crash on invalid dwarf, specifically an inter-CU
+# reference pointing to a dummy CU.
+
+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 .S
+
+# Create the DWARF.
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ declare_labels label1
+
+ cu {} {
+ compile_unit {{language @DW_LANG_C}} {
+ subprogram {
+ {MACRO_AT_range { main }}
+ {DW_AT_specification %$label1}
+ }
+ }
+ }
+
+ label1: cu {} {
+ }
+}
+
+if [prepare_for_testing "failed to prepare" $testfile \
+ [list $asm_file $srcfile] {nodebug}] {
+ return -1
+}
+
+gdb_assert \
+ { [regexp "DWARF Error: cannot follow reference" $gdb_file_cmd_msg] } \
+ "Error message"
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inter-cu-error.exp b/gdb/testsuite/gdb.dwarf2/dw2-inter-cu-error.exp
new file mode 100644
index 0000000..92ffcae
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-inter-cu-error.exp
@@ -0,0 +1,51 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+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 .S
+
+# Create the DWARF.
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ declare_labels label1
+
+ cu {} {
+ compile_unit {{language @DW_LANG_C}} {
+ subprogram {
+ {MACRO_AT_range { main }}
+ {DW_AT_specification %$label1}
+ }
+ }
+ }
+
+ cu {} {
+ compile_unit {{language @DW_LANG_C}} {
+ label1:
+ }
+ }
+}
+
+if [prepare_for_testing "failed to prepare" $testfile \
+ [list $asm_file $srcfile] {nodebug}] {
+ return -1
+}
+
+# Verify that GDB notices the null DIE.
+gdb_assert { [regexp "DWARF Error: Unexpected null DIE" $gdb_file_cmd_msg] } \
+ "Null DIE error missing"
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inter-cu-forth-and-back.exp b/gdb/testsuite/gdb.dwarf2/dw2-inter-cu-forth-and-back.exp
new file mode 100644
index 0000000..62674bd
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-inter-cu-forth-and-back.exp
@@ -0,0 +1,60 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Check that the cooked index reader can handle inter-CU references:
+# - DIE1@CU1 -> DIE2@CU2
+# - DIE2@CU2 -> DIE3@CU1.
+
+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 .S
+
+# Create the DWARF.
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ declare_labels label1 label2
+
+ cu {} {
+ compile_unit {{language @DW_LANG_C}} {
+ subprogram {
+ {MACRO_AT_range { main }}
+ {DW_AT_specification %$label1}
+ }
+
+ label2: subprogram {
+ {DW_AT_name main}
+ }
+ }
+ }
+
+ cu {} {
+ compile_unit {{language @DW_LANG_C}} {
+ label1: subprogram {
+ {DW_AT_specification %$label2}
+ }
+ }
+ }
+}
+
+if [prepare_for_testing "failed to prepare" $testfile \
+ [list $asm_file $srcfile] {nodebug}] {
+ return -1
+}
+
+# Regression test for PR32081.
+gdb_assert { ![regexp -nocase "error:" $gdb_file_cmd_msg] } "No Error message"
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp b/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
index c510de4..9124aff 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
@@ -56,6 +56,10 @@ Dwarf::assemble $asm_file {
file_name "$srcfile" 1
program {
+ DW_LNE_set_address $bar1_start
+ line 25
+ DW_LNS_copy
+
DW_LNE_set_address bar1_label
line 27
DW_LNS_copy
@@ -76,6 +80,10 @@ Dwarf::assemble $asm_file {
DW_LNE_end_sequence
+ DW_LNE_set_address $bar2_start
+ line 39
+ DW_LNS_copy
+
DW_LNE_set_address bar2_label
line 41
DW_LNS_copy
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-lines.c b/gdb/testsuite/gdb.dwarf2/dw2-lines.c
index 67c98fe..221d7b9 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-lines.c
+++ b/gdb/testsuite/gdb.dwarf2/dw2-lines.c
@@ -22,7 +22,7 @@ foo (int x)
void
bar (void)
-{
+{ /* bar: */
asm ("bar_label: .globl bar_label");
foo (1);
asm ("bar_label_2: .globl bar_label_2");
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-lines.exp b/gdb/testsuite/gdb.dwarf2/dw2-lines.exp
index af5b6b7..4814f49 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-lines.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-lines.exp
@@ -88,6 +88,10 @@ proc test_1 { _cv _cdw64 _lv _ldw64 {_string_form ""}} {
# to set the current file explicitly.
DW_LNS_set_file $diridx
+ DW_LNE_set_address $bar_start
+ line [line_for bar]
+ DW_LNS_copy
+
DW_LNE_set_address bar_label
line [line_for bar_label]
DW_LNS_copy
@@ -122,9 +126,9 @@ proc test_1 { _cv _cdw64 _lv _ldw64 {_string_form ""}} {
gdb_breakpoint "bar_label"
gdb_continue_to_breakpoint "foo \\(1\\)"
- gdb_test "next" "foo \\(2\\).*" "next to foo (2)"
- gdb_test "next" "foo \\(3\\).*" "next to foo (3)"
- gdb_test "next" "foo \\(4\\).*" "next to foo (4)"
+ gdb_test "next" "foo \\(2\\).*" "next to foo(2)"
+ gdb_test "next" "foo \\(3\\).*" "next to foo(3)"
+ gdb_test "next" "foo \\(4\\).*" "next to foo(4)"
}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.exp b/gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.exp
index 3eadeb2..f84142a 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.exp
@@ -56,7 +56,7 @@ gdb_test_no_output "maint set dwarf synchronous on"
set pattern1 \
[multi_line \
"Reading symbols from \[^\r\n\]+" \
- "Dwarf Error: unexpected tag 'DW_TAG_subprogram' at offset $hex"]
+ "DWARF Error: unexpected tag 'DW_TAG_subprogram' at offset $hex"]
# This pattern is hit when GDB does use -readnow (e.g. running with
# --target_board=readnow).
@@ -64,7 +64,7 @@ set pattern2 \
[multi_line \
"Reading symbols from \[^\r\n\]+" \
"Expanding full symbols from \[^\r\n\]+" \
- "Dwarf Error: unexpected tag 'DW_TAG_subprogram' at offset $hex"]
+ "DWARF Error: unexpected tag 'DW_TAG_subprogram' at offset $hex"]
# Load the executable, we expect an error from the DWARF parser.
gdb_test_multiple "file $host_binfile" "file $testfile" {
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-opt-structptr.exp b/gdb/testsuite/gdb.dwarf2/dw2-opt-structptr.exp
index cebed1d..d73f4a8 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-opt-structptr.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-opt-structptr.exp
@@ -126,6 +126,8 @@ proc build_test_program {} {
}
}
+set re_address_class "@\[^\r\n\]+"
+
# Test access to an optimized-out pointer-to-struct using the
# console interpreter.
@@ -210,13 +212,18 @@ proc do_mi_test {} {
# Test that -var-create for 'ptr' is successful.
mi_create_varobj "var1" "ptr" "create varobj for ptr"
+
+ set struct_foo_ptr \
+ [string cat \
+ [string_to_regexp "struct foo *"] "( $::re_address_class)?"]
# Test that -var-list-children of 'ptr' is successful.
- mi_list_varobj_children "var1" { \
- {var1.a a 0 integer} \
- {var1.x x 128 foo__array_type} \
- {var1.y y 3 "struct foo \\*"} \
- } "get children of var1 (ptr)"
+ mi_list_varobj_children "var1" \
+ [list \
+ {var1.a a 0 integer} \
+ {var1.x x 128 foo__array_type} \
+ [list "var1.y" "y" "3" $struct_foo_ptr]] \
+ "get children of var1 (ptr)"
# Test that dereferencing 'ptr' will throw an error.
mi_gdb_test "-var-create var2 * &((ptr)->a)" \
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp b/gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp
index 1a3d53c..2be211f 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp
@@ -40,7 +40,7 @@ Dwarf::assemble $asm_file {
[function_range frame3 [list ${srcdir}/${subdir}/$srcfile]]
# Very simple info for this test program. We don't care about
- # this information being correct (w.r.t. funtion / argument types)
+ # this information being correct (w.r.t. function / argument types)
# just so long as the compilation using makes use of the
# .debug_ranges data then the test achieves its objective.
cu { label cu_label } {
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-step-out-of-function-no-stmt.exp b/gdb/testsuite/gdb.dwarf2/dw2-step-out-of-function-no-stmt.exp
index a59c637..55f4373 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-step-out-of-function-no-stmt.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-step-out-of-function-no-stmt.exp
@@ -19,7 +19,7 @@
#
# This sort of thing can occur in optimized code, f.i. here a slightly more
# elaborate case with another is-stmt=no entry (the one with line number 12)
-# inbetween:
+# in between:
# INDEX LINE ADDRESS IS-STMT
# 12 13 0x00000000004003ed
# 13 12 0x00000000004003f2
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-using-debug-str.exp b/gdb/testsuite/gdb.dwarf2/dw2-using-debug-str.exp
index cd3dd0b..c84a530 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-using-debug-str.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-using-debug-str.exp
@@ -131,7 +131,7 @@ clean_restart
gdb_test_no_output "maint set dwarf synchronous on"
set line1 "Reading symbols from \[^\r\n\]+"
-set dwarf_error "Dwarf Error: DW_FORM_strp used without required section"
+set dwarf_error "DWARF Error: DW_FORM_strp used without required section"
# This pattern is hit when GDB does not use -readnow (i.e. the default
# behaviour).
diff --git a/gdb/testsuite/gdb.dwarf2/dwz-unused-pu.exp b/gdb/testsuite/gdb.dwarf2/dwz-unused-pu.exp
new file mode 100644
index 0000000..1dd91ee
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dwz-unused-pu.exp
@@ -0,0 +1,75 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Check that a symbol from an unused PU is not accessible.
+
+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
+
+# Create the DWARF.
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ declare_labels partial_label int_label int_label2
+
+ cu {} {
+ compile_unit {{language @DW_LANG_C}} {
+ subprogram {
+ {MACRO_AT_func { main }}
+ }
+ }
+ }
+
+ cu {} {
+ partial_unit {} {
+ int_label: base_type {
+ {name int}
+ {byte_size 4 sdata}
+ {encoding @DW_ATE_signed}
+ }
+
+ constant {
+ {name the_int}
+ {type :$int_label}
+ {const_value 99 data1}
+ }
+ }
+ }
+}
+
+if { [prepare_for_testing "failed to prepare" $testfile \
+ [list $asm_file $srcfile] {nodebug}] } {
+ return -1
+}
+
+set cmd "p the_int"
+set re \
+ [string_to_regexp \
+ {No symbol "the_int" in current context.}]
+
+# Check that the unreferenced PU is not expanded.
+gdb_test $cmd $re
+
+# This should expand all CUs and referenced PUs, but not an unreferenced PU.
+gdb_test_no_output "maint expand-symtabs"
+
+# Flush the symbol cache to do a new symbol lookup.
+gdb_test_no_output "maint flush symbol-cache"
+
+# Check that the unreferenced PU is not expanded after "maint expand-symtabs".
+gdb_test $cmd $re "$cmd, again"
diff --git a/gdb/testsuite/gdb.dwarf2/enum-type-c++.cc b/gdb/testsuite/gdb.dwarf2/enum-type-c++.cc
new file mode 100644
index 0000000..691c7fc
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/enum-type-c++.cc
@@ -0,0 +1,35 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+namespace ns {
+
+class A {
+public:
+ enum {
+ val1 = 1
+ };
+};
+
+enum class ec
+{
+ val2 = 2,
+};
+}
+
+int u1 = ns::A::val1;
+
+int u2 = (int)ns::ec::val2;
diff --git a/gdb/testsuite/gdb.dwarf2/enum-type-c++.exp b/gdb/testsuite/gdb.dwarf2/enum-type-c++.exp
new file mode 100644
index 0000000..4f9610c
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/enum-type-c++.exp
@@ -0,0 +1,67 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+require !readnow
+
+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 .cc
+
+if { [prepare_for_testing "failed to prepare" $testfile \
+ [list $srcfile $srcfile2] {debug c++}] } {
+ return -1
+}
+
+require {string equal [have_index $binfile] ""}
+
+set lines [gdb_get_lines "maint print objfiles"]
+set re_ws "\[ \t\]"
+
+# Regression test for PR31900.
+set val1 ns::A::val1
+set test "val1 has a parent"
+if { [regexp val1 $lines] } {
+ set re \
+ [multi_line \
+ "" \
+ "$re_ws+qualified:$re_ws+$val1" \
+ ".*"]
+ gdb_assert {[regexp $re $lines]} $test
+
+ gdb_test "print $val1" " = $val1"
+} else {
+ # Clang doesn't emit a DIE for val1.
+ unsupported $test
+}
+
+# Regression test for PR32158.
+set val2 ns::ec::val2
+set test "val2 has correct parent"
+if { [regexp val2 $lines] } {
+ set re \
+ [multi_line \
+ "" \
+ "$re_ws+qualified:$re_ws+$val2" \
+ ".*"]
+ gdb_assert {[regexp $re $lines]} $test
+
+ gdb_test "print $val2" " = $val2"
+} else {
+ # Clang doesn't emit a DIE for val2.
+ unsupported $test
+}
diff --git a/gdb/testsuite/gdb.dwarf2/enum-type.exp b/gdb/testsuite/gdb.dwarf2/enum-type.exp
index 394d287..ec12db5 100644
--- a/gdb/testsuite/gdb.dwarf2/enum-type.exp
+++ b/gdb/testsuite/gdb.dwarf2/enum-type.exp
@@ -65,6 +65,41 @@ Dwarf::assemble $asm_file {
}
}
}
+
+ cu {} {
+ DW_TAG_compile_unit {
+ {DW_AT_language @DW_LANG_C_plus_plus}
+ {DW_AT_name tmp.c}
+ {DW_AT_comp_dir /tmp}
+ } {
+ declare_labels integer_label forward
+
+ integer_label: DW_TAG_base_type {
+ {DW_AT_byte_size 4 DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_signed}
+ {DW_AT_name int}
+ }
+
+ DW_TAG_enumeration_type {
+ {DW_AT_specification :$forward}
+ } {
+ DW_TAG_enumerator {
+ {DW_AT_name val1}
+ {DW_AT_const_value 1 DW_FORM_sdata}
+ }
+ }
+
+ DW_TAG_namespace {
+ {DW_AT_name ns}
+ } {
+ forward: DW_TAG_enumeration_type {
+ {DW_AT_name e}
+ {DW_AT_type :$integer_label}
+ {DW_AT_declaration 1 flag}
+ }
+ }
+ }
+ }
}
if { [prepare_for_testing "failed to prepare" ${testfile} \
@@ -79,3 +114,18 @@ gdb_test "ptype enum EU" "type = enum EU {TWO = 2}" \
gdb_test_no_output "set lang c++"
gdb_test "ptype enum EU" "type = enum EU : unsigned int {TWO = 2}" \
"ptype EU in C++"
+
+gdb_test "p ns::val1" \
+ " = ns::val1"
+
+require !readnow
+require {string equal [have_index $binfile] ""}
+
+set re_ws "\[ \t\]"
+
+gdb_test_lines "maint print objfiles" \
+ "val1 has a parent" \
+ [multi_line \
+ "" \
+ "$re_ws+qualified:$re_ws+ns::val1" \
+ ".*"]
diff --git a/gdb/testsuite/gdb.dwarf2/fission-reread.S b/gdb/testsuite/gdb.dwarf2/fission-reread.S
index 1763fab..279f6f3 100644
--- a/gdb/testsuite/gdb.dwarf2/fission-reread.S
+++ b/gdb/testsuite/gdb.dwarf2/fission-reread.S
@@ -97,7 +97,7 @@ SYMBOL(main):
.byte 0x87
.4byte .Lskeleton_debug_line0 /* DW_AT_stmt_list */
- /* Manually inserted to have a DW_AT_specification refering to
+ /* Manually inserted to have a DW_AT_specification referring to
something and appearing ahead of it. */
.uleb128 0x8 /* DW_TAG_class_type */
.4byte .Ltu_class_type - .Ltu_start_dwo
diff --git a/gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp b/gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp
index d8367b0..b734c30 100644
--- a/gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp
+++ b/gdb/testsuite/gdb.dwarf2/forward-spec-inter-cu.exp
@@ -98,6 +98,7 @@ foreach_with_prefix worker_threads $worker_threads_list {
gdb_load $binfile
- gdb_test "maint print objfiles" "$eol$ws+qualified:$ws+ns::v$eol.*" \
+ 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/forward-spec.exp b/gdb/testsuite/gdb.dwarf2/forward-spec.exp
index b045c02..5d41f87 100644
--- a/gdb/testsuite/gdb.dwarf2/forward-spec.exp
+++ b/gdb/testsuite/gdb.dwarf2/forward-spec.exp
@@ -16,6 +16,8 @@
# Check that the DWARF reader works with a a DW_AT_specification that
# refers to a later DIE.
+require !readnow
+
load_lib dwarf.exp
# This test can only be run on targets which support DWARF-2 and use gas.
@@ -72,31 +74,13 @@ if {[prepare_for_testing "failed to prepare" ${testfile} \
return -1
}
-set in_v 0
-gdb_test_multiple "maint print objfiles" "v has a parent" {
- -re "^ *\\\[\[0-9\]\\\] *\\(\\(cooked_index_entry\[^\r\n\]*" {
- set in_v 0
- exp_continue
- }
- -re "^ *name: *v\[\r\n\]*" {
- set in_v 1
- exp_continue
- }
- -re "^ *parent: *\\(\\(cooked_index_entry \\*\\) (0|$hex)\\)" {
- if {$in_v} {
- if {$expect_out(1,string) == "0"} {
- fail $gdb_test_name
- } else {
- pass $gdb_test_name
- }
- set in_v 0
- }
- exp_continue
- }
- -re "^\[^\r\n\]*\[\r\n\]+" {
- exp_continue
- }
- -re "$gdb_prompt " {
- # Done.
- }
-}
+require {string equal [have_index $binfile] ""}
+
+set re_ws "\[ \t\]"
+
+gdb_test_lines "maint print objfiles" \
+ "v has a parent" \
+ [multi_line \
+ "" \
+ "$re_ws+qualified:$re_ws+ns::v" \
+ ".*"]
diff --git a/gdb/testsuite/gdb.dwarf2/gdb-index.exp b/gdb/testsuite/gdb.dwarf2/gdb-index.exp
index 4e44227..23d60da 100644
--- a/gdb/testsuite/gdb.dwarf2/gdb-index.exp
+++ b/gdb/testsuite/gdb.dwarf2/gdb-index.exp
@@ -95,7 +95,13 @@ proc local_add_gdb_index { program } {
# building an index from a program already using one.
set test "check if index present"
-gdb_test_multiple "mt print objfiles ${testfile}" $test {
+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]
+gdb_test_multiple $cmd $test {
+ -re ^$cmd_re {
+ exp_continue
+ }
-re "gdb_index.*${gdb_prompt} $" {
set binfile_with_index $binfile
set host_binfile_with_index [gdb_remote_download host $binfile]
diff --git a/gdb/testsuite/gdb.dwarf2/implptrconst.exp b/gdb/testsuite/gdb.dwarf2/implptrconst.exp
index 8e6dbf0..541331c 100644
--- a/gdb/testsuite/gdb.dwarf2/implptrconst.exp
+++ b/gdb/testsuite/gdb.dwarf2/implptrconst.exp
@@ -83,18 +83,11 @@ Dwarf::assemble $asm_file {
}
}
-if { [build_executable ${testfile}.exp ${testfile} \
+if { [prepare_for_testing "failed to prepare" ${testfile} \
[list $srcfile $asm_file] {nodebug}] } {
return -1
}
-# We need --readnow because otherwise we never read in the CU we
-# created above.
-save_vars { GDBFLAGS } {
- set GDBFLAGS "$GDBFLAGS -readnow"
- clean_restart ${testfile}
-}
-
if ![runto_main] {
return -1
}
diff --git a/gdb/testsuite/gdb.dwarf2/implptrpiece.exp b/gdb/testsuite/gdb.dwarf2/implptrpiece.exp
index 585cd74..867789f 100644
--- a/gdb/testsuite/gdb.dwarf2/implptrpiece.exp
+++ b/gdb/testsuite/gdb.dwarf2/implptrpiece.exp
@@ -101,18 +101,11 @@ Dwarf::assemble $asm_file {
}
}
-if { [build_executable ${testfile}.exp ${testfile} \
+if { [prepare_for_testing "failed to prepare" ${testfile} \
[list $srcfile $asm_file] {nodebug}] } {
return -1
}
-# We need --readnow because otherwise we never read in the CU we
-# created above.
-save_vars { GDBFLAGS } {
- set GDBFLAGS "$GDBFLAGS -readnow"
- clean_restart ${testfile}
-}
-
if ![runto_main] {
return -1
}
diff --git a/gdb/testsuite/gdb.dwarf2/macro-complaints.exp b/gdb/testsuite/gdb.dwarf2/macro-complaints.exp
new file mode 100644
index 0000000..01060b8
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/macro-complaints.exp
@@ -0,0 +1,198 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test complaints about .debug_macro section.
+
+load_lib dwarf.exp
+
+require dwarf2_support
+require !readnow
+
+standard_testfile main.c .S
+
+lassign [function_range main $srcdir/$subdir/$srcfile] \
+ main_start main_len
+
+set asm_file [standard_output_file $srcfile2]
+
+set line [gdb_get_line_number "return 0;"]
+
+Dwarf::assemble $asm_file {
+ declare_labels L cu_macro1
+
+ cu {} {
+ DW_TAG_compile_unit {
+ {DW_AT_name $::srcfile}
+ {DW_AT_macros $cu_macro1 DW_FORM_sec_offset}
+ {DW_AT_stmt_list $L DW_FORM_sec_offset}
+ } {
+ declare_labels int_type
+
+ int_type: DW_TAG_base_type {
+ {DW_AT_byte_size 4 DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_signed}
+ {DW_AT_name int}
+ }
+ DW_TAG_subprogram {
+ {MACRO_AT_func {main}}
+ {type :$int_type}
+ }
+ }
+ }
+
+ lines {version 2} L {
+ file_name $::srcfile 1
+ program {
+ DW_LNE_set_address $::main_start
+ line $::line
+ DW_LNS_copy
+ DW_LNE_set_address "$::main_start + $::main_len"
+ DW_LNE_end_sequence
+ }
+ }
+
+ # Define the .debug_macro section.
+ macro {
+ cu_macro1: unit {
+ "debug-line-offset-label" $L
+ } {
+ define 0 "M1_01_BUILTIN_OK 1"
+ define 1 "M1_02_BUILTIN_BADLINE 1"
+
+ start_file 0 1
+
+ define 1 "M1_03_OK 1"
+ define 0 "M1_04_BADLINE 1"
+
+ start_file 1 1234
+ define 1 "M1_05_BADFILE 1"
+ end_file
+
+ define 1 "M1_06_OK "
+ define 1 "M1_07_MALFORMED"
+ define 1 "M1_08_OK() 1"
+ define 1 "M1_09_OK(ARG) (ARG)"
+ define 1 "M1_10_OK(ARG1,ARG2) (ARG1+ARG2)"
+
+ define 1 "M1_11_MALFORMED(ARG"
+ define 1 "M1_12_MALFORMED(ARG,"
+ define 1 "M1_13_MALFORMED(ARG,)"
+ define 1 "M1_14_MALFORMED()1"
+
+ end_file
+ }
+ }
+}
+
+if { [build_executable "failed to prepare" $testfile \
+ [list $srcfile $asm_file] {nodebug}] } {
+ return
+}
+
+clean_restart
+
+set re_complaint1 \
+ "debug info gives command-line macro definition with non-zero line 1: M1_02_BUILTIN_BADLINE 1"
+
+set re_complaint2 \
+ "debug info gives in-file macro definition with zero line 0: M1_04_BADLINE 1"
+
+set re_complaint3 \
+ [string_to_regexp "bad file number in macro information (1234)"]
+
+set re_complaint4 \
+ [multi_line \
+ "macro debug info contains a malformed macro definition:" \
+ "`M1_07_MALFORMED'"]
+
+set re_complaint5 \
+ [multi_line \
+ "macro debug info contains a malformed macro definition:" \
+ [string_to_regexp "`M1_11_MALFORMED(ARG'"]]
+
+set re_complaint6 \
+ [multi_line \
+ "macro debug info contains a malformed macro definition:" \
+ [string_to_regexp "`M1_12_MALFORMED(ARG,'"]]
+
+set re_complaint7 \
+ [multi_line \
+ "macro debug info contains a malformed macro definition:" \
+ [string_to_regexp "`M1_13_MALFORMED(ARG,)'"]]
+
+set re_complaint8 \
+ [multi_line \
+ "macro debug info contains a malformed macro definition:" \
+ [string_to_regexp "`M1_14_MALFORMED()1'"]]
+
+set prefix \
+ "During symbol reading"
+
+set re \
+ [multi_line \
+ "$prefix: $re_complaint1" \
+ "$prefix: $re_complaint2" \
+ "$prefix: $re_complaint3" \
+ "$prefix: $re_complaint4" \
+ "$prefix: $re_complaint5" \
+ "$prefix: $re_complaint6" \
+ "$prefix: $re_complaint7" \
+ "$prefix: $re_complaint8" \
+ [string cat [string_to_regexp {$}] "$decimal = \[^\r\n\]+"]]
+
+with_complaints 10 {
+ gdb_load $binfile
+ gdb_test "p main" ^$re "complaints"
+}
+
+set re_explicit \
+ [multi_line \
+ "Defined at $srcfile:0" \
+ "-DM1_01_BUILTIN_OK=1" \
+ "Defined at $srcfile:1" \
+ "#define M1_02_BUILTIN_BADLINE 1" \
+ "Defined at $srcfile:1" \
+ "#define M1_03_OK 1" \
+ "Defined at $srcfile:0" \
+ "-DM1_04_BADLINE=1" \
+ "Defined at <bad macro file number 1234>:1" \
+ " included at $srcfile:1" \
+ "#define M1_05_BADFILE 1" \
+ "Defined at $srcfile:1" \
+ "#define M1_06_OK " \
+ "Defined at $srcfile:1" \
+ "#define M1_07_MALFORMED " \
+ "Defined at $srcfile:1" \
+ [string_to_regexp "#define M1_08_OK() 1"] \
+ "Defined at $srcfile:1" \
+ [string_to_regexp "#define M1_09_OK(ARG) (ARG)"] \
+ "Defined at $srcfile:1" \
+ [string_to_regexp "#define M1_10_OK(ARG1, ARG2) (ARG1+ARG2)"] \
+ "Defined at $srcfile:1" \
+ [string_to_regexp "#define M1_13_MALFORMED(ARG) "]]
+
+set re_implicit \
+ [multi_line \
+ "Defined at $srcfile:-1" \
+ "#define __FILE__ \"$srcfile\"" \
+ "Defined at $srcfile:-1" \
+ "#define __LINE__ $line"]
+
+gdb_test "info macros $line" \
+ [multi_line \
+ $re_explicit \
+ $re_implicit]
diff --git a/gdb/testsuite/gdb.dwarf2/member-ptr-forwardref.exp b/gdb/testsuite/gdb.dwarf2/member-ptr-forwardref.exp
index c97c887..21ad111 100644
--- a/gdb/testsuite/gdb.dwarf2/member-ptr-forwardref.exp
+++ b/gdb/testsuite/gdb.dwarf2/member-ptr-forwardref.exp
@@ -34,5 +34,19 @@ gdb_test "show cp-abi" {The currently selected C\+\+ ABI is "gnu-v3".*}
gdb_load ${binfile}
+set re_address_class "@\[^\r\n\]+"
+
+set re_C_ptr \
+ [string cat \
+ [string_to_regexp "C *"] "( const)?( $re_address_class)?"]
+
gdb_test_no_output "set language c++"
-gdb_test "ptype c" "type = struct C {\[\r\n \t\]*private:\[\r\n \t\]*int \\(C::\\*fp\\)\\(C \\*( const)?\\);\[\r\n \t\]*}"
+gdb_test "ptype c" \
+ [multi_line \
+ "type = struct C {" \
+ " private:" \
+ [string cat \
+ [string_to_regexp " int (C::*fp)("] \
+ $re_C_ptr \
+ [string_to_regexp ");"]] \
+ "}"]
diff --git a/gdb/testsuite/gdb.dwarf2/multidictionary.exp b/gdb/testsuite/gdb.dwarf2/multidictionary.exp
index 36c0bb4..4c7dc0e 100644
--- a/gdb/testsuite/gdb.dwarf2/multidictionary.exp
+++ b/gdb/testsuite/gdb.dwarf2/multidictionary.exp
@@ -23,7 +23,7 @@ require dwarf2_support
standard_testfile main.c .S
# Create the DWARF. This is derived from the reproducer in the bug
-# mentioned above. This DIE tree is typical of compilations wtih
+# mentioned above. This DIE tree is typical of compilations with
# LTO enabled.
set asm_file [standard_output_file $srcfile2]
diff --git a/gdb/testsuite/gdb.dwarf2/per-bfd-sharing.exp b/gdb/testsuite/gdb.dwarf2/per-bfd-sharing.exp
index ef1ed19..7df68a9 100644
--- a/gdb/testsuite/gdb.dwarf2/per-bfd-sharing.exp
+++ b/gdb/testsuite/gdb.dwarf2/per-bfd-sharing.exp
@@ -19,7 +19,7 @@
standard_testfile
if { [build_executable "failed to prepare" $testfile $srcfile \
- {debug ldflags=-Wl,--build-id}] == -1 } {
+ {debug build-id}] == -1 } {
return
}
set host_binfile [gdb_remote_download host $binfile]
diff --git a/gdb/testsuite/gdb.dwarf2/pr13961.S b/gdb/testsuite/gdb.dwarf2/pr13961.S
index 856d211..2423ee9 100644
--- a/gdb/testsuite/gdb.dwarf2/pr13961.S
+++ b/gdb/testsuite/gdb.dwarf2/pr13961.S
@@ -101,7 +101,7 @@ SYMBOL(main):
.byte 0x87
.4byte .Ldebug_line0 /* DW_AT_stmt_list */
- /* Manually inserted to have a DW_AT_specification refering to
+ /* Manually inserted to have a DW_AT_specification referring to
something and appearing ahead of it. */
.uleb128 0x8 /* DW_TAG_class_type */
.4byte .Ltu_class_type - .Ldebug_types0
@@ -185,7 +185,7 @@ SYMBOL(main):
.byte 0x3 /* DW_OP_addr */
.4byte baz
- /* Manually inserted to have a DW_AT_specification refering to
+ /* Manually inserted to have a DW_AT_specification referring to
something and appearing ahead of it. */
.uleb128 0x8 /* DW_TAG_class_type */
.4byte .Lcu_class_type - .Ldebug_info0 /* DW_AT_specification */
diff --git a/gdb/testsuite/gdb.dwarf2/pr13961.exp b/gdb/testsuite/gdb.dwarf2/pr13961.exp
index a306c45..e4ea9d0 100644
--- a/gdb/testsuite/gdb.dwarf2/pr13961.exp
+++ b/gdb/testsuite/gdb.dwarf2/pr13961.exp
@@ -36,7 +36,8 @@ gdb_test "break -q main" "Breakpoint.*at.*"
pass $testfile
# Regression test for PR symtab/30739.
-gdb_test_multiple "maint print objfiles $binfile" "no foo::foo" {
+set cmd "pipe maint print objfiles $binfile | grep foo::foo"
+gdb_test_multiple $cmd "no foo::foo" {
-re -wrap "\r\n *qualified: *foo::foo\r\n.*" {
fail $gdb_test_name
}
diff --git a/gdb/testsuite/gdb.dwarf2/self-spec.exp b/gdb/testsuite/gdb.dwarf2/self-spec.exp
index 2e8fe6b..9bb4064 100644
--- a/gdb/testsuite/gdb.dwarf2/self-spec.exp
+++ b/gdb/testsuite/gdb.dwarf2/self-spec.exp
@@ -59,8 +59,8 @@ require {string eq $index ""}
require !readnow
-gdb_test "maint print objfiles $testfile" \
- "\r\n *qualified: *c1\r\n.*" \
+gdb_test "pipe maint print objfiles $testfile | grep c1" \
+ " *qualified: *c1" \
"class c1 in cooked index"
gdb_test "maint expand-symtabs"
diff --git a/gdb/testsuite/gdb.dwarf2/struct-with-sig-2.exp b/gdb/testsuite/gdb.dwarf2/struct-with-sig-2.exp
index 111de43..00af725 100644
--- a/gdb/testsuite/gdb.dwarf2/struct-with-sig-2.exp
+++ b/gdb/testsuite/gdb.dwarf2/struct-with-sig-2.exp
@@ -128,5 +128,5 @@ save_vars { GDBFLAGS } {
}
}
-set re "Dwarf Error: .debug_types section not supported in dwz file"
+set re "DWARF Error: .debug_types section not supported in dwz file"
gdb_assert { [regexp $re $gdb_file_cmd_msg] } "Dwarf Error message"
diff --git a/gdb/testsuite/gdb.fortran/entry-point.exp b/gdb/testsuite/gdb.fortran/entry-point.exp
index 4e4706d..51550ad 100644
--- a/gdb/testsuite/gdb.fortran/entry-point.exp
+++ b/gdb/testsuite/gdb.fortran/entry-point.exp
@@ -72,12 +72,12 @@ set entry_point_name "mod::mod_foo"
# GCC moves subroutines with entry points out of the module scope into the
# compile unit scope.
-if {[test_compiler_info {gcc-*}]} {
+if {[test_compiler_info {gcc-*}] || [test_compiler_info {clang-*}]} {
setup_xfail "gcc/105272" "*-*-*"
}
gdb_breakpoint $entry_point_name
-if {[test_compiler_info {gcc-*}]} {
+if {[test_compiler_info {gcc-*}] || [test_compiler_info {clang-*}]} {
setup_xfail "gcc/105272" "*-*-*"
}
gdb_continue_to_breakpoint "continue to breakpoint: $entry_point_name" \
diff --git a/gdb/testsuite/gdb.fortran/info-types.exp b/gdb/testsuite/gdb.fortran/info-types.exp
index 52ce7ac..ad2c988 100644
--- a/gdb/testsuite/gdb.fortran/info-types.exp
+++ b/gdb/testsuite/gdb.fortran/info-types.exp
@@ -27,10 +27,8 @@ if { [prepare_for_testing "failed to prepare" $testfile \
return -1
}
-if { ![fortran_runto_main] } {
- perror "Could not run to main."
- return
-}
+# Don't run to main to avoid increasing the search scope to include
+# debug info of shared libraries like libc, libgcc, libgfortran etc.
set integer4 [fortran_int4]
set integer8 [fortran_int8]
diff --git a/gdb/testsuite/gdb.fortran/intrinsics.exp b/gdb/testsuite/gdb.fortran/intrinsics.exp
index 60c79f9..060bb53 100644
--- a/gdb/testsuite/gdb.fortran/intrinsics.exp
+++ b/gdb/testsuite/gdb.fortran/intrinsics.exp
@@ -112,10 +112,14 @@ gdb_test "ptype cmplx (4,4)" "= complex\\*4"
gdb_test "p cmplx (-14,-4)" "= \\(-14,-4\\)"
gdb_test "p cmplx (4,4,4)" "\\(4,4\\)"
gdb_test "p cmplx (4,4,8)" "\\(4,4\\)"
-gdb_test "p cmplx (4,4,16)" "\\(4,4\\)"
+set re_unsupported_kind_16 \
+ [string_to_regexp "unsupported kind 16 for type complex*4"]
+gdb_test "p cmplx (4,4,16)" \
+ ([string_to_regexp " = (4,4)"]|$re_unsupported_kind_16)
gdb_test "ptype cmplx (4,4,4)" "= complex\\*4"
gdb_test "ptype cmplx (4,4,8)" "= complex\\*8"
-gdb_test "ptype cmplx (4,4,16)" "= complex\\*16"
+gdb_test "ptype cmplx (4,4,16)" \
+ ([string_to_regexp " = complex*16"]|$re_unsupported_kind_16)
gdb_test "p cmplx (4,4,1)" "unsupported kind 1 for type complex\\*4"
gdb_test "p cmplx (4,4,-1)" "unsupported kind -1 for type complex\\*4"
diff --git a/gdb/testsuite/gdb.fortran/multi-dim.exp b/gdb/testsuite/gdb.fortran/multi-dim.exp
index 3325e52..eda2d6a 100644
--- a/gdb/testsuite/gdb.fortran/multi-dim.exp
+++ b/gdb/testsuite/gdb.fortran/multi-dim.exp
@@ -41,19 +41,19 @@ gdb_test "print foo(2,3,4)" \
gdb_test "print foo(0,0,0)" \
"no such vector element" \
- "print an invalid array index (0,0,0)"
+ "print an invalid array index @ 0,0,0"
gdb_test "print foo(2,3,5)" \
"no such vector element" \
- "print an invalid array index (2,3,5)"
+ "print an invalid array index @ 2,3,5"
gdb_test "print foo(2,4,4)" \
"no such vector element" \
- "print an invalid array index (2,4,4)"
+ "print an invalid array index @ 2,4,4"
gdb_test "print foo(3,3,4)" \
"no such vector element" \
- "print an invalid array index (3,3,4)"
+ "print an invalid array index @ 3,3,4"
gdb_test "print foo" \
{ = \(\(\(10, 10\) \(10, 10\) \(10, 10\)\) \(\(10, 10\) \(10, 10\) \(10, 10\)\) \(\(10, 10\) \(10, 10\) \(10, 10\)\) \(\(10, 10\) \(10, 10\) \(10, 20\)\)\)} \
diff --git a/gdb/testsuite/gdb.fortran/size.exp b/gdb/testsuite/gdb.fortran/size.exp
index 93fb444..925aeed 100644
--- a/gdb/testsuite/gdb.fortran/size.exp
+++ b/gdb/testsuite/gdb.fortran/size.exp
@@ -95,7 +95,7 @@ gdb_assert {$found_dealloc_breakpoint} "ran all compiled in tests"
foreach var {array_1d_p array_2d_p allocatable_array_1d \
allocatable_array_2d} {
- gdb_test_multiple "p size ($var, 3)" "p size ($var, 3)" {
+ gdb_test_multiple "p size ($var, 3)" "" {
-re -wrap "DIM argument to SIZE must be between 1 and \[1-2\]" {
pass $gdb_test_name
}
@@ -129,7 +129,7 @@ gdb_continue_to_breakpoint "Final Breakpoint"
foreach var {array_1d_p array_2d_p allocatable_array_1d \
allocatable_array_2d} {
- gdb_test_multiple "p size ($var)" "p size ($var)" {
+ gdb_test_multiple "p size ($var)" "" {
-re -wrap "SIZE can only be used on allocated/associated arrays" {
pass $gdb_test_name
}
diff --git a/gdb/testsuite/gdb.fortran/type-kinds.exp b/gdb/testsuite/gdb.fortran/type-kinds.exp
index ab5f19f..a6f2aa4 100644
--- a/gdb/testsuite/gdb.fortran/type-kinds.exp
+++ b/gdb/testsuite/gdb.fortran/type-kinds.exp
@@ -43,12 +43,20 @@ proc test_basic_parsing_of_type_kinds {} {
test_cast_1_to_type_kind "complex" "" "\\(1,0\\)" "8"
test_cast_1_to_type_kind "complex" "4" "\\(1,0\\)" "8"
test_cast_1_to_type_kind "complex" "8" "\\(1,0\\)" "16"
- test_cast_1_to_type_kind "complex" "16" "\\(1,0\\)" "32"
+ set re_unsupported_kind \
+ [string_to_regexp "unsupported kind 16 for type complex*4"]
+ test_cast_1_to_type_kind "complex" "16" \
+ [string_to_regexp (1,0)]|$re_unsupported_kind \
+ 32|$re_unsupported_kind
test_cast_1_to_type_kind "real" "" "1" "4"
test_cast_1_to_type_kind "real" "4" "1" "4"
test_cast_1_to_type_kind "real" "8" "1" "8"
- test_cast_1_to_type_kind "real" "16" "1" "16"
+ set re_unsupported_kind \
+ [string_to_regexp "unsupported kind 16 for type real*4"]
+ test_cast_1_to_type_kind "real" "16" \
+ 1|$re_unsupported_kind \
+ 16|$re_unsupported_kind
test_cast_1_to_type_kind "logical" "" "\\.TRUE\\." "4"
test_cast_1_to_type_kind "logical" "1" "\\.TRUE\\." "1"
@@ -83,11 +91,17 @@ proc test_old_star_type_sizes {} {
gdb_test "p ((complex*4) 1)" " = \\(1,0\\)"
gdb_test "p ((complex*8) 1)" " = \\(1,0\\)"
- gdb_test "p ((complex*16) 1)" " = \\(1,0\\)"
+ set re_unsupported_kind \
+ [string_to_regexp "unsupported kind 16 for type complex*4"]
+ gdb_test "p ((complex*16) 1)" \
+ [string_to_regexp " = (1,0)"]|$re_unsupported_kind
gdb_test "p ((real*4) 1)" " = 1"
gdb_test "p ((real*8) 1)" " = 1"
- gdb_test "p ((real*16) 1)" " = 1"
+ set re_unsupported_kind \
+ [string_to_regexp "unsupported kind 16 for type real*4"]
+ gdb_test "p ((real*16) 1)" \
+ "( = 1|$re_unsupported_kind)"
gdb_test "p ((logical*1) 1)" " = \\.TRUE\\."
gdb_test "p ((logical*4) 1)" " = \\.TRUE\\."
diff --git a/gdb/testsuite/gdb.fortran/types.exp b/gdb/testsuite/gdb.fortran/types.exp
index 83b1098..494ed1e 100644
--- a/gdb/testsuite/gdb.fortran/types.exp
+++ b/gdb/testsuite/gdb.fortran/types.exp
@@ -60,7 +60,7 @@ proc test_float_literal_types_accepted {} {
# Test various floating point formats
# this used to guess whether to look for "real*4" or
- # "real*8" based on a target config variable, but noone
+ # "real*8" based on a target config variable, but no one
# maintained it properly.
gdb_test "pt .44" "type = real\\*\[0-9\]+"
@@ -94,7 +94,24 @@ proc test_primitive_types_known {} {
# While TYPE_KIND is allowed as input, GDB will always return the
# Fortran notation TYPE*KIND
regsub -all "_" $type "\*" type_res
- gdb_test "ptype $type" [string_to_regexp "type = $type_res"]
+ set re [string_to_regexp "type = $type_res"]
+ switch $type {
+ real*16 - complex*16 {
+ regexp {^[^*_]*} $type base
+ set re_unsupported \
+ [string_to_regexp \
+ "unsupported kind 16 for type $base*4"]
+ set re ($re|$re_unsupported)
+ }
+ real_16 - complex_16 {
+ set re_unsupported \
+ [string_to_regexp \
+ "unsupported type $type_res"]
+ set re ($re|$re_unsupported)
+ }
+ }
+
+ gdb_test "ptype $type" $re
}
}
diff --git a/gdb/testsuite/gdb.fortran/vla-alloc-assoc.exp b/gdb/testsuite/gdb.fortran/vla-alloc-assoc.exp
index 5e6c3f8..01717b0 100644
--- a/gdb/testsuite/gdb.fortran/vla-alloc-assoc.exp
+++ b/gdb/testsuite/gdb.fortran/vla-alloc-assoc.exp
@@ -32,32 +32,32 @@ if ![fortran_runto_main] {
gdb_breakpoint [gdb_get_line_number "vla1-allocated"]
gdb_continue_to_breakpoint "vla1-allocated"
gdb_test "print l" " = \\.TRUE\\." \
- "print vla1 allocation status (allocated)"
+ "print vla1 allocation status, allocated"
gdb_breakpoint [gdb_get_line_number "vla2-allocated"]
gdb_continue_to_breakpoint "vla2-allocated"
gdb_test "print l" " = \\.TRUE\\." \
- "print vla2 allocation status (allocated)"
+ "print vla2 allocation status, allocated"
gdb_breakpoint [gdb_get_line_number "pvla-associated"]
gdb_continue_to_breakpoint "pvla-associated"
gdb_test "print l" " = \\.TRUE\\." \
- "print pvla associated status (associated)"
+ "print pvla associated status, associated"
gdb_breakpoint [gdb_get_line_number "pvla-re-associated"]
gdb_continue_to_breakpoint "pvla-re-associated"
gdb_test "print l" " = \\.TRUE\\." \
- "print pvla associated status (re-associated)"
+ "print pvla associated status, re-associated"
gdb_breakpoint [gdb_get_line_number "pvla-deassociated"]
gdb_continue_to_breakpoint "pvla-deassociated"
gdb_test "print l" " = \\.FALSE\\." \
- "print pvla allocation status (deassociated)"
+ "print pvla allocation status, deassociated"
gdb_breakpoint [gdb_get_line_number "vla1-deallocated"]
gdb_continue_to_breakpoint "vla1-deallocated"
gdb_test "print l" " = \\.FALSE\\." \
- "print vla1 allocation status (deallocated)"
+ "print vla1 allocation status, deallocated"
gdb_test "print vla1" " = <not allocated>" \
"print deallocated vla1"
diff --git a/gdb/testsuite/gdb.fortran/vla-datatypes.exp b/gdb/testsuite/gdb.fortran/vla-datatypes.exp
index ed3b0f1..8227f23 100644
--- a/gdb/testsuite/gdb.fortran/vla-datatypes.exp
+++ b/gdb/testsuite/gdb.fortran/vla-datatypes.exp
@@ -74,12 +74,12 @@ gdb_test "print charactervla(5,5,5)" " = 'K'" \
gdb_breakpoint [gdb_get_line_number "vlas-modified"]
gdb_continue_to_breakpoint "vlas-modified"
-gdb_test "print intvla(5,5,5)" " = 42" "print intvla(5,5,5) (2nd)"
+gdb_test "print intvla(5,5,5)" " = 42" "print intvla(5,5,5), 2nd"
gdb_test "print realvla(5,5,5)" " = 4.13\\d+" \
- "print realvla(5,5,5) (2nd)"
+ "print realvla(5,5,5), 2nd"
gdb_test "print complexvla(5,5,5)" " = \\\(-3,2\\\)" \
- "print complexvla(5,5,5) (2nd)"
+ "print complexvla(5,5,5), 2nd"
gdb_test "print logicalvla(5,5,5)" " = \\.FALSE\\." \
- "print logicalvla(5,5,5) (2nd)"
+ "print logicalvla(5,5,5), 2nd"
gdb_test "print charactervla(5,5,5)" " = 'X'" \
- "print charactervla(5,5,5) (2nd)"
+ "print charactervla(5,5,5), 2nd"
diff --git a/gdb/testsuite/gdb.fortran/vla-ptype-sub.exp b/gdb/testsuite/gdb.fortran/vla-ptype-sub.exp
index cf3fcfe..78b711b 100644
--- a/gdb/testsuite/gdb.fortran/vla-ptype-sub.exp
+++ b/gdb/testsuite/gdb.fortran/vla-ptype-sub.exp
@@ -33,7 +33,7 @@ set real [fortran_real4]
# Pass fixed array to function and handle them as vla in function.
gdb_breakpoint [gdb_get_line_number "not-filled"]
-gdb_continue_to_breakpoint "not-filled (1st)"
+gdb_continue_to_breakpoint "not-filled, 1st"
gdb_test "ptype array1" "type = $int \\\(42,42\\\)" \
"ptype array1 (passed fixed)"
gdb_test "ptype array2" "type = $real \\\(42,42,42\\\)" \
@@ -44,15 +44,15 @@ gdb_test "ptype array2(13, 11, 5)" "type = $real" \
"ptype array2(13, 11, 5) (passed fixed)"
# Pass sub arrays to function and handle them as vla in function.
-gdb_continue_to_breakpoint "not-filled (2nd)"
+gdb_continue_to_breakpoint "not-filled, 2nd"
gdb_test "ptype array1" "type = $int \\\(6,6\\\)" \
- "ptype array1 (passed sub-array)"
+ "ptype array1, passed sub-array"
gdb_test "ptype array2" "type = $real \\\(6,6,6\\\)" \
- "ptype array2 (passed sub-array)"
+ "ptype array2, passed sub-array"
gdb_test "ptype array1(3, 3)" "type = $int" \
- "ptype array1(3, 3) (passed sub-array)"
+ "ptype array1(3, 3), passed sub-array"
gdb_test "ptype array2(4, 4, 4)" "type = $real" \
- "ptype array2(4, 4, 4) (passed sub-array)"
+ "ptype array2(4, 4, 4), passed sub-array"
# Check ptype outside of bounds. This should not crash GDB.
gdb_test "ptype array1(100, 100)" "no such vector element" \
@@ -61,15 +61,15 @@ gdb_test "ptype array2(100, 100, 100)" "no such vector element" \
"ptype array2(100, 100, 100) subarray do not crash (passed sub-array)"
# Pass vla to function.
-gdb_continue_to_breakpoint "not-filled (3rd)"
+gdb_continue_to_breakpoint "not-filled, 3rd"
gdb_test "ptype array1" "type = $int \\\(20,20\\\)" \
- "ptype array1 (passed vla)"
+ "ptype array1, passed vla"
gdb_test "ptype array2" "type = $real \\\(10,10,10\\\)" \
- "ptype array2 (passed vla)"
+ "ptype array2, passed vla"
gdb_test "ptype array1(3, 3)" "type = $int" \
- "ptype array1(3, 3) (passed vla)"
+ "ptype array1(3, 3), passed vla"
gdb_test "ptype array2(4, 4, 4)" "type = $real" \
- "ptype array2(4, 4, 4) (passed vla)"
+ "ptype array2(4, 4, 4), passed vla"
# Check ptype outside of bounds. This should not crash GDB.
gdb_test "ptype array1(100, 100)" "no such vector element" \
@@ -83,11 +83,11 @@ gdb_breakpoint [gdb_get_line_number "end-of-bar"]
gdb_continue_to_breakpoint "end-of-bar"
gdb_test "ptype array1" \
"type = (PTR TO -> \\( )?$int \\(\\*\\)\\)?" \
- "ptype array1 (arbitrary length)"
+ "ptype array1, arbitrary length"
gdb_test "ptype array2" \
"type = (PTR TO -> \\( )?$int \\(4:9,10:\\*\\)\\)?" \
- "ptype array2 (arbitrary length)"
+ "ptype array2, arbitrary length"
gdb_test "ptype array1(100)" "type = $int" \
- "ptype array1(100) (arbitrary length)"
+ "ptype array1(100), arbitrary length"
gdb_test "ptype array2(4,100)" "type = $int" \
- "ptype array2(4,100) (arbitrary length)"
+ "ptype array2(4,100), arbitrary length"
diff --git a/gdb/testsuite/gdb.fortran/vla-value-sub-arbitrary.exp b/gdb/testsuite/gdb.fortran/vla-value-sub-arbitrary.exp
index 1ec9576..64e86ac 100644
--- a/gdb/testsuite/gdb.fortran/vla-value-sub-arbitrary.exp
+++ b/gdb/testsuite/gdb.fortran/vla-value-sub-arbitrary.exp
@@ -27,11 +27,11 @@ if ![fortran_runto_main] {
return -1
}
-# Check VLA with arbitary length and check that elements outside of
+# Check VLA with arbitrary length and check that elements outside of
# bounds of the passed VLA can be accessed correctly.
gdb_breakpoint [gdb_get_line_number "end-of-bar"]
gdb_continue_to_breakpoint "end-of-bar"
-gdb_test "p array1(42)" " = 3" "print arbitary array1(42)"
-gdb_test "p array1(100)" " = 100" "print arbitary array1(100)"
-gdb_test "p array2(4,10)" " = 1" "print arbitary array2(4,10)"
-gdb_test "p array2(4,100)" " = 1" "print arbitary array2(4,100)"
+gdb_test "p array1(42)" " = 3" "print arbitrary array1(42)"
+gdb_test "p array1(100)" " = 100" "print arbitrary array1(100)"
+gdb_test "p array2(4,10)" " = 1" "print arbitrary array2(4,10)"
+gdb_test "p array2(4,100)" " = 1" "print arbitrary array2(4,100)"
diff --git a/gdb/testsuite/gdb.fortran/vla-value-sub.exp b/gdb/testsuite/gdb.fortran/vla-value-sub.exp
index cbeec34..23ee539 100644
--- a/gdb/testsuite/gdb.fortran/vla-value-sub.exp
+++ b/gdb/testsuite/gdb.fortran/vla-value-sub.exp
@@ -45,7 +45,7 @@ gdb_test "print array1(1, 1)" " = 30" \
"print array1(1, 1) after filled in foo (passed fixed array)"
gdb_breakpoint [gdb_get_line_number "array2-almost-filled"]
-gdb_continue_to_breakpoint "array2-almost-filled (1st)"
+gdb_continue_to_breakpoint "array2-almost-filled, 1st"
# array2 size is 296352 bytes.
gdb_test_no_output "set max-value-size 1024*1024"
gdb_test "print array2" " = \\( *\\( *\\( *30, *3, *3,\[()3, .\]*\\)" \
@@ -57,40 +57,40 @@ gdb_test "print array2" " = \\( *\\( *\\( *30, *20, *3,\[()3, .\]*\\)" \
# Try to access values from a fixed sub-array handled as VLA in subroutine.
-gdb_continue_to_breakpoint "not-filled (2nd)"
+gdb_continue_to_breakpoint "not-filled, 2nd"
gdb_test "print array1" " = \\(\[()5, .\]*\\)" \
- "print passed array1 in foo (passed sub-array)"
+ "print passed array1 in foo, passed sub-array"
-gdb_continue_to_breakpoint "array1-filled (2nd)"
+gdb_continue_to_breakpoint "array1-filled, 2nd"
gdb_test "print array1(5, 5)" " = 5" \
- "print array1(5, 5) after filled in foo (passed sub-array)"
+ "print array1(5, 5) after filled in foo, passed sub-array"
gdb_test "print array1(1, 1)" " = 30" \
- "print array1(1, 1) after filled in foo (passed sub-array)"
+ "print array1(1, 1) after filled in foo, passed sub-array"
-gdb_continue_to_breakpoint "array2-almost-filled (2nd)"
+gdb_continue_to_breakpoint "array2-almost-filled, 2nd"
gdb_test "print array2" " = \\( *\\( *\\( *30, *3, *3,\[()3, .\]*\\)" \
- "print array2 in foo after it was filled (passed sub-array)"
+ "print array2 in foo after it was filled, passed sub-array"
gdb_test "print array2(2,1,1)=20" " = 20" \
- "set array(2,2,2) to 20 in subroutine (passed sub-array)"
+ "set array(2,2,2) to 20 in subroutine, passed sub-array"
gdb_test "print array2" " = \\( *\\( *\\( *30, *20, *3,\[()3, .\]*\\)" \
- "print array2 in foo after it was mofified in debugger (passed sub-array)"
+ "print array2 in foo after it was mofified in debugger, passed sub-array"
# Try to access values from a VLA passed to subroutine.
-gdb_continue_to_breakpoint "not-filled (3rd)"
+gdb_continue_to_breakpoint "not-filled, 3rd"
gdb_test "print array1" " = \\(\[()42, .\]*\\)" \
- "print passed array1 in foo (passed vla)"
+ "print passed array1 in foo, passed vla"
-gdb_continue_to_breakpoint "array1-filled (3rd)"
+gdb_continue_to_breakpoint "array1-filled, 3rd"
gdb_test "print array1(5, 5)" " = 5" \
- "print array1(5, 5) after filled in foo (passed vla)"
+ "print array1(5, 5) after filled in foo, passed vla"
gdb_test "print array1(1, 1)" " = 30" \
- "print array1(1, 1) after filled in foo (passed vla)"
+ "print array1(1, 1) after filled in foo, passed vla"
-gdb_continue_to_breakpoint "array2-almost-filled (3rd)"
+gdb_continue_to_breakpoint "array2-almost-filled, 3rd"
gdb_test "print array2" " = \\( *\\( *\\( *30, *3, *3,\[()3, .\]*\\)" \
- "print array2 in foo after it was filled (passed vla)"
+ "print array2 in foo after it was filled, passed vla"
gdb_test "print array2(2,1,1)=20" " = 20" \
- "set array(2,2,2) to 20 in subroutine (passed vla)"
+ "set array(2,2,2) to 20 in subroutine, passed vla"
gdb_test "print array2" " = \\( *\\( *\\( *30, *20, *3,\[()3, .\]*\\)" \
- "print array2 in foo after it was mofified in debugger (passed vla)"
+ "print array2 in foo after it was mofified in debugger, passed vla"
diff --git a/gdb/testsuite/gdb.fortran/vla-value.exp b/gdb/testsuite/gdb.fortran/vla-value.exp
index 587a491..a3f50d1 100644
--- a/gdb/testsuite/gdb.fortran/vla-value.exp
+++ b/gdb/testsuite/gdb.fortran/vla-value.exp
@@ -39,10 +39,10 @@ gdb_test "print &vla1" \
" = \\\(PTR TO -> \\\( $real, allocatable \\\(:,:,:\\\) \\\)\\\) $hex" \
"print non-allocated &vla1"
gdb_test "print vla1(1,1,1)" "no such vector element \\\(vector not allocated\\\)" \
- "print member in non-allocated vla1 (1)"
+ "print member in non-allocated vla1, 1"
gdb_test "print vla1(101,202,303)" \
"no such vector element \\\(vector not allocated\\\)" \
- "print member in non-allocated vla1 (2)"
+ "print member in non-allocated vla1, 2"
gdb_test "print vla1(5,2,18)=1" "no such vector element \\\(vector not allocated\\\)" \
"set member in non-allocated vla1"
@@ -68,11 +68,11 @@ gdb_test "print vla1(9, 9, 9) = 999" " = 999" \
gdb_breakpoint [gdb_get_line_number "vla1-filled"]
gdb_continue_to_breakpoint "vla1-filled"
gdb_test "print vla1(3, 6, 9)" " = 42" \
- "print allocated vla1(3,6,9) after specific assignment (filled)"
+ "print allocated vla1(3,6,9) after specific assignment, filled"
gdb_test "print vla1(1, 3, 8)" " = 1001" \
- "print allocated vla1(1,3,8) after specific assignment (filled)"
+ "print allocated vla1(1,3,8) after specific assignment, filled"
gdb_test "print vla1(9, 9, 9)" " = 999" \
- "print allocated vla1(9,9,9) after assignment in debugger (filled)"
+ "print allocated vla1(9,9,9) after assignment in debugger, filled"
# Try to access values in undefined pointer to VLA (dangling)
gdb_test "print pvla" " = <not associated>" "print undefined pvla"
@@ -120,11 +120,11 @@ gdb_test "print pvla" " = <not associated>" \
gdb_breakpoint [gdb_get_line_number "vla1-deallocated"]
gdb_continue_to_breakpoint "vla1-deallocated"
gdb_test "print vla1(3, 6, 9)" "no such vector element \\\(vector not allocated\\\)" \
- "print allocated vla1(3,6,9) after specific assignment (deallocated)"
+ "print allocated vla1(3,6,9) after specific assignment, deallocated"
gdb_test "print vla1(1, 3, 8)" "no such vector element \\\(vector not allocated\\\)" \
- "print allocated vla1(1,3,8) after specific assignment (deallocated)"
+ "print allocated vla1(1,3,8) after specific assignment, deallocated"
gdb_test "print vla1(9, 9, 9)" "no such vector element \\\(vector not allocated\\\)" \
- "print allocated vla1(9,9,9) after assignment in debugger (deallocated)"
+ "print allocated vla1(9,9,9) after assignment in debugger, deallocated"
# Try to assign VLA to user variable
@@ -147,7 +147,7 @@ gdb_test "print \$myvar" \
" = \\( *\\( *\\( *1311, *1311, *1311,\[()1311, .\]*\\)" \
"print \$myvar set to vla1"
-gdb_test "next" "\\d+.*vla1\\(1, 3, 8\\) = 1001" "next (2)"
+gdb_test "next" "\\d+.*vla1\\(1, 3, 8\\) = 1001" "next, 2"
gdb_test "print \$myvar(3,6,9)" " = 1311"
gdb_breakpoint [gdb_get_line_number "pvla-associated"]
diff --git a/gdb/testsuite/gdb.gdb/index-file.exp b/gdb/testsuite/gdb.gdb/index-file.exp
index 72088ca..c30f417 100644
--- a/gdb/testsuite/gdb.gdb/index-file.exp
+++ b/gdb/testsuite/gdb.gdb/index-file.exp
@@ -38,12 +38,28 @@ with_timeout_factor $timeout_factor {
# Record how many worker threads GDB is using.
set worker_threads [gdb_get_worker_threads]
+if { $worker_threads eq "UNKNOWN" } {
+ unresolved "unable to get worker thread count"
+ return -1
+}
+
# Generate an index file.
set dir1 [standard_output_file "index_1"]
remote_exec host "mkdir -p ${dir1}"
with_timeout_factor $timeout_factor {
- gdb_test_no_output "save gdb-index $dir1" \
- "create gdb-index file"
+ set ok 0
+ gdb_test_multiple "save gdb-index $dir1" "create gdb-index file" {
+ -re -wrap "Error while writing index for \[^\r\n\]*: No debugging symbols" {
+ unsupported $gdb_test_name
+ }
+ -re -wrap "^" {
+ pass $gdb_test_name
+ set ok 1
+ }
+ }
+ if { ! $ok } {
+ return -1
+ }
gdb_test_no_output "save gdb-index -dwarf-5 $dir1" \
"create dwarf-index files"
diff --git a/gdb/testsuite/gdb.gdb/python-helper.exp b/gdb/testsuite/gdb.gdb/python-helper.exp
index 8a8afb1..c17523a 100644
--- a/gdb/testsuite/gdb.gdb/python-helper.exp
+++ b/gdb/testsuite/gdb.gdb/python-helper.exp
@@ -111,6 +111,16 @@ proc test_python_helper {} {
}
}
+ # Add a second inferior, useful to the intrusive_list pretty-printer test
+ # below.
+ send_inferior "add-inferior\n"
+ gdb_test_multiple "" "add second inferior in inner GDB" {
+ -i "$inferior_spawn_id"
+ -re "Added inferior 2\r\n$gdb_prompt $" {
+ pass $gdb_test_name
+ }
+ }
+
# Send Ctrl-C to the inner GDB, this should kick us back to the
# prompt of the outer GDB.
send_inferior "\003"
@@ -253,6 +263,11 @@ proc test_python_helper {} {
# Test the htab_t pretty-printer.
gdb_test -prompt $outer_prompt_re "print all_bfds" "htab_t with ${::decimal} elements = \\{${::hex}.*\\}"
+ # 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,.*}"
+
return 0
}
diff --git a/gdb/testsuite/gdb.go/integers.exp b/gdb/testsuite/gdb.go/integers.exp
index fec8422..7837542 100644
--- a/gdb/testsuite/gdb.go/integers.exp
+++ b/gdb/testsuite/gdb.go/integers.exp
@@ -66,7 +66,7 @@ gdb_test "print i + k" " = 4"
gdb_test "print j + k" " = 5"
gdb_test "print i + j + k" " = 6"
-# Test substraction
+# Test subtraction
gdb_test "print j - i" " = 1"
gdb_test "print i - j" "= -1"
gdb_test "print k -i -j" " = 0"
diff --git a/gdb/testsuite/gdb.guile/scm-frame.exp b/gdb/testsuite/gdb.guile/scm-frame.exp
index 34c9f8c..bd54e63 100644
--- a/gdb/testsuite/gdb.guile/scm-frame.exp
+++ b/gdb/testsuite/gdb.guile/scm-frame.exp
@@ -91,9 +91,9 @@ gdb_test "guile (print (eq? bframe (newest-frame)))" \
#t "newest frame -vs- newest frame"
gdb_test "guile (print (eq? f0 f1))" \
- "#f" "test equality comparison (false)"
+ "#f" "test equality comparison, false"
gdb_test "guile (print (eq? f0 f0))" \
- "#t" "test equality comparison (true)"
+ "#t" "test equality comparison, true"
gdb_test "guile (print (frame-valid? f0))" \
"#t" "test frame-valid?"
gdb_test "guile (print (frame-name f0))" \
diff --git a/gdb/testsuite/gdb.guile/scm-parameter.exp b/gdb/testsuite/gdb.guile/scm-parameter.exp
index 20c601e..d10e9d2 100644
--- a/gdb/testsuite/gdb.guile/scm-parameter.exp
+++ b/gdb/testsuite/gdb.guile/scm-parameter.exp
@@ -62,11 +62,11 @@ gdb_test_multiline "Simple gdb boolean parameter" \
"end"
with_test_prefix "test-param" {
- gdb_test "guile (print (parameter-value test-param))" "= #t" "parameter value (true)"
+ gdb_test "guile (print (parameter-value test-param))" "= #t" "parameter value, true"
gdb_test "show print test-param" "The state of the Test Parameter is on." "show parameter on"
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 "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"
@@ -94,11 +94,11 @@ gdb_test_multiline "enum gdb parameter" \
"end"
with_test_prefix "test-enum-param" {
- gdb_test "guile (print (parameter-value test-enum-param))" "one" "enum parameter value (one)"
+ gdb_test "guile (print (parameter-value test-enum-param))" "one" "enum parameter value, one"
gdb_test "show print test-enum-param" "The state of the enum is one." "show initial value"
gdb_test_no_output "set print test-enum-param two"
gdb_test "show print test-enum-param" "The state of the enum is two." "show new value"
- gdb_test "guile (print (parameter-value test-enum-param))" "two" "enum parameter value (two)"
+ gdb_test "guile (print (parameter-value test-enum-param))" "two" "enum parameter value, two"
gdb_test "set print test-enum-param three" "Undefined item: \"three\".*" "set invalid enum parameter"
}
@@ -241,14 +241,14 @@ foreach_with_prefix kind {
with_test_prefix "test-$kind-param" {
gdb_test "guile (print (parameter-value test-$kind-param))" \
- 3 "$kind parameter value (3)"
+ 3 "$kind parameter value, 3"
gdb_test "show print test-$kind-param" \
"The state of $kind is 3." "show initial value"
gdb_test_no_output "set print test-$kind-param 2"
gdb_test "show print test-$kind-param" \
"The state of $kind is 2." "show new value"
gdb_test "guile (print (parameter-value test-$kind-param))" \
- 2 "$kind parameter value (2)"
+ 2 "$kind parameter value, 2"
scm_param_test_maybe_no_output \
"guile (set-parameter-value! test-$kind-param #:unlimited)" \
$param_set_unlimited
@@ -257,18 +257,18 @@ foreach_with_prefix kind {
"show unlimited value"
gdb_test_no_output "guile (set-parameter-value! test-$kind-param 1)"
gdb_test "guile (print (parameter-value test-$kind-param))" \
- 1 "$kind parameter value (1)"
+ 1 "$kind parameter value, 1"
gdb_test_no_output "guile (set-parameter-value! test-$kind-param 0)"
gdb_test "guile (print (parameter-value test-$kind-param))" \
- $param_get_zero "$kind parameter value (0)"
+ $param_get_zero "$kind parameter value, 0"
scm_param_test_maybe_no_output "set print test-$kind-param -1" \
$param_set_minus_one
gdb_test "guile (print (parameter-value test-$kind-param))" \
- $param_get_minus_one "$kind parameter value (-1)"
+ $param_get_minus_one "$kind parameter value, -1"
scm_param_test_maybe_no_output "set print test-$kind-param -2" \
$param_set_minus_two
gdb_test "guile (print (parameter-value test-$kind-param))" \
- $param_get_minus_two "$kind parameter value (-2)"
+ $param_get_minus_two "$kind parameter value, -2"
}
}
@@ -378,11 +378,11 @@ gdb_test_multiline "previously ambiguously named boolean parameter" \
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 "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_no_output "set print s on"
gdb_test "show print s" "Command is not documented is on." "show parameter on"
- gdb_test "guile (print (parameter-value prev-ambig))" "= #t" "parameter value (true)"
+ 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"
diff --git a/gdb/testsuite/gdb.guile/scm-symbol.exp b/gdb/testsuite/gdb.guile/scm-symbol.exp
index 0b85848..ad22a8b 100644
--- a/gdb/testsuite/gdb.guile/scm-symbol.exp
+++ b/gdb/testsuite/gdb.guile/scm-symbol.exp
@@ -37,9 +37,9 @@ gdb_install_guile_module
gdb_scm_test_silent_cmd "guile (define main-func (lookup-global-symbol \"main\"))" \
"lookup main"
gdb_test "guile (print (symbol-function? main-func))" \
- "= #t" "test (symbol-function? main)"
+ "= #t" "test, symbol-function? main"
gdb_test "guile (print (lookup-global-symbol \"junk\"))" \
- "= #f" "test (lookup-global-symbol junk)"
+ "= #f" "test, lookup-global-symbol junk"
gdb_test "guile (print (symbol-value main-func))" \
"= {int \\(int, char \[*\]\[*\]\\)} $hex \\<main\\>" "print value of main"
diff --git a/gdb/testsuite/gdb.guile/scm-type.exp b/gdb/testsuite/gdb.guile/scm-type.exp
index 71fbe5b..3a4f2d0 100644
--- a/gdb/testsuite/gdb.guile/scm-type.exp
+++ b/gdb/testsuite/gdb.guile/scm-type.exp
@@ -70,7 +70,7 @@ proc test_fields {lang} {
if {$lang == "c++"} {
# Test usage with a class.
- gdb_scm_test_silent_cmd "print c" "print value (c)"
+ gdb_scm_test_silent_cmd "print c" "print value, c"
gdb_scm_test_silent_cmd "guile (define c (history-ref 0))" \
"get value (c) from history"
gdb_scm_test_silent_cmd "guile (define fields (type-fields (value-type c)))" \
@@ -84,7 +84,7 @@ proc test_fields {lang} {
}
# Test normal fields usage in structs.
- gdb_scm_test_silent_cmd "print st" "print value (st)"
+ gdb_scm_test_silent_cmd "print st" "print value, st"
gdb_scm_test_silent_cmd "guile (define st (history-ref 0))" \
"get value (st) from history"
gdb_scm_test_silent_cmd "guile (define st-type (value-type st))" \
@@ -120,7 +120,7 @@ proc test_fields {lang} {
"check field iterator on bad type"
# Test type-array.
- gdb_scm_test_silent_cmd "print ar" "print value (ar)"
+ gdb_scm_test_silent_cmd "print ar" "print value, ar"
gdb_scm_test_silent_cmd "guile (define ar (history-ref 0))" \
"get value (ar) from history"
gdb_scm_test_silent_cmd "guile (define ar0 (value-subscript ar 0))" \
@@ -133,11 +133,11 @@ proc test_fields {lang} {
# Test type-vector.
# Note: vectors cast differently than arrays. Here ar[0] is replicated
# for the size of the vector.
- gdb_scm_test_silent_cmd "print vec_data_1" "print value (vec_data_1)"
+ gdb_scm_test_silent_cmd "print vec_data_1" "print value, vec_data_1"
gdb_scm_test_silent_cmd "guile (define vec_data_1 (history-ref 0))" \
"get value (vec_data_1) from history"
- gdb_scm_test_silent_cmd "print vec_data_2" "print value (vec_data_2)"
+ gdb_scm_test_silent_cmd "print vec_data_2" "print value, vec_data_2"
gdb_scm_test_silent_cmd "guile (define vec_data_2 (history-ref 0))" \
"get value (vec_data_2) from history"
@@ -192,7 +192,7 @@ proc test_equality {lang} {
proc test_enums {} {
with_test_prefix "test_enum" {
- gdb_scm_test_silent_cmd "print e" "print value (e)"
+ gdb_scm_test_silent_cmd "print e" "print value, e"
gdb_scm_test_silent_cmd "guile (define e (history-ref 0))" \
"get value (e) from history"
gdb_scm_test_silent_cmd "guile (define fields (type-fields (value-type e)))" \
@@ -208,9 +208,9 @@ proc test_enums {} {
gdb_test "guile (print (type-num-fields (value-type e)))" \
"= 3" "check the number of enum values"
gdb_test "guile (print (field-name (type-field (value-type e) \"v1\")))" \
- "= v1" "check enum field lookup by name (v1)"
+ "= v1" "check enum field lookup by name, v1"
gdb_test "guile (print (field-name (type-field (value-type e) \"v3\")))" \
- "= v3" "check enum field lookup by name (v3)"
+ "= v3" "check enum field lookup by name, v3"
gdb_test "guile (print (iterator-map field-enumval (make-field-iterator (value-type e))))" \
"\\(0 1 2\\)" "check enum fields iteration"
}
@@ -218,7 +218,7 @@ proc test_enums {} {
proc test_base_class {} {
with_test_prefix "test_base_class" {
- gdb_scm_test_silent_cmd "print d" "print value (d)"
+ gdb_scm_test_silent_cmd "print d" "print value, d"
gdb_scm_test_silent_cmd "guile (define d (history-ref 0))" \
"get value (d) from history"
gdb_scm_test_silent_cmd "guile (define fields (type-fields (value-type d)))" \
@@ -226,9 +226,9 @@ proc test_base_class {} {
gdb_test "guile (print (length fields))" \
"= 3" "check the number of fields"
gdb_test "guile (print (field-baseclass? (car fields)))" \
- "= #t" "check base class (fields\[0\])"
+ "= #t" {check base class, fields[0]}
gdb_test "guile (print (field-baseclass? (cadr fields)))" \
- "= #f" "check base class (fields\[1\])"
+ "= #f" {check base class, fields[1]}
}
}
@@ -236,7 +236,7 @@ proc test_range {} {
with_test_prefix "test_range" {
with_test_prefix "on ranged value" {
# Test a valid range request.
- gdb_scm_test_silent_cmd "print ar" "print value (ar)"
+ gdb_scm_test_silent_cmd "print ar" "print value, ar"
gdb_scm_test_silent_cmd "guile (define ar (history-ref 0))" \
"get value (ar) from history"
gdb_test "guile (print (length (type-range (value-type ar))))" \
@@ -247,7 +247,7 @@ proc test_range {} {
with_test_prefix "on unranged value" {
# Test where a range does not exist.
- gdb_scm_test_silent_cmd "print st" "print value (st)"
+ gdb_scm_test_silent_cmd "print st" "print value, st"
gdb_scm_test_silent_cmd "guile (define st (history-ref 0))" \
"get value (st) from history"
gdb_test "guile (print (type-range (value-type st)))" \
@@ -256,7 +256,7 @@ proc test_range {} {
}
with_test_prefix "on flexible array member" {
- gdb_scm_test_silent_cmd "print f" "print value (f)"
+ gdb_scm_test_silent_cmd "print f" "print value, f"
gdb_scm_test_silent_cmd "guile (define f (history-ref 0))" \
"get value (f) from history"
gdb_test "guile (print (type-range (field-type (type-field (value-type (value-dereference f)) \"items\"))))" \
diff --git a/gdb/testsuite/gdb.linespec/cp-replace-typedefs-ns-template.exp b/gdb/testsuite/gdb.linespec/cp-replace-typedefs-ns-template.exp
index 68cd11a..214242f 100644
--- a/gdb/testsuite/gdb.linespec/cp-replace-typedefs-ns-template.exp
+++ b/gdb/testsuite/gdb.linespec/cp-replace-typedefs-ns-template.exp
@@ -30,7 +30,7 @@ if {[prepare_for_testing "failed to prepare" $testfile $srcfile \
gdb_test_no_output "set max-completions unlimited"
# Confirm that the important global namespace typedefs were indeed
-# emited in the debug info.
+# emitted in the debug info.
gdb_test "ptype NS2" "type = int"
gdb_test "ptype object" "type = struct NS1::NS2::object {.*"
gdb_test "ptype Templ1" "type = struct NS1::NS2::Templ1<unsigned int> .*"
diff --git a/gdb/testsuite/gdb.linespec/cpcompletion.exp b/gdb/testsuite/gdb.linespec/cpcompletion.exp
index 480e034..09bd9a2 100644
--- a/gdb/testsuite/gdb.linespec/cpcompletion.exp
+++ b/gdb/testsuite/gdb.linespec/cpcompletion.exp
@@ -831,7 +831,7 @@ proc_with_prefix template-class-with-method {} {
}
}
-# Test completion of a const-overloaded funtion (const-overload).
+# Test completion of a const-overloaded function (const-overload).
# Note that "const" appears after the function/method parameters.
proc_with_prefix const-overload {} {
diff --git a/gdb/testsuite/gdb.linespec/cpexplicit.exp b/gdb/testsuite/gdb.linespec/cpexplicit.exp
index 5c93c34..62033d5 100644
--- a/gdb/testsuite/gdb.linespec/cpexplicit.exp
+++ b/gdb/testsuite/gdb.linespec/cpexplicit.exp
@@ -80,7 +80,7 @@ namespace eval $testfile {
add linespecs "-function myclass::myfunction -line 3" $location(normal)
add linespecs "-function myclass::myfunction -label top -line 3" \
$location(top)
- add linespecs "-line 3" $location(normal)
+ add linespecs "-line 25" $location(normal)
add linespecs "-function myclass::operator," $location(operator)
add linespecs "-function 'myclass::operator,'" $location(operator)
add linespecs "-function \"myclass::operator,\"" $location(operator)
diff --git a/gdb/testsuite/gdb.linespec/explicit.exp b/gdb/testsuite/gdb.linespec/explicit.exp
index 625f9ce..e8ae10a 100644
--- a/gdb/testsuite/gdb.linespec/explicit.exp
+++ b/gdb/testsuite/gdb.linespec/explicit.exp
@@ -86,7 +86,7 @@ namespace eval $testfile {
# These are also not yet supported; -line is silently ignored.
add linespecs "-function myfunction -line 3" $location(normal)
add linespecs "-function myfunction -label top -line 3" $location(top)
- add linespecs "-line 3" $location(normal)
+ add linespecs "-line 25" $location(normal)
# Fire up gdb.
if {![runto_main]} {
@@ -575,22 +575,30 @@ namespace eval $testfile {
allow-pending]} {
fail "set $tst"
} else {
- gdb_test "info break" ".*PENDING.*myfunction if foofoofoo == 1.*" $tst
+ gdb_test "info break" ".*PENDING.*myfunction\r\n\\s+stop only if foofoofoo == 1.*" $tst
}
gdb_exit
gdb_start
+ if {[target_info gdb_protocol] == "extended-remote"} {
+ set evals_re "(?: \\(\[^) \]+ evals\\))?"
+ } else {
+ set evals_re ""
+ }
+
set tst "pending valid conditional explicit breakpoint"
if {![gdb_breakpoint "-func myfunction if arg == 0" \
allow-pending]} {
fail "set $tst"
} else {
- gdb_test "info break" ".*PENDING.*myfunction if arg == 0" $tst
+ gdb_test "info break" \
+ ".*PENDING.*myfunction\r\n\\s+stop only if arg == 0${evals_re}" \
+ $tst
gdb_load [standard_output_file $exefile]
gdb_test "info break" \
- ".*in myfunction at .*$srcfile:.*stop only if arg == 0.*" \
+ ".*in myfunction at .*$srcfile:.*stop only if arg == 0${evals_re}" \
"$tst resolved"
}
diff --git a/gdb/testsuite/gdb.linespec/keywords.exp b/gdb/testsuite/gdb.linespec/keywords.exp
index 36a919c..d2596d2 100644
--- a/gdb/testsuite/gdb.linespec/keywords.exp
+++ b/gdb/testsuite/gdb.linespec/keywords.exp
@@ -55,7 +55,7 @@ with_test_prefix "trailing whitespace" {
gdb_test "break thread 123" "Unknown thread 123\\."
gdb_test "break thread foo" "Invalid thread ID: foo"
gdb_test "break task 123" "Unknown task 123\\."
-gdb_test "break task foo" "Junk after task keyword\\."
+gdb_test "break task foo" "Junk 'foo' after task keyword\\."
gdb_breakpoint "thread if 0" "message"
# These are also NULL locations, but using a subsequent keyword
@@ -63,9 +63,9 @@ gdb_breakpoint "thread if 0" "message"
gdb_test "break thread thread" "Invalid thread ID: thread"
gdb_test "break thread task" "Invalid thread ID: task"
gdb_test "break thread if" "Invalid thread ID: if"
-gdb_test "break task task" "Junk after task keyword\\."
-gdb_test "break task thread" "Junk after task keyword\\."
-gdb_test "break task if" "Junk after task keyword\\."
+gdb_test "break task task" "Junk 'task' after task keyword\\."
+gdb_test "break task thread" "Junk 'thread' after task keyword\\."
+gdb_test "break task if" "Junk 'if' after task keyword\\."
# Test locations containing keyword followed by keyword.
gdb_test "break thread thread 123" "Unknown thread 123\\."
diff --git a/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.c b/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.c
new file mode 100644
index 0000000..93c4383
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.c
@@ -0,0 +1,51 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2022-2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* The section where THE_LIB_PATH is not defined is compiled as a shared
+ library. The rest is compiled as the main executable (which loads the
+ shared library. */
+
+#if !defined(THE_LIB_PATH)
+
+void
+the_lib_func (void)
+{
+ static int x;
+ /* break here */
+ x++;
+}
+
+#else
+#include <dlfcn.h>
+#include <assert.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+ void *lib = dlopen (THE_LIB_PATH, RTLD_NOW);
+ assert (lib != NULL);
+
+ void (*the_lib_func) (void) = dlsym (lib, "the_lib_func");
+ assert (the_lib_func != NULL);
+
+ the_lib_func ();
+
+ return 0;
+}
+
+#endif
diff --git a/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.exp b/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.exp
new file mode 100644
index 0000000..946304a
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.exp
@@ -0,0 +1,55 @@
+# Copyright 2022-2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test that placing a line breakpoint outside a function results in a pending
+# breakpoint. More importantly, that it does "drift" and place a
+# breakpoint on the next function.
+#
+# See the .c file for more details.
+
+standard_testfile
+
+set shlib_path [standard_output_file ${testfile}-lib.so]
+if {[build_executable "build shlib" $shlib_path $srcfile {debug shlib}]} {
+ return
+}
+
+set opts [list debug shlib_load additional_flags=-DTHE_LIB_PATH="${shlib_path}"]
+if {[build_executable "failed to prepare" ${testfile} ${srcfile} $opts]} {
+ return
+}
+
+proc do_test {} {
+ clean_restart $::binfile
+
+ # To make things easier, just so we don't have to deal with the question.
+ gdb_test_no_output "set breakpoint pending on"
+
+ set lineno [gdb_get_line_number "break here"]
+ gdb_test "break $lineno" \
+ [multi_line \
+ "No compiled code for line $lineno in the current file\\." \
+ "Breakpoint 1 \\($lineno\\) pending\\."] \
+ "breakpoint on a line outside any function"
+
+ gdb_run_cmd
+ gdb_test_multiple "" "stop on lib function breakpoint" {
+ -re -wrap "Breakpoint 1, the_lib_func .*29.*x\\+\\+.*" {
+ pass $gdb_test_name
+ }
+ }
+}
+
+do_test
diff --git a/gdb/testsuite/gdb.linespec/ls-errs.c b/gdb/testsuite/gdb.linespec/ls-errs.c
index 73b06fc..1dfccab 100644
--- a/gdb/testsuite/gdb.linespec/ls-errs.c
+++ b/gdb/testsuite/gdb.linespec/ls-errs.c
@@ -21,6 +21,16 @@ myfunction (int aa)
int i;
i = aa + 42;
+
+ /* These lines are intentionally left blank such that the tests trying
+ to place breakpoints at line -10 relative to the "set.breakpoint.here"
+ line below land on a valid breakpoint location, inside the function. */
+
+
+
+
+
+
return i; /* set breakpoint here */
}
diff --git a/gdb/testsuite/gdb.linespec/ls-errs.exp b/gdb/testsuite/gdb.linespec/ls-errs.exp
index 48c8a5f..58125f3 100644
--- a/gdb/testsuite/gdb.linespec/ls-errs.exp
+++ b/gdb/testsuite/gdb.linespec/ls-errs.exp
@@ -71,8 +71,8 @@ proc do_test {lang} {
"Undefined convenience variable or function \"%s\" not defined in \"%s\"."
invalid_label "No label \"%s\" defined in function \"%s\"."
invalid_parm "invalid linespec argument, \"%s\""
- invalid_offset "No line %d in the current file."
- invalid_offset_f "No line %d in file \"%s\"."
+ invalid_offset "No compiled code for line %d in the current file."
+ invalid_offset_f "No compiled code for line %d in file \"%s\"."
malformed_line_offset "malformed line offset: \"%s\""
source_incomplete \
"Source filename requires function, label, or line offset."
@@ -135,14 +135,14 @@ proc do_test {lang} {
foreach x {1 +1 +100 -10} {
test_break "3 $x" unexpected_opt "number" $x
- test_break "-line 3 $x" garbage $x
+ test_break "-line 34 $x" garbage $x
test_break "+10 $x" unexpected_opt "number" $x
test_break "-line +10 $x" garbage $x
test_break "-10 $x" unexpected_opt "number" $x
test_break "-line -10 $x" garbage $x
}
- foreach x {3 +10 -10} {
+ foreach x {34 +10 -10} {
test_break "$x foo" unexpected_opt "string" "foo"
test_break "-line $x foo" garbage "foo"
}
@@ -207,12 +207,12 @@ proc do_test {lang} {
test_break "${srcfile}::" invalid_function "${srcfile}::"
test_break "$srcfile:3 1" unexpected_opt "number" "1"
- test_break "-source $srcfile -line 3 1" garbage "1"
+ test_break "-source $srcfile -line 34 1" garbage "1"
test_break "$srcfile:3 +100" unexpected_opt "number" "+100"
- test_break "-source $srcfile -line 3 +100" garbage "+100"
+ test_break "-source $srcfile -line 34 +100" garbage "+100"
test_break "$srcfile:3 -100" unexpected_opt "number" "-100"
test_break "$srcfile:3 foo" unexpected_opt "string" "foo"
- test_break "-source $srcfile -line 3 foo" garbage "foo"
+ test_break "-source $srcfile -line 34 foo" garbage "foo"
foreach x $invalid_offsets {
test_break "$srcfile:$x" invalid_offset_f $x $srcfile
diff --git a/gdb/testsuite/gdb.mi/dw2-ref-missing-frame.exp b/gdb/testsuite/gdb.mi/dw2-ref-missing-frame.exp
index 73b25bd..b91f915 100644
--- a/gdb/testsuite/gdb.mi/dw2-ref-missing-frame.exp
+++ b/gdb/testsuite/gdb.mi/dw2-ref-missing-frame.exp
@@ -20,6 +20,16 @@ set MIFLAGS "-i=mi"
require dwarf2_support
+# Clang reorders global assembly labels, placing them all side by side.
+# This results in having low and high PCs what have the same value for
+# the CU and all the functions (in my system, they are all 0x1130). If
+# this test is rewritten to use the dwarf assembler instead, we can enable
+# this test with clang again.
+if {[test_compiler_info {clang-*-*}]} {
+ unsupported "can't generate debug info"
+ return
+}
+
standard_testfile .S dw2-ref-missing-frame-func.c dw2-ref-missing-frame-main.c
set objsfile [standard_output_file ${testfile}.o]
set objfuncfile [standard_output_file ${testfile}-func.o]
diff --git a/gdb/testsuite/gdb.mi/mi-break-qualified.exp b/gdb/testsuite/gdb.mi/mi-break-qualified.exp
index 7543d98..20e2bb8 100644
--- a/gdb/testsuite/gdb.mi/mi-break-qualified.exp
+++ b/gdb/testsuite/gdb.mi/mi-break-qualified.exp
@@ -69,7 +69,7 @@ proc test_break_qualified {} {
-enabled "y" \
-func "$func" \
-file ".*mi-break-qualified.cc" \
- -line="$line_no"]
+ -line $line_no]
}
set loc1 [make_loc_re "NS::func\\(int\\)" $loc_ns_func_line]
diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp
index bfe839d..86e7b57 100644
--- a/gdb/testsuite/gdb.mi/mi-break.exp
+++ b/gdb/testsuite/gdb.mi/mi-break.exp
@@ -313,7 +313,7 @@ proc_with_prefix test_explicit_breakpoints {} {
mi_create_breakpoint "-c \"intarg == 3\" --function callee2" \
"insert explicit conditional breakpoint in callee2" \
- -func callee2 ".*$srcfile" -line $line_callee2_body \
+ -func callee2 -file ".*$srcfile" -line $line_callee2_body \
-cond "intarg == 3"
# mi_create_breakpoint cannot deal with displaying canonical
@@ -357,7 +357,7 @@ proc_with_prefix test_forced_conditions {} {
"dprintf with forced condition"
# Define a plain breakpoint first, and a condition later.
- mi_create_breakpoint "callme" "define a bp" ""
+ mi_create_breakpoint "callme" "define a bp"
mi_gdb_test "-break-condition --force 16 bad == 42" \
"${warning}\\^done" \
"invalid condition is forced"
diff --git a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
index d7f8132..305c061 100644
--- a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
+++ b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
@@ -15,6 +15,8 @@
require allow_shlib_tests
+set supports_catch_syscall [supports_catch_syscall]
+
load_lib mi-support.exp
standard_testfile pending.c
@@ -85,17 +87,34 @@ proc test_insert_delete_modify { } {
mi_gdb_test ${test} \
{(&.*)*.*~".*atchpoint 3: .*\\n".*=breakpoint-created,bkpt=\{number="3",type="(hw |)watchpoint".*\}.*\n\^done} \
$test
+
set test "trace marker"
mi_gdb_test $test \
{(&.*)*.*~"Tracepoint 4 at .*\\n".*=breakpoint-created,bkpt=\{number="4",type="tracepoint".*\}.*\n\^done} \
$test
+
set test "catch syscall"
- mi_gdb_test $test \
- {(&.*)*.*~"Catchpoint 5 .*\\n".*=breakpoint-created,bkpt=\{number="5",type="catchpoint".*\}.*\n\^done} \
- $test
+ if { $::supports_catch_syscall } {
+ mi_gdb_test $test \
+ {(&.*)*.*~"Catchpoint 5 .*\\n".*=breakpoint-created,bkpt=\{number="5",type="catchpoint".*\}.*\n\^done} \
+ $test
+ set bp_nr 6
+ } else {
+ unsupported $test
+ set bp_nr 5
+ }
+
set test "dprintf marker, \"arg\" \""
+ set bp_re [mi_make_breakpoint \
+ -number $bp_nr \
+ -type dprintf \
+ -func marker \
+ -script [string_to_regexp {["printf \"arg\" \""]}]]
mi_gdb_test $test \
- {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\[\"printf \\\"arg\\\" \\\"\"\].*\}\r\n\^done} \
+ [multi_line \
+ ".*" \
+ "=breakpoint-created,${bp_re}" \
+ "\\^done"] \
$test
# 2. when modifying condition
@@ -143,7 +162,7 @@ proc test_insert_delete_modify { } {
# Delete some breakpoints and verify that '=breakpoint-deleted
# notification is correctly emitted.
- for {set i 3} {$i < 7} {incr i} {
+ for {set i 3} {$i <= $bp_nr} {incr i} {
mi_gdb_test "delete ${i}" ".*=breakpoint-deleted,id=\"${i}\".*\\^done" \
"delete ${i}"
}
@@ -153,7 +172,7 @@ with_test_prefix "test_insert_delete_modify" {
test_insert_delete_modify
}
-# Test 'breakpoint-modified' notification is emited when pending breakpoints are
+# Test 'breakpoint-modified' notification is emitted when pending breakpoints are
# resolved.
proc test_pending_resolved { } {
diff --git a/gdb/testsuite/gdb.mi/mi-catch-cpp-exceptions.cc b/gdb/testsuite/gdb.mi/mi-catch-cpp-exceptions.cc
index be1f50f..d41b55d 100644
--- a/gdb/testsuite/gdb.mi/mi-catch-cpp-exceptions.cc
+++ b/gdb/testsuite/gdb.mi/mi-catch-cpp-exceptions.cc
@@ -43,8 +43,7 @@ foo ()
try
{
bar ();
- }
- catch (const my_exception &ex) /* Catch 1. */
+ } catch (const my_exception &ex) /* Catch 1. */
{
if (i == 1)
throw; /* Throw 2. */
@@ -60,8 +59,7 @@ main ()
try
{
foo ();
- }
- catch (const my_exception &ex) /* Catch 2. */
+ } catch (const my_exception &ex) /* Catch 2. */
{
if (i == 1)
return 1; /* Stop here. */
diff --git a/gdb/testsuite/gdb.mi/mi-complete.exp b/gdb/testsuite/gdb.mi/mi-complete.exp
index 91564a4..7fccaa2 100644
--- a/gdb/testsuite/gdb.mi/mi-complete.exp
+++ b/gdb/testsuite/gdb.mi/mi-complete.exp
@@ -28,7 +28,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debu
mi_clean_restart $binfile
-mi_runto_main
+# Don't run to main to avoid increasing the search scope to include
+# debug info of shared libraries like glibc, libgcc, etc.
mi_gdb_test "1-complete br" \
"1\\^done,completion=\"break\",matches=\\\[.*\"break\",.*\"break-range\".*\\\],max_completions_reached=\"0\"" \
diff --git a/gdb/testsuite/gdb.mi/mi-dprintf-pending.exp b/gdb/testsuite/gdb.mi/mi-dprintf-pending.exp
index fd5684b..4cf6dec 100644
--- a/gdb/testsuite/gdb.mi/mi-dprintf-pending.exp
+++ b/gdb/testsuite/gdb.mi/mi-dprintf-pending.exp
@@ -50,7 +50,8 @@ set bp_location1 [gdb_get_line_number "set breakpoint 1 here"]
# Set pending dprintf via MI.
set bp [mi_make_breakpoint_pending -number "1" -type "dprintf" \
-disp "keep" -enabled "y" -pending "pendfunc1" \
- -original-location "pendfunc1"]
+ -original-location "pendfunc1" \
+ -script {\["printf \\\"hello\\\""\]}]
mi_gdb_test "-dprintf-insert -f pendfunc1 \"hello\"" \
".*\\^done,$bp" "mi set dprintf"
diff --git a/gdb/testsuite/gdb.mi/mi-file.exp b/gdb/testsuite/gdb.mi/mi-file.exp
index 8e404f9..00d2888 100644
--- a/gdb/testsuite/gdb.mi/mi-file.exp
+++ b/gdb/testsuite/gdb.mi/mi-file.exp
@@ -42,16 +42,10 @@ proc test_file_list_exec_source_file {} {
}
# get the path and absolute path to the current executable
- #
- # In gdb 6.2 (at least), the default line number is set by
- # select_source_symtab to the first line of "main" minus
- # the value of "lines_to_list" (which defaults to 10) plus one.
- # --chastain 2004-08-13
set line_main_head [gdb_get_line_number "main ("]
- set line_main_body [expr $line_main_head + 2]
- set gdb_lines_to_list 10
- set line_default [expr $line_main_body - $gdb_lines_to_list + 1]
+ set line_main_prologue [expr $line_main_head + 1]
+ set line_default $line_main_prologue
mi_gdb_test "111-file-list-exec-source-file" \
"111\\\^done,line=\"$line_default\",file=\"${srcfilepath}\",fullname=\"$fullname_syntax${srcfile}\",macro-info=\"0\"" \
diff --git a/gdb/testsuite/gdb.mi/mi-multi-commands.exp b/gdb/testsuite/gdb.mi/mi-multi-commands.exp
index 3a2e774..028e187 100644
--- a/gdb/testsuite/gdb.mi/mi-multi-commands.exp
+++ b/gdb/testsuite/gdb.mi/mi-multi-commands.exp
@@ -103,7 +103,7 @@ proc run_test { args } {
set seen_first_message true
exp_continue
}
- -re "\r\n$mi_gdb_prompt" {
+ -re "$mi_gdb_prompt" {
gdb_assert $seen_first_message $gdb_test_name
}
}
diff --git a/gdb/testsuite/gdb.mi/mi-nsmoribund.exp b/gdb/testsuite/gdb.mi/mi-nsmoribund.exp
index ba6ff5a..270dbc1 100644
--- a/gdb/testsuite/gdb.mi/mi-nsmoribund.exp
+++ b/gdb/testsuite/gdb.mi/mi-nsmoribund.exp
@@ -50,7 +50,7 @@ set bkpt_line [gdb_get_line_number "set breakpoint here"]
mi_create_breakpoint "$srcfile:$bkpt_line" \
"breakpoint at thread_function" \
- -number 2 -function thread_function
+ -number 2 -func thread_function
mi_send_resuming_command "exec-continue --all" "resume all"
for {set i 0} {$i < $nthreads} {incr i} {
diff --git a/gdb/testsuite/gdb.mi/mi-nsthrexec.exp b/gdb/testsuite/gdb.mi/mi-nsthrexec.exp
index fdfdd05..dba7847 100644
--- a/gdb/testsuite/gdb.mi/mi-nsthrexec.exp
+++ b/gdb/testsuite/gdb.mi/mi-nsthrexec.exp
@@ -47,7 +47,7 @@ if { [mi_runto_main] < 0 } {
mi_create_breakpoint thread_execler \
"breakpoint at thread_execler" \
- -number 2 -function thread_execler
+ -number 2 -func thread_execler
# All threads should stop, except the main thread.
mi_send_resuming_command "exec-continue --all" "resume all"
diff --git a/gdb/testsuite/gdb.mi/mi-pending.exp b/gdb/testsuite/gdb.mi/mi-pending.exp
index 99dbab4..4358c18 100644
--- a/gdb/testsuite/gdb.mi/mi-pending.exp
+++ b/gdb/testsuite/gdb.mi/mi-pending.exp
@@ -66,8 +66,8 @@ mi_create_breakpoint_pending "-f pendfunc1" \
mi_gdb_test "-break-commands 1 \"print 1\" \"print 2\" \"print 3\""\
"\\^done" \
"set breakpoint commands on pending breakpoint"
-set bp [mi_make_breakpoint_pending -number 1 -disp keep -func pendfunc1 \
- -disp keep -enabled y -original-location pendfunc1 \
+set bp [mi_make_breakpoint_pending -number 1 -disp keep \
+ -enabled y -original-location pendfunc1 \
-script {\["print 1","print 2","print 3"\]}]
mi_gdb_test "-break-info 1" \
"\\^done,[mi_make_breakpoint_table [list $bp]]" \
diff --git a/gdb/testsuite/gdb.mi/mi-stepi.exp b/gdb/testsuite/gdb.mi/mi-stepi.exp
index 3f4fc03..28aa293 100644
--- a/gdb/testsuite/gdb.mi/mi-stepi.exp
+++ b/gdb/testsuite/gdb.mi/mi-stepi.exp
@@ -41,25 +41,25 @@ proc test_stepi_nexti {} {
set line [mi_execute_to "exec-step-instruction" "end-stepping-range" "main" "" \
".*basics.c" "\[0-9\]+" "" "step-instruction at main"]
if { $line >= $line_main_body && $line <= $line_main_hello } {
- pass "step-instruction at main (line check)"
+ pass "step-instruction at main, line check"
} else {
- fail "step-instruction at main (line check)"
+ fail "step-instruction at main, line check"
}
set line [mi_execute_to "exec-next-instruction" "end-stepping-range" "main" "" \
".*basics.c" "\[0-9\]+" "" "next-instruction at main"]
if { $line >= $line_main_body && $line <= $line_main_hello } {
- pass "next-instruction at main (line check)"
+ pass "next-instruction at main, line check"
} else {
- fail "next-instruction at main (line check)"
+ fail "next-instruction at main, line check"
}
set line [mi_execute_to "exec-next-instruction" "end-stepping-range" "main" "" \
".*basics.c" "\[0-9\]+" "" "next-instruction at main 2"]
if { $line >= $line_main_body && $line <= $line_main_hello } {
- pass "next-instruction at main 2 (line check)"
+ pass "next-instruction at main 2, line check"
} else {
- fail "next-instruction at main 2 (line check)"
+ fail "next-instruction at main 2, line check"
}
}
diff --git a/gdb/testsuite/gdb.mi/mi-sym-info.exp b/gdb/testsuite/gdb.mi/mi-sym-info.exp
index 40c0644..b8db2af 100644
--- a/gdb/testsuite/gdb.mi/mi-sym-info.exp
+++ b/gdb/testsuite/gdb.mi/mi-sym-info.exp
@@ -35,7 +35,8 @@ if {[build_executable "failed to prepare" ${testfile} \
mi_clean_restart $binfile
-mi_runto_main
+# Don't run to main to avoid increasing the search scope to include
+# debug info of shared libraries like libc, libgcc, etc.
set qstr "\"\[^\"\]+\""
set fun_re \
diff --git a/gdb/testsuite/gdb.mi/mi-thread-bp-deleted.exp b/gdb/testsuite/gdb.mi/mi-thread-bp-deleted.exp
index c048aca..08c7218 100644
--- a/gdb/testsuite/gdb.mi/mi-thread-bp-deleted.exp
+++ b/gdb/testsuite/gdb.mi/mi-thread-bp-deleted.exp
@@ -73,7 +73,7 @@ foreach_mi_ui_mode mode {
# UI.
if {$mode eq "separate"} {
with_spawn_id $gdb_main_spawn_id {
- gdb_test_multiple "" "drain CLI output upto breakpoint" {
+ gdb_test_multiple "" "drain CLI output up to breakpoint" {
-re "Thread 1 \[^\r\n\]+ hit Breakpoint $decimal,\
breakpt \\(\\) at\
\[^\r\n\]+\r\n$decimal\\s+\[^\r\n\]+\r\n" {
diff --git a/gdb/testsuite/gdb.mi/mi-var-cmd.exp b/gdb/testsuite/gdb.mi/mi-var-cmd.exp
index a4789e5..1f97200 100644
--- a/gdb/testsuite/gdb.mi/mi-var-cmd.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-cmd.exp
@@ -150,7 +150,7 @@ mi_gdb_test "-var-update *" \
"update all vars: linteger changed"
# Step over "lpinteger = &linteger;"
-mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 1] "step at do_locals_tests (2)"
+mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 1] "step at do_locals_tests, 2"
# Test: c_variable-2.3
# Desc: check whether only lpinteger changed
@@ -159,7 +159,7 @@ mi_gdb_test "-var-update *" \
"update all vars: lpinteger changed"
# Step over "lcharacter = 'a';"
-mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 2] "step at do_locals_tests (3)"
+mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 2] "step at do_locals_tests, 3"
# Test: c_variable-2.4
# Desc: check whether only lcharacter changed
@@ -168,7 +168,7 @@ mi_gdb_test "-var-update *" \
"update all vars: lcharacter changed"
# Step over "lpcharacter = &lcharacter;"
-mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 3] "step at do_locals_tests (4)"
+mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 3] "step at do_locals_tests, 4"
# Test: c_variable-2.5
# Desc: check whether only lpcharacter changed
@@ -189,7 +189,7 @@ mi_gdb_test "-var-update *" \
# lsimple.character = 'a';
mi_execute_to "exec-step 9" "end-stepping-range" "do_locals_tests" "" \
- "var-cmd.c" [expr $line_dlt_linteger + 12] "" "step at do_locals_tests (5)"
+ "var-cmd.c" [expr $line_dlt_linteger + 12] "" "step at do_locals_tests, 5"
# Test: c_variable-2.6
# Desc: check whether llong, lplong, lfloat, lpfloat, ldouble, lpdouble, lsimple.integer,
@@ -207,7 +207,7 @@ mi_gdb_test "-var-update *" \
set line_dlt_4321 [gdb_get_line_number "linteger = 4321;"]
mi_execute_to "exec-step 4" "end-stepping-range" "do_locals_tests" "" \
- "var-cmd.c" $line_dlt_4321 "" "step at do_locals_tests (6)"
+ "var-cmd.c" $line_dlt_4321 "" "step at do_locals_tests, 6"
# Test: c_variable-2.7
# Desc: check whether (lsimple.signed_character, lsimple.char_ptr) lpsimple, func changed
@@ -226,7 +226,7 @@ mi_gdb_test "-var-update *" \
# lsimple.character = 'b';
mi_execute_to "exec-step 8" "end-stepping-range" "do_locals_tests" "" \
- "var-cmd.c" [expr $line_dlt_4321 + 8] "" "step at do_locals_tests (7)"
+ "var-cmd.c" [expr $line_dlt_4321 + 8] "" "step at do_locals_tests, 7"
# Test: c_variable-2.8
# Desc: check whether linteger, lcharacter, llong, lfoat, ldouble, lsimple.integer,
@@ -374,7 +374,7 @@ mi_gdb_test "-var-assign func do_block_tests" \
mi_gdb_test "-var-update *" \
"\\^done,changelist=\\\[\\\]" \
- "assign same value to func (update)"
+ "assign same value to func, update"
mi_gdb_test "-var-create array_ptr * array_ptr" \
"\\^done,name=\"array_ptr\",numchild=\"1\",value=\"$hex <array>\",type=\"int \\*\",has_more=\"0\"" \
@@ -386,7 +386,7 @@ mi_gdb_test "-var-assign array_ptr array2" \
mi_gdb_test "-var-update *" \
"\\^done,changelist=\\\[\{name=\"array_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
- "assign array to pointer (update)"
+ "assign array to pointer, update"
mi_gdb_test "-var-assign array_ptr array2" \
"\\^done,value=\"$hex <array2>\"" \
@@ -394,7 +394,7 @@ mi_gdb_test "-var-assign array_ptr array2" \
mi_gdb_test "-var-update *" \
"\\^done,changelist=\\\[\\\]" \
- "assign same array to pointer (update)"
+ "assign same array to pointer, update"
######
@@ -434,7 +434,7 @@ mi_gdb_test "-var-update *" \
clear_xfail *-*-*
mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\}" \
- "var-cmd.c" [expr $line_subroutine1_body + 2] "step at subroutine1 (2)"
+ "var-cmd.c" [expr $line_subroutine1_body + 2] "step at subroutine1, 2"
# Test: c_variable-2.13
# Desc: change subroutine1 local i
@@ -443,7 +443,7 @@ mi_gdb_test "-var-update *" \
"update all vars: i changed"
mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\}" \
- "var-cmd.c" [expr $line_subroutine1_body + 3] "step at subroutine1 (3)"
+ "var-cmd.c" [expr $line_subroutine1_body + 3] "step at subroutine1, 3"
# Test: c_variable-2.14
# Desc: change do_locals_tests local llong
diff --git a/gdb/testsuite/gdb.mi/mi-var-cp.cc b/gdb/testsuite/gdb.mi/mi-var-cp.cc
index 4befab9..c40bdcf 100644
--- a/gdb/testsuite/gdb.mi/mi-var-cp.cc
+++ b/gdb/testsuite/gdb.mi/mi-var-cp.cc
@@ -19,15 +19,15 @@ void reference_update_tests ()
int x = 167;
/*: mi_create_varobj "RX" "rx" "create varobj for rx" :*/
int& rx = x;
- /*: mi_varobj_update RX {RX} "update RX (1)"
+ /*: mi_varobj_update RX {RX} "update RX, 1"
mi_check_varobj_value RX 167 "check RX: expect 167"
:*/
x = 567;
- /*: mi_varobj_update RX {RX} "update RX (2)"
+ /*: mi_varobj_update RX {RX} "update RX, 2"
mi_check_varobj_value RX 567 "check RX: expect 567"
:*/
x = 567;
- /*: mi_varobj_update RX {} "update RX (3)"
+ /*: mi_varobj_update RX {} "update RX, 3"
mi_delete_varobj RX "delete RX"
:*/
/* Dummy assignment to keep 'x' in scope. */
@@ -42,7 +42,7 @@ struct S2 : S {};
int base_in_reference_test (S2& s2)
{
/*: BEGIN: base_in_reference :*/
- return s2.i;
+ int x = s2.i + s2.j;
/*:
mi_create_varobj "S2" "s2" "create varobj for s2"
mi_list_varobj_children "S2" {
@@ -62,6 +62,7 @@ int base_in_reference_test (S2& s2)
:*/
/*: END: base_in_reference :*/
+ return x;
}
void base_in_reference_test_main ()
diff --git a/gdb/testsuite/gdb.mi/mi-var-display.exp b/gdb/testsuite/gdb.mi/mi-var-display.exp
index 560a871..b420d12 100644
--- a/gdb/testsuite/gdb.mi/mi-var-display.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-display.exp
@@ -237,11 +237,11 @@ mi_list_varobj_children weird {
# Desc: change format of weird.func_ptr and weird.func_ptr_ptr
mi_gdb_test "-var-set-format weird.func_ptr hexadecimal" \
"\\^done,format=\"hexadecimal\",value=\"$hex\"" \
- "set format variable weird.func_ptr in hex (1)"
+ "set format variable weird.func_ptr in hex, 1"
mi_gdb_test "-var-show-format weird.func_ptr" \
"\\^done,format=\"hexadecimal\"" \
- "show format variable weird.func_ptr (hex)"
+ "show format variable weird.func_ptr, hex"
mi_gdb_test "-var-set-format weird.func_ptr_ptr hexadecimal" \
"\\^done,format=\"hexadecimal\",value=\"$hex\"" \
@@ -249,7 +249,7 @@ mi_gdb_test "-var-set-format weird.func_ptr_ptr hexadecimal" \
mi_gdb_test "-var-show-format weird.func_ptr_ptr" \
"\\^done,format=\"hexadecimal\"" \
- "show format variable weird.func_ptr_ptr (hex)"
+ "show format variable weird.func_ptr_ptr, hex"
mi_gdb_test "-var-set-format weird.func_ptr zero-hexadecimal" \
"\\^done,format=\"zero-hexadecimal\",value=\"$hex\"" \
@@ -257,7 +257,7 @@ mi_gdb_test "-var-set-format weird.func_ptr zero-hexadecimal" \
mi_gdb_test "-var-show-format weird.func_ptr" \
"\\^done,format=\"zero-hexadecimal\"" \
- "show format variable weird.func_ptr (zhex)"
+ "show format variable weird.func_ptr, zhex"
mi_gdb_test "-var-set-format weird.func_ptr_ptr zero-hexadecimal" \
"\\^done,format=\"zero-hexadecimal\",value=\"$hex\"" \
@@ -265,7 +265,7 @@ mi_gdb_test "-var-set-format weird.func_ptr_ptr zero-hexadecimal" \
mi_gdb_test "-var-show-format weird.func_ptr_ptr" \
"\\^done,format=\"zero-hexadecimal\"" \
- "show format variable weird.func_ptr_ptr (zhex)"
+ "show format variable weird.func_ptr_ptr, zhex"
# Test: c_variable-6.24
# Desc: format of weird and children
@@ -299,7 +299,7 @@ mi_gdb_test "-var-set-format weird.long_array natural" \
mi_gdb_test "-var-set-format weird.func_ptr hexadecimal" \
"\\^done,format=\"hexadecimal\",value=\"$hex\"" \
- "set format variable weird.func_ptr in hex (2)"
+ "set format variable weird.func_ptr in hex, 2"
mi_gdb_test "-var-set-format weird.func_ptr_struct hexadecimal" \
"\\^done,format=\"hexadecimal\",value=\"$hex\"" \
diff --git a/gdb/testsuite/gdb.mi/mi-var-invalidate.exp b/gdb/testsuite/gdb.mi/mi-var-invalidate.exp
index 7ea2d17..60e29a9 100644
--- a/gdb/testsuite/gdb.mi/mi-var-invalidate.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-invalidate.exp
@@ -80,7 +80,7 @@ mi_gdb_test "-var-update linteger" \
mi_gdb_test "-var-info-type linteger" \
"\\^done,type=\"\"" \
- "no type for invalid variable linteger (1)"
+ "no type for invalid variable linteger, 1"
# Check global variable is still correct.
mi_gdb_test "-var-update global_simple" \
@@ -105,7 +105,7 @@ mi_gdb_test "-var-update linteger" \
mi_gdb_test "-var-info-type linteger" \
"\\^done,type=\"\"" \
- "no type for invalid variable linteger (2)"
+ "no type for invalid variable linteger, 2"
# Check global variable are still correct.
mi_gdb_test "-var-update global_simple" \
diff --git a/gdb/testsuite/gdb.mi/mi-vla-c99.exp b/gdb/testsuite/gdb.mi/mi-vla-c99.exp
index ee4bc26..a8a77ac 100644
--- a/gdb/testsuite/gdb.mi/mi-vla-c99.exp
+++ b/gdb/testsuite/gdb.mi/mi-vla-c99.exp
@@ -37,7 +37,7 @@ set bp_lineno [gdb_get_line_number "vla-filled"]
mi_create_breakpoint "-t vla.c:$bp_lineno" \
"insert breakpoint at line $bp_lineno after vla is filled" \
- -function func -line $bp_lineno -file ".*vla.c" -disp del
+ -func func -line $bp_lineno -file ".*vla.c" -disp del
mi_run_cmd
mi_expect_stop "breakpoint-hit" "func" "\{name=\"n\",value=\"5\"\}" \
diff --git a/gdb/testsuite/gdb.mi/mi-vla-fortran.exp b/gdb/testsuite/gdb.mi/mi-vla-fortran.exp
index e27f0ec..6097c02 100644
--- a/gdb/testsuite/gdb.mi/mi-vla-fortran.exp
+++ b/gdb/testsuite/gdb.mi/mi-vla-fortran.exp
@@ -41,7 +41,7 @@ if {[mi_clean_restart $binfile]} {
set bp_lineno [gdb_get_line_number "vla1-not-allocated"]
mi_create_breakpoint "-t vla.f90:$bp_lineno" \
"insert breakpoint at line $bp_lineno (vla not allocated)" \
- -number 1 -disp del -func vla ".*vla.f90" $bp_lineno $hex
+ -number 1 -disp del -func vla
mi_run_cmd
mi_expect_stop "breakpoint-hit" "vla" "" ".*vla.f90" "$bp_lineno" \
{ "" "disp=\"del\"" } "run to breakpoint at line $bp_lineno"
@@ -67,7 +67,7 @@ mi_list_array_varobj_children_with_index "vla1_not_allocated" "0" "1" \
set bp_lineno [gdb_get_line_number "vla1-allocated"]
mi_create_breakpoint "-t vla.f90:$bp_lineno" \
"insert breakpoint at line $bp_lineno (vla allocated)" \
- -number 2 -disp del -func vla ".*vla.f90" $bp_lineno $hex
+ -number 2 -disp del -func vla
mi_run_cmd
mi_expect_stop "breakpoint-hit" "vla" "" ".*vla.f90" "$bp_lineno" \
{ "" "disp=\"del\"" } "run to breakpoint at line $bp_lineno"
@@ -92,7 +92,7 @@ mi_list_array_varobj_children_with_index "vla1_allocated" "5" "1" \
set bp_lineno [gdb_get_line_number "vla1-filled"]
mi_create_breakpoint "-t vla.f90:$bp_lineno" \
"insert breakpoint at line $bp_lineno" \
- -number 3 -disp del -func vla ".*vla.f90" $bp_lineno $hex
+ -number 3 -disp del -func vla
mi_run_cmd
mi_expect_stop "breakpoint-hit" "vla" "" ".*vla.f90" "$bp_lineno" \
{ "" "disp=\"del\"" } "run to breakpoint at line $bp_lineno"
@@ -103,7 +103,7 @@ mi_gdb_test "520-data-evaluate-expression vla1" \
set bp_lineno [gdb_get_line_number "vla1-modified"]
mi_create_breakpoint "-t vla.f90:$bp_lineno" \
"insert breakpoint at line $bp_lineno" \
- -number 4 -disp del -func vla ".*vla.f90" $bp_lineno $hex
+ -number 4 -disp del -func vla
mi_run_cmd
mi_expect_stop "breakpoint-hit" "vla" "" ".*vla.f90" "$bp_lineno" \
{ "" "disp=\"del\"" } "run to breakpoint at line $bp_lineno"
@@ -120,7 +120,7 @@ mi_gdb_test "560-data-evaluate-expression vla1(4)" \
set bp_lineno [gdb_get_line_number "vla1-deallocated"]
mi_create_breakpoint "-t vla.f90:$bp_lineno" \
"insert breakpoint at line $bp_lineno" \
- -number 5 -disp del -func vla ".*vla.f90" $bp_lineno $hex
+ -number 5 -disp del -func vla
mi_run_cmd
mi_expect_stop "breakpoint-hit" "vla" "" ".*vla.f90" "$bp_lineno" \
{ "" "disp=\"del\"" } "run to breakpoint at line $bp_lineno"
@@ -131,7 +131,7 @@ mi_gdb_test "570-data-evaluate-expression vla1" \
set bp_lineno [gdb_get_line_number "pvla2-not-associated"]
mi_create_breakpoint "-t vla.f90:$bp_lineno" \
"insert breakpoint at line $bp_lineno" \
- -number 6 -disp "del" -func "vla" ".*vla.f90" $bp_lineno $hex
+ -number 6 -disp "del" -func "vla"
mi_run_cmd
mi_expect_stop "breakpoint-hit" "vla" "" ".*vla.f90" "$bp_lineno" \
{ "" "disp=\"del\"" } "run to breakpoint at line $bp_lineno"
@@ -172,7 +172,7 @@ gdb_expect {
set bp_lineno [gdb_get_line_number "pvla2-associated"]
mi_create_breakpoint "-t vla.f90:$bp_lineno" \
"insert breakpoint at line $bp_lineno" \
- -number 7 -disp del -func vla ".*vla.f90" $bp_lineno $hex
+ -number 7 -disp del -func vla
mi_run_cmd
mi_expect_stop "breakpoint-hit" "vla" "" ".*vla.f90" "$bp_lineno" \
{ "" "disp=\"del\"" } "run to breakpoint at line $bp_lineno"
@@ -196,7 +196,7 @@ mi_gdb_test "593-var-evaluate-expression pvla2_associated" \
set bp_lineno [gdb_get_line_number "pvla2-set-to-null"]
mi_create_breakpoint "-t vla.f90:$bp_lineno" \
"insert breakpoint at line $bp_lineno" \
- -number 8 -disp del -func vla ".*vla.f90" $bp_lineno $hex
+ -number 8 -disp del -func vla
mi_run_cmd
mi_expect_stop "breakpoint-hit" "vla" "" ".*vla.f90" "$bp_lineno" \
{ "" "disp=\"del\"" } "run to breakpoint at line $bp_lineno"
diff --git a/gdb/testsuite/gdb.mi/new-ui-bp-deleted.exp b/gdb/testsuite/gdb.mi/new-ui-bp-deleted.exp
index f736994..938e6de 100644
--- a/gdb/testsuite/gdb.mi/new-ui-bp-deleted.exp
+++ b/gdb/testsuite/gdb.mi/new-ui-bp-deleted.exp
@@ -76,8 +76,12 @@ foreach_mi_ui_mode mode {
set loc2 [make_bp_loc "$::decimal\\.2"]
# Create the inferior-specific breakpoint.
- mi_create_breakpoint_multi "-g i2 foo" "create breakpoint in inferior 2" \
- -inferior "2" -locations "\\\[$loc1,$loc2\\\]"
+ mi_create_breakpoint "-g i2 foo" "create breakpoint in inferior 2" \
+ -number "$decimal" \
+ -type "breakpoint" \
+ -enabled "y" \
+ -func "foo" \
+ -inferior "2"
set bpnum [mi_get_valueof "/d" "\$bpnum" "INVALID"]
if {$mode eq "separate"} {
diff --git a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
index 93b91b4..e168a5e 100644
--- a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
+++ b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
@@ -364,15 +364,9 @@ proc test_continue_to_start { mode inf } {
# Consume MI output.
with_spawn_id $mi_spawn_id {
- if { $inf == 1} {
- mi_expect_stop "breakpoint-hit" "child_sub_function" \
- "" "$srcfile" "$decimal" {"" "disp=\"del\""} \
- "thread $inf.2 stops MI"
- } else {
- mi_expect_stop "breakpoint-hit" "child_sub_function" \
- "" "$srcfile" "$decimal" {"" "disp=\"del\"" "locno=\"[0-9]+\""} \
- "thread $inf.2 stops MI"
- }
+ mi_expect_stop "breakpoint-hit" "child_sub_function" \
+ "" "$srcfile" "$decimal" {"" "disp=\"del\""} \
+ "thread $inf.2 stops MI"
}
}
}
@@ -439,7 +433,7 @@ proc_with_prefix test_setup { mode } {
with_spawn_id $mi_spawn_id {
mi_expect_stop "breakpoint-hit" "main" "" "$srcfile" "$decimal" \
- {"" "disp=\"del\"" "locno=\"[0-9]+\""} "main stop"
+ {"" "disp=\"del\""} "main stop"
}
# Consume CLI output.
diff --git a/gdb/testsuite/gdb.mi/var-cmd.c b/gdb/testsuite/gdb.mi/var-cmd.c
index 963bcd4..3aa5126 100644
--- a/gdb/testsuite/gdb.mi/var-cmd.c
+++ b/gdb/testsuite/gdb.mi/var-cmd.c
@@ -485,15 +485,15 @@ void do_at_tests ()
:*/
i++;
/*:
- mi_varobj_update F {F} "update F (1)"
- mi_check_varobj_value F 11 "check F (1)"
+ mi_varobj_update F {F} "update F, 1"
+ mi_check_varobj_value F 11 "check F, 1"
:*/
i++;
{
double i = 15;
/*:
- mi_varobj_update_with_type_change F "double" "0" "update F (2)"
- mi_check_varobj_value F 15 "check F (2)"
+ mi_varobj_update_with_type_change F "double" "0" "update F, 2"
+ mi_check_varobj_value F 15 "check F, 2"
:*/
i += 2.0;
}
@@ -506,8 +506,8 @@ void do_at_tests ()
}
i++;
/*:
- mi_varobj_update_with_type_change F "int" "0" "update F (3)"
- mi_check_varobj_value F 13 "check F (3)"
+ mi_varobj_update_with_type_change F "int" "0" "update F, 3"
+ mi_check_varobj_value F 13 "check F, 3"
:*/
i++;
do_at_tests_callee ();
diff --git a/gdb/testsuite/gdb.modula2/builtin-procedure-adr.exp b/gdb/testsuite/gdb.modula2/builtin-procedure-adr.exp
new file mode 100644
index 0000000..6588020
--- /dev/null
+++ b/gdb/testsuite/gdb.modula2/builtin-procedure-adr.exp
@@ -0,0 +1,32 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite. It contains tests for printing
+# the elements of an unbounded array using the Modula-2 language mode of
+# gdb.
+
+standard_testfile unbounded1.c
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug quiet}]} {
+ return -1
+}
+
+if {![runto main]} {
+ return
+}
+
+gdb_test "set lang modula-2" ".*does not match.*" "switch to modula-2"
+
+gdb_test "print ADR(i)" ".*0x.*" "print the address of local variable i"
diff --git a/gdb/testsuite/gdb.multi/base.exp b/gdb/testsuite/gdb.multi/base.exp
index db11bcd..834d961 100644
--- a/gdb/testsuite/gdb.multi/base.exp
+++ b/gdb/testsuite/gdb.multi/base.exp
@@ -139,14 +139,14 @@ gdb_test "list commonfun" "from hello.*" "list commonfun in hello"
gdb_test "print hglob" "1"
-gdb_test "print glob" "92" "print glob (${exec1})"
+gdb_test "print glob" "92" "print glob, ${exec1}"
gdb_test "inferior 3" ".*" "switch to inferior 3 to print globals"
gdb_test "print gglob" "2"
-gdb_test "print glob" "45" "print glob (${exec3})"
+gdb_test "print glob" "45" "print glob, ${exec3}"
gdb_test "list commonfun" "from goodbye.*" "list commonfun in goodbye"
diff --git a/gdb/testsuite/gdb.multi/bp-thread-specific.exp b/gdb/testsuite/gdb.multi/bp-thread-specific.exp
index 7635e84..11dc248 100644
--- a/gdb/testsuite/gdb.multi/bp-thread-specific.exp
+++ b/gdb/testsuite/gdb.multi/bp-thread-specific.exp
@@ -32,9 +32,33 @@ if {![runto_main]} {
return -1
}
+delete_breakpoints
+
+# Create a thread-specific b/p on main.
+gdb_breakpoint "main thread 1"
+set bpnum [get_integer_valueof "\$bpnum" "INVALID" \
+ "get number for thread specific b/p on main"]
+
+# Check the b/p has a location and is displayed correctly.
+gdb_test "info breakpoints" \
+ [multi_line \
+ "" \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$hex\\s+in main at \[^\r\n\]+/$srcfile:$decimal"\
+ "\\s+stop only in thread 1"] \
+ "check thread b/p on main has a location"
+
gdb_test "add-inferior -exec ${binfile}" "Added inferior 2.*" "add inferior 2"
gdb_test "inferior 2"
+# The breakpoint should still have a location, but should now display
+# information indicating this breakpoint is only in inferior 1.
+gdb_test "info breakpoints" \
+ [multi_line \
+ "" \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$hex\\s+in main at \[^\r\n\]+/$srcfile:$decimal inf 1"\
+ "\\s+stop only in thread 1\\.1"] \
+ "check thread b/p on main still has updated correctly"
+
if {![runto_main]} {
return -1
}
@@ -50,7 +74,7 @@ gdb_test "info threads" \
# locations ('foo' in both inferiors) even though only one of those
# locations will ever trigger ('foo' in inferior 2).
gdb_test "break foo thread 2.1" \
- "Breakpoint $decimal at $hex: foo\\. \\(2 locations\\)"
+ "Breakpoint $decimal at $hex: file \[^\r\n\]+$srcfile, line $decimal\\."
set bpnum [get_integer_valueof "\$bpnum" "INVALID"]
@@ -58,10 +82,7 @@ set bpnum [get_integer_valueof "\$bpnum" "INVALID"]
# earlier breakpoint. Check that the thread-id used when describing
# the earlier breakpoints is correct.
gdb_test "break foo thread 1.1" \
- [multi_line \
- "Note: breakpoint $bpnum \\(thread 2.1\\) also set at pc $hex\\." \
- "Note: breakpoint $bpnum \\(thread 2.1\\) also set at pc $hex\\." \
- "Breakpoint $decimal at $hex: foo\\. \\(2 locations\\)"]
+ "Breakpoint $decimal at $hex: file \[^\r\n\]+$srcfile, line $decimal\\."
# Save the breakpoints into a file.
if {[is_remote host]} {
diff --git a/gdb/testsuite/gdb.multi/dummy-frame-restore.exp b/gdb/testsuite/gdb.multi/dummy-frame-restore.exp
index 31d05e3..0bc5e6a 100644
--- a/gdb/testsuite/gdb.multi/dummy-frame-restore.exp
+++ b/gdb/testsuite/gdb.multi/dummy-frame-restore.exp
@@ -62,12 +62,12 @@ proc test { inf1 inf2 } {
with_test_prefix "inf $inf1 first" {
gdb_test "inferior 2" "witching to inferior 2 .*" \
- "switch to inferior 2 (1)"
+ "switch to inferior 2, 1"
check_bt 2 "before infcall"
gdb_test "p commonfun()" "Breakpoint .*The program being debugged stopped while in a function called from GDB.*" "infcall in inferior 2"
gdb_test "inferior 1" "witching to inferior 1 .*" \
- "switch to inferior 1 (1)"
+ "switch to inferior 1, 1"
check_bt 1 "before infcall"
gdb_test "p commonfun()" "Breakpoint .*The program being debugged stopped while in a function called from GDB.*" "infcall in inferior 1"
@@ -75,13 +75,13 @@ proc test { inf1 inf2 } {
"two dummy frames"
gdb_test "inferior $inf1" "witching to inferior $inf1 .*" \
- "switch to inferior $inf1 (2)"
+ "switch to inferior $inf1, 2"
gdb_test "finish" "Run till exit from #0 commonfun .*" \
"finish in inferior $inf1"
check_bt $inf1 "after infcall"
gdb_test "inferior $inf2" "witching to inferior $inf2 .*" \
- "switch to inferior $inf2 (2)"
+ "switch to inferior $inf2, 2"
gdb_test "finish" "Run till exit from #0 commonfun .*" \
"finish in inferior $inf2"
check_bt $inf2 "after infcall"
diff --git a/gdb/testsuite/gdb.multi/inferior-specific-bp-1.c b/gdb/testsuite/gdb.multi/inferior-specific-bp-1.c
index 59a6e32..16db062 100644
--- a/gdb/testsuite/gdb.multi/inferior-specific-bp-1.c
+++ b/gdb/testsuite/gdb.multi/inferior-specific-bp-1.c
@@ -35,7 +35,7 @@ foo (void)
static void
bar (void)
{
- global_var = 0;
+ global_var = 0; /* First location of bar. */
foo ();
}
diff --git a/gdb/testsuite/gdb.multi/inferior-specific-bp-2.c b/gdb/testsuite/gdb.multi/inferior-specific-bp-2.c
index cbae745..3a45c21 100644
--- a/gdb/testsuite/gdb.multi/inferior-specific-bp-2.c
+++ b/gdb/testsuite/gdb.multi/inferior-specific-bp-2.c
@@ -30,13 +30,14 @@ main (void)
{
int ret = baz ();
stop_breakpt ();
- return ret;
+ /* We have to call bar here, otherwise it might be optimized away. */
+ return ret + bar ();
}
static int
bar (void)
{
- return baz ();
+ return baz (); /* Second location of bar. */
}
static int
diff --git a/gdb/testsuite/gdb.multi/inferior-specific-bp.exp b/gdb/testsuite/gdb.multi/inferior-specific-bp.exp
index 5cc451b..82cc924 100644
--- a/gdb/testsuite/gdb.multi/inferior-specific-bp.exp
+++ b/gdb/testsuite/gdb.multi/inferior-specific-bp.exp
@@ -51,9 +51,9 @@ if {![runto_main]} {
# this should fail. Try with the keywords in both orders just in case the
# parser has a bug.
gdb_test "break foo thread 1.1 inferior 1" \
- "You can specify only one of inferior or thread\\."
+ "You can specify only one of thread, inferior, or task\\."
gdb_test "break foo inferior 1 thread 1.1" \
- "You can specify only one of inferior or thread\\."
+ "You can specify only one of thread, inferior, or task\\."
# Try to create a breakpoint using the 'inferior' keyword multiple times.
gdb_test "break foo inferior 1 inferior 2" \
@@ -62,6 +62,73 @@ gdb_test "break foo inferior 1 inferior 2" \
# Clear out any other breakpoints.
delete_breakpoints
+# Create an inferior specific breakpoint and then change the inferior
+# using the Python API. Use 'info breakpoint' to check that the
+# breakpoint was updated as we expect.
+if { [allow_python_tests] } {
+ with_test_prefix "update breakpoint inferior" {
+ # Create the b/p and grab its number.
+ gdb_breakpoint "bar inferior 1"
+ set bpnum [get_integer_valueof "\$bpnum" "INVALID" \
+ "get b/p number for breakpoint on bar"]
+
+ # Get the line number for the two locations, the first in
+ # inferior 1, the second in inferior 2.
+ set bar_lineno_1 \
+ [gdb_get_line_number "First location of bar" $srcfile]
+ set bar_lineno_2 \
+ [gdb_get_line_number "Second location of bar" $srcfile2]
+
+ # Check the b/p was created with a single location where we
+ # expect it.
+ gdb_test "info breakpoint $bpnum" \
+ [multi_line \
+ "" \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$hex\\s+in bar at \[^\r\n\]+/$srcfile:$bar_lineno_1 inf 1" \
+ "\\s+stop only in inferior 1"] \
+ "check original details for breakpoint on bar"
+
+ # Use the Python API to update the b/p's inferior.
+ gdb_test_no_output "python bp = gdb.breakpoints()\[0\]"
+ gdb_test_no_output "python bp.inferior = 2"
+
+ # We should still only have a single location, but now in
+ # inferior 2.
+ gdb_test "info breakpoint $bpnum" \
+ [multi_line \
+ "" \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$hex\\s+in bar at \[^\r\n\]+/$srcfile2:$bar_lineno_2 inf 2" \
+ "\\s+stop only in inferior 2"] \
+ "check updated details for breakpoint on bar"
+
+ # Use the Python API to remove the inferior restriction on the
+ # breakpoint.
+ gdb_test_no_output "python bp.inferior = None"
+
+ # The breakpoint should now have multiple locations.
+ gdb_test "info breakpoint $bpnum" \
+ [multi_line \
+ "" \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<MULTIPLE>\\s*" \
+ "$bpnum.1\\s+y\\s+$hex\\s+in bar at\[^\r\n\]+$srcfile:$bar_lineno_1 inf 1" \
+ "$bpnum.2\\s+y\\s+$hex\\s+in bar at\[^\r\n\]+$srcfile2:$bar_lineno_2 inf 2"] \
+ "check breakpoint bar now inferior requirement is gone"
+
+ # Finally, add the inferior requirement back.
+ gdb_test_no_output "python bp.inferior = 1"
+
+ # Check the original location and restriction is restored.
+ gdb_test "info breakpoint $bpnum" \
+ [multi_line \
+ "" \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$hex\\s+in bar at \[^\r\n\]+/$srcfile:$bar_lineno_1 inf 1" \
+ "\\s+stop only in inferior 1"] \
+ "check original details for breakpoint on bar are back"
+
+ delete_breakpoints
+ }
+}
+
# Use 'info breakpoint' to check that the inferior specific breakpoint is
# present in the breakpoint list. TESTNAME is the name used for this test,
# BP_NUMBER is the number for the breakpoint, and EXPECTED_LOC_COUNT is the
@@ -105,16 +172,8 @@ proc check_info_breakpoints { testname bp_number expected_loc_count } {
# Create an inferior-specific breakpoint. Use gdb_test instead of
# gdb_breakpoint here as we want to check the breakpoint was placed in
# multiple locations.
-#
-# Currently GDB still places inferior specific breakpoints into every
-# inferior, just like it does with thread specific breakpoints.
-# Hopefully this will change in the future, at which point, this test
-# will need updating.
-#
-# Two of these locations are in inferior 1, while the third is in
-# inferior 2.
gdb_test "break foo inferior 1" \
- "Breakpoint $decimal at $hex: foo\\. \\(3 locations\\)"
+ "Breakpoint $decimal at $hex: foo\\. \\(2 locations\\)"
set bp_number [get_integer_valueof "\$bpnum" "INVALID" \
"get b/p number for inferior specific breakpoint"]
@@ -123,7 +182,7 @@ set location_count 0
set saw_inf_cond false
check_info_breakpoints "first check for inferior specific breakpoint" \
- $bp_number 3
+ $bp_number 2
# Create a multi-inferior breakpoint to stop at.
gdb_breakpoint "stop_breakpt" message
diff --git a/gdb/testsuite/gdb.multi/multi-target-continue.exp b/gdb/testsuite/gdb.multi/multi-target-continue.exp
index d220106..d4b2fc2 100644
--- a/gdb/testsuite/gdb.multi/multi-target-continue.exp
+++ b/gdb/testsuite/gdb.multi/multi-target-continue.exp
@@ -30,7 +30,7 @@ proc test_continue {non-stop} {
proc set_break {inf} {
gdb_test "break function${inf} thread ${inf}.1" \
- "Breakpoint .* function${inf}\\..*"
+ "Breakpoint ${::decimal} at ${::hex}: file .*, line ${::decimal}\\."
}
# Select inferior INF, and then run to a breakpoint on inferior
diff --git a/gdb/testsuite/gdb.multi/multi-target-ping-pong-next.exp b/gdb/testsuite/gdb.multi/multi-target-ping-pong-next.exp
index 0aff708..36f9d24 100644
--- a/gdb/testsuite/gdb.multi/multi-target-ping-pong-next.exp
+++ b/gdb/testsuite/gdb.multi/multi-target-ping-pong-next.exp
@@ -52,12 +52,12 @@ proc test_ping_pong_next {} {
gdb_test "thread 1.1" "Switching to thread 1.1 .*"
gdb_test "break $srcfile:$line1 thread 1.1" \
- "Breakpoint .*$srcfile:$line1\\..*"
+ "Breakpoint .*$srcfile, line $line1\\."
gdb_test "continue" "hit Breakpoint .*"
gdb_test "break $srcfile:$line2 thread 2.1" \
- "Breakpoint .*$srcfile:$line2\\..*"
+ "Breakpoint .*$srcfile, line $line2\\."
# Now block inferior 1 and issue "next". We should stop at the
# breakpoint for inferior 2, given schedlock off.
diff --git a/gdb/testsuite/gdb.multi/multi-term-settings.c b/gdb/testsuite/gdb.multi/multi-term-settings.c
index 6880206..e9e7e95 100644
--- a/gdb/testsuite/gdb.multi/multi-term-settings.c
+++ b/gdb/testsuite/gdb.multi/multi-term-settings.c
@@ -22,7 +22,6 @@
#include <stdio.h>
#include <sys/types.h>
#include <termios.h>
-#include <unistd.h>
#include <signal.h>
int
diff --git a/gdb/testsuite/gdb.multi/multi-term-settings.exp b/gdb/testsuite/gdb.multi/multi-term-settings.exp
index 59ff8ce..0aeba1f 100644
--- a/gdb/testsuite/gdb.multi/multi-term-settings.exp
+++ b/gdb/testsuite/gdb.multi/multi-term-settings.exp
@@ -94,7 +94,7 @@ proc create_inferior {which_inf inf_how} {
"attach"] == 0} {
# The program is now stopped, but if testing against
- # gdbserver, then the inferior's output emmitted before it
+ # gdbserver, then the inferior's output emitted before it
# stopped isn't flushed unless we explicitly do so,
# because it is on a different spawn_id. Do it now, to
# avoid confusing tests further below.
diff --git a/gdb/testsuite/gdb.multi/pending-bp-del-inferior.c b/gdb/testsuite/gdb.multi/pending-bp-del-inferior.c
new file mode 100644
index 0000000..1d03000
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/pending-bp-del-inferior.c
@@ -0,0 +1,28 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2023 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
+foo (void)
+{
+ return 0;
+}
+
+int
+main (void)
+{
+ return foo ();
+}
diff --git a/gdb/testsuite/gdb.multi/pending-bp-del-inferior.exp b/gdb/testsuite/gdb.multi/pending-bp-del-inferior.exp
new file mode 100644
index 0000000..12c0a84
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/pending-bp-del-inferior.exp
@@ -0,0 +1,214 @@
+# Copyright 2023 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/>.
+
+# Setup two inferiors. Select one inferior and create a pending
+# thread specific breakpoint in the other inferior.
+#
+# Delete the selected inferior (the one for which the thread specific
+# breakpoint doesn't apply), and check that the breakpoint still exists.
+#
+# Repeat this process, but this time, create an inferior specific
+# breakpoint.
+
+# The plain remote target can't do multiple inferiors.
+require !use_gdb_stub
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} {
+ return -1
+}
+
+# Setup for the tests. Create two inferiors, both running the global
+# BINFILE, and proceed to main in both inferiors. Delete all
+# breakpoints, and check that we do have two threads.
+#
+# Return true after a successful setup, otherwise, return false.
+proc test_setup {} {
+ clean_restart $::binfile
+
+ if {![runto_main]} {
+ return 0
+ }
+
+ gdb_test "add-inferior -exec ${::binfile}" "Added inferior 2.*" \
+ "add inferior 2"
+ gdb_test "inferior 2" "Switching to inferior 2 .*" \
+ "select inferior 2"
+
+ if {![runto_main]} {
+ return 0
+ }
+
+ delete_breakpoints
+
+ gdb_test "info threads" \
+ [multi_line \
+ " Id\\s+Target Id\\s+Frame\\s*" \
+ " 1\\.1\\s+\[^\r\n\]+" \
+ "\\* 2\\.1\\s+\[^\r\n\]+"] \
+ "check we have the expected threads"
+
+ return 1
+}
+
+# Assuming inferior 2 is already selected, kill the current inferior
+# (inferior 2), select inferior 1, and then remove inferior 2.
+proc kill_and_remove_inferior_2 {} {
+ gdb_test "kill" "" "kill inferior 2" \
+ "Kill the program being debugged.*y or n. $" "y"
+
+ gdb_test "inferior 1" "Switching to inferior 1 .*" \
+ "select inferior 1"
+
+ gdb_test_no_output "remove-inferiors 2"
+}
+
+# Setup two inferiors, then create a breakpoint. If BP_PENDING is
+# true then the breakpoint will be pending, otherwise, the breakpoint
+# will be non-pending.
+#
+# BP_TYPE is either 'thread' or 'inferior', and indicates if the
+# created breakpoint should be thread or inferior specific.
+#
+# The breakpoint is created while inferior 2 is selected, and the
+# thread/inferior restriction always identifies inferior 1.
+#
+# Then inferior 2 is killed and removed.
+#
+# Finally, check that the breakpoint still exists and correctly refers
+# to inferior 1.
+proc do_bp_test { bp_type bp_pending } {
+ if {![test_setup]} {
+ return
+ }
+
+ if { $bp_pending } {
+ set bp_func "bar"
+ } else {
+ set bp_func "foo"
+ }
+
+ if { $bp_type eq "thread" } {
+ set bp_restriction "thread 1.1"
+ } else {
+ set bp_restriction "inferior 1"
+ }
+
+ gdb_breakpoint "$bp_func $bp_restriction" allow-pending
+ set bp_number [get_integer_valueof "\$bpnum" "INVALID" \
+ "get b/p number for previous breakpoint"]
+
+ if { $bp_restriction eq "thread 1.1" } {
+ set bp_after_restriction "thread 1"
+ } else {
+ set bp_after_restriction $bp_restriction
+ }
+
+ if { $bp_pending } {
+ set bp_pattern_before \
+ [multi_line \
+ "$bp_number\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+${bp_func}" \
+ "\\s+stop only in [string_to_regexp $bp_restriction]"]
+ set bp_pattern_after \
+ [multi_line \
+ "$bp_number\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+${bp_func}" \
+ "\\s+stop only in [string_to_regexp $bp_after_restriction]"]
+ } else {
+ set bp_pattern_before \
+ [multi_line \
+ "$bp_number\\s+breakpoint\\s+keep\\s+y\\s+$::hex in $bp_func at \[^\r\n\]+ inf 1" \
+ "\\s+stop only in [string_to_regexp $bp_restriction]"]
+
+ set bp_pattern_after \
+ [multi_line \
+ "$bp_number\\s+breakpoint\\s+keep\\s+y\\s+$::hex in $bp_func at \[^\r\n\]+" \
+ "\\s+stop only in [string_to_regexp $bp_after_restriction]"]
+ }
+
+ gdb_test "info breakpoints" $bp_pattern_before \
+ "info breakpoints before inferior removal"
+
+ kill_and_remove_inferior_2
+
+ gdb_test "info breakpoints" $bp_pattern_after \
+ "info breakpoints after inferior removal"
+}
+
+# Setup two inferiors, then create a dprintf. If BP_PENDING is
+# true then the dprintf will be pending, otherwise, the dprintf
+# will be non-pending.
+#
+# The dprintf is created while inferior 2 is selected. Then inferior
+# 2 is killed and removed.
+#
+# Finally, check that the dprintf still exists.
+proc do_dprintf_test { bp_pending } {
+ if {![test_setup]} {
+ return
+ }
+
+ if { $bp_pending } {
+ set bp_func "bar"
+
+ gdb_test "dprintf $bp_func,\"in $bp_func\"" ".*" \
+ "create dprintf breakpoint" \
+ "Make dprintf pending on future shared library load\\? \\(y or .n.\\) $" "y"
+ } else {
+ set bp_func "foo"
+
+ gdb_test "dprintf $bp_func,\"in $bp_func\"" ".*" \
+ "create dprintf breakpoint"
+ }
+
+ set bp_number [get_integer_valueof "\$bpnum" "INVALID" \
+ "get b/p number for previous breakpoint"]
+
+ if { $bp_pending } {
+ set bp_pattern_before \
+ [multi_line \
+ "$bp_number\\s+dprintf\\s+keep\\s+y\\s+<PENDING>\\s+${bp_func}" \
+ "\\s+printf \"in $bp_func\""]
+ set bp_pattern_after $bp_pattern_before
+ } else {
+ set bp_pattern_before \
+ [multi_line \
+ "$bp_number\\s+dprintf\\s+keep\\s+y\\s+<MULTIPLE>\\s*" \
+ "\\s+printf \"in $bp_func\"" \
+ "$bp_number\\.1\\s+y\\s+$::hex in $bp_func at \[^\r\n\]+ inf 1" \
+ "$bp_number\\.2\\s+y\\s+$::hex in $bp_func at \[^\r\n\]+ inf 2"]
+
+ set bp_pattern_after \
+ [multi_line \
+ "$bp_number\\s+dprintf\\s+keep\\s+y\\s+$::hex in $bp_func at \[^\r\n\]+" \
+ "\\s+printf \"in $bp_func\""]
+ }
+
+ gdb_test "info breakpoints" $bp_pattern_before \
+ "info breakpoints before inferior removal"
+
+ kill_and_remove_inferior_2
+
+ gdb_test "info breakpoints" $bp_pattern_after \
+ "info breakpoints after inferior removal"
+}
+
+foreach_with_prefix bp_pending { true false } {
+ foreach_with_prefix bp_type { thread inferior } {
+ do_bp_test $bp_type $bp_pending
+ }
+
+ do_dprintf_test $bp_pending
+}
diff --git a/gdb/testsuite/gdb.multi/pending-bp-lib.c b/gdb/testsuite/gdb.multi/pending-bp-lib.c
new file mode 100644
index 0000000..c48e7f2
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/pending-bp-lib.c
@@ -0,0 +1,22 @@
+/* Copyright 2023-2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int global_var = 0;
+
+void
+foo (int arg)
+{
+ global_var = arg;
+}
diff --git a/gdb/testsuite/gdb.multi/pending-bp.c b/gdb/testsuite/gdb.multi/pending-bp.c
new file mode 100644
index 0000000..17d9181
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/pending-bp.c
@@ -0,0 +1,66 @@
+/* Copyright 2023-2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <stdlib.h>
+
+void
+breakpt (void)
+{
+ /* Nothing. */
+}
+
+volatile int global_counter = 0;
+
+volatile int call_count = 1;
+
+int
+main (void)
+{
+ void *handle;
+ void (*func)(int);
+
+ /* Some filler work so that we don't initially stop on the breakpt call
+ below. */
+ ++global_counter;
+
+ breakpt (); /* Break before open. */
+
+ /* Now load the shared library. */
+ handle = dlopen (SHLIB_NAME, RTLD_LAZY);
+ if (handle == NULL)
+ abort ();
+
+ breakpt (); /* Break after open. */
+
+ /* Find the function symbol. */
+ func = (void (*)(int)) dlsym (handle, "foo");
+
+ for (; call_count > 0; --call_count)
+ {
+ /* Call the library function. */
+ func (1);
+ }
+
+ breakpt (); /* Break before close. */
+
+ /* Unload the shared library. */
+ if (dlclose (handle) != 0)
+ abort ();
+
+ breakpt (); /* Break after close. */
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.multi/pending-bp.exp b/gdb/testsuite/gdb.multi/pending-bp.exp
new file mode 100644
index 0000000..2a0644b
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/pending-bp.exp
@@ -0,0 +1,332 @@
+# Copyright 2023-2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Tests related to pending breakpoints in a multi-inferior environment.
+
+require allow_shlib_tests !use_gdb_stub
+
+standard_testfile
+
+set libname $testfile-lib
+set srcfile_lib $srcdir/$subdir/$libname.c
+set binfile_lib [standard_output_file $libname.so]
+
+if { [gdb_compile_shlib $srcfile_lib $binfile_lib {}] != "" } {
+ untested "failed to compile shared library 1"
+ return -1
+}
+
+set binfile_lib_target [gdb_download_shlib $binfile_lib]
+
+if { [build_executable "failed to prepare" $testfile $srcfile \
+ [list debug \
+ additional_flags=-DSHLIB_NAME=\"$binfile_lib_target\" \
+ shlib_load]] } {
+ return -1
+}
+
+# Start two inferiors, both running the same test binary. The arguments
+# INF_1_STOP and INF_2_STOP are source code patterns that are passed to
+# gdb_get_line_number to figure out where each inferior should be stopped.
+#
+# This proc does a clean_restart and leaves inferior 2 selected. Also the
+# '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}
+
+ gdb_locate_shlib $::binfile_lib
+
+ if {![runto_main]} {
+ return false
+ }
+
+ gdb_breakpoint [gdb_get_line_number ${inf_1_stop}] temporary
+ gdb_continue_to_breakpoint "move inferior 1 into position"
+
+ gdb_test "add-inferior -exec ${::binfile}" \
+ "Added inferior 2.*" "add inferior 2"
+ gdb_test "inferior 2" "Switching to inferior 2 .*" "switch to inferior 2"
+
+ if {![runto_main]} {
+ return false
+ }
+
+ gdb_breakpoint [gdb_get_line_number ${inf_2_stop}] temporary
+ gdb_continue_to_breakpoint "move inferior 2 into position"
+
+ gdb_test_no_output "set breakpoint pending on"
+
+ return true
+}
+
+# Create a breakpoint on the function 'foo' in THREAD. It is expected
+# that the breakpoint created will be pending, this is checked by
+# running the 'info breakpoints' command.
+#
+# Returns the number for the newly created breakpoint.
+proc do_create_pending_foo_breakpoint { {thread "1.1"} } {
+ gdb_test "break foo thread $thread" \
+ [multi_line \
+ "Function \"foo\" not defined\\." \
+ "Breakpoint $::decimal \\(foo\\) pending\."] \
+ "set pending thread-specific breakpoint"
+ set bpnum [get_integer_valueof "\$bpnum" "*INVALID*" \
+ "get number for thread-specific breakpoint on foo"]
+ gdb_test "info breakpoints $bpnum" \
+ [multi_line \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
+ "\\s+stop only in thread [string_to_regexp $thread]"] \
+ "check thread-specific breakpoint is initially pending"
+
+ return $bpnum
+}
+
+# Create a breakpoint on the function 'foo' in THREAD. It is expected
+# that the breakpoint created will not be pending, this is checked by
+# running the 'info breakpoints' command.
+#
+# Returns the number for the newly created breakpoint.
+proc do_create_foo_breakpoint { {thread "1.1"} } {
+ gdb_test "break foo thread $thread" \
+ "Breakpoint $::decimal at $::hex" \
+ "set thread-specific breakpoint"
+ set bpnum [get_integer_valueof "\$bpnum" "*INVALID*" \
+ "get number for thread-specific breakpoint on foo"]
+ gdb_test "info breakpoints $bpnum" \
+ [multi_line \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$::hex\\s+<foo\[^>\]*> inf $::decimal" \
+ "\\s+stop only in thread [string_to_regexp $thread]"] \
+ "check thread-specific breakpoint is initially pending"
+
+ return $bpnum
+}
+
+# Check that when a breakpoint is in the pending state, but that breakpoint
+# does have some locations (those locations themselves are pending), GDB
+# doesn't display the inferior list in the 'info breakpoints' output.
+proc_with_prefix test_no_inf_display {} {
+ do_test_setup "Break before open" "Break before open"
+
+ # Create a breakpoint on 'foo'. As the shared library (that
+ # contains foo) has not been loaded into any inferior yet, then
+ # there will be no locations and the breakpoint will be created
+ # pending. Pass the 'allow-pending' flag so the gdb_breakpoint
+ # correctly expects the new breakpoint to be pending.
+ gdb_breakpoint "foo" allow-pending
+ set bpnum [get_integer_valueof "\$bpnum" "*INVALID*" \
+ "get foo breakpoint number"]
+
+ # Check the 'info breakpoints' output; the breakpoint is pending with
+ # no 'inf X' appearing at the end of the line.
+ gdb_test "info breakpoint $bpnum" \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
+ "check info bp before locations have been created"
+
+ # Now select inferior 1 and allow the inferior to run forward to the
+ # point where a breakpoint location for foo will have been created.
+ gdb_test "inferior 1" "Switching to inferior 1 .*"
+ gdb_breakpoint [gdb_get_line_number "Break after open"] temporary
+ gdb_continue_to_breakpoint \
+ "move inferior 1 until a location has been added"
+
+ # Check the 'info breakpoints' output. Notice we display the inferior
+ # list at the end of the breakpoint line.
+ gdb_test "info breakpoint $bpnum" \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$::hex\\s+<foo\[^>\]*>\\s+inf 1" \
+ "check info breakpoints while breakpoint is inserted"
+
+ # Continue inferior 1 until the shared library has been unloaded. The
+ # breakpoint on 'foo' will return to the pending state. We will need to
+ # 'continue' twice as the first time will hit the 'foo' breakpoint.
+ gdb_breakpoint [gdb_get_line_number "Break after close"] temporary
+ gdb_continue_to_breakpoint "hit the breakpoint in foo"
+ gdb_continue_to_breakpoint "after close library"
+
+ # Check the 'info breakpoints' output, check there is no 'inf 1' at the
+ # end of the breakpoint line.
+ gdb_test "info breakpoint $bpnum" \
+ [multi_line \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
+ "\\s+breakpoint already hit 1 time"] \
+ "check info breakpoints while breakpoint is pending"
+}
+
+# Setup two inferiors. In #1 the symbol 'foo' has not yet been
+# loaded, while in #2 the symbol 'foo' has been loaded.
+#
+# Create a thread-specific breakpoint on 'foo' tied to a thread in
+# inferior #1, the breakpoint should be pending -- 'foo' is not yet
+# loaded in #1.
+#
+# Now move inferior #1 forward until 'foo' is loaded, check the
+# breakpoint is no longer pending.
+#
+# Move inferior #1 forward more until 'foo' is unloaded, check that
+# the breakpoint returns to the pending state.
+proc_with_prefix test_pending_toggle { } {
+
+ do_test_setup "Break before open" "Break before close"
+
+ set bpnum [do_create_pending_foo_breakpoint]
+
+ # Now return to inferior 1 and continue until the shared library is
+ # loaded, the breakpoint should become non-pending.
+ gdb_test "inferior 1" "Switching to inferior 1 .*" \
+ "switch back to inferior 1"
+ gdb_continue_to_breakpoint "stop in foo in inferior 1" "foo \\(\\) .*"
+
+ gdb_test "info breakpoint $bpnum" \
+ [multi_line \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$::hex <foo\[^>\]*> inf 1" \
+ "\\s+stop only in thread 1\\.1" \
+ "\\s+breakpoint already hit 1 time"] \
+ "check thread-specific breakpoint is no longer pending"
+
+ gdb_breakpoint [gdb_get_line_number "Break after close"] temporary
+ gdb_continue_to_breakpoint "close library"
+ gdb_test "info breakpoints $bpnum" \
+ [multi_line \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
+ "\\s+stop only in thread 1\\.1" \
+ "\\s+breakpoint already hit 1 time"] \
+ "check thread-specific breakpoint is pending again"
+}
+
+# Create a Python variable VAR and set it to the gdb.Breakpoint object
+# corresponding to the breakpoint numbered BPNUM. If THREAD is not
+# the empty string then THREAD should be an integer, check that
+# gdb.Breakpoint.thread is set to the value of THREAD. Otherwise, if
+# THREAD is the empty string, check that gdb.Breakpoint.thread is set
+# to None.
+proc py_find_breakpoint { var bpnum {thread ""} } {
+ gdb_test_no_output \
+ "python ${var}=\[b for b in gdb.breakpoints() if b.number == $bpnum\]\[0\]" \
+ "find Python gdb.Breakpoint object"
+ if { $thread ne "" } {
+ gdb_test_no_output "python assert(${var}.thread == ${thread})" \
+ "check thread attribute is currently correct"
+ } else {
+ gdb_test_no_output "python assert(${var}.thread is None)" \
+ "check thread attribute is currently correct"
+ }
+}
+
+# Setup two inferiors. In #1 the symbol 'foo' has not yet been
+# loaded, while in #2 the symbol 'foo' has been loaded.
+#
+# Create a thread-specific breakpoint on 'foo' tied to a thread in
+# inferior #1, the breakpoint should be pending -- 'foo' is not yet
+# loaded in #1.
+#
+# Use Python to change the thread of the thread-specific breakpoint to
+# a thread in inferior #2, at this point the thread should gain a
+# location and become non-pending.
+#
+# Set the thread back to a thread in inferior #1, the breakpoint
+# should return to the pending state.
+proc_with_prefix py_test_toggle_thread {} {
+ do_test_setup "Break before open" "Break after open"
+
+ set bpnum [do_create_pending_foo_breakpoint]
+
+ py_find_breakpoint "bp" $bpnum 1
+
+ gdb_test_no_output "python bp.thread = 2" \
+ "change thread on thread-specific breakpoint"
+ gdb_test "info breakpoint $bpnum" \
+ [multi_line \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$::hex <foo\[^>\]*> inf 2" \
+ "\\s+stop only in thread 2\\.1"] \
+ "check thread-specific breakpoint now has a location"
+
+ gdb_test_no_output "set call_count = 2" "set call_count in inferior 2"
+ gdb_continue_to_breakpoint "stop at foo in inferior 2" "foo \\(\\) .*"
+
+ gdb_test_no_output "python bp.thread = 1" \
+ "restore thread on thread-specific breakpoint"
+ gdb_test "info breakpoints $bpnum" \
+ [multi_line \
+ "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
+ "\\s+stop only in thread 1\\.1" \
+ "\\s+breakpoint already hit 1 time"] \
+ "check thread-specific breakpoint has returned to pending"
+
+ gdb_breakpoint [gdb_get_line_number "Break after close"] temporary
+ gdb_continue_to_breakpoint "stop after close in inferior 2" \
+ ".* Break after close\\. .*"
+
+ gdb_test "inferior 1" "Switching to inferior 1 .*" \
+ "switch to inferior 1"
+ gdb_continue_to_breakpoint "stop at foo in inferior 1" "foo \\(\\) .*"
+}
+
+# Setup two inferiors. Both inferiors have the symbol 'foo'
+# available.
+#
+# Create a thread-specific breakpoint on 'foo' tied to a thread in
+# inferior #1, the breakpoint should not be pending, but will only
+# have a single location, the location in inferior #1.
+#
+# Use Python to change the thread of the thread-specific breakpoint to
+# None. At this point the breakpoint should gain a second location, a
+# location in inferior #2.
+proc_with_prefix py_test_clear_thread {} {
+ do_test_setup "Break after open" "Break after open"
+
+ set bpnum [do_create_foo_breakpoint]
+
+ py_find_breakpoint "bp" $bpnum 1
+
+ gdb_test_no_output "python bp.thread = None" \
+ "clear thread on thread-specific breakpoint"
+ gdb_test "info breakpoints $bpnum" \
+ [multi_line \
+ "${bpnum}\\s+breakpoint\\s+keep y\\s+<MULTIPLE>\\s*" \
+ "${bpnum}\\.1\\s+y\\s+${::hex}\\s+<foo\[^>\]*> inf $::decimal" \
+ "${bpnum}\\.2\\s+y\\s+${::hex}\\s+<foo\[^>\]*> inf $::decimal"] \
+ "check for a location in both inferiors"
+
+ gdb_continue_to_breakpoint "stop at foo in inferior 2" "foo \\(\\) .*"
+ gdb_test_no_output "set call_count = 2" "set call_count in inferior 2"
+
+ gdb_test "inferior 1" "Switching to inferior 1 .*" \
+ "switch to inferior 1"
+ gdb_continue_to_breakpoint "stop at foo in inferior 1" "foo \\(\\) .*"
+ gdb_test_no_output "set call_count = 2" "set call_count in inferior 1"
+
+ gdb_test_no_output "python bp.thread = 2"
+ gdb_test "info breakpoints $bpnum" \
+ [multi_line \
+ "${bpnum}\\s+breakpoint\\s+keep y\\s+${::hex}\\s+<foo\[^>\]*> inf 2" \
+ "\\s+stop only in thread 2\\.1" \
+ "\\s+breakpoint already hit 2 times"] \
+ "check for a location only in inferior 2"
+
+ gdb_breakpoint [gdb_get_line_number "Break after close"] temporary
+ gdb_continue_to_breakpoint "stop after close in inferior 1" \
+ ".* Break after close\\. .*"
+
+ gdb_test "inferior 2" "Switching to inferior 2 .*" \
+ "switch back to inferior 2"
+ gdb_continue_to_breakpoint "stop at foo again in inferior 2" \
+ "foo \\(\\) .*"
+}
+
+# Run all the tests.
+test_no_inf_display
+test_pending_toggle
+py_test_toggle_thread
+py_test_clear_thread
diff --git a/gdb/testsuite/gdb.multi/tids.exp b/gdb/testsuite/gdb.multi/tids.exp
index 573b02f..4f78884 100644
--- a/gdb/testsuite/gdb.multi/tids.exp
+++ b/gdb/testsuite/gdb.multi/tids.exp
@@ -433,11 +433,13 @@ if { [allow_python_tests] } {
gdb_py_test_silent_cmd "python bp = gdb.breakpoints()\[0\]" \
"get python breakpoint" 0
- gdb_test "python bp.thread = 6" "thread = 6" \
+ gdb_test_no_output "python bp.thread = 6" \
"make breakpoint thread-specific with python"
# Check that the inferior-qualified ID is correct.
gdb_test "info breakpoint" \
- "stop only in thread 1.3\r\n.*" \
+ [multi_line \
+ "$decimal\\s+\[^\r\n\]+ in thread_function1 at \[^\r\n\]+" \
+ "\\s+stop only in thread 1\\.3"] \
"thread specific breakpoint right thread"
}
}
diff --git a/gdb/testsuite/gdb.opt/break-on-_exit.exp b/gdb/testsuite/gdb.opt/break-on-_exit.exp
index 59a1c61..59fecaa 100644
--- a/gdb/testsuite/gdb.opt/break-on-_exit.exp
+++ b/gdb/testsuite/gdb.opt/break-on-_exit.exp
@@ -18,7 +18,7 @@
# set past the syscall due to faulty prologue skipping, the breakpoint will not
# trigger.
#
-# In particular, we're trying to excercise the instruction analysis
+# In particular, we're trying to exercise the instruction analysis
# functionality of prologue skipping. If the non-minimal symbols are
# read for libc, then that functionality might not be used because f.i.
# line-info is used instead. Also, if the minimal symbols are not read
diff --git a/gdb/testsuite/gdb.opt/inline-bt.exp b/gdb/testsuite/gdb.opt/inline-bt.exp
index 7220ec7..9e1fb19 100644
--- a/gdb/testsuite/gdb.opt/inline-bt.exp
+++ b/gdb/testsuite/gdb.opt/inline-bt.exp
@@ -32,23 +32,23 @@ if { [skip_inline_frame_tests] } {
set line1 [gdb_get_line_number "set breakpoint 1 here" ${srcfile2}]
gdb_breakpoint $srcfile2:$line1
-gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (1)"
-gdb_test "backtrace" "#0 bar.*#1 .*main.*" "backtrace from bar (1)"
+gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar, 1"
+gdb_test "backtrace" "#0 bar.*#1 .*main.*" "backtrace from bar, 1"
gdb_test "info frame" ".*called by frame.*" "bar not inlined"
-gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (2)"
+gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar, 2"
gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*main.*" \
- "backtrace from bar (2)"
-gdb_test "up" "#1 .*func1.*" "up from bar (2)"
-gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (2)"
+ "backtrace from bar, 2"
+gdb_test "up" "#1 .*func1.*" "up from bar, 2"
+gdb_test "info frame" ".*inlined into frame.*" "func1 inlined, 2"
-gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (3)"
+gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar, 3"
gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*func2.*#3 .*main.*" \
- "backtrace from bar (3)"
-gdb_test "up" "#1 .*func1.*" "up from bar (3)"
-gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (3)"
-gdb_test "up" "#2 .*func2.*" "up from func1 (3)"
-gdb_test "info frame" ".*inlined into frame.*" "func2 inlined (3)"
+ "backtrace from bar, 3"
+gdb_test "up" "#1 .*func1.*" "up from bar, 3"
+gdb_test "info frame" ".*inlined into frame.*" "func1 inlined, 3"
+gdb_test "up" "#2 .*func2.*" "up from func1, 3"
+gdb_test "info frame" ".*inlined into frame.*" "func2 inlined, 3"
# A regression test for having a backtrace limit that forces unwinding
# to stop after an inline frame. GDB needs to compute the frame_id of
@@ -61,7 +61,7 @@ gdb_test "info frame" ".*inlined into frame.*" "func2 inlined (3)"
gdb_test_no_output "set backtrace limit 2"
# Force flushing the frame cache.
gdb_test "maint flush register-cache" "Register cache flushed."
-gdb_test "up" "#1 .*func1.*" "up from bar (4)"
+gdb_test "up" "#1 .*func1.*" "up from bar, 4"
gdb_test "info frame" ".*in func1.*" "info frame still works"
# Verify the user visible limit works as expected.
gdb_test "up" "Initial frame selected; you cannot go up." "up hits limit"
diff --git a/gdb/testsuite/gdb.opt/inline-cmds.exp b/gdb/testsuite/gdb.opt/inline-cmds.exp
index bd645e5..7a9f2e0 100644
--- a/gdb/testsuite/gdb.opt/inline-cmds.exp
+++ b/gdb/testsuite/gdb.opt/inline-cmds.exp
@@ -40,19 +40,19 @@ gdb_breakpoint $srcfile2:$line1
set line2 [gdb_get_line_number "set breakpoint 2 here" ${srcfile2}]
gdb_breakpoint $srcfile2:$line2
-gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (1)"
+gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar, 1"
gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*main.*" \
- "backtrace from bar (1)"
-gdb_test "up" "#1 .*func1.*" "up from bar (1)"
-gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (1)"
+ "backtrace from bar, 1"
+gdb_test "up" "#1 .*func1.*" "up from bar, 1"
+gdb_test "info frame" ".*inlined into frame.*" "func1 inlined, 1"
-gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (2)"
+gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar, 2"
gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*func2.*#3 .*main.*" \
"backtrace from bar (2)"
-gdb_test "up" "#1 .*func1.*" "up from bar (2)"
-gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (2)"
-gdb_test "up" "#2 .*func2.*" "up from func1 (2)"
-gdb_test "info frame" ".*inlined into frame.*" "func2 inlined (2)"
+gdb_test "up" "#1 .*func1.*" "up from bar, 2"
+gdb_test "info frame" ".*inlined into frame.*" "func1 inlined, 2"
+gdb_test "up" "#2 .*func2.*" "up from func1, 2"
+gdb_test "info frame" ".*inlined into frame.*" "func2 inlined, 2"
gdb_test "continue" ".*set breakpoint 2 here.*" "continue to marker"
gdb_test "backtrace" "#0 marker.*#1 .*main.*" "backtrace from marker"
diff --git a/gdb/testsuite/gdb.pascal/floats.exp b/gdb/testsuite/gdb.pascal/floats.exp
index 3e836a3..d96fb9b 100644
--- a/gdb/testsuite/gdb.pascal/floats.exp
+++ b/gdb/testsuite/gdb.pascal/floats.exp
@@ -87,7 +87,7 @@ gdb_test "print r + (-1)" " = 0\\.2(499.*|5|500.*)"
gdb_test "print r + (-5)" " = -3\\.7(499.*|5|500.*)"
gdb_test "print r + (-10)" " = -8\\.7(499.*|5|500.*)"
-# Test substraction
+# Test subtraction
gdb_test "print r - s" " = -0\\.9(499.*|5|500.*)"
gdb_test "print r - t" " = 4\\.4(499.*|5|500.*)"
diff --git a/gdb/testsuite/gdb.pascal/integers.exp b/gdb/testsuite/gdb.pascal/integers.exp
index ec5f53c..974de6f 100644
--- a/gdb/testsuite/gdb.pascal/integers.exp
+++ b/gdb/testsuite/gdb.pascal/integers.exp
@@ -71,7 +71,7 @@ gdb_test "print i + k" " = 4"
gdb_test "print j + k" " = 5"
gdb_test "print i + j + k" " = 6"
-# Test substraction
+# Test subtraction
gdb_test "print j - i" " = 1"
gdb_test "print i - j" "= -1"
gdb_test "print k -i -j" " = 0"
diff --git a/gdb/testsuite/gdb.pascal/types.exp b/gdb/testsuite/gdb.pascal/types.exp
index 5b8d00b..262045e 100644
--- a/gdb/testsuite/gdb.pascal/types.exp
+++ b/gdb/testsuite/gdb.pascal/types.exp
@@ -59,7 +59,7 @@ proc test_float_literal_types_accepted {} {
# Test various floating point formats
# this used to guess whether to look for "real*4" or
- # "real*8" based on a target config variable, but noone
+ # "real*8" based on a target config variable, but no one
# maintained it properly.
gdb_test "pt .44" "type = double"
diff --git a/gdb/testsuite/gdb.python/py-arch.exp b/gdb/testsuite/gdb.python/py-arch.exp
index 3c58bf1..aef4186 100644
--- a/gdb/testsuite/gdb.python/py-arch.exp
+++ b/gdb/testsuite/gdb.python/py-arch.exp
@@ -28,7 +28,7 @@ if ![runto_main] {
# internal GDB assert.
gdb_py_test_silent_cmd "python empty = gdb.Architecture()" "get empty arch" 0
gdb_test "python print(repr (empty))" "<gdb\\.Architecture \\(invalid\\)>" \
- "Test empty achitecture __repr__ does not trigger an assert"
+ "Test empty architecture __repr__ does not trigger an assert"
gdb_test "python print(empty.name())" ".*Architecture is invalid.*" \
"Test empty architecture.name does not trigger an assert"
gdb_test "python print(empty.disassemble())" ".*Architecture is invalid.*" \
diff --git a/gdb/testsuite/gdb.python/py-breakpoint.exp b/gdb/testsuite/gdb.python/py-breakpoint.exp
index c44477c..934690d 100644
--- a/gdb/testsuite/gdb.python/py-breakpoint.exp
+++ b/gdb/testsuite/gdb.python/py-breakpoint.exp
@@ -743,7 +743,9 @@ proc_with_prefix test_bkpt_explicit_loc {} {
"No source file named foo.*" \
"set invalid explicit breakpoint by missing source and line"
gdb_test "python bp1 = gdb.Breakpoint (source=\"$srcfile\", line=\"900\")" \
- "No line 900 in file \"$srcfile\".*" \
+ [multi_line \
+ "^No compiled code for line 900 in file \"$srcfile\"\\." \
+ "Breakpoint $::decimal \[^\r\n\]+ pending\\."] \
"set invalid explicit breakpoint by source and invalid line"
gdb_test "python bp1 = gdb.Breakpoint (function=\"blah\")" \
"Function \"blah\" not defined.*" \
diff --git a/gdb/testsuite/gdb.python/py-cmd.exp b/gdb/testsuite/gdb.python/py-cmd.exp
index 82cb4cb..b083a80 100644
--- a/gdb/testsuite/gdb.python/py-cmd.exp
+++ b/gdb/testsuite/gdb.python/py-cmd.exp
@@ -128,19 +128,19 @@ gdb_test "test_error_cmd ugh" "you lose!" "call error command"
gdb_test "python print (gdb.string_to_argv (\"1 2 3\"))" \
{\['1', '2', '3'\]} \
- "string_to_argv (\"1 2 3\")"
+ "string_to_argv (\"1 2 3\"), case 1"
gdb_test "python print (gdb.string_to_argv (\"'1 2' 3\"))" \
{\['1 2', '3'\]} \
- "string_to_argv (\"'1 2' 3\")"
+ "string_to_argv (\"'1 2' 3\"), case 2"
gdb_test "python print (gdb.string_to_argv ('\"1 2\" 3'))" \
{\['1 2', '3'\]} \
- "string_to_argv ('\"1 2\" 3')"
+ "string_to_argv ('\"1 2\" 3'), case 3"
gdb_test "python print (gdb.string_to_argv ('1\\ 2 3'))" \
{\['1 2', '3'\]} \
- "string_to_argv ('1\\ 2 3')"
+ "string_to_argv ('1\\ 2 3'), case 4"
# Test user-defined python commands.
gdb_test_multiline "input simple user-defined command" \
diff --git a/gdb/testsuite/gdb.python/py-disasm-exec.exp b/gdb/testsuite/gdb.python/py-disasm-exec.exp
new file mode 100644
index 0000000..546c4b8
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-disasm-exec.exp
@@ -0,0 +1,21 @@
+# Copyright (C) 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite. It validates the Python
+# disassembler API.
+
+set kind exec
+
+source $srcdir/$subdir/py-disasm.exp.tcl
diff --git a/gdb/testsuite/gdb.python/py-disasm-obj.exp b/gdb/testsuite/gdb.python/py-disasm-obj.exp
new file mode 100644
index 0000000..37ff965
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-disasm-obj.exp
@@ -0,0 +1,21 @@
+# Copyright (C) 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite. It validates the Python
+# disassembler API.
+
+set kind obj
+
+source $srcdir/$subdir/py-disasm.exp.tcl
diff --git a/gdb/testsuite/gdb.python/py-disasm.exp b/gdb/testsuite/gdb.python/py-disasm.exp.tcl
index 5d7d922..8ed634e 100644
--- a/gdb/testsuite/gdb.python/py-disasm.exp
+++ b/gdb/testsuite/gdb.python/py-disasm.exp.tcl
@@ -20,26 +20,54 @@ load_lib gdb-python.exp
require allow_python_tests
-standard_testfile
+standard_testfile py-disasm.c
-if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} "debug"] } {
- return -1
-}
+if { $kind == "obj" } {
+
+ set obj [standard_output_file ${gdb_test_file_name}.o]
+
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $obj object "debug"] != "" } {
+ untested "failed to compile object file [file tail $obj]"
+ return -1
+ }
+
+ clean_restart $obj
+
+} else {
+
+ if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+ return -1
+ }
+
+ if { ![runto_main] } {
+ fail "can't run to main"
+ return 0
+ }
-if {![runto_main]} {
- fail "can't run to main"
- return 0
}
-set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
+set pyfile [gdb_remote_download host ${srcdir}/${subdir}/py-disasm.py]
gdb_test "source ${pyfile}" "Python script imported" \
"import python scripts"
-gdb_breakpoint [gdb_get_line_number "Break here."]
-gdb_continue_to_breakpoint "Break here."
+set line [gdb_get_line_number "Break here."]
-set curr_pc [get_valueof "/x" "\$pc" "*unknown*"]
+if { $kind == "obj" } {
+ set curr_pc "*unknown*"
+ set line [gdb_get_line_number "Break here."]
+ gdb_test_multiple "info line $line" "" {
+ -re -wrap "starts at address ($hex) \[^\r\n\]*" {
+ set curr_pc $expect_out(1,string)
+ pass $gdb_test_name
+ }
+ }
+} else {
+ gdb_breakpoint $line
+ gdb_continue_to_breakpoint "Break here."
+
+ set curr_pc [get_valueof "/x" "\$pc" "*unknown*"]
+}
gdb_test_no_output "python current_pc = ${curr_pc}"
@@ -67,7 +95,11 @@ proc py_remove_all_disassemblers {} {
# Python disassembler API.
set nop "(nop|nop\t0|[string_to_regexp nop\t{0}])"
set unknown_error_pattern "unknown disassembler error \\(error = -1\\)"
-set addr_pattern "\r\n=> ${curr_pc_pattern} <\[^>\]+>:\\s+"
+if { $kind == "obj" } {
+ set addr_pattern "\r\n ${curr_pc_pattern} <\[^>\]+>:\\s+"
+} else {
+ set addr_pattern "\r\n=> ${curr_pc_pattern} <\[^>\]+>:\\s+"
+}
set base_pattern "${addr_pattern}${nop}"
# Helper proc to format a Python exception of TYPE with MSG.
diff --git a/gdb/testsuite/gdb.python/py-disasm.py b/gdb/testsuite/gdb.python/py-disasm.py
index 2741fdb..f105657 100644
--- a/gdb/testsuite/gdb.python/py-disasm.py
+++ b/gdb/testsuite/gdb.python/py-disasm.py
@@ -252,7 +252,7 @@ class MemoryErrorEarlyDisassembler(TestDisassembler):
def disassemble(self, info):
tag = "## FAIL"
try:
- info.read_memory(1, -info.address + 2)
+ info.read_memory(1, -info.address - 1)
except gdb.MemoryError:
tag = "## AFTER ERROR"
result = builtin_disassemble_wrapper(info)
@@ -267,7 +267,7 @@ class MemoryErrorLateDisassembler(TestDisassembler):
def disassemble(self, info):
result = builtin_disassemble_wrapper(info)
# The following read will throw an error.
- info.read_memory(1, -info.address + 2)
+ info.read_memory(1, -info.address - 1)
return DisassemblerResult(1, "BAD")
@@ -276,9 +276,9 @@ class RethrowMemoryErrorDisassembler(TestDisassembler):
def disassemble(self, info):
try:
- info.read_memory(1, -info.address + 2)
+ info.read_memory(1, -info.address - 1)
except gdb.MemoryError as e:
- raise gdb.MemoryError("cannot read code at address 0x2")
+ raise gdb.MemoryError("cannot read code at address -1")
return DisassemblerResult(1, "BAD")
diff --git a/gdb/testsuite/gdb.python/py-format-string.exp b/gdb/testsuite/gdb.python/py-format-string.exp
index 0c70ad5..d0349c5 100644
--- a/gdb/testsuite/gdb.python/py-format-string.exp
+++ b/gdb/testsuite/gdb.python/py-format-string.exp
@@ -82,7 +82,7 @@ set default_pointer_regexp "0x\[a-fA-F0-9\]+"
# A regular expression for a non-expanded C++ reference.
#
-# Stringifying a C++ reference produces an address preceeded by a "@" in
+# Stringifying a C++ reference produces an address preceded by a "@" in
# Python, but, by default, the C++ reference/class is expanded by the
# GDB print command.
set default_ref_regexp "@${default_pointer_regexp}"
@@ -1104,10 +1104,16 @@ proc_with_prefix test_invalid_args {} {
"12" \
"TypeError.*: format_string\\(\\) takes 0 positional arguments but 1 were given.*"
+ # For python <= 3.12.
+ set re1 \
+ "TypeError.*: 'invalid' is an invalid keyword argument for this function"
+ # For python >= 3.13.
+ set re2 \
+ "TypeError.*: this function got an unexpected keyword argument 'invalid'"
check_format_string \
"a_point_t" \
"invalid=True" \
- "TypeError.*: 'invalid' is an invalid keyword argument for this function.*"
+ "($re1|$re2).*"
check_format_string \
"a_point_t" \
diff --git a/gdb/testsuite/gdb.python/py-frame.exp b/gdb/testsuite/gdb.python/py-frame.exp
index 8f776eb..0f1528e 100644
--- a/gdb/testsuite/gdb.python/py-frame.exp
+++ b/gdb/testsuite/gdb.python/py-frame.exp
@@ -127,10 +127,10 @@ gdb_test "python print (f1 == gdb.newest_frame())" False \
gdb_test "python print (bframe == gdb.newest_frame())" True \
"newest frame -vs- newest frame"
-gdb_test "python print ('result = %s' % (f0 == f1))" " = False" "test equality comparison (false)"
-gdb_test "python print ('result = %s' % (f0 == f0))" " = True" "test equality comparison (true)"
-gdb_test "python print ('result = %s' % (f0 != f1))" " = True" "test inequality comparison (true)"
-gdb_test "python print ('result = %s' % (f0 != f0))" " = False" "test inequality comparison (false)"
+gdb_test "python print ('result = %s' % (f0 == f1))" " = False" "test equality comparison, false"
+gdb_test "python print ('result = %s' % (f0 == f0))" " = True" "test equality comparison, true"
+gdb_test "python print ('result = %s' % (f0 != f1))" " = True" "test inequality comparison, true"
+gdb_test "python print ('result = %s' % (f0 != f0))" " = False" "test inequality comparison, false"
gdb_test "python print ('result = %s' % f0.is_valid ())" " = True" "test Frame.is_valid"
gdb_test "python print ('result = %s' % f0.name ())" " = f2" "test Frame.name"
gdb_test "python print ('result = %s' % (f0.type () == gdb.NORMAL_FRAME))" " = True" "test Frame.type"
diff --git a/gdb/testsuite/gdb.python/py-framefilter-invalidarg.exp b/gdb/testsuite/gdb.python/py-framefilter-invalidarg.exp
index 481eead..0e78f8d 100644
--- a/gdb/testsuite/gdb.python/py-framefilter-invalidarg.exp
+++ b/gdb/testsuite/gdb.python/py-framefilter-invalidarg.exp
@@ -58,4 +58,4 @@ set remote_python_file [gdb_remote_download host \
${srcdir}/${subdir}/${testfile}.py]
gdb_test_no_output "source ${remote_python_file}" "load python file"
-gdb_test "bt" "niam \\(argc=<error reading variable: dwarf expression stack underflow>, argv=0x\[0-9a-f\]+\\) at py-framefilter-invalidarg.c:\[0-9\]+" "bt full with filters"
+gdb_test "bt" "niam \\(argc=<error reading variable: dwarf expression stack underflow>, argv=0x\[0-9a-f\]+\\) at \[^\r\n\]*py-framefilter-invalidarg.c:\[0-9\]+" "bt full with filters"
diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp
index ee30390..58475bd 100644
--- a/gdb/testsuite/gdb.python/py-inferior.exp
+++ b/gdb/testsuite/gdb.python/py-inferior.exp
@@ -27,12 +27,13 @@ if { [gdb_compile_pthreads ${srcdir}/${subdir}/${srcfile} ${binfile} executable
}
# Start with a fresh gdb.
-save_vars { env(ASAN_OPTIONS) } {
+save_vars { env(ASAN_OPTIONS) env(TSAN_OPTIONS) } {
# The call to gdb.selected_inferior().read_memory (0, 0xffffffffffffffff)
# triggers address sanitizer. Suppress the error, leaving us with just
# this warning:
# WARNING: AddressSanitizer failed to allocate 0xffffffffffffffff bytes
set_sanitizer ASAN_OPTIONS allocator_may_return_null 1
+ set_sanitizer TSAN_OPTIONS allocator_may_return_null 1
clean_restart ${testfile}
}
diff --git a/gdb/testsuite/gdb.python/py-mi-cmd.exp b/gdb/testsuite/gdb.python/py-mi-cmd.exp
index 28c71cd..5291409 100644
--- a/gdb/testsuite/gdb.python/py-mi-cmd.exp
+++ b/gdb/testsuite/gdb.python/py-mi-cmd.exp
@@ -119,13 +119,47 @@ mi_gdb_test "-pycmd dash-key" \
# With this argument the command raises a gdb.GdbError with no message
# string. GDB considers this a bug in the user program, so prints a
# backtrace, and a generic error message.
-mi_gdb_test "-pycmd exp" \
- [multi_line ".*&\"Traceback \\(most recent call last\\):..\"" \
- "&\"\[^\r\n\]+${testfile}.py\[^\r\n\]+\"" \
- "&\"\[^\r\n\]+raise gdb.GdbError\\(\\)..\"" \
- "&\"gdb.GdbError..\"" \
- "\\^error,msg=\"Error occurred in Python\\.\""] \
- "-pycmd exp"
+
+set line1 \
+ [string_to_regexp {Traceback (most recent call last):\n}]
+set line2 \
+ [string cat \
+ [string_to_regexp { File \"}] \
+ "\[^\r\n\]+" \
+ [string_to_regexp ${testfile}.py] \
+ [string_to_regexp {\", line }] \
+ $decimal \
+ [string_to_regexp {, in invoke\n}]]
+set line3 \
+ [string_to_regexp { raise gdb.GdbError()\n}]
+set line4 \
+ [string_to_regexp {gdb.GdbError\n}]
+set errline \
+ [string_to_regexp {^error,msg="Error occurred in Python."}]
+
+set start_line \
+ [string_to_regexp {&"}]
+set end_line \
+ [string_to_regexp {"}]
+
+# With python <= 3.12.
+set re1 \
+ [multi_line \
+ $start_line$line1$end_line \
+ $start_line$line2$end_line \
+ $start_line$line3$end_line \
+ $start_line$line4$end_line \
+ $errline]
+
+# With python >= 3.13.
+set re2 \
+ [multi_line \
+ $start_line$line1$end_line \
+ $start_line$line2$line3$end_line \
+ $start_line$line4$end_line \
+ $errline]
+
+mi_gdb_test "-pycmd exp" ($re1|$re2)
mi_gdb_test "python pycmd2('-pycmd')" \
".*\\^done" \
diff --git a/gdb/testsuite/gdb.python/py-missing-debug.exp b/gdb/testsuite/gdb.python/py-missing-debug.exp
index d1eef34..dfc0a46 100644
--- a/gdb/testsuite/gdb.python/py-missing-debug.exp
+++ b/gdb/testsuite/gdb.python/py-missing-debug.exp
@@ -19,7 +19,8 @@ require allow_python_tests
standard_testfile
-if {[build_executable "failed to prepare" ${testfile} ${srcfile}]} {
+if {[build_executable "failed to prepare" ${testfile} ${srcfile} \
+ {debug build-id}]} {
return -1
}
diff --git a/gdb/testsuite/gdb.python/py-pp-cast.py b/gdb/testsuite/gdb.python/py-pp-cast.py
index 6eff800..c071920 100644
--- a/gdb/testsuite/gdb.python/py-pp-cast.py
+++ b/gdb/testsuite/gdb.python/py-pp-cast.py
@@ -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/>.
+import gdb.printing
+
class PpIntPrinter(object):
def __init__(self, val):
diff --git a/gdb/testsuite/gdb.python/py-pp-maint.exp b/gdb/testsuite/gdb.python/py-pp-maint.exp
index f224ae7..1ee206c 100644
--- a/gdb/testsuite/gdb.python/py-pp-maint.exp
+++ b/gdb/testsuite/gdb.python/py-pp-maint.exp
@@ -55,7 +55,7 @@ gdb_test "print flt" " = x=<42> y=<43>" \
gdb_test "print ss" " = a=<a=<1> b=<$hex>> b=<a=<2> b=<$hex>>" \
"print ss enabled #1"
-set num_pp 7
+set num_pp 6
gdb_test "disable pretty-printer" \
"$num_pp printers disabled.*0 of $num_pp printers enabled"
@@ -75,7 +75,7 @@ gdb_test "disable pretty-printer global lookup_function_lookup_test" \
"1 printer disabled.*[expr $num_pp - 1] of $num_pp printers enabled"
gdb_test "disable pretty-printer global pp-test;.*" \
- "[expr $num_pp - 2] printers disabled.*1 of $num_pp printers enabled"
+ "[expr 5] printers disabled.*0 of $num_pp printers enabled"
gdb_test "info pretty-printer global .*function" \
{.*function_lookup_test \[disabled\].*} \
@@ -92,13 +92,13 @@ gdb_test "print ss" " = {a = {a = 1, b = $hex}, b = {a = 2, b = $hex}}" \
"print ss disabled"
gdb_test "enable pretty-printer global lookup_function_lookup_test" \
- "1 printer enabled.*2 of $num_pp printers enabled"
+ "1 printer enabled.*1 of $num_pp printers enabled"
# This doesn't enable any printers because each subprinter in the collection
# is still individually disabled. But this is still needed, to enable the
# collection itself.
gdb_test "enable pretty-printer global pp-test" \
- "0 printers enabled.*2 of $num_pp printers enabled"
+ "0 printers enabled.*1 of $num_pp printers enabled"
gdb_test "enable pretty-printer global pp-test;.*ss.*" \
"2 printers enabled.*[expr $num_pp - 3] of $num_pp printers enabled"
diff --git a/gdb/testsuite/gdb.python/py-pp-re-notag.py b/gdb/testsuite/gdb.python/py-pp-re-notag.py
index 6aefad1..00bc5c7 100644
--- a/gdb/testsuite/gdb.python/py-pp-re-notag.py
+++ b/gdb/testsuite/gdb.python/py-pp-re-notag.py
@@ -16,6 +16,7 @@
from time import asctime, gmtime
import gdb # silence pyflakes
+import gdb.printing
class TimePrinter:
diff --git a/gdb/testsuite/gdb.python/py-prettyprint-stub.py b/gdb/testsuite/gdb.python/py-prettyprint-stub.py
index 565ae19..2378f55 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint-stub.py
+++ b/gdb/testsuite/gdb.python/py-prettyprint-stub.py
@@ -16,6 +16,8 @@
# This file is part of the GDB testsuite.
# It tests Python-based pretty-printing of stubs.
+import gdb.printing
+
class SPrinter:
def __init__(self, val):
diff --git a/gdb/testsuite/gdb.python/py-progspace-events.exp b/gdb/testsuite/gdb.python/py-progspace-events.exp
index 95e4ca8..9dfc757 100644
--- a/gdb/testsuite/gdb.python/py-progspace-events.exp
+++ b/gdb/testsuite/gdb.python/py-progspace-events.exp
@@ -79,37 +79,16 @@ gdb_test "continue" \
"\\\[Inferior $decimal \[^\r\n\]+ exited normally\\\]"] \
"continue until inferior 2 exits"
-gdb_test "inferior 1" "\\\[Switching to inferior 1 .*"
-
-# Step the inferior. During this process GDB will prune the now
+# Switch to inferior 1. During this process GDB will prune the now
# defunct inferior, which deletes its program space, which should
# trigger the FreeProgspaceEvent.
#
-# However, there is a slight problem. When the target is remote, and
-# GDB is accessing files using remote fileio, then GDB will attempt to
-# prune the inferior at a point in time when the remote target is
-# waiting for a stop reply. Pruning an inferior causes GDB to close
-# files associated with that inferior.
-#
-# In non-async mode we can't send fileio packets while waiting for a
-# stop reply, so the attempts to close files fails, and this shows up
-# as an error.
-#
-# As this error has nothing to do with the feature being tested here,
-# we just accept the error message, the important part is the
-# 'FreeProgspaceEvent' string, so long as that appears (just once)
-# then the test is a success.
-set warning_msg \
- [multi_line \
- "warning: cannot close \"\[^\r\n\]+\": Cannot execute this command while the target is running\\." \
- "Use the \"interrupt\" command to stop the target" \
- "and then try again\\."]
-gdb_test "step" \
+gdb_test "inferior 1" \
[multi_line \
- "^FreeProgspaceEvent.*: <gdb.Progspace object at $hex>(?:\r\n$warning_msg)*" \
- "do_parent_stuff \\(\\) at \[^\r\n\]+" \
- "$decimal\\s+\[^\r\n\]+"]
+ "\\\[Switching to inferior 1 .*" \
+ ".*" \
+ "FreeProgspaceEvent.*: <gdb.Progspace object at $hex>"]
# Let this inferior run to completion.
gdb_continue_to_end
diff --git a/gdb/testsuite/gdb.python/py-progspace.exp b/gdb/testsuite/gdb.python/py-progspace.exp
index 0ae5b56..fe46537 100644
--- a/gdb/testsuite/gdb.python/py-progspace.exp
+++ b/gdb/testsuite/gdb.python/py-progspace.exp
@@ -42,7 +42,7 @@ gdb_py_test_silent_cmd "python progspace = gdb.current_progspace()" \
"Get current progspace" 1
gdb_test "python print (progspace.filename)" "py-progspace" \
- "current progspace filename (py-progspace)"
+ "current progspace filename, py-progspace"
gdb_test "python print (gdb.current_progspace().symbol_file)" \
"<gdb.Objfile filename=.*/py-progspace>" \
diff --git a/gdb/testsuite/gdb.python/py-read-memory-leak.c b/gdb/testsuite/gdb.python/py-read-memory-leak.c
new file mode 100644
index 0000000..75035cd
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-read-memory-leak.c
@@ -0,0 +1,27 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014-2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+static struct x
+{
+ char unsigned u[4096];
+} x, *px = &x;
+
+int
+main (void)
+{
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.python/py-read-memory-leak.exp b/gdb/testsuite/gdb.python/py-read-memory-leak.exp
new file mode 100644
index 0000000..52b072f
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-read-memory-leak.exp
@@ -0,0 +1,44 @@
+# Copyright (C) 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite. It checks for memory leaks
+# associated with calling gdb.Inferior.read_memory().
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
+ return -1
+}
+
+if ![runto_main] {
+ return -1
+}
+
+# Skip this test if the tracemalloc module is not available.
+if { ![gdb_py_module_available "tracemalloc"] } {
+ unsupported "tracemalloc module not available"
+ return
+}
+
+set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
+
+# Source the Python script, this runs the test (which is written
+# completely in Python), and either prints PASS, or throws an
+# exception.
+gdb_test "source ${pyfile}" "PASS" "source python script"
diff --git a/gdb/testsuite/gdb.python/py-read-memory-leak.py b/gdb/testsuite/gdb.python/py-read-memory-leak.py
new file mode 100644
index 0000000..430c5c2
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-read-memory-leak.py
@@ -0,0 +1,93 @@
+# Copyright (C) 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import tracemalloc
+
+import gdb
+
+# A global variable in which we store a reference to the memory buffer
+# returned from gdb.Inferior.read_memory().
+mem_buf = None
+
+
+# A global filters list, we only care about memory allocations
+# originating from this script.
+filters = [tracemalloc.Filter(True, "*" + os.path.basename(__file__))]
+
+
+# Run the test. When CLEAR is True we clear the global INF variable
+# before comparing the before and after memory allocation traces.
+# When CLEAR is False we leave INF set to reference the gdb.Inferior
+# object, thus preventing the gdb.Inferior from being deallocated.
+def test(clear):
+ global filters, mem_buf
+
+ addr = gdb.parse_and_eval("px")
+ inf = gdb.inferiors()[0]
+
+ # Start tracing, and take a snapshot of the current allocations.
+ tracemalloc.start()
+ snapshot1 = tracemalloc.take_snapshot()
+
+ # Read from the inferior, this allocate a memory buffer object.
+ mem_buf = inf.read_memory(addr, 4096)
+
+ # Possibly clear the global INF variable.
+ if clear:
+ mem_buf = None
+
+ # Now grab a second snapshot of memory allocations, and stop
+ # tracing memory allocations.
+ snapshot2 = tracemalloc.take_snapshot()
+ tracemalloc.stop()
+
+ # Filter the snapshots; we only care about allocations originating
+ # from this file.
+ snapshot1 = snapshot1.filter_traces(filters)
+ snapshot2 = snapshot2.filter_traces(filters)
+
+ # Compare the snapshots, this leaves only things that were
+ # allocated, but not deallocated since the first snapshot.
+ stats = snapshot2.compare_to(snapshot1, "traceback")
+
+ # Total up all the allocated things.
+ total = 0
+ for stat in stats:
+ total += stat.size_diff
+ return total
+
+
+# The first time we run this some global state will be allocated which
+# shows up as memory that is allocated, but not released. So, run the
+# test once and discard the result.
+test(True)
+
+# Now run the test twice, the first time we clear our global reference
+# to the memory buffer object, which should allow Python to deallocate
+# the object. The second time we hold onto the global reference,
+# preventing Python from performing the deallocation.
+bytes_with_clear = test(True)
+bytes_without_clear = test(False)
+
+# The bug that used to exist in GDB was that even when we released the
+# global reference the gdb.Inferior object would not be deallocated.
+if bytes_with_clear > 0:
+ raise gdb.GdbError("memory leak when memory buffer should be released")
+if bytes_without_clear == 0:
+ raise gdb.GdbError("memory buffer object is no longer allocated")
+
+# Print a PASS message that the test script can see.
+print("PASS")
diff --git a/gdb/testsuite/gdb.python/py-record-btrace.exp b/gdb/testsuite/gdb.python/py-record-btrace.exp
index fba0b98..b035e14 100644
--- a/gdb/testsuite/gdb.python/py-record-btrace.exp
+++ b/gdb/testsuite/gdb.python/py-record-btrace.exp
@@ -198,3 +198,14 @@ with_test_prefix "level" {
gdb_test "python print(gdb.current_recording().function_call_history\[0\].level)" "1"
gdb_test "python print(gdb.current_recording().function_call_history\[1\].level)" "0"
}
+
+# Note: GDB can incrementally add to the recording from the raw trace data.
+# After a clear(), GDB might not have all the raw trace data available in its
+# buffer to recreate the full recording it had before the clear().
+# So, do this testing last to avoid disturbing subsequent tests.
+with_test_prefix "clear" {
+ gdb_test_no_output "python r.clear()"
+ gdb_test "python insn = r.instruction_history"
+ gdb_test_no_output "python i = insn\[0\]"
+ gdb_test "python print(i.size)" "$decimal"
+}
diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp
index e524959..7e469c9 100644
--- a/gdb/testsuite/gdb.python/py-type.exp
+++ b/gdb/testsuite/gdb.python/py-type.exp
@@ -57,10 +57,10 @@ proc test_fields {lang} {
if {$lang == "c++"} {
# Test usage with a class
- gdb_py_test_silent_cmd "print (c)" "print value (c)" 1
+ gdb_py_test_silent_cmd "print (c)" "print value(c)" 1
gdb_py_test_silent_cmd "python c = gdb.history (0)" "get value (c) from history" 1
gdb_py_test_silent_cmd "python fields = c.type.fields()" "get fields from c.type" 1
- gdb_test "python print (len(fields))" "2" "check number of fields (c)"
+ gdb_test "python print (len(fields))" "2" "check number of fields, c"
gdb_test "python print (fields\[0\].name)" "c" "check class field c name"
gdb_test "python print (fields\[1\].name)" "d" "check class field d name"
@@ -94,12 +94,12 @@ proc test_fields {lang} {
}
# Test normal fields usage in structs.
- gdb_py_test_silent_cmd "print (st)" "print value (st)" 1
+ gdb_py_test_silent_cmd "print (st)" "print value(st)" 1
gdb_py_test_silent_cmd "python st = gdb.history (0)" "get value (st) from history" 1
gdb_py_test_silent_cmd "python fields = st.type.fields()" "get fields from st.type" 1
gdb_test "python print (st.type.objfile.filename == gdb.current_progspace ().filename)" "True" \
"check type.objfile"
- gdb_test "python print (len(fields))" "2" "check number of fields (st)"
+ gdb_test "python print (len(fields))" "2" "check number of fields, st"
gdb_test "python print (fields\[0\].name)" "a" "check structure field a name"
gdb_test "python print (fields\[1\].name)" "b" "check structure field b name"
@@ -118,7 +118,7 @@ proc test_fields {lang} {
"Check that dir includes name"
# Test Python mapping behavior of gdb.Type for structs/classes
- gdb_test "python print (len(st.type))" "2" "check number of fields (st.type)"
+ gdb_test "python print (len(st.type))" "2" "check number of fields, st.type"
gdb_test "python print (st.type\['a'\].name)" "a" "check fields lookup by name"
gdb_test "python print (\[v.bitpos for v in st.type.itervalues()\])" {\[0L?, 32L?\]} "Check fields iteration over values"
gdb_test "python print (\[(n, v.bitpos) for (n, v) in st.type.items()\])" {\[\('a', 0L?\), \('b', 32L?\)\]} "Check fields items list"
@@ -136,7 +136,7 @@ proc test_fields {lang} {
gdb_test "python print (not not st.type\['a'\].type)" "True"
# Test regression PR python/10805
- gdb_py_test_silent_cmd "print (ar)" "print value (ar)" 1
+ gdb_py_test_silent_cmd "print (ar)" "print value(ar)" 1
gdb_py_test_silent_cmd "python ar = gdb.history (0)" "get value (ar) from history" 1
gdb_test "python fields = ar.type.fields()"
gdb_test "python print (len(fields))" "1" "check the number of fields"
@@ -153,10 +153,10 @@ proc test_fields {lang} {
# Test gdb.Type.vector.
# Note: vectors cast differently than arrays. Here ar[0] is replicated
# for the size of the vector.
- gdb_py_test_silent_cmd "print (vec_data_1)" "print value (vec_data_1)" 1
+ gdb_py_test_silent_cmd "print (vec_data_1)" "print value(vec_data_1)" 1
gdb_py_test_silent_cmd "python vec_data_1 = gdb.history (0)" "get value (vec_data_1) from history" 1
- gdb_py_test_silent_cmd "print (vec_data_2)" "print value (vec_data_2)" 1
+ gdb_py_test_silent_cmd "print (vec_data_2)" "print value(vec_data_2)" 1
gdb_py_test_silent_cmd "python vec_data_2 = gdb.history (0)" "get value (vec_data_2) from history" 1
gdb_py_test_silent_cmd "python vec1 = vec_data_1.cast(ar\[0\].type.vector(1))" "set vec1" 1
@@ -179,7 +179,7 @@ proc test_fields {lang} {
proc test_enums {} {
with_test_prefix "test_enum" {
- gdb_py_test_silent_cmd "print (e)" "print value (e)" 1
+ gdb_py_test_silent_cmd "print (e)" "print value(e)" 1
gdb_py_test_silent_cmd "python (e) = gdb.history (0)" "get value (e) from history" 1
gdb_py_test_silent_cmd "python fields = e.type.fields()" "extract type fields from e" 1
gdb_test "python print (len(fields))" "3" "check the number of enum fields"
@@ -188,8 +188,8 @@ proc test_enums {} {
# Ditto but by mapping operations
gdb_test "python print (len(e.type))" "3" "check the number of type fields"
- gdb_test "python print (e.type\['v1'\].name)" "v1" "check enum field lookup by name (v1)"
- gdb_test "python print (e.type\['v3'\].name)" "v3" "check enum field lookup by name (v3)"
+ gdb_test "python print (e.type\['v1'\].name)" "v1" "check enum field lookup by name, v1"
+ gdb_test "python print (e.type\['v3'\].name)" "v3" "check enum field lookup by name, v3"
gdb_test "python print (\[v.enumval for v in e.type.itervalues()\])" {\[0L?, 1L?, 2L?\]} "Check num fields iteration over values"
gdb_test "python print (\[(n, v.enumval) for (n, v) in e.type.items()\])" {\[\('v1', 0L?\), \('v2', 1L?\), \('v3', 2L?\)\]} "Check enum fields items list"
}
@@ -197,12 +197,12 @@ proc test_enums {} {
proc test_base_class {} {
with_test_prefix "test_base_class" {
- gdb_py_test_silent_cmd "print (d)" "print value (d)" 1
+ gdb_py_test_silent_cmd "print (d)" "print value(d)" 1
gdb_py_test_silent_cmd "python d = gdb.history (0)" "get value (d) from history" 1
gdb_py_test_silent_cmd "python fields = d.type.fields()" "extract type fields from d" 1
gdb_test "python print (len(fields))" "3" "check the number of fields"
- gdb_test "python print (fields\[0\].is_base_class)" "True" "check base class (fields\[0\])"
- gdb_test "python print (fields\[1\].is_base_class)" "False" "check base class (fields\[1\])"
+ gdb_test "python print (fields\[0\].is_base_class)" "True" {check base class, fields[0]}
+ gdb_test "python print (fields\[1\].is_base_class)" "False" {check base class, fields[1]}
}
}
@@ -210,7 +210,7 @@ proc test_range {} {
with_test_prefix "test_range" {
with_test_prefix "on ranged value" {
# Test a valid range request.
- gdb_py_test_silent_cmd "print (ar)" "print value (ar)" 1
+ gdb_py_test_silent_cmd "print (ar)" "print value(ar)" 1
gdb_py_test_silent_cmd "python ar = gdb.history (0)" "get value (ar) from history" 1
gdb_test "python print (len(ar.type.range()))" "2" "check correct tuple length"
gdb_test "python print (ar.type.range()\[0\])" "0" "check range low bound"
@@ -219,7 +219,7 @@ proc test_range {} {
with_test_prefix "on ranged type" {
# Test a range request on a ranged type.
- gdb_py_test_silent_cmd "print (ar)" "print value (ar)" 1
+ gdb_py_test_silent_cmd "print (ar)" "print value(ar)" 1
gdb_py_test_silent_cmd "python ar = gdb.history (0)" "get value (ar) from history" 1
gdb_py_test_silent_cmd "python fields = ar.type.fields()" "get fields" 1
gdb_test "python print (fields\[0\].type.range()\[0\])" "0" "check range low bound"
@@ -228,7 +228,7 @@ proc test_range {} {
with_test_prefix "on unranged value" {
# Test where a range does not exist.
- gdb_py_test_silent_cmd "print (st)" "print value (st)" 1
+ gdb_py_test_silent_cmd "print (st)" "print value(st)" 1
gdb_py_test_silent_cmd "python st = gdb.history (0)" "get value (st) from history" 1
gdb_test "python print (st.type.range())" "RuntimeError.*: This type does not have a range.*" "check range for non ranged type."
}
diff --git a/gdb/testsuite/gdb.python/py-xmethods.exp b/gdb/testsuite/gdb.python/py-xmethods.exp
index 1ff7067..55ec66c 100644
--- a/gdb/testsuite/gdb.python/py-xmethods.exp
+++ b/gdb/testsuite/gdb.python/py-xmethods.exp
@@ -179,8 +179,8 @@ gdb_test_no_output "python gdb.set_parameter('max-value-size', 16)"
gdb_test "p a1.getarray()" \
"From Python <A_getarray>.*value requires $decimal bytes,\
which is more than max-value-size" \
- "after: a1.getarray (max-value-size)"
+ "after: a1.getarray, max-value-size"
gdb_test "p b1.getarray()" \
"From Python <B_getarray>.*value requires $decimal bytes,\
which is more than max-value-size" \
- "after: b1.getarray (max-value-size)"
+ "after: b1.getarray, max-value-size"
diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp
index 175a6de..e8eb9ec 100644
--- a/gdb/testsuite/gdb.python/python.exp
+++ b/gdb/testsuite/gdb.python/python.exp
@@ -561,3 +561,12 @@ if { [use_gdb_stub] == 0 } {
}
}
}
+
+# Regression test for PR python/32163: several types were not
+# previously registered with the module, so could not be inspected
+# directly.
+foreach type {Instruction LazyString Membuf Record RecordFunctionSegment \
+ RecordGap RecordInstruction TuiWindow} {
+ gdb_test "python print(type(gdb.$type))" "<class 'type'>" \
+ "gdb.$type is registered"
+}
diff --git a/gdb/testsuite/gdb.python/sys-exit.exp b/gdb/testsuite/gdb.python/sys-exit.exp
new file mode 100644
index 0000000..3396b8d
--- /dev/null
+++ b/gdb/testsuite/gdb.python/sys-exit.exp
@@ -0,0 +1,69 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Check that python sys.exit makes gdb exit, with the correct exit status.
+
+require allow_python_tests
+
+# Have this code in a proc avoids clashing with runtest variable exit_status.
+
+proc do_test { n {expected_exit_status ""} {msg ""}} {
+ if { $expected_exit_status == "" } {
+ set expected_exit_status $n
+ }
+
+ with_test_prefix $n {
+ clean_restart
+
+ # Regression test for PR python/31946.
+ set seen_message 0
+ gdb_test_multiple "python sys.exit ($n)" "python sys.exit" {
+ -re "\r\n$msg\r\n" {
+ set seen_message 1
+ exp_continue
+ }
+ eof {
+ set wait_status [wait -i $::gdb_spawn_id]
+ clear_gdb_spawn_id
+
+ verbose -log "GDB process exited with wait status $wait_status"
+
+ set os_error [lindex $wait_status 2]
+ set exit_status [lindex $wait_status 3]
+
+ gdb_assert \
+ { $os_error == 0 \
+ && $exit_status == $expected_exit_status } \
+ $gdb_test_name
+
+ if { $msg != "" } {
+ gdb_assert { $seen_message }
+ }
+ }
+ }
+ }
+}
+
+# Test sys.exit (<int>).
+do_test 0
+do_test 1
+do_test 2
+
+# Test sys.exit (None).
+do_test None 0
+
+# Test sys.exit (<string>).
+do_test {"Error Message"} 1 "Error Message"
+do_test {""} 1
diff --git a/gdb/testsuite/gdb.reverse/break-precsave.exp b/gdb/testsuite/gdb.reverse/break-precsave.exp
index b9d9468..6d9b312 100644
--- a/gdb/testsuite/gdb.reverse/break-precsave.exp
+++ b/gdb/testsuite/gdb.reverse/break-precsave.exp
@@ -73,7 +73,7 @@ proc precsave_tests {} {
-re ".*Breakpoint $decimal,.*$srcfile:$end_location.*$gdb_prompt $" {
pass "go to end of main forward"
}
- -re "No more reverse-execution history.* end of main .*$gdb_prompt $" {
+ -re -wrap "Reached end of recorded.*Following forward.* end of main .*" {
pass "go to end of main forward"
}
}
@@ -87,7 +87,7 @@ proc precsave_tests {} {
-re ".*Breakpoint $decimal,.*$srcfile:$main_location.*$gdb_prompt $" {
pass "main backward"
}
- -re "No more reverse-execution history.* break in main .*$gdb_prompt $" {
+ -re -wrap "Reached end of recorded.*Backward execution.* break in main .*" {
pass "main backward"
}
}
@@ -103,7 +103,7 @@ proc precsave_tests {} {
-re ".*Breakpoint $decimal,.*$srcfile:$end_location.*$gdb_prompt $" {
pass "end of record log"
}
- -re "No more reverse-execution history.* end of main .*$gdb_prompt $" {
+ -re -wrap "Reached end of recorded.*Following forward.* end of main .*" {
pass "end of record log"
}
}
diff --git a/gdb/testsuite/gdb.reverse/break-reverse.exp b/gdb/testsuite/gdb.reverse/break-reverse.exp
index 1dd327c..66e9712 100644
--- a/gdb/testsuite/gdb.reverse/break-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/break-reverse.exp
@@ -64,7 +64,7 @@ gdb_test_multiple "continue" "main backward" {
-re ".*Breakpoint $decimal,.*$srcfile:$main_location.*$gdb_prompt $" {
pass "main backward"
}
- -re "No more reverse-execution history.* break in main .*$gdb_prompt $" {
+ -re -wrap "Reached end of recorded history.*Backward execution.*" {
pass "main backward"
}
}
@@ -80,7 +80,7 @@ gdb_test_multiple "continue" "end of record log" {
-re ".*Breakpoint $decimal,.*$srcfile:$end_location.*$gdb_prompt $" {
pass "end of record log"
}
- -re "No more reverse-execution history.* end of main .*$gdb_prompt $" {
+ -re -wrap "Reached end of recorded history.*Following forward.*" {
pass "end of record log"
}
}
diff --git a/gdb/testsuite/gdb.reverse/func-map-to-same-line.exp b/gdb/testsuite/gdb.reverse/func-map-to-same-line.exp
index 9949907..8f933eb 100644
--- a/gdb/testsuite/gdb.reverse/func-map-to-same-line.exp
+++ b/gdb/testsuite/gdb.reverse/func-map-to-same-line.exp
@@ -37,7 +37,7 @@ proc run_tests {} {
gdb_test_no_output "record" "turn on process record"
# This regression test verifies the reverse-step and reverse-next
- # commands work properly when executing backwards thru a source line
+ # commands work properly when executing backwards through a source line
# containing two function calls on the same source line, i.e.
# func1 (); func2 ();. This test is compiled so the dwarf info
# does not contain the line table information.
@@ -100,7 +100,7 @@ proc run_tests {} {
# the called function, stopping at the beginning of the last
# statement in the called function (typically a return statement).
# Also, as with the step command, if non-debuggable functions are
- # called, reverse-step will run thru them backward without
+ # called, reverse-step will run through them backward without
# stopping.
gdb_continue_to_breakpoint \
diff --git a/gdb/testsuite/gdb.reverse/machinestate-precsave.exp b/gdb/testsuite/gdb.reverse/machinestate-precsave.exp
index 19c5934..cedca0f 100644
--- a/gdb/testsuite/gdb.reverse/machinestate-precsave.exp
+++ b/gdb/testsuite/gdb.reverse/machinestate-precsave.exp
@@ -85,7 +85,7 @@ gdb_test_multiple "continue" "go to end of main forward" {
-re ".*Breakpoint $decimal,.*$srcfile:$endmain.*$gdb_prompt $" {
pass "go to end of main forward"
}
- -re "No more reverse-execution history.* end main .*$gdb_prompt $" {
+ -re -wrap "Reached end of recorded history.*Following forward.*" {
pass "go to end of main forward"
}
}
diff --git a/gdb/testsuite/gdb.reverse/ppc_record_test_isa_3_1.c b/gdb/testsuite/gdb.reverse/ppc_record_test_isa_3_1.c
index 290a584..2c0be65 100644
--- a/gdb/testsuite/gdb.reverse/ppc_record_test_isa_3_1.c
+++ b/gdb/testsuite/gdb.reverse/ppc_record_test_isa_3_1.c
@@ -28,7 +28,7 @@ main ()
pmxvi4ger8*, pmxvi8ger4* pmxvi16ger2* instructions were officially changed
to pmdmxbf16ger*, pmdmxvf32ger*, pmdmxvf64ger*, pmdmxvi4ger8*,
pmdmxvi8ger4*, pmdmxvi16ger* respectively. The old mnemonics are used in
- this test for backward compatibity. */
+ this test for backward compatibility. */
ra = 0xABCDEF012;
rb = 0;
rs = 0x012345678;
diff --git a/gdb/testsuite/gdb.reverse/sigall-precsave.exp b/gdb/testsuite/gdb.reverse/sigall-precsave.exp
index e5890ad..aab4551 100644
--- a/gdb/testsuite/gdb.reverse/sigall-precsave.exp
+++ b/gdb/testsuite/gdb.reverse/sigall-precsave.exp
@@ -128,7 +128,7 @@ proc test_one_sig_reverse {prevsig} {
xfail "$testmsg (handled)"
}
}
- -re "No more reverse-execution history.*kill.*$gdb_prompt " {
+ -re "Reached end of recorded history.*Backward execution.*kill.*$gdb_prompt " {
if {$saw_signal} {
pass "$testmsg (handled)"
} else {
diff --git a/gdb/testsuite/gdb.reverse/sigall-reverse.exp b/gdb/testsuite/gdb.reverse/sigall-reverse.exp
index f2cf55b..884b178 100644
--- a/gdb/testsuite/gdb.reverse/sigall-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/sigall-reverse.exp
@@ -134,7 +134,7 @@ proc test_one_sig_reverse {prevsig} {
xfail "$testmsg (handled)"
}
}
- -re "No more reverse-execution history.*kill.*$gdb_prompt " {
+ -re "Reached end of recorded.*Backward execution.*kill.*$gdb_prompt " {
if {$saw_signal} {
pass "$testmsg (handled)"
} else {
diff --git a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
index 971d88b..7392356 100644
--- a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
@@ -50,11 +50,13 @@ gdb_test "next" {nodebug \(\);} "next to nodebug"
gdb_test "next" {v = 3;} "next to v = 3"
# FAIL was:
-# No more reverse-execution history.
+# Reached end of recorded history; stopping.
+# Backward execution from here not possible.
# {
gdb_test "reverse-step" {nodebug \(\);}
# FAIL was:
-# No more reverse-execution history.
+# Reached end of recorded history; stopping.
+# Backward execution from here not possible.
# {
gdb_test "reverse-next" {f \(\);}
diff --git a/gdb/testsuite/gdb.reverse/step-precsave.exp b/gdb/testsuite/gdb.reverse/step-precsave.exp
index d937763..a3979b7 100644
--- a/gdb/testsuite/gdb.reverse/step-precsave.exp
+++ b/gdb/testsuite/gdb.reverse/step-precsave.exp
@@ -69,6 +69,8 @@ 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}
+
gdb_test "record restore $precsave" \
"Restored records from core file .*" \
"reload core file"
@@ -151,7 +153,7 @@ gdb_test_multiple "stepi" "$test_message" {
}
}
-# stepi thru return of a function call
+# stepi through return of a function call
set test_message "stepi back from function call"
gdb_test_multiple "stepi" "$test_message" {
@@ -183,10 +185,10 @@ gdb_test_multiple "stepi" "$test_message" {
gdb_test_no_output "set exec-dir reverse" "set reverse execution"
-# stepi backward thru return and into a function
+# stepi backward through return and into a function
set stepi_location [gdb_get_line_number "ARRIVED IN CALLEE" "$srcfile"]
-set test_message "reverse stepi thru function return"
+set test_message "reverse stepi through function return"
gdb_test_multiple "stepi" "$test_message" {
-re "NEXTI TEST.*$gdb_prompt $" {
fail "$test_message (start statement)"
diff --git a/gdb/testsuite/gdb.reverse/step-reverse.exp b/gdb/testsuite/gdb.reverse/step-reverse.exp
index 2db73e9..a3c3b5a 100644
--- a/gdb/testsuite/gdb.reverse/step-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/step-reverse.exp
@@ -114,7 +114,7 @@ gdb_test_multiple "stepi" "$test_message" {
}
}
-# stepi thru return of a function call
+# stepi through return of a function call
set test_message "stepi back from function call"
gdb_test_multiple "stepi" "$test_message" {
@@ -145,10 +145,10 @@ gdb_test_multiple "stepi" "$test_message" {
# Set reverse execution direction
gdb_test_no_output "set exec-dir reverse" "set reverse execution"
-# stepi backward thru return and into a function
+# stepi backward through return and into a function
set stepi_location [gdb_get_line_number "ARRIVED IN CALLEE" "$srcfile"]
-set test_message "reverse stepi thru function return"
+set test_message "reverse stepi through function return"
gdb_test_multiple "stepi" "$test_message" {
-re "NEXTI TEST.*$gdb_prompt $" {
fail "$test_message (start statement)"
diff --git a/gdb/testsuite/gdb.server/build-id-seqno.c b/gdb/testsuite/gdb.server/build-id-seqno.c
new file mode 100644
index 0000000..e2119ba7
--- /dev/null
+++ b/gdb/testsuite/gdb.server/build-id-seqno.c
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+main (void)
+{
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.server/build-id-seqno.exp b/gdb/testsuite/gdb.server/build-id-seqno.exp
new file mode 100644
index 0000000..7db1f11
--- /dev/null
+++ b/gdb/testsuite/gdb.server/build-id-seqno.exp
@@ -0,0 +1,200 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2024 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Setup a .build-id/ based debug directory containing multiple entries
+# for the same build-id, with each entry given a different sequence
+# number.
+#
+# Ensure that GDB will scan over broken symlinks for the same build-id
+# (but different sequence number) to find later working symlinks.
+#
+# This test places the build-id files within a directory next to where
+# gdbserver is started, and places a relative address in the
+# debug-file-directory, in this way we require GDB to find the debug
+# information via gdbserver.
+
+require {!is_remote host}
+
+load_lib gdbserver-support.exp
+
+require allow_gdbserver_tests
+
+standard_testfile
+
+if {[build_executable "failed to prepare" $testfile $srcfile] == -1} {
+ return -1
+}
+
+# Split out BINFILE.debug. Remove debug from BINFILE.
+if {[gdb_gnu_strip_debug $binfile] != 0} {
+ return -1
+}
+
+# Get the '.build-id/xx/xxx...xxx' part of the filename.
+set build_id_filename [build_id_debug_filename_get $binfile]
+
+# Hide (rename) BINFILE.debug, this should ensure GDB can't find it
+# directly but needs to look for the build-id based file in the debug
+# directory.
+set hidden_debuginfo [standard_output_file "hidden_$testfile.debug"]
+remote_exec build "mv ${binfile}.debug $hidden_debuginfo"
+
+# A filename that doesn't exist. Some symlinks will point at this
+# file.
+set missing_debuginfo "missing_debuginfo"
+
+# Helper called from gdb_finish when the 'target' is remote. Ensure the
+# debug directory we create is deleted.
+proc cleanup_remote_target {} {
+ remote_exec target "rm -fr debug/"
+}
+
+if { ![is_remote target] } {
+ set gdbserver_dir [standard_output_file "gdbserver-dir"]/
+} else {
+ lappend gdb_finish_hooks cleanup_remote_target
+ set gdbserver_dir ""
+}
+
+# Copy files to the target (if needed).
+set target_binfile [gdb_remote_download target $binfile]
+set target_debuginfo [gdb_remote_download target $hidden_debuginfo]
+
+# Setup the debug information on the target.
+set debugdir "${gdbserver_dir}debug"
+remote_exec target \
+ "mkdir -p $debugdir/[file dirname $build_id_filename]"
+remote_exec target \
+ "ln -sf $target_debuginfo $debugdir/$build_id_filename"
+
+# Start GDB and load global BINFILE. If DEBUGINFO_FILE is not the
+# empty string then this contains the '.build-id/xx/xxx....xxxx' part
+# of the filename which we expect GDB to read from the remote target.
+# If DEBUGINFO_FILE is the empty string then we don't expect GDB to
+# find any debug information.
+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
+ # 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.
+ foreach_with_prefix stat_pkt {auto off} {
+ clean_restart
+
+ gdb_test_no_output "set debug-file-directory debug" \
+ "set debug-file-directory"
+
+ gdb_test_no_output "set sysroot target:"
+
+ gdb_test "set remote hostio-stat-packet $stat_pkt"
+
+ # Make sure we're disconnected, in case we're testing with an
+ # extended-remote board, therefore already connected.
+ gdb_test "disconnect" ".*"
+
+ # Start gdbserver. This needs to be done after starting GDB. When
+ # gdbserver is running local to GDB, start gdbserver in a sub-directory,
+ # this prevents GDB from finding the debug information itself.
+ if { ![is_remote target] } {
+ with_cwd $::gdbserver_dir {
+ set res [gdbserver_start "" $::target_binfile]
+ }
+ } else {
+ set res [gdbserver_start "" $::target_binfile]
+ }
+ set gdbserver_protocol [lindex $res 0]
+ set gdbserver_gdbport [lindex $res 1]
+
+ # Connect to gdbserver. The output will be placed into the global
+ # GDB_TARGET_REMOTE_CMD_MSG, and we'll match against this below.
+ gdb_assert {[gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport] == 0} \
+ "connect to gdbserver"
+
+ if { $debuginfo_file ne "" } {
+ gdb_assert { [regexp "Reading symbols from target:debug/[string_to_regexp $debuginfo_file]\\.\\.\\." \
+ $::gdb_target_remote_cmd_msg] } \
+ "debuginfo was read via build-id"
+ gdb_assert { [regexp "Reading debug/[string_to_regexp $debuginfo_file] from remote target\\.\\.\\." \
+ $::gdb_target_remote_cmd_msg] } \
+ "debuginfo was read from remote target"
+ } else {
+ gdb_assert { [regexp "\\(No debugging symbols found in \[^\r\n\]+/$::testfile\\)" \
+ $::gdb_target_remote_cmd_msg] }
+ }
+ }
+ }
+ }
+}
+
+# Return a copy of FILENAME, which should end '.debug', with NUMBER
+# added, e.g. add_seqno 1 "foo.debug" --> "foo.1.debug".
+proc add_seqno { number filename } {
+ return [regsub "\.debug\$" $filename ".${number}.debug"]
+}
+
+# Precompute sequence numbered build-id filenames.
+set build_id_1_filename [add_seqno 1 $build_id_filename]
+set build_id_2_filename [add_seqno 2 $build_id_filename]
+set build_id_3_filename [add_seqno 3 $build_id_filename]
+
+load_binfile_check_debug_is_found $build_id_filename \
+ "find debuginfo with a single build-id file"
+
+remote_exec target "ln -fs $target_debuginfo \
+ $debugdir/$build_id_1_filename"
+remote_exec target "ln -fs $target_debuginfo \
+ $debugdir/$build_id_2_filename"
+remote_exec target "ln -fs $target_debuginfo \
+ $debugdir/$build_id_3_filename"
+
+load_binfile_check_debug_is_found $build_id_filename \
+ "find debuginfo with 4 build-id files"
+
+remote_exec target "ln -fs $missing_debuginfo $debugdir/$build_id_filename"
+
+load_binfile_check_debug_is_found $build_id_1_filename \
+ "find debuginfo, first build-id file is bad"
+
+remote_exec target "ln -fs $missing_debuginfo \
+ $debugdir/$build_id_1_filename"
+remote_exec target "ln -fs $missing_debuginfo \
+ $debugdir/$build_id_3_filename"
+
+load_binfile_check_debug_is_found $build_id_2_filename \
+ "find debuginfo, first 2 build-id files are bad"
+
+remote_exec target "ln -fs $missing_debuginfo \
+ $debugdir/$build_id_2_filename"
+
+load_binfile_check_debug_is_found "" \
+ "cannot find debuginfo, all build-id files are bad"
+
+remote_exec target "ln -fs $target_debuginfo \
+ $debugdir/$build_id_3_filename"
+
+load_binfile_check_debug_is_found $build_id_3_filename \
+ "find debuginfo, last build-id file is good"
+
+remote_exec target "rm -f $debugdir/$build_id_1_filename"
+
+load_binfile_check_debug_is_found "" \
+ "cannot find debuginfo, file with seqno 1 is missing"
diff --git a/gdb/testsuite/gdb.server/exit-multiple-threads.c b/gdb/testsuite/gdb.server/exit-multiple-threads.c
index 989f1f2..5bf0fc8 100644
--- a/gdb/testsuite/gdb.server/exit-multiple-threads.c
+++ b/gdb/testsuite/gdb.server/exit-multiple-threads.c
@@ -20,7 +20,6 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
-#include <pthread.h>
/* The number of threads to create. */
int thread_count = 3;
diff --git a/gdb/testsuite/gdb.server/remote-read-msgs.exp b/gdb/testsuite/gdb.server/remote-read-msgs.exp
index d2d659a..e204655 100644
--- a/gdb/testsuite/gdb.server/remote-read-msgs.exp
+++ b/gdb/testsuite/gdb.server/remote-read-msgs.exp
@@ -30,7 +30,8 @@ require {!is_remote host}
standard_testfile
-if {[build_executable "failed to prepare" $testfile $srcfile] == -1} {
+if {[build_executable "failed to prepare" $testfile $srcfile \
+ {debug build-id}] == -1} {
return -1
}
diff --git a/gdb/testsuite/gdb.server/server-pipe.exp b/gdb/testsuite/gdb.server/server-pipe.exp
index b369759..3d73c2e 100644
--- a/gdb/testsuite/gdb.server/server-pipe.exp
+++ b/gdb/testsuite/gdb.server/server-pipe.exp
@@ -49,11 +49,12 @@ if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
# or "extended-remote". Check the output of 'info connections', and
# the contents of the gdb.TargetConnection.details string.
proc do_test { target } {
+ global timeout
clean_restart ${::binfile}
# Make sure we're disconnected, in case we're testing with an
# extended-remote board, therefore already connected.
- gdb_test "disconnect" ".*"
+ gdb_test "disconnect" ".*" "disconnect before running the test"
gdb_test "target ${target} | ${::gdbserver} - ${::binfile}" ".*" \
"start gdbserver using pipe syntax"
@@ -68,6 +69,16 @@ proc do_test { target } {
gdb_test_no_output "python conn = gdb.selected_inferior().connection"
gdb_test "python print(conn.details)" "\| ${::gdbserver} - ${::binfile}"
}
+
+ # Make sure GDB server doesn't attempt to reconnect with a closed STDIN.
+ # Here we set the timeout to a short value to see if GDB will hang in an
+ # attempt to reconnect with the now closed STDIN. For this test to be
+ # useful the new temporary timeout MUST be shorter than PIPE_CLOSE_TIMEOUT
+ # defined in gdb/ser-pipe.c (5 seconds at the time of writing).
+ set prev_timeout $timeout
+ set timeout 2
+ gdb_test "disconnect" ".*" "disconnect and test for hang"
+ set timeout $prev_timeout
}
save_vars { GDBFLAGS } {
diff --git a/gdb/testsuite/gdb.server/server-run.exp b/gdb/testsuite/gdb.server/server-run.exp
index 92eb38b..af5a5f5 100644
--- a/gdb/testsuite/gdb.server/server-run.exp
+++ b/gdb/testsuite/gdb.server/server-run.exp
@@ -52,3 +52,36 @@ if { [istarget *-*-linux*] } {
gdb_breakpoint main
gdb_test "continue" "Breakpoint.* main .*" "continue to main"
+
+if { [istarget "aarch64*-*-*"]
+ || [istarget "arm*-*-*"]
+ || [istarget "csky*-*-*"]
+ || [istarget "loongarch*-*-*"]
+ || [istarget "riscv*-*-*"] } {
+ set pc_regname "pc"
+} elseif { [is_amd64_regs_target] } {
+ set pc_regname "rip"
+} elseif { [is_x86_like_target] } {
+ set pc_regname "eip"
+} elseif { [istarget "tic6x-*-*"] } {
+ set pc_regname "PC"
+}
+
+# Sending the PC register in advance is good practice. Test that this is
+# actually done for the targets where gdbserver is supposed to.
+set expedited_pc_test_name "send PC as expedited register in stop reply"
+if { [info exists pc_regname] } {
+ set seen_line false
+ gdb_test_multiple "maintenance print remote-registers" \
+ $expedited_pc_test_name -lbl {
+ -re " ${pc_regname}\[\[:space:\]\]+${decimal}.*${decimal} yes" {
+ set seen_line true
+ exp_continue
+ }
+ -re "\r\n$gdb_prompt $" {
+ gdb_assert { $seen_line } $gdb_test_name
+ }
+ }
+} else {
+ untested $expedited_pc_test_name
+}
diff --git a/gdb/testsuite/gdb.server/solib-list.exp b/gdb/testsuite/gdb.server/solib-list.exp
index b9cc6c8..bbc5df4 100644
--- a/gdb/testsuite/gdb.server/solib-list.exp
+++ b/gdb/testsuite/gdb.server/solib-list.exp
@@ -30,7 +30,7 @@ set srclibfile ${testfile}-lib.c
set binlibfile [standard_output_file ${testfile}.so]
if { [gdb_compile_shlib "${srcdir}/${subdir}/${srclibfile}" "${binlibfile}" {debug}] != ""
- || [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "shlib=${binlibfile}"] != "" } {
+ || [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "shlib=${binlibfile} build-id"] != "" } {
untested "failed to compile"
return -1
}
diff --git a/gdb/testsuite/gdb.testsuite/parse_options_args.exp b/gdb/testsuite/gdb.testsuite/parse_options_args.exp
index 19ad67a..7239ef7 100644
--- a/gdb/testsuite/gdb.testsuite/parse_options_args.exp
+++ b/gdb/testsuite/gdb.testsuite/parse_options_args.exp
@@ -38,7 +38,7 @@ with_test_prefix parse_options {
with_test_prefix parse_args {
proc test2 { args } {
- parse_args {
+ parse_some_args {
{ opt1 defval1 }
{ opt2 defval2 }
{ opt3 }
diff --git a/gdb/testsuite/gdb.threads/create-fail.c b/gdb/testsuite/gdb.threads/create-fail.c
index 01633e4..e4cd27e 100644
--- a/gdb/testsuite/gdb.threads/create-fail.c
+++ b/gdb/testsuite/gdb.threads/create-fail.c
@@ -23,10 +23,8 @@
#include <errno.h>
#include <string.h>
#include <assert.h>
-#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
-#include <assert.h>
#include <unistd.h>
/* Count the number of tasks/threads in the PID thread group. */
diff --git a/gdb/testsuite/gdb.threads/del-pending-thread-bp-lib.c b/gdb/testsuite/gdb.threads/del-pending-thread-bp-lib.c
new file mode 100644
index 0000000..15d1b98
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/del-pending-thread-bp-lib.c
@@ -0,0 +1,22 @@
+/* Copyright 2023 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 global_var = 0;
+
+void
+foo (int arg)
+{
+ global_var = arg;
+}
diff --git a/gdb/testsuite/gdb.threads/del-pending-thread-bp.c b/gdb/testsuite/gdb.threads/del-pending-thread-bp.c
new file mode 100644
index 0000000..6fc76db
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/del-pending-thread-bp.c
@@ -0,0 +1,85 @@
+/* Copyright 2023 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+pthread_barrier_t barrier;
+
+static void
+barrier_wait (pthread_barrier_t *b)
+{
+ int res = pthread_barrier_wait (b);
+ if (res != 0 && res != PTHREAD_BARRIER_SERIAL_THREAD)
+ abort ();
+}
+
+static void *
+thread_worker (void *arg)
+{
+ barrier_wait (&barrier);
+ return NULL;
+}
+
+void
+breakpt (void)
+{
+ /* Nothing. */
+}
+
+int
+main (void)
+{
+ void *handle;
+ void (*func)(int);
+ pthread_t thread;
+
+ if (pthread_barrier_init (&barrier, NULL, 2) != 0)
+ abort ();
+
+ if (pthread_create (&thread, NULL, thread_worker, NULL) != 0)
+ abort ();
+
+ breakpt ();
+
+ /* Allow the worker thread to complete. */
+ barrier_wait (&barrier);
+
+ if (pthread_join (thread, NULL) != 0)
+ abort ();
+
+ breakpt ();
+
+ /* Now load the shared library. */
+ handle = dlopen (SHLIB_NAME, RTLD_LAZY);
+ if (handle == NULL)
+ abort ();
+
+ /* Find the function symbol. */
+ func = (void (*)(int)) dlsym (handle, "foo");
+
+ /* Call the library function. */
+ func (1);
+
+ /* Unload the shared library. */
+ if (dlclose (handle) != 0)
+ abort ();
+
+ breakpt ();
+
+ return 0;
+}
+
diff --git a/gdb/testsuite/gdb.threads/del-pending-thread-bp.exp b/gdb/testsuite/gdb.threads/del-pending-thread-bp.exp
new file mode 100644
index 0000000..14a91a4
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/del-pending-thread-bp.exp
@@ -0,0 +1,98 @@
+# Copyright 2023 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 checks that pending thread-specific breakpoints are
+# correctly deleted when the thread the breakpoint is for goes out of
+# scope.
+#
+# We also check that we can't create a pending thread-specific
+# breakpoint for a non-existent thread.
+
+require allow_shlib_tests
+
+standard_testfile
+
+set libname $testfile-lib
+set srcfile_lib $srcdir/$subdir/$libname.c
+set binfile_lib [standard_output_file $libname.so]
+
+if { [gdb_compile_shlib $srcfile_lib $binfile_lib {}] != "" } {
+ untested "failed to compile shared library 1"
+ return -1
+}
+
+set binfile_lib_target [gdb_download_shlib $binfile_lib]
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
+ [list debug \
+ additional_flags=-DSHLIB_NAME=\"$binfile_lib_target\" \
+ shlib_load pthreads]] } {
+ return -1
+}
+
+gdb_locate_shlib $binfile_lib
+
+if ![runto_main] {
+ return 0
+}
+
+# Run until we have two threads.
+gdb_breakpoint "breakpt"
+gdb_continue_to_breakpoint "first breakpt call"
+
+# Confirm that we have a thread '2'.
+gdb_test "info threads" "\r\n\\s+2\\s+\[^\r\n\]+"
+
+# Create a pending, thread-specific, breakpoint on 'foo'.
+gdb_breakpoint "foo thread 2" allow-pending
+set bpnum [get_integer_valueof "\$bpnum" "*INVALID*" \
+ "get breakpoint number"]
+
+# Check we can't create a pending thread-specific breakpoint for a
+# non-existent thread.
+gdb_test "with breakpoint pending on -- break foo thread 99" \
+ "Unknown thread 99\\."
+
+# Continue to 'breakpt' again. Don't use gdb_continue_to_breakpoint
+# as we are looking for the thread exited and breakpoint deleted
+# messages.
+gdb_test "continue" \
+ [multi_line \
+ "Continuing\\." \
+ "\\\[Thread \[^\r\n\]+ exited\\\]" \
+ "Thread-specific breakpoint $bpnum deleted - thread 2 no longer in the thread list\\." \
+ "" \
+ "Thread 1 \[^\r\n\]+, breakpt \\(\\) at \[^\r\n\]+" \
+ "$decimal\\s+\[^\r\n\]+"] \
+ "second breakpt call"
+
+# Confirm breakpoint has been deleted.
+gdb_test "info breakpoints $bpnum" \
+ "No breakpoint, watchpoint, tracepoint, or catchpoint matching '$bpnum'\\."
+
+# Continue again. This will pass through 'foo'. We should not stop
+# in 'foo', the breakpoint has been deleted. We should next stop in
+# breakpt again.
+gdb_test "continue" \
+ [multi_line \
+ "Continuing\\." \
+ "" \
+ "Thread 1 \[^\r\n\]+ hit Breakpoint $decimal, breakpt \\(\\) at \[^\r\n\]+" \
+ "$decimal\\s+\[^\r\n\]+"] \
+ "third breakpt call"
+gdb_test "bt 1" \
+ [multi_line \
+ "#0\\s+breakpt \\(\\) at \[^\r\n\]+" \
+ "\\(More stack frames follow\\.\\.\\.\\)"]
diff --git a/gdb/testsuite/gdb.threads/fork-thread-pending.c b/gdb/testsuite/gdb.threads/fork-thread-pending.c
index 01dcc40..a9b557a 100644
--- a/gdb/testsuite/gdb.threads/fork-thread-pending.c
+++ b/gdb/testsuite/gdb.threads/fork-thread-pending.c
@@ -21,7 +21,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
-#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
diff --git a/gdb/testsuite/gdb.threads/interrupt-while-step-over.exp b/gdb/testsuite/gdb.threads/interrupt-while-step-over.exp
index bb05754..89c1d06 100644
--- a/gdb/testsuite/gdb.threads/interrupt-while-step-over.exp
+++ b/gdb/testsuite/gdb.threads/interrupt-while-step-over.exp
@@ -67,7 +67,7 @@ proc return_if_nonzero { result } {
}
}
-# Do one iteration of "c -a& -> interrupt -a". Return zero on sucess,
+# Do one iteration of "c -a& -> interrupt -a". Return zero on success,
# and non-zero if some test fails.
proc test_one_iteration {} {
diff --git a/gdb/testsuite/gdb.threads/leader-exit-attach.exp b/gdb/testsuite/gdb.threads/leader-exit-attach.exp
index c1ed1ba..5334de2 100644
--- a/gdb/testsuite/gdb.threads/leader-exit-attach.exp
+++ b/gdb/testsuite/gdb.threads/leader-exit-attach.exp
@@ -41,32 +41,24 @@ set is_gdbserver [target_is_gdbserver]
set attached 0
gdb_test_multiple "attach $testpid" "attach" {
- -re "Attaching to process $testpid failed.*" {
+ -re -wrap "Attaching to process $testpid failed.*" {
# GNU/Linux gdbserver. Linux ptrace does not let you attach
# to zombie threads.
setup_kfail "gdb/31555" *-*-linux*
fail $gdb_test_name
}
- -re "warning: process $testpid is a zombie - the process has already terminated.*" {
+ -re -wrap "warning: process $testpid is a zombie - the process has already terminated.*" {
# Native GNU/Linux. Linux ptrace does not let you attach to
# zombie threads.
setup_kfail "gdb/31555" *-*-linux*
fail $gdb_test_name
}
- -re "Attaching to program: $escapedbinfile, process $testpid.*$gdb_prompt $" {
+ -re -wrap "Attaching to program: $escapedbinfile, process $testpid.*" {
pass $gdb_test_name
set attached 1
}
}
-# With gdbserver, after we failed to attach, we hit PR server/31554:
-# print $_inferior_thread_count
-# Remote connection closed
-# (gdb) KFAIL: gdb.threads/leader-exit-attach.exp: get valueof "$_inferior_thread_count"
-if {!$attached && $is_gdbserver} {
- setup_kfail "server/31554" "*-*-*"
-}
-
set thread_count [get_valueof "" "\$_inferior_thread_count" -1]
if {$thread_count == -1} {
diff --git a/gdb/testsuite/gdb.threads/print-threads.exp b/gdb/testsuite/gdb.threads/print-threads.exp
index e2be48b..6fae36a 100644
--- a/gdb/testsuite/gdb.threads/print-threads.exp
+++ b/gdb/testsuite/gdb.threads/print-threads.exp
@@ -93,7 +93,7 @@ gdb_test_no_output "set var slow = 0"
test_all_threads "fast" 0
runto_main
-gdb_test "break thread_function" "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file .*print-threads.c, line \[0-9\]*\\." "break thread_function (2)"
+gdb_test "break thread_function" "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file .*print-threads.c, line \[0-9\]*\\." "break thread_function, 2"
gdb_test_no_output "set var slow = 1"
# Extend the timeout for slower tests.
set timeout [expr $oldtimeout + 120]
@@ -101,8 +101,8 @@ test_all_threads "slow" 0
set timeout $oldtimeout
runto_main
-gdb_test "break thread_function" "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file .*print-threads.c, line \[0-9\]*\\." "break thread_function (3)"
-gdb_test_no_output "set var slow = 1" "set var slow = 1 (2)"
+gdb_test "break thread_function" "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file .*print-threads.c, line \[0-9\]*\\." "break thread_function, 3"
+gdb_test_no_output "set var slow = 1" "set var slow = 1, 2"
gdb_breakpoint "kill"
# Extend the timeout for slower tests.
set timeout [expr $oldtimeout + 120]
diff --git a/gdb/testsuite/gdb.threads/schedlock.exp b/gdb/testsuite/gdb.threads/schedlock.exp
index bd5d5d2..4e99961 100644
--- a/gdb/testsuite/gdb.threads/schedlock.exp
+++ b/gdb/testsuite/gdb.threads/schedlock.exp
@@ -45,7 +45,7 @@ proc get_args { description } {
append pattern ", (\[0-9\]+)"
}
- set test "listed args ($description)"
+ set test "listed args, $description"
gdb_test_multiple "print args" $test {
-re "\\\$\[0-9\]+ = {$pattern}.*$gdb_prompt $" {
pass $test
@@ -80,7 +80,7 @@ proc stop_process { description } {
proc get_current_thread { description } {
global gdb_prompt
- set test "find current thread ($description)"
+ set test "find current thread, $description"
gdb_test_multiple "bt" $test {
-re "thread_function \\(arg=0x(\[0-9\])\\).*$gdb_prompt $" {
@@ -124,7 +124,7 @@ proc step_ten_loops { cmd } {
for {set i 0} {[expr $i < 10]} {set i [expr $i + 1]} {
set other_step 0
- set test "$cmd to increment ($i)"
+ set test "$cmd to increment, $i"
gdb_test_multiple $cmd $test {
-re ".*myp\\) \\+\\+;\[\r\n\]+$gdb_prompt $" {
pass $test
diff --git a/gdb/testsuite/gdb.threads/signal-command-handle-nopass.c b/gdb/testsuite/gdb.threads/signal-command-handle-nopass.c
index 6d82bd6..548d0d3 100644
--- a/gdb/testsuite/gdb.threads/signal-command-handle-nopass.c
+++ b/gdb/testsuite/gdb.threads/signal-command-handle-nopass.c
@@ -21,6 +21,8 @@
#include <pthread.h>
#include <signal.h>
+static pthread_barrier_t barrier;
+
void
handler (int sig)
{
@@ -35,6 +37,13 @@ thread_function (void *arg)
usleep (1);
}
+void *
+thread_function_sync (void *arg)
+{
+ pthread_barrier_wait (&barrier);
+ return thread_function (arg);
+}
+
int
main (void)
{
@@ -42,7 +51,15 @@ main (void)
int i;
signal (SIGUSR1, handler);
- pthread_create (&child_thread, NULL, thread_function, NULL);
+
+ pthread_barrier_init (&barrier, NULL, 2);
+
+ pthread_create (&child_thread, NULL, thread_function_sync, NULL);
+
+ /* Make sure that pthread_create is done once the breakpoint on
+ thread_function triggers. */
+ pthread_barrier_wait (&barrier);
+
pthread_join (child_thread, NULL);
return 0;
diff --git a/gdb/testsuite/gdb.threads/signal-sigtrap.c b/gdb/testsuite/gdb.threads/signal-sigtrap.c
index 24625ba..7c903a1 100644
--- a/gdb/testsuite/gdb.threads/signal-sigtrap.c
+++ b/gdb/testsuite/gdb.threads/signal-sigtrap.c
@@ -20,6 +20,8 @@
#include <pthread.h>
#include <signal.h>
+static pthread_barrier_t barrier;
+
void
sigtrap_handler (int sig)
{
@@ -31,6 +33,13 @@ thread_function (void *arg)
return NULL;
}
+void *
+thread_function_sync (void *arg)
+{
+ pthread_barrier_wait (&barrier);
+ return thread_function (arg);
+}
+
int
main (void)
{
@@ -38,7 +47,13 @@ main (void)
signal (SIGTRAP, sigtrap_handler);
- pthread_create (&child_thread, NULL, thread_function, NULL);
+ pthread_barrier_init (&barrier, NULL, 2);
+
+ pthread_create (&child_thread, NULL, thread_function_sync, NULL);
+
+ /* Make sure that pthread_create is done once the breakpoint on
+ thread_function triggers. */
+ pthread_barrier_wait (&barrier);
pthread_join (child_thread, NULL);
diff --git a/gdb/testsuite/gdb.threads/stepi-over-clone.exp b/gdb/testsuite/gdb.threads/stepi-over-clone.exp
index da8bbf6..b93cfe6 100644
--- a/gdb/testsuite/gdb.threads/stepi-over-clone.exp
+++ b/gdb/testsuite/gdb.threads/stepi-over-clone.exp
@@ -50,7 +50,7 @@ gdb_test_multiple "catch syscall group:process" "catch process syscalls" {
set re_loc1 "$hex in (__)?clone\[23\]? \\(\\)"
set re_loc2 "$decimal\[ \t\]+in \[^\r\n\]+"
-set re_loc3 "clone\[23\]? \\(\\) at \[^:\]+:$decimal"
+set re_loc3 "(__)?clone\[23\]? \\(\\) at \[^:\]+:$decimal"
gdb_test "continue" \
"Catchpoint $decimal \\(call to syscall clone\[23\]?\\), ($re_loc1|$re_loc3).*"
diff --git a/gdb/testsuite/gdb.threads/thread-bp-deleted.exp b/gdb/testsuite/gdb.threads/thread-bp-deleted.exp
index 5d15a29..3851f8f 100644
--- a/gdb/testsuite/gdb.threads/thread-bp-deleted.exp
+++ b/gdb/testsuite/gdb.threads/thread-bp-deleted.exp
@@ -124,7 +124,7 @@ if {$is_remote} {
#
# However, we might be too quick sending the 'info threads 99' command,
# so, if we see the output of that command without any thread exited
- # text, we wait for a short while and try again. We wait for upto 5
+ # text, we wait for a short while and try again. We wait for up to 5
# seconds (5 tries). However, this might mean on a _really_ slow
# machine that the thread still hasn't exited. I guess if we start
# seeing that then we can just update ATTEMPT_COUNT below.
diff --git a/gdb/testsuite/gdb.threads/thread_check.exp b/gdb/testsuite/gdb.threads/thread_check.exp
index 83fa86d..658f15e 100644
--- a/gdb/testsuite/gdb.threads/thread_check.exp
+++ b/gdb/testsuite/gdb.threads/thread_check.exp
@@ -47,7 +47,7 @@ if {![runto_main]} {
#
-# set breakpoint at thread fucntion tf
+# set breakpoint at thread function tf
#
gdb_test "break tf" \
"Breakpoint.*at.* file .*$srcfile, line.*" \
diff --git a/gdb/testsuite/gdb.threads/tls-sepdebug.exp b/gdb/testsuite/gdb.threads/tls-sepdebug.exp
index 14a0c45..4a322e0 100644
--- a/gdb/testsuite/gdb.threads/tls-sepdebug.exp
+++ b/gdb/testsuite/gdb.threads/tls-sepdebug.exp
@@ -65,16 +65,21 @@ if { [gdb_compile_pthreads \
}
set absdir [file dirname [standard_output_file ${binsharedbase}]]
+if { [info exists ::env(LD_LIBRARY_PATH)] } {
+ set ld_library_path $::env(LD_LIBRARY_PATH)
+} else {
+ set ld_library_path ""
+}
-foreach ld_library_path [list $absdir [relative_filename [pwd] $absdir]] \
+foreach library_path [list $absdir [relative_filename [pwd] $absdir]] \
name { absolute relative } {
with_test_prefix $name {
# Restart, but defer loading until after setting LD_LIBRARY_PATH.
clean_restart
-
- gdb_test_no_output "set env LD_LIBRARY_PATH=$ld_library_path" \
- "set env LD_LIBRARY_PATH"
+ gdb_test_no_output \
+ "set env LD_LIBRARY_PATH=$ld_library_path:$library_path" \
+ "set env LD_LIBRARY_PATH"
gdb_load ${binmainfile}
diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c b/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c
index b74a841..eb65d45 100644
--- a/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c
+++ b/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c
@@ -27,7 +27,6 @@
#include <pthread.h>
#include <asm/unistd.h>
-#include <unistd.h>
#define gettid() syscall (__NR_gettid)
/* Non-atomic `var++' should not hurt as we synchronize the threads by the STEP
diff --git a/gdb/testsuite/gdb.trace/basic-libipa.exp b/gdb/testsuite/gdb.trace/basic-libipa.exp
index e28f61e..c49192a 100644
--- a/gdb/testsuite/gdb.trace/basic-libipa.exp
+++ b/gdb/testsuite/gdb.trace/basic-libipa.exp
@@ -25,13 +25,9 @@ require allow_shlib_tests
standard_testfile
+require allow_in_proc_agent
set libipa [get_in_proc_agent]
-if { ![file exists $libipa] } {
- unsupported "missing libinproctrace.so"
- return -1
-}
-
gdb_download_shlib $libipa
if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
diff --git a/gdb/testsuite/gdb.trace/change-loc.exp b/gdb/testsuite/gdb.trace/change-loc.exp
index fb55153..1316d92 100644
--- a/gdb/testsuite/gdb.trace/change-loc.exp
+++ b/gdb/testsuite/gdb.trace/change-loc.exp
@@ -346,6 +346,7 @@ tracepoint_change_loc_2 "trace"
tracepoint_install_in_trace_disabled "trace"
# Re-compile test case with IPA.
+require allow_in_proc_agent
set libipa [get_in_proc_agent]
gdb_load_shlib $libipa
diff --git a/gdb/testsuite/gdb.trace/collection.exp b/gdb/testsuite/gdb.trace/collection.exp
index b7d0f9f..9c6d3f5 100644
--- a/gdb/testsuite/gdb.trace/collection.exp
+++ b/gdb/testsuite/gdb.trace/collection.exp
@@ -161,7 +161,7 @@ proc gdb_collect_args_test { myargs msg } {
# collected. In C, an array as function parameters is a special
# case; it's just a pointer into the caller's array, and as such,
# that's what normally the debug info describes. Maybe this was
- # originaly written for a compiler where array parameters were
+ # originally written for a compiler where array parameters were
# really described as arrays in debug info.
setup_xfail "*-*-*"
@@ -250,7 +250,7 @@ proc gdb_collect_argarray_test { myargs msg } {
# are collected. In C, an array as function parameters is a
# special case; it's just a pointer into the caller's array,
# and as such, that's what normally the debug info describes.
- # Maybe this was originaly written for a compiler where array
+ # Maybe this was originally written for a compiler where array
# parameters were really described as arrays in debug info.
setup_xfail "*-*-*"
diff --git a/gdb/testsuite/gdb.trace/entry-values.exp b/gdb/testsuite/gdb.trace/entry-values.exp
index 0711100..82ae5a8 100644
--- a/gdb/testsuite/gdb.trace/entry-values.exp
+++ b/gdb/testsuite/gdb.trace/entry-values.exp
@@ -53,6 +53,8 @@ if { [istarget "arm*-*-*"] || [istarget "aarch64*-*-*"] } {
# returns. The only exception is JALRC, in which case execution
# resumes from `insn1' instead.
set call_insn {jalrc|[jb]al[sxr]*[ \t][^\r\n]+\r\n}
+} elseif { [istarget "riscv64*-*-*"] } {
+ set call_insn jal
} else {
set call_insn "call"
}
@@ -171,7 +173,7 @@ gdb_continue_to_breakpoint "foo"
gdb_test_no_output "set print entry-values both"
-gdb_test_sequence "bt" "bt (1)" {
+gdb_test_sequence "bt" "bt, 1" {
"\[\r\n\]#0 .* foo \\(i=[-]?[0-9]+, i@entry=2, j=[-]?[0-9]+, j@entry=3\\)"
"\[\r\n\]#1 .* bar \\(i=<optimized out>, i@entry=<optimized out>\\)"
"\[\r\n\]#2 .* \.?main \\(\\)"
@@ -183,7 +185,7 @@ gdb_test_sequence "bt" "bt (1)" {
gdb_test_no_output "set var *(int *) &global1=10"
gdb_test_no_output "set var *(int *) &global2=11"
-gdb_test_sequence "bt" "bt (2)" {
+gdb_test_sequence "bt" "bt, 2" {
"\[\r\n\]#0 .* foo \\(i=[-]?[0-9]+, i@entry=10, j=[-]?[0-9]+, j@entry=11\\)"
"\[\r\n\]#1 .* bar \\(i=<optimized out>, i@entry=<optimized out>\\)"
"\[\r\n\]#2 .* \.?main \\(\\)"
diff --git a/gdb/testsuite/gdb.trace/ftrace-lock.exp b/gdb/testsuite/gdb.trace/ftrace-lock.exp
index ce2b890..637d5eb 100644
--- a/gdb/testsuite/gdb.trace/ftrace-lock.exp
+++ b/gdb/testsuite/gdb.trace/ftrace-lock.exp
@@ -48,6 +48,7 @@ with_test_prefix "runtime trace support check" {
}
# Compile the test case with the in-process agent library.
+require allow_in_proc_agent
set libipa [get_in_proc_agent]
set remote_libipa [gdb_load_shlib $libipa]
diff --git a/gdb/testsuite/gdb.trace/ftrace.exp b/gdb/testsuite/gdb.trace/ftrace.exp
index 9b100ce..408cd37 100644
--- a/gdb/testsuite/gdb.trace/ftrace.exp
+++ b/gdb/testsuite/gdb.trace/ftrace.exp
@@ -39,6 +39,7 @@ if ![gdb_target_supports_trace] {
return -1
}
+require allow_in_proc_agent
set libipa [get_in_proc_agent]
set remote_libipa [gdb_load_shlib $libipa]
diff --git a/gdb/testsuite/gdb.trace/mi-tracepoint-changed.exp b/gdb/testsuite/gdb.trace/mi-tracepoint-changed.exp
index e6672db..dee7142 100644
--- a/gdb/testsuite/gdb.trace/mi-tracepoint-changed.exp
+++ b/gdb/testsuite/gdb.trace/mi-tracepoint-changed.exp
@@ -148,7 +148,7 @@ proc test_reconnect { } {
}
}
-# Test 'breakpoint-modified' notification is emited when pending tracepoints are
+# Test 'breakpoint-modified' notification is emitted when pending tracepoints are
# resolved.
proc test_pending_resolved { } {
diff --git a/gdb/testsuite/gdb.trace/pending.exp b/gdb/testsuite/gdb.trace/pending.exp
index b836be0..66209ad 100644
--- a/gdb/testsuite/gdb.trace/pending.exp
+++ b/gdb/testsuite/gdb.trace/pending.exp
@@ -494,6 +494,7 @@ pending_tracepoint_with_action_resolved "trace"
pending_tracepoint_installed_during_trace "trace"
# Re-compile test case with IPA.
+require allow_in_proc_agent
set libipa [get_in_proc_agent]
gdb_load_shlib $libipa
diff --git a/gdb/testsuite/gdb.trace/range-stepping.exp b/gdb/testsuite/gdb.trace/range-stepping.exp
index e3af2e5..373a0bf 100644
--- a/gdb/testsuite/gdb.trace/range-stepping.exp
+++ b/gdb/testsuite/gdb.trace/range-stepping.exp
@@ -67,6 +67,7 @@ range_stepping_with_tracepoint "trace"
require allow_shlib_tests
+require allow_in_proc_agent
set libipa [get_in_proc_agent]
set remote_libipa [gdb_load_shlib $libipa]
diff --git a/gdb/testsuite/gdb.trace/strace.exp b/gdb/testsuite/gdb.trace/strace.exp
index 99b199e..ef243a4 100644
--- a/gdb/testsuite/gdb.trace/strace.exp
+++ b/gdb/testsuite/gdb.trace/strace.exp
@@ -19,6 +19,7 @@ require allow_shlib_tests
standard_testfile
set executable $testfile
+require allow_in_proc_agent
set libipa [get_in_proc_agent]
set lib_opts debug
diff --git a/gdb/testsuite/gdb.trace/tfind.exp b/gdb/testsuite/gdb.trace/tfind.exp
index 9d1f6e3..c6ac80b 100644
--- a/gdb/testsuite/gdb.trace/tfind.exp
+++ b/gdb/testsuite/gdb.trace/tfind.exp
@@ -342,10 +342,10 @@ gdb_test "disassemble gdb_c_test" \
"8.36: trace disassembly"
gdb_test "tfind line 0" \
- "out of range.*|failed to find.*|No line 0 in .*" \
+ "out of range.*|failed to find.*|No compiled code for line 0 in .*" \
"8.18: tfind line 0"
gdb_test "tfind line 32767" \
- "out of range.*|failed to find.*|No line 32767 in .*" \
+ "out of range.*|failed to find.*|No compiled code for line 32767 in .*" \
"8.27: tfind line 32767"
gdb_test "tfind line NoSuChFiLe.c:$baseline" \
"No source file named.*" \
diff --git a/gdb/testsuite/gdb.trace/trace-break.exp b/gdb/testsuite/gdb.trace/trace-break.exp
index 7e5820c..cac4aa5 100644
--- a/gdb/testsuite/gdb.trace/trace-break.exp
+++ b/gdb/testsuite/gdb.trace/trace-break.exp
@@ -344,6 +344,7 @@ break_trace_same_addr_6 "trace" "disable" "trace" "enable"
require allow_shlib_tests
+require allow_in_proc_agent
set libipa [get_in_proc_agent]
set remote_libipa [gdb_load_shlib $libipa]
diff --git a/gdb/testsuite/gdb.trace/trace-condition.exp b/gdb/testsuite/gdb.trace/trace-condition.exp
index 42453bc..17acda8 100644
--- a/gdb/testsuite/gdb.trace/trace-condition.exp
+++ b/gdb/testsuite/gdb.trace/trace-condition.exp
@@ -39,6 +39,7 @@ if ![gdb_target_supports_trace] {
return -1
}
+require allow_in_proc_agent
set libipa [get_in_proc_agent]
set remote_libipa [gdb_load_shlib $libipa]
diff --git a/gdb/testsuite/gdb.trace/trace-enable-disable.exp b/gdb/testsuite/gdb.trace/trace-enable-disable.exp
index 280f2e4..c2c8381 100644
--- a/gdb/testsuite/gdb.trace/trace-enable-disable.exp
+++ b/gdb/testsuite/gdb.trace/trace-enable-disable.exp
@@ -42,6 +42,7 @@ if ![gdb_target_supports_trace] {
}
# Compile the test case with the in-process agent library.
+require allow_in_proc_agent
set libipa [get_in_proc_agent]
gdb_load_shlib $libipa
diff --git a/gdb/testsuite/gdb.trace/trace-mt.exp b/gdb/testsuite/gdb.trace/trace-mt.exp
index e56064b..7246ddc 100644
--- a/gdb/testsuite/gdb.trace/trace-mt.exp
+++ b/gdb/testsuite/gdb.trace/trace-mt.exp
@@ -103,6 +103,7 @@ step_over_tracepoint $binfile "trace"
require allow_shlib_tests
+require allow_in_proc_agent
set libipa [get_in_proc_agent]
set remote_libipa [gdb_load_shlib $libipa]
diff --git a/gdb/testsuite/gdb.trace/tracecmd.exp b/gdb/testsuite/gdb.trace/tracecmd.exp
index 96596ea..688980c 100644
--- a/gdb/testsuite/gdb.trace/tracecmd.exp
+++ b/gdb/testsuite/gdb.trace/tracecmd.exp
@@ -64,7 +64,8 @@ gdb_test "info trace" "in gdb_recursion_test.*$srcfile:$testline2.
# 1.2 trace invalid source line
gdb_delete_tracepoints
gdb_test_no_output "set breakpoint pending off"
-gdb_test "trace $srcfile:99999" "No line 99999 in file \".*$srcfile\"." \
+gdb_test "trace $srcfile:99999" \
+ "No compiled code for line 99999 in file \".*$srcfile\"\\." \
"1.2a: trace invalid line in sourcefile"
gdb_test "info trace" "No tracepoints.*" \
"1.2b: reject invalid line in srcfile"
diff --git a/gdb/testsuite/gdb.trace/tspeed.exp b/gdb/testsuite/gdb.trace/tspeed.exp
index 7ade5c2..c74680b 100644
--- a/gdb/testsuite/gdb.trace/tspeed.exp
+++ b/gdb/testsuite/gdb.trace/tspeed.exp
@@ -43,6 +43,7 @@ if ![gdb_target_supports_trace] {
}
# Compile the test case with the in-process agent library.
+require allow_in_proc_agent
set ipalib [get_in_proc_agent]
if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
diff --git a/gdb/testsuite/gdb.tui/info-win.exp b/gdb/testsuite/gdb.tui/info-win.exp
index 36c7815..4d71f04 100644
--- a/gdb/testsuite/gdb.tui/info-win.exp
+++ b/gdb/testsuite/gdb.tui/info-win.exp
@@ -40,7 +40,7 @@ Term::command "layout h"
Term::command "winheight cmd + 3"
# As the tuiterm.exp library just waits for the prompt and command to
-# be echo'ed bcak to the screen, multiple 'info win' calls like this
+# be echo'ed back to the screen, multiple 'info win' calls like this
# have a problem. Dejagnu will send the command to gdb, but will then
# immediately see the '(gdb) info win' output from the first use
# above. This means we end up rushing ahead, and some tests might
diff --git a/gdb/testsuite/gdb.tui/wrap-line.exp b/gdb/testsuite/gdb.tui/wrap-line.exp
index 9cddcf1..d3020bf 100644
--- a/gdb/testsuite/gdb.tui/wrap-line.exp
+++ b/gdb/testsuite/gdb.tui/wrap-line.exp
@@ -50,7 +50,7 @@ proc fill_line { width } {
}
# Test wrapping.
-proc test_wrap { wrap_width } {
+proc test_wrap { wrap_width tui } {
# Generate a prompt and parse it.
send_gdb "\003"
gdb_assert { [Term::wait_for "(^|$::gdb_prompt )$::re_control_c"] } "start line"
@@ -65,12 +65,31 @@ proc test_wrap { wrap_width } {
send_gdb "W"
# Check that the wrap occurred at the expected location.
- gdb_assert { [Term::wait_for_region_contents 0 0 $::cols $::lines \
- "$::gdb_prompt $str$space\r\nW"] } "wrap"
+ set re_wrap \
+ [multi_line \
+ "$::gdb_prompt $str$space" \
+ "W"]
+ set re_no_wrap \
+ [multi_line \
+ "" \
+ "<.*W"]
+ if { $tui } {
+ set re $re_wrap
+ } else {
+ set re ($re_wrap|$re_no_wrap)
+ }
+ gdb_assert { [Term::wait_for_region_contents 0 0 $::cols $::lines $re] } "wrap"
# Generate a prompt and parse it.
send_gdb "\003"
- gdb_assert { [Term::wait_for "^W$::re_control_c"] } "prompt after wrap"
+ set re_wrap W$::re_control_c
+ set re_no_wrap <.*W$::re_control_c
+ if { $tui } {
+ set re $re_wrap
+ } else {
+ set re ($re_wrap|$re_no_wrap)
+ }
+ gdb_assert { [Term::wait_for ^$re] } "prompt after wrap"
}
# Test wrapping in both CLI and TUI.
@@ -107,7 +126,7 @@ proc test_wrap_cli_tui { auto_detected_width } {
with_test_prefix cli {
set wrap_width $readline_width
- test_wrap $wrap_width
+ test_wrap $wrap_width 0
}
with_test_prefix tui {
@@ -126,7 +145,7 @@ proc test_wrap_cli_tui { auto_detected_width } {
# for wrapping from curses.
set wrap_width $::cols
- test_wrap $wrap_width
+ test_wrap $wrap_width 1
}
}
diff --git a/gdb/testsuite/gdb.xml/tdesc-arch.exp b/gdb/testsuite/gdb.xml/tdesc-arch.exp
index f9b037f..6c8c592 100644
--- a/gdb/testsuite/gdb.xml/tdesc-arch.exp
+++ b/gdb/testsuite/gdb.xml/tdesc-arch.exp
@@ -73,7 +73,7 @@ proc set_arch { arch which trans_mode } {
# Anchor the test output, so that error messages are detected.
set cmd "set tdesc filename $filename"
- set msg "set tdesc filename tdesc-arch.xml ($which architecture)"
+ set msg "set tdesc filename tdesc-arch.xml, $which architecture"
set cmd_regex [string_to_regexp $cmd]
gdb_test_multiple $cmd $msg {
-re "^$cmd_regex\r\n$gdb_prompt $" {
@@ -87,7 +87,7 @@ proc set_arch { arch which trans_mode } {
set cmd "show architecture"
gdb_test $cmd \
"The target architecture is set to \"auto\" \\(currently \"$arch\"\\)\\." \
- "$cmd ($which architecture)"
+ "$cmd, $which architecture"
remote_file host delete $filename
}
@@ -115,11 +115,11 @@ if {[is_remote host]} {
set cmd "set tdesc filename $filename"
gdb_test $cmd \
"warning:.*Target description specified unknown architecture.*" \
- "set tdesc filename tdesc-arch.xml (invalid architecture)"
+ "set tdesc filename tdesc-arch.xml, invalid architecture"
set cmd "show architecture"
gdb_test $cmd \
"The target architecture is set to \"auto\" \\(currently \"$default_arch\"\\)\\." \
- "$cmd (invalid architecture)"
+ "$cmd, invalid architecture"
remote_file host delete $filename
diff --git a/gdb/testsuite/gdb.xml/tdesc-regs.exp b/gdb/testsuite/gdb.xml/tdesc-regs.exp
index 7c8b0b8..344e387 100644
--- a/gdb/testsuite/gdb.xml/tdesc-regs.exp
+++ b/gdb/testsuite/gdb.xml/tdesc-regs.exp
@@ -80,21 +80,38 @@ switch -glob -- [istarget] {
set regdir "i386/"
set core-regs {64bit-core.xml 64bit-sse.xml}
}
+ "riscv64*-*-*" {
+ set architecture "riscv:rv64"
+ set regdir "riscv/"
+ set core-regs 64bit-cpu.xml
+ }
}
-# If no core registers were specified, assume this target does not
-# support target-defined registers. Verify that we get a warning if
-# we try to use them. This not only tests the warning, but also
-# reminds maintainers to add test support when they add the feature.
-
set single_reg_xml [gdb_remote_download host \
"$srcdir/$subdir/single-reg.xml"]
if {[string equal ${core-regs} ""]} {
- gdb_test "set tdesc file $single_reg_xml" \
- "warning: Target-supplied registers are not supported.*" \
- "set tdesc file single-reg.xml"
- unsupported "register tests"
+ set test "set tdesc file single-reg.xml"
+ set feature_unsupported 0
+ set feature_test_unsupported 0
+ gdb_test_multiple "set tdesc file $single_reg_xml" $test {
+ -re -wrap "warning: Target-supplied registers are not supported" {
+ set feature_unsupported 1
+ pass $gdb_test_name
+ }
+ -re -wrap "warning: Architecture rejected target-supplied description" {
+ set feature_test_unsupported 1
+ pass $gdb_test_name
+ }
+ }
+
+ if { $feature_unsupported } {
+ unsupported "register tests"
+ } elseif { $feature_test_unsupported } {
+ # Remind maintainers to add test support.
+ unsupported "register tests (missing architecture-specific core-regs setting)"
+ }
+
return 0
}
diff --git a/gdb/testsuite/lib/ada.exp b/gdb/testsuite/lib/ada.exp
index 1bc0dc1..05151d3 100644
--- a/gdb/testsuite/lib/ada.exp
+++ b/gdb/testsuite/lib/ada.exp
@@ -13,6 +13,25 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# A wrapper for foreach_with_prefix that applies suitable
+# -fgnat-encodings arguments to a command line. SCENARIO_ARG is the
+# name of a loop variable that will hold the scenario currently being
+# evaluated. FLAGS_ARG will be set to the appropriate compiler flags
+# (if any) for this scenario. LIST is the list of desired scenarios
+# to run, and BODY is what actually does the work.
+
+proc foreach_gnat_encoding {scenario_arg flags_arg list body} {
+ upvar 1 $scenario_arg scenario
+ upvar 1 $flags_arg flags
+ foreach_with_prefix scenario $list {
+ set flags {}
+ if {$scenario != "none"} {
+ lappend flags additional_flags=-fgnat-encodings=$scenario
+ }
+ uplevel 1 $body
+ }
+}
+
# Call target_compile with SOURCE DEST TYPE and OPTIONS as argument,
# after having temporarily changed the current working directory to
# BUILDDIR.
@@ -169,6 +188,18 @@ proc gnatmake_version_at_least { major } {
return 1
}
+# Compare the GNAT version against L2 using version_compare. If the
+# compiler does not appear to be GCC, this will always return false.
+
+proc gnat_version_compare {op l2} {
+ set gccvers [gcc_major_version]
+ if {$gccvers == -1} {
+ return 0
+ }
+
+ return [version_compare [split $gccvers .] $op $l2]
+}
+
# Return 1 if the GNAT runtime appears to have debug info.
proc gnat_runtime_has_debug_info_1 { shared } {
diff --git a/gdb/testsuite/lib/cache.exp b/gdb/testsuite/lib/cache.exp
index 8066734..ca3dca2 100644
--- a/gdb/testsuite/lib/cache.exp
+++ b/gdb/testsuite/lib/cache.exp
@@ -46,12 +46,81 @@ proc gdb_do_cache_wrap {real_name args} {
return $result
}
+# Global written to by gdb_exit_called proc. Is set to true to
+# indicate that a caching proc has called gdb_exit.
+
+set gdb_exit_called false
+
+# This proc is called via TCL's trace mechanism whenever gdb_exit is
+# called during the execution of a caching proc. This sets the global
+# flag to indicate that gdb_exit has been called.
+
+proc gdb_exit_called { args } {
+ set ::gdb_exit_called true
+}
+
+# While calling the implementation of a caching proc, that
+# implementation might itself call additional caching procs. We need
+# to track all of the nested caching procs that are called and we do
+# that in this list which is a list containing the names of any nested
+# caching procs that are called.
+
+set gdb_nested_caching_proc_calls {}
+
+# Called before returning from gdb_do_cache. NAME is the name of the
+# caching proc that was called.
+#
+# When DO_EXIT is true then this proc should call gdb_exit before
+# returning, otherwise gdb_exit is not called.
+#
+# ALSO_CALLED is a list of the names all the nested caching procs that
+# the proc NAME called. This proc appends NAME as well as everything
+# in ALSO_CALLED to the global GDB_NESTED_CACHING_PROC_CALLS, this
+# aids in tracking recursive caching proc calls.
+
+proc gdb_cache_maybe_gdb_exit { name do_exit also_called } {
+
+ # Record all the procs that have been called, but only if the exit
+ # trace is in place (this is done in gdb_do_cache) and indicates
+ # that we are in data gathering mode.
+ if { [info exists ::gdb_exit_trace_in_place] } {
+ set ::gdb_nested_caching_proc_calls \
+ [list {*}$::gdb_nested_caching_proc_calls $name {*}$also_called]
+ }
+
+ # The cache 'exit' entry will be true if this caching proc, or any
+ # caching proc that is recursively called from this caching proc,
+ # called exit.
+ if { !$do_exit } {
+ return
+ }
+
+ # To track if this proc has been called for NAME we create a
+ # global variable. In gdb_cleanup_globals (see gdb.exp) this
+ # global will be deleted when the test has finished.
+ set global_name __${name}__cached_gdb_exit_called
+ if { ![info exists ::${global_name}] } {
+ gdb_exit
+ verbose -log "gdb_caching_proc $name caused gdb_exit to be called"
+ set ::${global_name} true
+ verbose -log " gdb_caching_proc $name marked as called"
+
+ foreach other_name $also_called {
+ verbose -log " gdb_caching_proc $other_name marked as called"
+ set global_name __${other_name}__cached_gdb_exit_called
+ set ::${global_name} true
+ }
+ }
+}
+
# A helper for gdb_caching_proc that handles the caching.
proc gdb_do_cache {name args} {
global gdb_data_cache objdir
global GDB_PARALLEL
+ verbose -log "gdb_do_cache: $name ( $args )"
+
# Normally, if we have a cached value, we skip computation and return
# the cached value. If set to 1, instead don't skip computation and
# verify against the cached value.
@@ -70,11 +139,14 @@ proc gdb_do_cache {name args} {
set cache_name [file join [target_info name] $name {*}$args]
set is_cached 0
- if {[info exists gdb_data_cache($cache_name)]} {
- set cached $gdb_data_cache($cache_name)
- verbose "$name: returning '$cached' from cache" 2
+ if {[info exists gdb_data_cache(${cache_name},value)]} {
+ set cached_value $gdb_data_cache(${cache_name},value)
+ set cached_exit $gdb_data_cache(${cache_name},exit)
+ set cached_also_called $gdb_data_cache(${cache_name},also_called)
+ verbose "$name: returning '$cached_value' from cache" 2
if { $cache_verify == 0 } {
- return $cached
+ gdb_cache_maybe_gdb_exit $name $cached_exit $cached_also_called
+ return $cached_value
}
set is_cached 1
}
@@ -83,37 +155,135 @@ proc gdb_do_cache {name args} {
set cache_filename [make_gdb_parallel_path cache $cache_name]
if {[file exists $cache_filename]} {
set fd [open $cache_filename]
- set gdb_data_cache($cache_name) [read -nonewline $fd]
+ set content [split [read -nonewline $fd] \n]
close $fd
- set cached $gdb_data_cache($cache_name)
- verbose "$name: returning '$cached' from file cache" 2
+ set gdb_data_cache(${cache_name},value) [lindex $content 0]
+ set gdb_data_cache(${cache_name},exit) [lindex $content 1]
+ set gdb_data_cache(${cache_name},also_called) [lindex $content 2]
+ set cached_value $gdb_data_cache(${cache_name},value)
+ set cached_exit $gdb_data_cache(${cache_name},exit)
+ set cached_also_called $gdb_data_cache(${cache_name},also_called)
+ verbose "$name: returning '$cached_value' from file cache" 2
if { $cache_verify == 0 } {
- return $cached
+ gdb_cache_maybe_gdb_exit $name $cached_exit $cached_also_called
+ return $cached_value
}
set is_cached 1
}
}
+ # Add a trace hook to gdb_exit. In the case of recursive calls to
+ # gdb_do_cache we only want to install the trace hook once, so we
+ # set a global to indicate that the trace is in place.
+ #
+ # We also set a local flag to indicate that this is the scope in
+ # which the debug trace needs to be removed.
+ if { ![info exists ::gdb_exit_trace_in_place] } {
+ trace add execution gdb_exit enter gdb_exit_called
+ set ::gdb_exit_trace_in_place true
+ set gdb_exit_trace_created true
+ } else {
+ set gdb_exit_trace_created false
+ }
+
+ # As above, we need to consider recursive calls into gdb_do_cache.
+ # Store the old value of gdb_exit_called global and then set the
+ # flag to false. Initially gdb_exit_called is always false, but
+ # for recursive calls to gdb_do_cache we can't know the state of
+ # gdb_exit_called.
+ #
+ # Before starting a recursive gdb_do_cache call we need
+ # gdb_exit_called to be false, that way the inner call can know if
+ # it invoked gdb_exit or not.
+ #
+ # Once the recursive call completes, if it did call gdb_exit then
+ # the outer, parent call to gdb_do_cache should also be considered
+ # as having called gdb_exit.
+ set old_gdb_exit_called $::gdb_exit_called
+ set ::gdb_exit_called false
+
+ # As with the exit tracking above we also need to track any nested
+ # caching procs that this proc might call. To do this we backup
+ # the current global list of nested caching proc calls and reset
+ # the global back ot the empty list. As nested caching procs are
+ # called their names are added to the global list, see
+ # gdb_cache_maybe_gdb_exit for where this is done.
+ set old_gdb_nested_caching_proc_calls $::gdb_nested_caching_proc_calls
+ set ::gdb_nested_caching_proc_calls {}
+
set real_name gdb_real__$name
- set gdb_data_cache($cache_name) [gdb_do_cache_wrap $real_name {*}$args]
+ set gdb_data_cache(${cache_name},value) [gdb_do_cache_wrap $real_name {*}$args]
+ set gdb_data_cache(${cache_name},exit) $::gdb_exit_called
+ set gdb_data_cache(${cache_name},also_called) \
+ [lsort -unique $::gdb_nested_caching_proc_calls]
+
+ # Now that the actual implementation of this caching proc has been
+ # executed the gdb_nested_caching_proc_calls global will contain
+ # the names of any nested caching procs that were called. We
+ # append this new set of names onto the set of names we backed up
+ # above.
+ set ::gdb_nested_caching_proc_calls \
+ [list {*}$old_gdb_nested_caching_proc_calls \
+ {*}$::gdb_nested_caching_proc_calls]
+
+ # See comment above where OLD_GDB_EXIT_CALLED is set: if
+ # GDB_EXIT_CALLED was previously true then this is a recursive
+ # call and the outer caching proc set the global true, so restore
+ # the true value now.
+ if { $old_gdb_exit_called } {
+ set ::gdb_exit_called true
+ }
+
+ # See comment above where GDB_EXIT_TRACE_CREATED is set: this is
+ # the frame in which the trace was installed. This must be the
+ # outer caching proc call (if an recursion occurred).
+ if { $gdb_exit_trace_created } {
+ trace remove execution gdb_exit enter gdb_exit_called
+ unset ::gdb_exit_trace_in_place
+ set ::gdb_exit_called false
+ set ::gdb_nested_caching_proc_calls {}
+ }
+
+ # If a value being stored in the cache contains a newline then
+ # when we try to read the value back from an on-disk cache file
+ # we'll interpret the second line of the value as the ',exit' value.
+ if { [regexp "\[\r\n\]" $gdb_data_cache(${cache_name},value)] } {
+ set computed_value $gdb_data_cache(${cache_name},value)
+ error "Newline found in value for $cache_name: $computed_value"
+ }
+
if { $cache_verify == 1 && $is_cached == 1 } {
- set computed $gdb_data_cache($cache_name)
- if { $cached != $computed } {
- error [join [list "Inconsistent results for $cache_name:"
- "cached: $cached vs. computed: $computed"]]
+ set computed_value $gdb_data_cache(${cache_name},value)
+ set computed_exit $gdb_data_cache(${cache_name},exit)
+ set computed_also_called $gdb_data_cache(${cache_name},also_called)
+ if { $cached_value != $computed_value } {
+ error [join [list "Inconsistent value results for $cache_name:"
+ "cached: $cached_value vs. computed: $computed_value"]]
+ }
+ if { $cached_exit != $computed_exit } {
+ error [join [list "Inconsistent exit results for $cache_name:"
+ "cached: $cached_exit vs. computed: $computed_exit"]]
+ }
+ if { $cached_also_called != $computed_also_called } {
+ error [join [list "Inconsistent also_called results for $cache_name:"
+ "cached: $cached_also_called vs. computed: $computed_also_called"]]
}
}
if {[info exists GDB_PARALLEL]} {
- verbose "$name: returning '$gdb_data_cache($cache_name)' and writing file" 2
+ verbose "$name: returning '$gdb_data_cache(${cache_name},value)' and writing file" 2
file mkdir [file dirname $cache_filename]
# Make sure to write the results file atomically.
set fd [open $cache_filename.[pid] w]
- puts $fd $gdb_data_cache($cache_name)
+ puts $fd $gdb_data_cache(${cache_name},value)
+ puts $fd $gdb_data_cache(${cache_name},exit)
+ puts $fd $gdb_data_cache(${cache_name},also_called)
close $fd
file rename -force -- $cache_filename.[pid] $cache_filename
}
- return $gdb_data_cache($cache_name)
+ gdb_cache_maybe_gdb_exit $name $gdb_data_cache(${cache_name},exit) \
+ $gdb_data_cache(${cache_name},also_called)
+ return $gdb_data_cache(${cache_name},value)
}
# Define a new proc named NAME, with optional args ARGS. BODY is the body of
diff --git a/gdb/testsuite/lib/check-test-names.exp b/gdb/testsuite/lib/check-test-names.exp
index 8f86f31..11aed63 100644
--- a/gdb/testsuite/lib/check-test-names.exp
+++ b/gdb/testsuite/lib/check-test-names.exp
@@ -64,6 +64,16 @@ namespace eval ::CheckTestNames {
proc _check_duplicates { message } {
variable all_test_names
+ # Remove test-case prefix, including the space separator.
+ set prefix [string_to_regexp "$::subdir/$::gdb_test_file_name.exp: "]
+ set message [regsub ^$prefix $message ""]
+
+ # Remove the "extra information" part.
+ set message [regsub { \([^()]*\)$} $message ""]
+
+ # Add back the test-case prefix.
+ set message "${prefix}$message"
+
# Initialise a count, or increment the count for this test name.
if {![info exists all_test_names($message)]} {
set all_test_names($message) 0
diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index 995cdca..f9be6c4 100644
--- a/gdb/testsuite/lib/dwarf.exp
+++ b/gdb/testsuite/lib/dwarf.exp
@@ -2771,7 +2771,7 @@ namespace eval Dwarf {
# section_version n
# - section version number to emit
# default = 2
- # seg_size n - the size of the adress selector in bytes: 0, 4, or 8
+ # seg_size n - the size of the address selector in bytes: 0, 4, or 8
# default = 0
#
# LABEL is the label of the corresponding CU.
diff --git a/gdb/testsuite/lib/gdb-utils.exp b/gdb/testsuite/lib/gdb-utils.exp
index 95c53d0..33b56fb 100644
--- a/gdb/testsuite/lib/gdb-utils.exp
+++ b/gdb/testsuite/lib/gdb-utils.exp
@@ -38,6 +38,14 @@ proc string_to_regexp {str} {
return $result
}
+# Convenience function that calls string_to_regexp for each arg, and
+# joins the results using "\r\n".
+
+proc multi_line_string_to_regexp { args } {
+ set res [lmap arg $args {string_to_regexp $arg}]
+ return [multi_line {*}$res]
+}
+
# Given a list of strings, adds backslashes as needed to each string to
# create a regexp that will match the string, and join the result.
@@ -56,7 +64,7 @@ proc string_list_to_regexp { args } {
# STYLE can either be the payload part of an ANSI terminal sequence,
# or a shorthand for one of the gdb standard styles: "file",
-# "function", "variable", or "address".
+# "function", "variable", "address", etc.
proc style {str style} {
switch -exact -- $style {
@@ -68,6 +76,7 @@ proc style {str style} {
address { set style 34 }
metadata { set style 2 }
version { set style "35;1" }
+ line-number { set style 2 }
none { return $str }
}
return "\033\\\[${style}m${str}\033\\\[m"
@@ -102,14 +111,31 @@ proc gdb_get_bp_addr { num } {
}
# Compare the version numbers in L1 to those in L2 using OP, and
-# return 1 if the comparison is true. OP can be "<", "<=", or "==".
-# It is ok if the lengths of the lists differ.
+# return 1 if the comparison is true. OP can be "<", "<=", ">", ">=",
+# or "==". It is ok if the lengths of the lists differ.
proc version_compare { l1 op l2 } {
switch -exact $op {
"==" -
"<=" -
"<" {}
+
+ ">=" {
+ # a >= b => b <= a
+ set x $l2
+ set l2 $l1
+ set l1 $x
+ set op "<="
+ }
+
+ ">" {
+ # a > b => b < a
+ set x $l2
+ set l2 $l1
+ set l1 $x
+ set op "<"
+ }
+
default { error "unsupported op: $op" }
}
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index dfe19c9..f0a8939 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -158,6 +158,23 @@ load_lib gdb-utils.exp
load_lib memory.exp
load_lib check-test-names.exp
+# The path to the GCORE script to test.
+global GCORE
+if {![info exists GCORE]} {
+ set GCORE [findfile $base_dir/../../gdb/gcore]
+}
+verbose "using GCORE = $GCORE" 2
+
+# Return 0 if the gcore scipt is missing.
+proc has_gcore_script {} {
+ global GCORE
+ if {$GCORE == ""} {
+ return 0
+ } else {
+ return 1
+ }
+}
+
# The path to the GDB binary to test.
global GDB
@@ -733,19 +750,24 @@ proc gdb_breakpoint { linespec args } {
# single quoted C++ function specifier.
#
# If there are additional arguments, pass them to gdb_breakpoint.
-# We recognize no-message/message ourselves.
+# We recognize no-message/message ourselves as well as no-delete-brekpoints.
#
# no-message is messed up here, like gdb_breakpoint: to preserve
# historical usage fails are always printed by default.
# no-message: turns off printing of fails (and passes, but they're already off)
# message: turns on printing of passes (and fails, but they're already on)
+#
+# The 'no-delete-brekpoints' option stops this proc from deleting all
+# breakpoints.
proc runto { linespec args } {
global gdb_prompt
global bkptno_numopt_re
global decimal
- delete_breakpoints
+ if {[lsearch -exact $args no-delete-breakpoints] == -1} {
+ delete_breakpoints
+ }
set print_pass 0
set print_fail 1
@@ -769,7 +791,7 @@ proc runto { linespec args } {
# the "at foo.c:36" output we get with -g.
# the "in func" output we get without -g.
gdb_expect {
- -re "(?:Break|Temporary break).* at .*:$decimal.*$gdb_prompt $" {
+ -re "(?:Break|Temporary break).* at .*:.*$decimal.*$gdb_prompt $" {
if { $print_pass } {
pass $test_name
}
@@ -821,11 +843,11 @@ proc runto { linespec args } {
# Ask gdb to run until we hit a breakpoint at main.
#
-# N.B. This function deletes all existing breakpoints.
-# If you don't want that, use gdb_start_cmd.
+# N.B. By default this function deletes all existing breakpoints. If
+# you don't want that then pass the 'no-delete-breakpoints' argument.
-proc runto_main { } {
- return [runto main qualified]
+proc runto_main { args } {
+ return [runto main qualified {*}$args]
}
### Continue, and expect to hit a breakpoint.
@@ -965,6 +987,31 @@ proc fill_in_default_prompt {prompt_regexp with_anchor} {
return $prompt_regexp
}
+# Generate message from COMMAND.
+#
+# This is not trivial in the case that the command contains parentheses.
+# Trailing text between parentheses prefixed with a space is interpreted as
+# extra information, and not as part of the test name [1]. Consequently,
+# "PASS: print (1)" and "PASS: print (2)" count as duplicates.
+#
+# We fix this here by using "PASS: gdb-command<print (1)>" and
+# "PASS: gdb-command<print (2)>".
+#
+# A trivial way to fix this in a test-case is by using gdb_test "print(1)",
+# which produces the nicer-looking "PASS: print(1)".
+#
+# [1] https://sourceware.org/gdb/wiki/GDBTestcaseCookbook#Do_not_use_.22tail_parentheses.22_on_test_messages
+
+proc command_to_message { command } {
+ set message $command
+
+ if { [regexp { \(([^()]*)\)$} $message] } {
+ set message gdb-command<$message>
+ }
+
+ return $message
+}
+
# gdb_test_multiple COMMAND MESSAGE [ -prompt PROMPT_REGEXP] [ -lbl ]
# EXPECT_ARGUMENTS
# Send a command to gdb; test the result.
@@ -1095,7 +1142,7 @@ proc gdb_test_multiple { command message args } {
set prompt_regexp [fill_in_default_prompt $prompt_regexp true]
if { $message == "" } {
- set message $command
+ set message [command_to_message $command]
}
if [string match "*\[\r\n\]" $command] {
@@ -1471,7 +1518,6 @@ proc gdb_test_multiline { name args } {
return 0
}
-
# gdb_test [-prompt PROMPT_REGEXP] [-lbl]
# COMMAND [PATTERN] [MESSAGE] [QUESTION RESPONSE]
# Send a command to gdb; test the result.
@@ -1513,7 +1559,7 @@ proc gdb_test { args } {
global gdb_prompt
upvar timeout timeout
- parse_args {
+ parse_some_args {
{prompt ""}
{no-prompt-anchor}
{lbl}
@@ -1521,7 +1567,8 @@ proc gdb_test { args } {
{nonl}
}
- lassign $args command pattern message question response
+ set args [lassign $args command pattern message question response]
+ check_no_args_left
# Can't have a question without a response.
if { $question != "" && $response == "" || [llength $args] > 5 } {
@@ -1529,7 +1576,7 @@ proc gdb_test { args } {
}
if { $message == "" } {
- set message $command
+ set message [command_to_message $command]
}
set prompt [fill_in_default_prompt $prompt [expr !${no-prompt-anchor}]]
@@ -1656,6 +1703,16 @@ if { [tcl_version_at_least 8 6] == 0 } {
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 } {
@@ -1685,13 +1742,14 @@ if { [tcl_version_at_least 8 6 2] == 0 } {
proc gdb_test_no_output { args } {
global gdb_prompt
- parse_args {
+ parse_some_args {
{prompt ""}
{no-prompt-anchor}
{nopass}
}
- lassign $args command message
+ set args [lassign $args command message]
+ check_no_args_left
set prompt [fill_in_default_prompt $prompt [expr !${no-prompt-anchor}]]
@@ -1733,7 +1791,7 @@ proc gdb_test_no_output { args } {
proc gdb_test_sequence { args } {
global gdb_prompt
- parse_args {{prompt ""}}
+ parse_some_args {{prompt ""}}
if { $prompt == "" } {
set prompt "$gdb_prompt $"
@@ -1759,6 +1817,55 @@ proc gdb_test_sequence { args } {
}
+# Issue COMMAND, and return corresponding output lines. Helper function for
+# gdb_get_lines_no_pass and gdb_get_lines.
+
+proc gdb_get_lines_1 { command message } {
+ set no_pass [string equal $message ""]
+ set lines ""
+ set ok 0
+ gdb_test_multiple $command $message {
+ -re "\r\n(\[^\r\n\]*)(?=\r\n)" {
+ set line $expect_out(1,string)
+ if { $lines eq "" } {
+ append lines "$line"
+ } else {
+ append lines "\r\n$line"
+ }
+ exp_continue
+ }
+ -re -wrap "" {
+ append lines "\r\n"
+ set ok 1
+ if { ! $no_pass } {
+ pass $gdb_test_name
+ }
+ }
+ }
+
+ if { ! $ok } {
+ return ""
+ }
+
+ return $lines
+}
+
+# Issue COMMAND, and return corresponding output lines. Don't generate a pass.
+
+proc gdb_get_lines_no_pass { command } {
+ gdb_get_lines_1 $command ""
+}
+
+# Issue COMMAND, and return corresponding output lines. Generate a pass.
+
+proc gdb_get_lines { command {message ""} } {
+ if { $message == "" } {
+ set message [command_to_message $command]
+ }
+
+ gdb_get_lines_1 $command $message
+}
+
# Match output of COMMAND using RE. Read output line-by-line.
# Report pass/fail with MESSAGE.
# For a command foo with output:
@@ -1795,25 +1902,10 @@ proc gdb_test_lines { command message re args } {
}
if { $message == ""} {
- set message $command
- }
-
- set lines ""
- gdb_test_multiple $command $message {
- -re "\r\n(\[^\r\n\]*)(?=\r\n)" {
- set line $expect_out(1,string)
- if { $lines eq "" } {
- append lines "$line"
- } else {
- append lines "\r\n$line"
- }
- exp_continue
- }
- -re -wrap "" {
- append lines "\r\n"
- }
+ set message [command_to_message $command]
}
+ set lines [gdb_get_lines_no_pass $command]
gdb_assert { [regexp $re $lines] } $message
foreach re $re_not {
@@ -2012,7 +2104,7 @@ proc gdb_test_stdio {command inferior_pattern {gdb_pattern ""} {message ""}} {
global gdb_prompt
if {$message == ""} {
- set message $command
+ set message [command_to_message $command]
}
set inferior_matched 0
@@ -3522,6 +3614,55 @@ gdb_caching_proc supports_memtag {} {
return 0
}
+# Return 1 if catch syscall is supported, otherwise return 0.
+
+gdb_caching_proc supports_catch_syscall {} {
+ set me "supports_catch_syscall"
+
+ # Compile a test program.
+ set src {
+ int main() {
+ return 0;
+ }
+ }
+ if {![gdb_simple_compile $me $src executable]} {
+ verbose -log "$me: failed to compile"
+ return 0
+ }
+
+ # 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] } {
+ verbose -log "$me: failed to run to main"
+ return 0
+ }
+
+ # To make sure we test both setting and inserting the catchpoint.
+ gdb_test_no_output "set breakpoint always-inserted on"
+
+ set res 0
+ set re_yes \
+ [string_to_regexp \
+ "Catchpoint 2 (any syscall)"]
+ gdb_test_multiple "catch syscall" "" {
+ -re -wrap ^$re_yes {
+ set res 1
+ }
+ -re -wrap "" {
+ }
+ }
+
+ gdb_exit
+ remote_file build delete $obj
+
+ verbose "$me: returning $res" 2
+ return $res
+}
+
# Return 1 if the target supports hardware single stepping.
proc can_hardware_single_step {} {
@@ -4258,6 +4399,135 @@ gdb_caching_proc allow_btrace_pt_tests {} {
return $allow_btrace_pt_tests
}
+# Run a test on the target to see if it supports ptwrite instructions and
+# if GDB can decode ptwrite events. Return 1 if so, 0 if it does not.
+
+gdb_caching_proc allow_btrace_ptw_tests {} {
+ global srcdir subdir gdb_prompt inferior_exited_re decimal
+
+ require allow_btrace_pt_tests
+ set me "allow_btrace_ptw_tests"
+
+ set src {
+ #include <immintrin.h>
+
+ int
+ main ()
+ {
+ _ptwrite32 (0x42);
+ return 0;
+ }
+ }
+
+ set compile_flags "additional_flags=-mptwrite"
+ if {![gdb_simple_compile $me $src executable $compile_flags]} {
+ return 0
+ }
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load "$obj"
+ if ![runto_main] {
+ return 1
+ }
+
+ gdb_test_no_output "record btrace pt" "$me: record btrace pt"
+
+ set allow_btrace_ptw_tests 0
+ gdb_test_multiple "next" "$me: next" {
+ -re -wrap ".*Illegal instruction.*" {
+ verbose -log "$me: ptwrite instruction support not detected."
+ }
+ -re -wrap ".*$inferior_exited_re normally.*" {
+ verbose -log "$me: ptwrite support not detected."
+ }
+ -re -wrap "$decimal.*(at|in|return 0).*" {
+ set allow_btrace_ptw_tests 1
+ }
+ }
+
+ if { $allow_btrace_ptw_tests == 1 } {
+ # Show the func-call-history to get the packet trace.
+ gdb_test "record function-call-history" ".*"
+
+ gdb_test_multiple "maintenance btrace packet-history 0,1000" \
+ "$me: check decoding support" {
+ -re "ptw" {
+ verbose -log "$me: ptwrite decoding support detected."
+ set allow_btrace_ptw_tests 1
+ }
+ -re -wrap "" {
+ verbose -log "$me: ptwrite decoding support not detected."
+ set allow_btrace_ptw_tests 0
+ }
+ }
+ }
+
+ gdb_exit
+ remote_file build delete $obj
+
+ verbose "$me: returning $allow_btrace_ptw_tests" 2
+ return $allow_btrace_ptw_tests
+}
+
+
+# Run a test on the target to see if GDB supports event tracing on it.
+# Return 1 if so, 0 if it does not.
+
+gdb_caching_proc allow_btrace_pt_event_trace_tests {} {
+ global srcdir subdir
+ set me "allow_btrace_pt_event_trace_tests"
+ require allow_btrace_pt_tests
+
+ set src {
+ int
+ main ()
+ {
+ return 0;
+ }
+ }
+
+ if {![gdb_simple_compile $me $src executable]} {
+ return 0
+ }
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load "$obj"
+ if ![runto_main] {
+ return 0
+ }
+
+ set allow_event_trace_tests 0
+ gdb_test_multiple "set record btrace pt event-tracing on" "$me: first check" {
+ -re -wrap "Event-tracing is not supported by GDB." {
+ }
+ -re -wrap "" {
+ set allow_event_trace_tests 1
+ }
+ }
+
+ if { $allow_event_trace_tests == 1 } {
+ gdb_test_multiple "record btrace pt" "$me: check OS support" {
+ -re -wrap "^" {
+ }
+ -re -wrap "" {
+ verbose -log "$me: Target doesn't support event tracing."
+ set allow_event_trace_tests 0
+ }
+ }
+ }
+
+ gdb_exit
+ remote_file build delete $obj
+
+ verbose "$me: returning $allow_event_trace_tests" 2
+ return $allow_event_trace_tests
+}
+
+
# Run a test on the target to see if it supports Aarch64 SVE hardware.
# Return 1 if so, 0 if it does not. Note this causes a restart of GDB.
@@ -5465,16 +5735,17 @@ proc gdb_compile {source dest type options} {
}
# If the 'build-id' option is used, then ensure that we generate a
- # build-id. GCC does this by default, but Clang does not, so
- # enable it now.
- if {[lsearch -exact $options build-id] > 0
- && [test_compiler_info "clang-*"]} {
- lappend new_options "additional_flags=-Wl,--build-id"
+ # build-id. It is possible that the compiler is configured to do
+ # so automatically, but at least for GCC the configure option
+ # --enable-linker-build-id is not enabled by default.
+ # So to be sure, enable it explicitly.
+ if {[lsearch -exact $options build-id] > 0} {
+ lappend new_options "ldflags=-Wl,--build-id"
}
# If the 'no-build-id' option is used then disable the build-id.
if {[lsearch -exact $options no-build-id] > 0} {
- lappend new_options "additional_flags=-Wl,--build-id=none"
+ lappend new_options "ldflags=-Wl,--build-id=none"
}
# Sanity check. If both 'build-id' and 'no-build-id' are used
@@ -6321,14 +6592,23 @@ proc gdb_exit { } {
catch default_gdb_exit
}
-# Helper function for can_spawn_for_attach. Try to spawn and attach, and
-# return 0 only if we cannot attach because it's unsupported.
+# Return true if we can spawn a program on the target and attach to
+# it.
-gdb_caching_proc can_spawn_for_attach_1 {} {
- # For the benefit of gdb-caching-proc-consistency.exp, which
- # calls can_spawn_for_attach_1 directly. Keep in sync with
- # can_spawn_for_attach.
- if { [is_remote target] || [target_info exists use_gdb_stub] } {
+gdb_caching_proc can_spawn_for_attach {} {
+ # We use exp_pid to get the inferior's pid, assuming that gives
+ # back the pid of the program. On remote boards, that would give
+ # us instead the PID of e.g., the ssh client, etc.
+ if {[is_remote target]} {
+ verbose -log "can't spawn for attach (target is remote)"
+ return 0
+ }
+
+ # The "attach" command doesn't make sense when the target is
+ # stub-like, where GDB finds the program already started on
+ # initial connection.
+ if {[target_info exists use_gdb_stub]} {
+ verbose -log "can't spawn for attach (target is stub)"
return 0
}
@@ -6353,6 +6633,9 @@ gdb_caching_proc can_spawn_for_attach_1 {} {
set test_spawn_id [spawn_wait_for_attach_1 $obj]
remote_file build delete $obj
+ # In case GDB is already running.
+ gdb_exit
+
gdb_start
set test_pid [spawn_id_get_pid $test_spawn_id]
@@ -6374,61 +6657,6 @@ gdb_caching_proc can_spawn_for_attach_1 {} {
return $res
}
-# Return true if we can spawn a program on the target and attach to
-# it. Calls gdb_exit for the first call in a test-case.
-
-proc can_spawn_for_attach { } {
- # We use exp_pid to get the inferior's pid, assuming that gives
- # back the pid of the program. On remote boards, that would give
- # us instead the PID of e.g., the ssh client, etc.
- if {[is_remote target]} {
- verbose -log "can't spawn for attach (target is remote)"
- return 0
- }
-
- # The "attach" command doesn't make sense when the target is
- # stub-like, where GDB finds the program already started on
- # initial connection.
- if {[target_info exists use_gdb_stub]} {
- verbose -log "can't spawn for attach (target is stub)"
- return 0
- }
-
- # The normal sequence to use for a runtime test like
- # can_spawn_for_attach_1 is:
- # - gdb_exit (don't use a running gdb, we don't know what state it is in),
- # - gdb_start (start a new gdb), and
- # - gdb_exit (cleanup).
- #
- # By making can_spawn_for_attach_1 a gdb_caching_proc, we make it
- # unpredictable which test-case will call it first, and consequently a
- # test-case may pass in say a full test run, but fail when run
- # individually, due to a can_spawn_for_attach call in a location where a
- # gdb_exit (as can_spawn_for_attach_1 does) breaks things.
- # To avoid this, we move the initial gdb_exit out of
- # can_spawn_for_attach_1, guaranteeing that we end up in the same state
- # regardless of whether can_spawn_for_attach_1 is called. However, that
- # is only necessary for the first call in a test-case, so cache the result
- # in a global (which should be reset after each test-case) to keep track
- # of that.
- #
- # In summary, we distinguish between three cases:
- # - first call in first test-case. Executes can_spawn_for_attach_1.
- # Calls gdb_exit, gdb_start, gdb_exit.
- # - first call in following test-cases. Uses cached result of
- # can_spawn_for_attach_1. Calls gdb_exit.
- # - rest. Use cached result in cache_can_spawn_for_attach_1. Calls no
- # gdb_start or gdb_exit.
- global cache_can_spawn_for_attach_1
- if { [info exists cache_can_spawn_for_attach_1] } {
- return $cache_can_spawn_for_attach_1
- }
- gdb_exit
-
- set cache_can_spawn_for_attach_1 [can_spawn_for_attach_1]
- return $cache_can_spawn_for_attach_1
-}
-
# Centralize the failure checking of "attach" command.
# Return 0 if attach failed, otherwise return 1.
@@ -8115,7 +8343,6 @@ gdb_caching_proc gdb_has_argv0 {} {
|| [istarget *-wince-pe] || [istarget *-*-mingw32ce*]
|| [istarget *-*-osf*]
|| [istarget *-*-dicos*]
- || [istarget *-*-nto*]
|| [istarget *-*-*vms*]
|| [istarget *-*-lynx*178]) } {
fail "argv\[0\] should be available on this target"
@@ -8181,14 +8408,17 @@ proc get_build_id { filename } {
# Return the build-id hex string (usually 160 bits as 40 hex characters)
# converted to the form: .build-id/ab/cdef1234...89.debug
+#
+# The '.debug' suffix can be changed by passing the SUFFIX argument.
+#
# Return "" if no build-id found.
-proc build_id_debug_filename_get { filename } {
+proc build_id_debug_filename_get { filename {suffix ".debug"} } {
set data [get_build_id $filename]
if { $data == "" } {
return ""
}
regsub {^..} $data {\0/} data
- return ".build-id/${data}.debug"
+ return ".build-id/${data}${suffix}"
}
# DEST should be a file compiled with debug information. This proc
@@ -9152,7 +9382,7 @@ proc using_fission { } {
#
# Example:
# proc myproc {foo args} {
-# parse_list args 1 {{bar} {baz "abc"} {qux}} "-" false
+# parse_list 1 args {{bar} {baz "abc"} {qux}} "-" false
# # ...
# }
# myproc ABC -bar -baz DEF peanut butter
@@ -9213,13 +9443,32 @@ proc parse_list { level listname argset prefix eval } {
# Search the caller's args variable and set variables according to the list of
# valid options described by ARGSET.
-proc parse_args { argset } {
+proc parse_some_args { argset } {
parse_list 2 args $argset "-" false
# The remaining args should be checked to see that they match the
# number of items expected to be passed into the procedure...
}
+# Check that the caller's args variable is empty.
+
+proc check_no_args_left {} {
+ # Require no remaining args.
+ upvar 1 args args
+ if { [llength $args] != 0 } {
+ error "Args left unparsed: $args"
+ }
+}
+
+# As parse_some_args, but check that no args remain after parsing.
+
+proc parse_args { argset } {
+ uplevel parse_some_args [list $argset]
+
+ # Require no remaining args.
+ uplevel check_no_args_left
+}
+
# Process the caller's options variable and set variables according
# to the list of valid options described by OPTIONSET.
@@ -9600,18 +9849,6 @@ gdb_caching_proc supports_statement_frontiers {} {
} executable "additional_flags=-gstatement-frontiers"]
}
-# Return 1 if compiler supports -mmpx -fcheck-pointer-bounds. Otherwise,
-# return 0.
-
-gdb_caching_proc supports_mpx_check_pointer_bounds {} {
- set flags "additional_flags=-mmpx additional_flags=-fcheck-pointer-bounds"
- return [gdb_can_simple_compile supports_mpx_check_pointer_bounds {
- int main () {
- return 0;
- }
- } executable $flags]
-}
-
# Return 1 if compiler supports -fcf-protection=. Otherwise,
# return 0.
@@ -10040,83 +10277,6 @@ gdb_caching_proc supports_gnuc {} {
return [gdb_simple_compile $me $src object ""]
}
-# Return 1 if target supports mpx, otherwise return 0.
-gdb_caching_proc have_mpx {} {
- global srcdir
-
- set me "have_mpx"
- if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } {
- verbose "$me: target does not support mpx, returning 0" 2
- return 0
- }
-
- # Compile a test program.
- set src {
- #include "nat/x86-cpuid.h"
-
- int main() {
- unsigned int eax, ebx, ecx, edx;
-
- if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
- return 0;
-
- if ((ecx & bit_OSXSAVE) == bit_OSXSAVE)
- {
- if (__get_cpuid_max (0, (void *)0) < 7)
- return 0;
-
- __cpuid_count (7, 0, eax, ebx, ecx, edx);
-
- if ((ebx & bit_MPX) == bit_MPX)
- return 1;
-
- }
- return 0;
- }
- }
- set compile_flags "incdir=${srcdir}/.."
- if {![gdb_simple_compile $me $src executable $compile_flags]} {
- return 0
- }
-
- set target_obj [gdb_remote_download target $obj]
- set result [remote_exec target $target_obj]
- set status [lindex $result 0]
- set output [lindex $result 1]
- if { $output != "" } {
- set status 0
- }
-
- remote_file build delete $obj
-
- if { $status == 0 } {
- verbose "$me: returning $status" 2
- return $status
- }
-
- # Compile program with -mmpx -fcheck-pointer-bounds, try to trigger
- # 'No MPX support', in other words, see if kernel supports mpx.
- set src { int main (void) { return 0; } }
- set comp_flags {}
- append comp_flags " additional_flags=-mmpx"
- append comp_flags " additional_flags=-fcheck-pointer-bounds"
- if {![gdb_simple_compile $me-2 $src executable $comp_flags]} {
- return 0
- }
-
- set target_obj [gdb_remote_download target $obj]
- set result [remote_exec target $target_obj]
- set status [lindex $result 0]
- set output [lindex $result 1]
- set status [expr ($status == 0) \
- && ![regexp "^No MPX support\r?\n" $output]]
-
- remote_file build delete $obj
-
- verbose "$me: returning $status" 2
- return $status
-}
-
# Return 1 if target supports avx, otherwise return 0.
gdb_caching_proc have_avx {} {
global srcdir
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index aa0f9df..3832137 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -1989,14 +1989,13 @@ proc get_mi_thread_list {name} {
return $thread_list
}
-# Check that MI and the console know of the same threads.
-# Appends NAME to all test names.
-proc check_mi_and_console_threads {name} {
+# Helper function for check_mi_and_console_threads.
+proc check_mi_and_console_threads_1 { name } {
global expect_out
mi_gdb_test "-thread-list-ids" \
{.*\^done,thread-ids={(thread-id="[0-9]+"(,)*)+},current-thread-id="[0-9]+",number-of-threads="[0-9]+"} \
- "-thread-list-ids ($name)"
+ "-thread-list-ids"
set mi_output {}
if {[info exists expect_out(buffer)]} {
set mi_output $expect_out(buffer)
@@ -2013,7 +2012,7 @@ proc check_mi_and_console_threads {name} {
# FIXME: kseitz/2002-09-05: Don't use the hack-cli method.
mi_gdb_test "info threads" \
{.*(~".*"[\r\n]*)+.*} \
- "info threads ($name)"
+ "info threads"
set console_output {}
if {[info exists expect_out(buffer)]} {
set console_output $expect_out(buffer)
@@ -2039,29 +2038,29 @@ proc check_mi_and_console_threads {name} {
}
}
if {$mi_result == ""} {
- fail "finding MI result string ($name)"
+ fail "finding MI result string"
} else {
- pass "finding MI result string ($name)"
+ pass "finding MI result string"
}
# Finally, extract the thread ids and compare them to the console
set num_mi_threads_str ""
if {![regexp {number-of-threads="[0-9]+"} $mi_result num_mi_threads_str]} {
- fail "finding number of threads in MI output ($name)"
+ fail "finding number of threads in MI output"
} else {
- pass "finding number of threads in MI output ($name)"
+ pass "finding number of threads in MI output"
# Extract the number of threads from the MI result
if {![scan $num_mi_threads_str {number-of-threads="%d"} num_mi_threads]} {
- fail "got number of threads from MI ($name)"
+ fail "got number of threads from MI"
} else {
- pass "got number of threads from MI ($name)"
+ pass "got number of threads from MI"
# Check if MI and console have same number of threads
if {$num_mi_threads != [llength $console_thread_list]} {
- fail "console and MI have same number of threads ($name)"
+ fail "console and MI have same number of threads"
} else {
- pass "console and MI have same number of threads ($name)"
+ pass "console and MI have same number of threads"
# Get MI thread list
set mi_thread_list [get_mi_thread_list $name]
@@ -2074,19 +2073,27 @@ proc check_mi_and_console_threads {name} {
}
}
if {$fails > 0} {
- fail "MI and console have same threads ($name)"
+ fail "MI and console have same threads"
# Send a list of failures to the log
send_log "Console has thread ids: $console_thread_list\n"
send_log "MI has thread ids: $mi_thread_list\n"
} else {
- pass "MI and console have same threads ($name)"
+ pass "MI and console have same threads"
}
}
}
}
}
+# Check that MI and the console know of the same threads.
+# Appends NAME to all test names.
+proc check_mi_and_console_threads { name } {
+ with_test_prefix $name {
+ check_mi_and_console_threads_1 $name
+ }
+}
+
# Set solib-search-path to allow gdb to locate shlib FILE.
proc mi_locate_shlib { file } {
global mi_spawn_id
@@ -2673,7 +2680,7 @@ proc mi_make_info_frame_regexp {args} {
# build the regexp for matching against the -stack-info-frame output.
proc mi_info_frame { test args } {
- parse_args {{frame ""} {thread ""}}
+ parse_some_args {{frame ""} {thread ""}}
set re [eval mi_make_info_frame_regexp $args]
diff --git a/gdb/testsuite/lib/prelink-support.exp b/gdb/testsuite/lib/prelink-support.exp
index 8be5067..894af39 100644
--- a/gdb/testsuite/lib/prelink-support.exp
+++ b/gdb/testsuite/lib/prelink-support.exp
@@ -57,7 +57,7 @@ proc symlink_resolve {file} {
} else {
set src2 $target
}
- verbose -log "Resolved symlink $file targetting $target as $src2"
+ verbose -log "Resolved symlink $file targeting $target as $src2"
set file $src2
set loop [expr $loop + 1]
diff --git a/gdb/testsuite/lib/selftest-support.exp b/gdb/testsuite/lib/selftest-support.exp
index 00d7e30..0d76e2f 100644
--- a/gdb/testsuite/lib/selftest-support.exp
+++ b/gdb/testsuite/lib/selftest-support.exp
@@ -100,7 +100,7 @@ proc selftest_setup { executable function } {
# self-test, then return an empty string.
proc selftest_prepare {} {
# Are we testing with a remote board? In that case, the target
- # won't have access to the GDB's auxilliary data files
+ # won't have access to the GDB's auxiliary data files
# (data-directory, etc.). It's simpler to just skip.
if { [is_remote target] || [is_remote host] } {
return
diff --git a/gdb/testsuite/lib/trace-support.exp b/gdb/testsuite/lib/trace-support.exp
index c9c9697..770a930 100644
--- a/gdb/testsuite/lib/trace-support.exp
+++ b/gdb/testsuite/lib/trace-support.exp
@@ -366,6 +366,20 @@ proc gdb_find_recursion_test_baseline { filename } {
return $baseline
}
+# Return 1 if the IPA library is available and 0 otherwise.
+
+proc allow_in_proc_agent {} {
+ global objdir
+
+ if [target_info exists in_proc_agent] {
+ return 1
+ } elseif [file exists "$objdir/../../gdbserver/libinproctrace.so"] {
+ return 1
+ } else {
+ return 0
+ }
+}
+
# Return the location of the IPA library.
proc get_in_proc_agent {} {
diff --git a/gdb/tid-parse.c b/gdb/tid-parse.c
index 623f55e..442d5b3 100644
--- a/gdb/tid-parse.c
+++ b/gdb/tid-parse.c
@@ -24,7 +24,7 @@
/* See tid-parse.h. */
-void ATTRIBUTE_NORETURN
+[[noreturn]] void
invalid_thread_id_error (const char *string)
{
error (_("Invalid thread ID: %s"), string);
@@ -47,40 +47,43 @@ get_positive_number_trailer (const char **pp, int trailer, const char *string)
return num;
}
-/* See tid-parse.h. */
+/* Parse TIDSTR as a per-inferior thread ID, in either INF_NUM.THR_NUM
+ or THR_NUM form, and return a pair, the first item of the pair is
+ INF_NUM and the second item is THR_NUM.
-struct thread_info *
-parse_thread_id (const char *tidstr, const char **end)
+ If TIDSTR does not include an INF_NUM component, then the first item in
+ the pair will be 0 (which is an invalid inferior number), this indicates
+ that TIDSTR references the current inferior.
+
+ This function does not validate the INF_NUM and THR_NUM are actually
+ valid numbers, that is, they might reference inferiors or threads that
+ don't actually exist; this function just splits the string into its
+ component parts.
+
+ If there is an error parsing TIDSTR then this function will raise an
+ exception. */
+
+static std::pair<int, int>
+parse_thread_id_1 (const char *tidstr, const char **end)
{
const char *number = tidstr;
const char *dot, *p1;
- struct inferior *inf;
- int thr_num;
- int explicit_inf_id = 0;
+ int thr_num, inf_num;
dot = strchr (number, '.');
if (dot != NULL)
{
/* Parse number to the left of the dot. */
- int inf_num;
-
p1 = number;
inf_num = get_positive_number_trailer (&p1, '.', number);
if (inf_num == 0)
invalid_thread_id_error (number);
-
- inf = find_inferior_id (inf_num);
- if (inf == NULL)
- error (_("No inferior number '%d'"), inf_num);
-
- explicit_inf_id = 1;
p1 = dot + 1;
}
else
{
- inf = current_inferior ();
-
+ inf_num = 0;
p1 = number;
}
@@ -88,6 +91,32 @@ parse_thread_id (const char *tidstr, const char **end)
if (thr_num == 0)
invalid_thread_id_error (number);
+ if (end != nullptr)
+ *end = p1;
+
+ return { inf_num, thr_num };
+}
+
+/* See tid-parse.h. */
+
+struct thread_info *
+parse_thread_id (const char *tidstr, const char **end)
+{
+ const auto [inf_num, thr_num] = parse_thread_id_1 (tidstr, end);
+
+ inferior *inf;
+ bool explicit_inf_id = false;
+
+ if (inf_num != 0)
+ {
+ inf = find_inferior_id (inf_num);
+ if (inf == nullptr)
+ error (_("No inferior number '%d'"), inf_num);
+ explicit_inf_id = true;
+ }
+ else
+ inf = current_inferior ();
+
thread_info *tp = nullptr;
for (thread_info *it : inf->threads ())
if (it->per_inf_num == thr_num)
@@ -96,7 +125,7 @@ parse_thread_id (const char *tidstr, const char **end)
break;
}
- if (tp == NULL)
+ if (tp == nullptr)
{
if (show_inferior_qualified_tids () || explicit_inf_id)
error (_("Unknown thread %d.%d."), inf->num, thr_num);
@@ -104,14 +133,27 @@ parse_thread_id (const char *tidstr, const char **end)
error (_("Unknown thread %d."), thr_num);
}
- if (end != NULL)
- *end = p1;
-
return tp;
}
/* See tid-parse.h. */
+bool
+is_thread_id (const char *tidstr, const char **end)
+{
+ try
+ {
+ (void) parse_thread_id_1 (tidstr, end);
+ return true;
+ }
+ catch (const gdb_exception_error &)
+ {
+ return false;
+ }
+}
+
+/* See tid-parse.h. */
+
tid_range_parser::tid_range_parser (const char *tidlist,
int default_inferior)
{
diff --git a/gdb/tid-parse.h b/gdb/tid-parse.h
index b7bd920..0ea58bb 100644
--- a/gdb/tid-parse.h
+++ b/gdb/tid-parse.h
@@ -26,7 +26,7 @@ struct thread_info;
/* Issue an invalid thread ID error, pointing at STRING, the invalid
ID. */
-extern void ATTRIBUTE_NORETURN invalid_thread_id_error (const char *string);
+[[noreturn]] extern void invalid_thread_id_error (const char *string);
/* Parse TIDSTR as a per-inferior thread ID, in either INF_NUM.THR_NUM
or THR_NUM form. In the latter case, the missing INF_NUM is filled
@@ -36,6 +36,14 @@ extern void ATTRIBUTE_NORETURN invalid_thread_id_error (const char *string);
thrown. */
struct thread_info *parse_thread_id (const char *tidstr, const char **end);
+/* Return true if TIDSTR is pointing to a string that looks like a
+ thread-id. This doesn't mean that TIDSTR identifies a valid thread, but
+ the string does at least look like a valid thread-id. If END is not
+ NULL, parse_thread_id stores the address of the first character after
+ the thread-id into *END. */
+
+bool is_thread_id (const char *tidstr, const char **end);
+
/* Parse a thread ID or a thread range list.
A range will be of the form
diff --git a/gdb/tilegx-linux-nat.c b/gdb/tilegx-linux-nat.c
index bbfeaef..440a5cc 100644
--- a/gdb/tilegx-linux-nat.c
+++ b/gdb/tilegx-linux-nat.c
@@ -57,7 +57,7 @@ static tilegx_linux_nat_target the_tilegx_linux_nat_target;
/* Mapping between the general-purpose registers in `struct user'
format and GDB's register array layout. Note that we map the
- first 56 registers (0 thru 55) one-to-one. GDB maps the pc to
+ first 56 registers (0 through 55) one-to-one. GDB maps the pc to
slot 64, but ptrace returns it in slot 56. */
static const int regmap[] =
{
diff --git a/gdb/top.c b/gdb/top.c
index d6bf1d4..d34e733 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -632,19 +632,9 @@ execute_fn_to_string (std::string &res, std::function<void(void)> fn,
{
string_file str_file (term_out);
- try
- {
- execute_fn_to_ui_file (&str_file, fn);
- }
- catch (...)
- {
- /* Finally. */
- res = str_file.release ();
- throw;
- }
+ SCOPE_EXIT { res = str_file.release (); };
- /* And finally. */
- res = str_file.release ();
+ execute_fn_to_ui_file (&str_file, fn);
}
/* See top.h. */
@@ -1389,6 +1379,11 @@ This GDB was configured as follows:\n\
configure --host=%s --target=%s\n\
"), host_name, target_name);
+#ifdef ENABLE_TARGETS
+ gdb_printf (stream, _("\
+ --enable-targets=%s\n"), ENABLE_TARGETS);
+#endif
+
gdb_printf (stream, _("\
--with-auto-load-dir=%s\n\
--with-auto-load-safe-path=%s\n\
diff --git a/gdb/top.h b/gdb/top.h
index dc3f2aa..b57cc3b 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -42,7 +42,7 @@ extern void read_command_file (FILE *);
extern void init_history (void);
extern void command_loop (void);
extern int quit_confirm (void);
-extern void quit_force (int *, int) ATTRIBUTE_NORETURN;
+[[noreturn]] extern void quit_force (int *, int);
extern void quit_command (const char *, int);
extern void quit_cover (void);
extern void execute_command (const char *, int);
diff --git a/gdb/tracectf.c b/gdb/tracectf.c
index 282a825..b4997f8 100644
--- a/gdb/tracectf.c
+++ b/gdb/tracectf.c
@@ -1111,7 +1111,7 @@ ctf_read_tp (struct uploaded_tp **uploaded_tps)
second packet which contains events on trace blocks. */
static void
-ctf_target_open (const char *dirname, int from_tty)
+ctf_target_open (const char *args, int from_tty)
{
struct bt_ctf_event *event;
uint32_t event_id;
@@ -1119,10 +1119,11 @@ ctf_target_open (const char *dirname, int from_tty)
struct uploaded_tsv *uploaded_tsvs = NULL;
struct uploaded_tp *uploaded_tps = NULL;
- if (!dirname)
+ std::string dirname = extract_single_filename_arg (args);
+ if (dirname.empty ())
error (_("No CTF directory specified."));
- ctf_open_dir (dirname);
+ ctf_open_dir (dirname.c_str ());
target_preopen (from_tty);
@@ -1162,7 +1163,7 @@ ctf_target_open (const char *dirname, int from_tty)
start_pos = bt_iter_get_pos (bt_ctf_get_iter (ctf_iter));
gdb_assert (start_pos->type == BT_SEEK_RESTORE);
- trace_dirname = make_unique_xstrdup (dirname);
+ trace_dirname = make_unique_xstrdup (dirname.c_str ());
current_inferior ()->push_target (&ctf_ops);
inferior_appeared (current_inferior (), CTF_PID);
@@ -1721,6 +1722,7 @@ void
_initialize_ctf ()
{
#if HAVE_LIBBABELTRACE
- add_target (ctf_target_info, ctf_target_open, filename_completer);
+ add_target (ctf_target_info, ctf_target_open,
+ filename_maybe_quoted_completer);
#endif
}
diff --git a/gdb/tracefile-tfile.c b/gdb/tracefile-tfile.c
index 4a4c4a2..b59b5c7 100644
--- a/gdb/tracefile-tfile.c
+++ b/gdb/tracefile-tfile.c
@@ -462,24 +462,24 @@ tfile_target_open (const char *arg, int from_tty)
struct uploaded_tsv *uploaded_tsvs = NULL;
target_preopen (from_tty);
- if (!arg)
+ std::string filename = extract_single_filename_arg (arg);
+ if (filename.empty ())
error (_("No trace file specified."));
- gdb::unique_xmalloc_ptr<char> filename (tilde_expand (arg));
- if (!IS_ABSOLUTE_PATH (filename.get ()))
- filename = make_unique_xstrdup (gdb_abspath (filename).c_str ());
+ if (!IS_ABSOLUTE_PATH (filename.c_str ()))
+ filename = gdb_abspath (filename);
flags = O_BINARY | O_LARGEFILE;
flags |= O_RDONLY;
- scratch_chan = gdb_open_cloexec (filename.get (), flags, 0).release ();
+ scratch_chan = gdb_open_cloexec (filename.c_str (), flags, 0).release ();
if (scratch_chan < 0)
- perror_with_name (filename.get ());
+ perror_with_name (filename.c_str ());
/* Looks semi-reasonable. Toss the old trace file and work on the new. */
current_inferior ()->unpush_target (&tfile_ops);
- trace_filename = std::move (filename);
+ trace_filename = make_unique_xstrdup (filename.c_str ());
trace_fd = scratch_chan;
/* Make sure this is clear. */
@@ -1120,5 +1120,6 @@ void _initialize_tracefile_tfile ();
void
_initialize_tracefile_tfile ()
{
- add_target (tfile_target_info, tfile_target_open, filename_completer);
+ add_target (tfile_target_info, tfile_target_open,
+ filename_maybe_quoted_completer);
}
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index e9bcbfd..ca6f616 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -671,7 +671,7 @@ validate_actionline (const char *line, tracepoint *t)
p = strchr (p, ',');
continue;
}
- /* else fall thru, treat p as an expression and parse it! */
+ /* else fall through, treat p as an expression and parse it! */
}
tmp_p = p;
for (bp_location &loc : t->locations ())
@@ -2110,7 +2110,7 @@ tfind_1 (enum trace_find_type type, int num,
if you're in a user-defined command or especially in a
loop, then you need a way to detect that the command
failed WITHOUT aborting. This allows you to write
- scripts that search thru the trace buffer until the end,
+ scripts that search through the trace buffer until the end,
and then continue on to do something else. */
if (from_tty)
@@ -2351,8 +2351,9 @@ tfind_line_command (const char *args, int from_tty)
{
if (start_pc == end_pc)
{
- gdb_printf ("Line %d of \"%s\"",
- sal.line,
+ gdb_printf ("Line %ps of \"%s\"",
+ styled_string (line_number_style.style (),
+ pulongest (sal.line)),
symtab_to_filename_for_display (sal.symtab));
gdb_stdout->wrap_here (2);
gdb_printf (" is at address ");
@@ -2363,8 +2364,9 @@ tfind_line_command (const char *args, int from_tty)
if (sal.line > 0
&& find_line_pc_range (sal, &start_pc, &end_pc)
&& start_pc != end_pc)
- gdb_printf ("Attempting to find line %d instead.\n",
- sal.line);
+ gdb_printf ("Attempting to find line %ps instead.\n",
+ styled_string (line_number_style.style (),
+ pulongest (sal.line)));
else
error (_("Cannot find a good line."));
}
@@ -2455,7 +2457,6 @@ tfind_outside_command (const char *args, int from_tty)
static void
info_scope_command (const char *args_in, int from_tty)
{
- struct bound_minimal_symbol msym;
const struct block *block;
const char *symname;
const char *save_args = args_in;
@@ -2579,17 +2580,20 @@ info_scope_command (const char *args_in, int from_tty)
sym->value_block ()->entry_pc ()));
break;
case LOC_UNRESOLVED:
- msym = lookup_minimal_symbol (sym->linkage_name (),
- NULL, NULL);
- if (msym.minsym == NULL)
- gdb_printf ("Unresolved Static");
- else
- {
- gdb_printf ("static storage at address ");
- gdb_printf ("%s",
- paddress (gdbarch, msym.value_address ()));
- }
- break;
+ {
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space,
+ sym->linkage_name ());
+ if (msym.minsym == NULL)
+ gdb_printf ("Unresolved Static");
+ else
+ {
+ gdb_printf ("static storage at address ");
+ gdb_printf ("%s",
+ paddress (gdbarch, msym.value_address ()));
+ }
+ break;
+ }
case LOC_OPTIMIZED_OUT:
gdb_printf ("optimized out.\n");
continue;
@@ -3642,7 +3646,7 @@ print_one_static_tracepoint_marker (int count,
else
uiout->field_skip ("fullname");
- uiout->field_signed ("line", sal.line);
+ uiout->field_signed ("line", sal.line, line_number_style.style ());
}
else
{
diff --git a/gdb/trad-frame.c b/gdb/trad-frame.c
index e64374a..35bf02e 100644
--- a/gdb/trad-frame.c
+++ b/gdb/trad-frame.c
@@ -154,12 +154,14 @@ trad_frame_set_reg_regmap (struct trad_frame_cache *this_trad_cache,
else
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- gdb_byte buf[slot_size];
+ gdb::byte_vector buf (slot_size);
- if (target_read_memory (addr + offs, buf, sizeof buf) == 0)
+ if (target_read_memory (addr + offs, buf.data (), buf.size ())
+ == 0)
{
LONGEST val
- = extract_unsigned_integer (buf, sizeof buf, byte_order);
+ = extract_unsigned_integer (buf.data (), buf.size (),
+ byte_order);
trad_frame_set_reg_value (this_trad_cache, regno, val);
}
}
diff --git a/gdb/tui/tui-command.c b/gdb/tui/tui-command.c
index b9bc19e..677721d 100644
--- a/gdb/tui/tui-command.c
+++ b/gdb/tui/tui-command.c
@@ -51,13 +51,3 @@ tui_cmd_window::resize (int height_, int width_, int origin_x, int origin_y)
wmove (handle.get (), 0, 0);
}
}
-
-/* See tui-command.h. */
-
-void
-tui_refresh_cmd_win (void)
-{
- WINDOW *w = tui_cmd_win ()->handle.get ();
-
- tui_wrefresh (w);
-}
diff --git a/gdb/tui/tui-command.h b/gdb/tui/tui-command.h
index 90b8de7..f167d95 100644
--- a/gdb/tui/tui-command.h
+++ b/gdb/tui/tui-command.h
@@ -26,8 +26,7 @@
/* The TUI command window. */
struct tui_cmd_window
- : public tui_noscroll_window, tui_nobox_window, tui_norefresh_window,
- tui_always_visible_window
+ : public tui_noscroll_window, tui_nobox_window, tui_always_visible_window
{
tui_cmd_window () = default;
@@ -63,7 +62,4 @@ tui_cmd_win ()
return dynamic_cast<tui_cmd_window *> (tui_win_list[CMD_WIN]);
}
-/* Refresh the command window. */
-extern void tui_refresh_cmd_win (void);
-
#endif /* TUI_TUI_COMMAND_H */
diff --git a/gdb/tui/tui-data.h b/gdb/tui/tui-data.h
index b9922db..79a4163 100644
--- a/gdb/tui/tui-data.h
+++ b/gdb/tui/tui-data.h
@@ -117,13 +117,6 @@ public:
return true;
}
- /* Disable output until the next call to doupdate. */
- void no_refresh ()
- {
- if (handle != nullptr)
- wnoutrefresh (handle.get ());
- }
-
/* Called after the tab width has been changed. */
virtual void update_tab_width ()
{
@@ -260,15 +253,6 @@ struct tui_nobox_window : public virtual tui_win_info
}
};
-/* A TUI window that is not refreshed. */
-
-struct tui_norefresh_window : public virtual tui_win_info
-{
- virtual void refresh_window () final override
- {
- }
-};
-
/* A TUI window that is always visible. */
struct tui_always_visible_window : public virtual tui_win_info
diff --git a/gdb/tui/tui-disasm.c b/gdb/tui/tui-disasm.c
index 0727d3a..cd82853 100644
--- a/gdb/tui/tui-disasm.c
+++ b/gdb/tui/tui-disasm.c
@@ -157,11 +157,11 @@ tui_disassemble (struct gdbarch *gdbarch,
static CORE_ADDR
tui_find_backward_disassembly_start_address (CORE_ADDR addr)
{
- struct bound_minimal_symbol msym, msym_prev;
-
- msym = lookup_minimal_symbol_by_pc_section (addr - 1, nullptr,
- lookup_msym_prefer::TEXT,
- &msym_prev);
+ bound_minimal_symbol msym_prev;
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol_by_pc_section (addr - 1, nullptr,
+ lookup_msym_prefer::TEXT,
+ &msym_prev);
if (msym.minsym != nullptr)
return msym.value_address ();
else if (msym_prev.minsym != nullptr)
@@ -389,10 +389,12 @@ tui_get_begin_asm_address (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
if (tui_location.addr () == 0)
{
- if (have_full_symbols () || have_partial_symbols ())
+ if (have_full_symbols (current_program_space)
+ || have_partial_symbols (current_program_space))
{
set_default_source_symtab_and_line ();
- struct symtab_and_line sal = get_current_source_symtab_and_line ();
+ symtab_and_line sal
+ = get_current_source_symtab_and_line (current_program_space);
if (sal.symtab != nullptr)
find_line_pc (sal.symtab, sal.line, &addr);
@@ -400,8 +402,8 @@ tui_get_begin_asm_address (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
if (addr == 0)
{
- struct bound_minimal_symbol main_symbol
- = lookup_minimal_symbol (main_name (), nullptr, nullptr);
+ bound_minimal_symbol main_symbol
+ = lookup_minimal_symbol (current_program_space, main_name ());
if (main_symbol.minsym != nullptr)
addr = main_symbol.value_address ();
}
diff --git a/gdb/tui/tui-file.c b/gdb/tui/tui-file.c
index 7878190..17ac138 100644
--- a/gdb/tui/tui-file.c
+++ b/gdb/tui/tui-file.c
@@ -25,7 +25,7 @@ tui_file::puts (const char *linebuffer)
{
tui_puts (linebuffer);
if (!m_buffered)
- tui_refresh_cmd_win ();
+ tui_cmd_win ()->refresh_window ();
}
void
@@ -33,13 +33,13 @@ tui_file::write (const char *buf, long length_buf)
{
tui_write (buf, length_buf);
if (!m_buffered)
- tui_refresh_cmd_win ();
+ tui_cmd_win ()->refresh_window ();
}
void
tui_file::flush ()
{
if (m_buffered)
- tui_refresh_cmd_win ();
+ tui_cmd_win ()->refresh_window ();
stdio_file::flush ();
}
diff --git a/gdb/tui/tui-hooks.c b/gdb/tui/tui-hooks.c
index e6673ab..25358d0 100644
--- a/gdb/tui/tui-hooks.c
+++ b/gdb/tui/tui-hooks.c
@@ -127,7 +127,8 @@ tui_refresh_frame_and_register_information ()
/* Make sure that the source window is displayed. */
tui_add_win_to_layout (SRC_WIN);
- struct symtab_and_line sal = get_current_source_symtab_and_line ();
+ symtab_and_line sal
+ = get_current_source_symtab_and_line (current_program_space);
tui_update_source_windows_with_line (sal);
}
}
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 665b521..2b6cb31 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -61,6 +61,8 @@ std::vector<tui_win_info *> tui_windows;
void
tui_apply_current_layout (bool preserve_cmd_win_size_p)
{
+ tui_batch_rendering defer;
+
for (tui_win_info *win_info : tui_windows)
win_info->make_visible (false);
diff --git a/gdb/tui/tui-regs.c b/gdb/tui/tui-regs.c
index 2be8187..38ddd23 100644
--- a/gdb/tui/tui-regs.c
+++ b/gdb/tui/tui-regs.c
@@ -151,8 +151,8 @@ tui_data_window::first_reg_element_no_inline (int line_no) const
return (-1);
}
-/* Show the registers of the given group in the data window
- and refresh the window. */
+/* See tui-regs.h. */
+
void
tui_data_window::set_register_group (const reggroup *group)
{
@@ -166,9 +166,6 @@ tui_data_window::set_register_group (const reggroup *group)
void
tui_data_window::update_register_data (const reggroup *group)
{
- if (group == nullptr)
- group = general_reggroup;
-
if (!target_has_registers ()
|| !target_has_stack ()
|| !target_has_memory ())
@@ -180,6 +177,9 @@ tui_data_window::update_register_data (const reggroup *group)
return;
}
+ if (group == nullptr)
+ group = general_reggroup;
+
frame_info_ptr frame = get_selected_frame (nullptr);
struct gdbarch *gdbarch = get_frame_arch (frame);
@@ -269,8 +269,6 @@ tui_data_window::display_registers_from (int start_element_no)
/* Mark register windows below the visible area. */
for (; i < m_regs_content.size (); i++)
m_regs_content[i].y = 0;
-
- refresh_window ();
}
/* See tui-regs.h. */
@@ -359,7 +357,7 @@ tui_data_window::rerender ()
erase_data_content ();
else
display_registers_from (0);
- tui_wrefresh (handle.get ());
+ refresh_window ();
}
@@ -382,6 +380,7 @@ tui_data_window::do_scroll_vertical (int num_to_scroll)
{
first_line += num_to_scroll;
display_registers_from_line (first_line);
+ refresh_window ();
}
}
@@ -391,29 +390,23 @@ tui_data_window::do_scroll_vertical (int num_to_scroll)
void
tui_data_window::check_register_values (const frame_info_ptr &frame)
{
- if (frame == nullptr)
+ /* If the frame architecture changed, we need to reset the register
+ group. */
+ if (frame == nullptr || get_frame_arch (frame) != m_gdbarch)
set_register_group (nullptr);
else
{
- /* If the frame architecture changed, we need to reset the
- register group. */
- struct gdbarch *gdbarch = get_frame_arch (frame);
- if (gdbarch != m_gdbarch)
- set_register_group (nullptr);
- else
+ for (tui_register_info &data_item_win : m_regs_content)
{
- for (tui_register_info &data_item_win : m_regs_content)
- {
- bool was_hilighted = data_item_win.highlighted ();
+ bool was_hilighted = data_item_win.highlighted ();
- data_item_win.update (frame);
+ data_item_win.update (frame);
- if ((data_item_win.highlighted () || was_hilighted)
- && data_item_win.visible ())
- data_item_win.rerender (handle.get (), m_item_width);
- }
+ if ((data_item_win.highlighted () || was_hilighted)
+ && data_item_win.visible ())
+ data_item_win.rerender (handle.get (), m_item_width);
}
- tui_wrefresh (handle.get ());
+ refresh_window ();
}
}
@@ -499,11 +492,11 @@ tui_reg_command (const char *args, int from_tty)
{
size_t len = strlen (args);
+ tui_batch_rendering suppress;
+
/* Make sure the curses mode is enabled. */
tui_enable ();
- tui_suppress_output suppress;
-
/* Make sure the register window is visible. If not, select an
appropriate layout. We need to do this before trying to run the
'next' or 'prev' commands. */
diff --git a/gdb/tui/tui-regs.h b/gdb/tui/tui-regs.h
index 61bfdd2..fa1a3dd 100644
--- a/gdb/tui/tui-regs.h
+++ b/gdb/tui/tui-regs.h
@@ -81,6 +81,8 @@ struct tui_data_window : public tui_win_info
void check_register_values (const frame_info_ptr &frame);
+ /* Set the current register and redisplay the window. If GROUP is
+ NULL, the general register group will be used. */
void set_register_group (const reggroup *group);
const reggroup *get_current_group () const
diff --git a/gdb/tui/tui-source.c b/gdb/tui/tui-source.c
index 444c0f7..503fb00 100644
--- a/gdb/tui/tui-source.c
+++ b/gdb/tui/tui-source.c
@@ -32,6 +32,20 @@
#include "tui/tui-winsource.h"
#include "tui/tui-source.h"
#include "tui/tui-location.h"
+#include "tui/tui-io.h"
+#include "cli/cli-style.h"
+
+tui_source_window::tui_source_window ()
+{
+ line_number_style.changed.attach
+ (std::bind (&tui_source_window::style_changed, this),
+ m_src_observable, "tui-source");
+}
+
+tui_source_window::~tui_source_window ()
+{
+ line_number_style.changed.detach (m_src_observable);
+}
/* Function to display source in the source window. */
bool
@@ -136,7 +150,8 @@ tui_source_window::do_scroll_vertical (int num_to_scroll)
if (!m_content.empty ())
{
struct symtab *s;
- struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+ symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
struct gdbarch *arch = m_gdbarch;
if (cursal.symtab == NULL)
@@ -220,7 +235,7 @@ void
tui_source_window::display_start_addr (struct gdbarch **gdbarch_p,
CORE_ADDR *addr_p)
{
- struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+ symtab_and_line cursal = get_current_source_symtab_and_line (current_program_space);
*gdbarch_p = m_gdbarch;
find_line_pc (cursal.symtab, m_start_line_or_addr.u.line_no, addr_p);
@@ -246,5 +261,7 @@ tui_source_window::show_line_number (int offset) const
tui_left_margin_verbose ? "%0*d%c" : "%*d%c", m_digits - 1,
lineno, space);
}
+ tui_apply_style (handle.get (), line_number_style.style ());
display_string (text);
+ tui_apply_style (handle.get (), ui_file_style ());
}
diff --git a/gdb/tui/tui-source.h b/gdb/tui/tui-source.h
index f32167f..d8f7189 100644
--- a/gdb/tui/tui-source.h
+++ b/gdb/tui/tui-source.h
@@ -30,7 +30,8 @@
struct tui_source_window : public tui_source_window_base
{
- tui_source_window () = default;
+ tui_source_window ();
+ ~tui_source_window ();
DISABLE_COPY_AND_ASSIGN (tui_source_window);
@@ -81,6 +82,9 @@ private:
/* It is the resolved form as returned by symtab_to_fullname. */
gdb::unique_xmalloc_ptr<char> m_fullname;
+
+ /* A token used to register and unregister an observer. */
+ gdb::observers::token m_src_observable;
};
/* Return the instance of the source window. */
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index c67c4f5..e9a8e46 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -473,11 +473,7 @@ void
tui_refresh_all_win (void)
{
clearok (curscr, TRUE);
- for (tui_win_info *win_info : all_tui_windows ())
- {
- if (win_info->is_visible ())
- win_info->refresh_window ();
- }
+ doupdate ();
}
void
diff --git a/gdb/tui/tui-wingeneral.c b/gdb/tui/tui-wingeneral.c
index d113d77..369d152 100644
--- a/gdb/tui/tui-wingeneral.c
+++ b/gdb/tui/tui-wingeneral.c
@@ -27,42 +27,27 @@
#include "gdb_curses.h"
-/* This is true if we're currently suppressing output, via
- wnoutrefresh. This is needed in case we create a new window while
- in this mode. */
+/* This is true when there is a live instance of tui_batch_rendering.
+ The outermost tui_batch_rendering will cause a flush to the
+ screen. */
static bool suppress_output;
/* See tui-data.h. */
-tui_suppress_output::tui_suppress_output ()
+tui_batch_rendering::tui_batch_rendering ()
: m_saved_suppress (suppress_output)
{
suppress_output = true;
-
- for (const auto &win : all_tui_windows ())
- win->no_refresh ();
}
/* See tui-data.h. */
-tui_suppress_output::~tui_suppress_output ()
+tui_batch_rendering::~tui_batch_rendering ()
{
suppress_output = m_saved_suppress;
if (!suppress_output)
doupdate ();
-
- for (const auto &win : all_tui_windows ())
- win->refresh_window ();
-}
-
-/* See tui-data.h. */
-
-void
-tui_wrefresh (WINDOW *win)
-{
- if (!suppress_output)
- wrefresh (win);
}
/* See tui-data.h. */
@@ -71,7 +56,7 @@ void
tui_win_info::refresh_window ()
{
if (handle != NULL)
- tui_wrefresh (handle.get ());
+ wnoutrefresh (handle.get ());
}
/* Draw a border around the window. */
diff --git a/gdb/tui/tui-wingeneral.h b/gdb/tui/tui-wingeneral.h
index 652cef9..83ecb7d 100644
--- a/gdb/tui/tui-wingeneral.h
+++ b/gdb/tui/tui-wingeneral.h
@@ -29,18 +29,20 @@ struct tui_win_info;
extern void tui_unhighlight_win (struct tui_win_info *);
extern void tui_highlight_win (struct tui_win_info *);
-/* An RAII class that suppresses output on construction (calling
- wnoutrefresh on the existing windows), and then flushes the output
- (via doupdate) when destroyed. */
+/* An RAII class that calls doupdate on destruction (really the
+ destruction of the outermost instance). This is used to prevent
+ flickering -- window implementations should only call wnoutrefresh,
+ and any time rendering is needed, an object of this type should be
+ instantiated. */
-class tui_suppress_output
+class tui_batch_rendering
{
public:
- tui_suppress_output ();
- ~tui_suppress_output ();
+ tui_batch_rendering ();
+ ~tui_batch_rendering ();
- DISABLE_COPY_AND_ASSIGN (tui_suppress_output);
+ DISABLE_COPY_AND_ASSIGN (tui_batch_rendering);
private:
@@ -48,8 +50,4 @@ private:
bool m_saved_suppress;
};
-/* Call wrefresh on the given window. However, if output is being
- suppressed via tui_suppress_output, do not call wrefresh. */
-extern void tui_wrefresh (WINDOW *win);
-
#endif /* TUI_TUI_WINGENERAL_H */
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
index 80297e5..a313e44 100644
--- a/gdb/tui/tui-winsource.c
+++ b/gdb/tui/tui-winsource.c
@@ -343,7 +343,7 @@ tui_source_window_base::refresh_window ()
int smincol = x + box_width () + left_margin;
int smaxrow = sminrow + m_content.size () - 1;
int smaxcol = smincol + view_width - 1;
- prefresh (m_pad.get (), 0, pad_x, sminrow, smincol, smaxrow, smaxcol);
+ pnoutrefresh (m_pad.get (), 0, pad_x, sminrow, smincol, smaxrow, smaxcol);
}
void
@@ -440,8 +440,8 @@ tui_source_window_base::rerender ()
if (!m_content.empty ())
{
- struct symtab_and_line cursal
- = get_current_source_symtab_and_line ();
+ symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
if (m_start_line_or_addr.loa == LOA_LINE)
cursal.line = m_start_line_or_addr.u.line_no;
@@ -451,8 +451,8 @@ tui_source_window_base::rerender ()
}
else if (deprecated_safe_get_selected_frame () != NULL)
{
- struct symtab_and_line cursal
- = get_current_source_symtab_and_line ();
+ symtab_and_line cursal
+ = get_current_source_symtab_and_line (current_program_space);
frame_info_ptr frame = deprecated_safe_get_selected_frame ();
struct gdbarch *gdbarch = get_frame_arch (frame);
@@ -492,7 +492,7 @@ tui_source_window_base::refill ()
if (this == tui_src_win ())
{
- sal = get_current_source_symtab_and_line ();
+ sal = get_current_source_symtab_and_line (current_program_space);
if (sal.symtab == NULL)
{
frame_info_ptr fi = deprecated_safe_get_selected_frame ();
diff --git a/gdb/tui/tui-winsource.h b/gdb/tui/tui-winsource.h
index 29828c1..a262c63 100644
--- a/gdb/tui/tui-winsource.h
+++ b/gdb/tui/tui-winsource.h
@@ -189,6 +189,11 @@ public:
update_source_windows_with_addr. */
void update_source_window_with_addr (struct gdbarch *, CORE_ADDR);
+protected:
+
+ /* Called when a user style setting is changed. */
+ void style_changed ();
+
private:
/* Used for horizontal scroll. */
@@ -236,9 +241,6 @@ private:
the initial escape that sets the color will still be applied. */
void puts_to_pad_with_skip (const char *string, int skip);
- /* Called when the user "set style enabled" setting is changed. */
- void style_changed ();
-
/* A token used to register and unregister an observer. */
gdb::observers::token m_observable;
diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
index 781ec85..bc96cd8 100644
--- a/gdb/tui/tui.c
+++ b/gdb/tui/tui.c
@@ -568,7 +568,7 @@ tui_disable_command (const char *args, int from_tty)
void
tui_show_assembly (struct gdbarch *gdbarch, CORE_ADDR addr)
{
- tui_suppress_output suppress;
+ tui_batch_rendering suppress;
tui_add_win_to_layout (DISASSEM_WIN);
tui_update_source_windows_with_addr (gdbarch, addr);
}
diff --git a/gdb/typeprint.c b/gdb/typeprint.c
index 2e1c5ea..274f602 100644
--- a/gdb/typeprint.c
+++ b/gdb/typeprint.c
@@ -513,7 +513,7 @@ whatis_exp (const char *exp, int show)
val = expr->evaluate_type ();
type = val->type ();
- if (show == -1 && expr->first_opcode () == OP_TYPE)
+ if (show == -1 && expr->type_p ())
{
/* The user expression names a type directly. */
diff --git a/gdb/ui-out.c b/gdb/ui-out.c
index 7e9f238..3330cc8 100644
--- a/gdb/ui-out.c
+++ b/gdb/ui-out.c
@@ -433,7 +433,8 @@ ui_out::end (ui_out_type type)
}
void
-ui_out::field_signed (const char *fldname, LONGEST value)
+ui_out::field_signed (const char *fldname, LONGEST value,
+ const ui_file_style &style)
{
int fldno;
int width;
@@ -441,7 +442,7 @@ ui_out::field_signed (const char *fldname, LONGEST value)
verify_field (&fldno, &width, &align);
- do_field_signed (fldno, width, align, fldname, value);
+ do_field_signed (fldno, width, align, fldname, value, style);
}
void
@@ -454,7 +455,8 @@ ui_out::field_fmt_signed (int input_width, ui_align input_align,
verify_field (&fldno, &width, &align);
- do_field_signed (fldno, input_width, input_align, fldname, value);
+ do_field_signed (fldno, input_width, input_align, fldname, value,
+ ui_file_style ());
}
/* See ui-out.h. */
diff --git a/gdb/ui-out.h b/gdb/ui-out.h
index ef9ce4f..f9d96de 100644
--- a/gdb/ui-out.h
+++ b/gdb/ui-out.h
@@ -182,7 +182,8 @@ class ui_out
void begin (ui_out_type type, const char *id);
void end (ui_out_type type);
- void field_signed (const char *fldname, LONGEST value);
+ void field_signed (const char *fldname, LONGEST value,
+ const ui_file_style &style = ui_file_style ());
void field_fmt_signed (int width, ui_align align, const char *fldname,
LONGEST value);
/* Like field_signed, but print an unsigned value. */
@@ -346,7 +347,8 @@ protected:
virtual void do_begin (ui_out_type type, const char *id) = 0;
virtual void do_end (ui_out_type type) = 0;
virtual void do_field_signed (int fldno, int width, ui_align align,
- const char *fldname, LONGEST value) = 0;
+ const char *fldname, LONGEST value,
+ const ui_file_style &style) = 0;
virtual void do_field_unsigned (int fldno, int width, ui_align align,
const char *fldname, ULONGEST value) = 0;
virtual void do_field_skip (int fldno, int width, ui_align align,
diff --git a/gdb/ui.c b/gdb/ui.c
index e5c7965..88a3a14 100644
--- a/gdb/ui.c
+++ b/gdb/ui.c
@@ -106,7 +106,7 @@ ui::input_interactive_p () const
/* When there is an event ready on the stdin file descriptor, instead
- of calling readline directly throught the callback function, or
+ of calling readline directly through the callback function, or
instead of calling gdb_readline_no_editing_callback, give gdb a
chance to detect errors and do something. */
diff --git a/gdb/unittests/enum-flags-selftests.c b/gdb/unittests/enum-flags-selftests.c
index b55d8c3..dddb1e2 100644
--- a/gdb/unittests/enum-flags-selftests.c
+++ b/gdb/unittests/enum-flags-selftests.c
@@ -29,49 +29,49 @@ namespace enum_flags_tests {
make it simpler to use. They could be named differently. */
/* A "real enum". */
-enum RE
- {
- RE_FLAG1 = 1 << 1,
- RE_FLAG2 = 1 << 2,
- };
+enum RawEnum
+{
+ RawEnum_Flag1 = 1 << 1,
+ RawEnum_Flag2 = 1 << 2,
+};
/* Another "real enum". */
-enum RE2
- {
- RE2_FLAG1 = 1 << 1,
- RE2_FLAG2 = 1 << 2,
- };
+enum RawEnum2
+{
+ RawEnum2_Flag1 = 1 << 1,
+ RawEnum2_Flag2 = 1 << 2,
+};
/* An unsigned "real enum". */
-enum URE : unsigned
- {
- URE_FLAG1 = 1 << 1,
- URE_FLAG2 = 1 << 2,
- URE_FLAG3 = 0xffffffff,
- };
+enum UnsignedRawEnum : unsigned
+{
+ UnsignedRawEnum_Flag1 = 1 << 1,
+ UnsignedRawEnum_Flag2 = 1 << 2,
+ UnsignedRawEnum_Flag3 = 0xffffffff,
+};
/* A non-flags enum. */
-enum NF
- {
- NF_FLAG1 = 1 << 1,
- NF_FLAG2 = 1 << 2,
- };
+enum NonFlagsEnum
+{
+ NonFlagsEnum_Flag1 = 1 << 1,
+ NonFlagsEnum_Flag2 = 1 << 2,
+};
/* The corresponding "enum flags" types. */
-DEF_ENUM_FLAGS_TYPE (RE, EF);
-DEF_ENUM_FLAGS_TYPE (RE2, EF2);
-DEF_ENUM_FLAGS_TYPE (URE, UEF);
+DEF_ENUM_FLAGS_TYPE (RawEnum, EnumFlag);
+DEF_ENUM_FLAGS_TYPE (RawEnum2, EnumFlag2);
+DEF_ENUM_FLAGS_TYPE (UnsignedRawEnum, UnsignedEnumFlag);
/* So that std::vectors of types that have enum_flags fields can
reallocate efficiently memcpy. */
-static_assert (std::is_trivially_copyable<EF>::value);
+static_assert (std::is_trivially_copyable<EnumFlag>::value);
/* A couple globals used as lvalues in the CHECK_VALID expressions
below. Their names (and types) match the uppercase type names
exposed by CHECK_VALID just to make the expressions easier to
follow. */
-static RE re ATTRIBUTE_UNUSED;
-static EF ef ATTRIBUTE_UNUSED;
+static RawEnum re ATTRIBUTE_UNUSED;
+static EnumFlag ef ATTRIBUTE_UNUSED;
/* First, compile-time tests that:
@@ -82,30 +82,32 @@ static EF ef ATTRIBUTE_UNUSED;
types do compile and that they return the correct type.
*/
-#define CHECK_VALID(VALID, EXPR_TYPE, EXPR) \
- CHECK_VALID_EXPR_6 (EF, RE, EF2, RE2, UEF, URE, VALID, EXPR_TYPE, EXPR)
+#define CHECK_VALID(VALID, EXPR_TYPE, EXPR) \
+ CHECK_VALID_EXPR_6 (EnumFlag, RawEnum, EnumFlag2, RawEnum2, \
+ UnsignedEnumFlag, UnsignedRawEnum, VALID, EXPR_TYPE, \
+ EXPR)
-typedef std::underlying_type<RE>::type und;
+using und = std::underlying_type<RawEnum>::type;
/* Test construction / conversion from/to different types. */
/* RE/EF -> underlying (explicit) */
-CHECK_VALID (true, und, und (RE ()))
-CHECK_VALID (true, und, und (EF ()))
+CHECK_VALID (true, und, und (RawEnum ()))
+CHECK_VALID (true, und, und (EnumFlag ()))
/* RE/EF -> int (explicit) */
-CHECK_VALID (true, int, int (RE ()))
-CHECK_VALID (true, int, int (EF ()))
+CHECK_VALID (true, int, int (RawEnum ()))
+CHECK_VALID (true, int, int (EnumFlag ()))
/* other -> RE */
/* You can construct a raw enum value from an int explicitly to punch
a hole in the type system if need to. */
-CHECK_VALID (true, RE, RE (1))
-CHECK_VALID (true, RE, RE (RE2 ()))
-CHECK_VALID (false, void, RE (EF2 ()))
-CHECK_VALID (true, RE, RE (RE ()))
-CHECK_VALID (false, void, RE (EF ()))
+CHECK_VALID (true, RawEnum, RawEnum (1))
+CHECK_VALID (true, RawEnum, RawEnum (RawEnum2 ()))
+CHECK_VALID (false, void, RawEnum (EnumFlag2 ()))
+CHECK_VALID (true, RawEnum, RawEnum (RawEnum ()))
+CHECK_VALID (false, void, RawEnum (EnumFlag ()))
/* other -> EF. */
@@ -113,125 +115,125 @@ CHECK_VALID (false, void, RE (EF ()))
enum. Unlike with raw enums, you can't construct an enum flags
from an integer nor from an unrelated enum type explicitly. Add an
intermediate conversion via the raw enum if you really need it. */
-CHECK_VALID (false, void, EF (1))
-CHECK_VALID (false, void, EF (1u))
-CHECK_VALID (false, void, EF (RE2 ()))
-CHECK_VALID (false, void, EF (EF2 ()))
-CHECK_VALID (true, EF, EF (RE ()))
-CHECK_VALID (true, EF, EF (EF ()))
+CHECK_VALID (false, void, EnumFlag (1))
+CHECK_VALID (false, void, EnumFlag (1u))
+CHECK_VALID (false, void, EnumFlag (RawEnum2 ()))
+CHECK_VALID (false, void, EnumFlag (EnumFlag2 ()))
+CHECK_VALID (true, EnumFlag, EnumFlag (RawEnum ()))
+CHECK_VALID (true, EnumFlag, EnumFlag (EnumFlag ()))
/* Test operators. */
/* operator OP (raw_enum, int) */
-CHECK_VALID (false, void, RE () | 1)
-CHECK_VALID (false, void, RE () & 1)
-CHECK_VALID (false, void, RE () ^ 1)
+CHECK_VALID (false, void, RawEnum () | 1)
+CHECK_VALID (false, void, RawEnum () & 1)
+CHECK_VALID (false, void, RawEnum () ^ 1)
/* operator OP (int, raw_enum) */
-CHECK_VALID (false, void, 1 | RE ())
-CHECK_VALID (false, void, 1 & RE ())
-CHECK_VALID (false, void, 1 ^ RE ())
+CHECK_VALID (false, void, 1 | RawEnum ())
+CHECK_VALID (false, void, 1 & RawEnum ())
+CHECK_VALID (false, void, 1 ^ RawEnum ())
/* operator OP (enum_flags, int) */
-CHECK_VALID (false, void, EF () | 1)
-CHECK_VALID (false, void, EF () & 1)
-CHECK_VALID (false, void, EF () ^ 1)
+CHECK_VALID (false, void, EnumFlag () | 1)
+CHECK_VALID (false, void, EnumFlag () & 1)
+CHECK_VALID (false, void, EnumFlag () ^ 1)
/* operator OP (int, enum_flags) */
-CHECK_VALID (false, void, 1 | EF ())
-CHECK_VALID (false, void, 1 & EF ())
-CHECK_VALID (false, void, 1 ^ EF ())
+CHECK_VALID (false, void, 1 | EnumFlag ())
+CHECK_VALID (false, void, 1 & EnumFlag ())
+CHECK_VALID (false, void, 1 ^ EnumFlag ())
/* operator OP (raw_enum, raw_enum) */
-CHECK_VALID (false, void, RE () | RE2 ())
-CHECK_VALID (false, void, RE () & RE2 ())
-CHECK_VALID (false, void, RE () ^ RE2 ())
-CHECK_VALID (true, RE, RE () | RE ())
-CHECK_VALID (true, RE, RE () & RE ())
-CHECK_VALID (true, RE, RE () ^ RE ())
+CHECK_VALID (false, void, RawEnum () | RawEnum2 ())
+CHECK_VALID (false, void, RawEnum () & RawEnum2 ())
+CHECK_VALID (false, void, RawEnum () ^ RawEnum2 ())
+CHECK_VALID (true, RawEnum, RawEnum () | RawEnum ())
+CHECK_VALID (true, RawEnum, RawEnum () & RawEnum ())
+CHECK_VALID (true, RawEnum, RawEnum () ^ RawEnum ())
/* operator OP (enum_flags, raw_enum) */
-CHECK_VALID (false, void, EF () | RE2 ())
-CHECK_VALID (false, void, EF () & RE2 ())
-CHECK_VALID (false, void, EF () ^ RE2 ())
-CHECK_VALID (true, EF, EF () | RE ())
-CHECK_VALID (true, EF, EF () & RE ())
-CHECK_VALID (true, EF, EF () ^ RE ())
+CHECK_VALID (false, void, EnumFlag () | RawEnum2 ())
+CHECK_VALID (false, void, EnumFlag () & RawEnum2 ())
+CHECK_VALID (false, void, EnumFlag () ^ RawEnum2 ())
+CHECK_VALID (true, EnumFlag, EnumFlag () | RawEnum ())
+CHECK_VALID (true, EnumFlag, EnumFlag () & RawEnum ())
+CHECK_VALID (true, EnumFlag, EnumFlag () ^ RawEnum ())
/* operator OP= (raw_enum, raw_enum), rvalue ref on the lhs. */
-CHECK_VALID (false, void, RE () |= RE2 ())
-CHECK_VALID (false, void, RE () &= RE2 ())
-CHECK_VALID (false, void, RE () ^= RE2 ())
-CHECK_VALID (false, void, RE () |= RE ())
-CHECK_VALID (false, void, RE () &= RE ())
-CHECK_VALID (false, void, RE () ^= RE ())
+CHECK_VALID (false, void, RawEnum () |= RawEnum2 ())
+CHECK_VALID (false, void, RawEnum () &= RawEnum2 ())
+CHECK_VALID (false, void, RawEnum () ^= RawEnum2 ())
+CHECK_VALID (false, void, RawEnum () |= RawEnum ())
+CHECK_VALID (false, void, RawEnum () &= RawEnum ())
+CHECK_VALID (false, void, RawEnum () ^= RawEnum ())
/* operator OP= (raw_enum, raw_enum), lvalue ref on the lhs. */
-CHECK_VALID (false, void, re |= RE2 ())
-CHECK_VALID (false, void, re &= RE2 ())
-CHECK_VALID (false, void, re ^= RE2 ())
-CHECK_VALID (true, RE&, re |= RE ())
-CHECK_VALID (true, RE&, re &= RE ())
-CHECK_VALID (true, RE&, re ^= RE ())
+CHECK_VALID (false, void, re |= RawEnum2 ())
+CHECK_VALID (false, void, re &= RawEnum2 ())
+CHECK_VALID (false, void, re ^= RawEnum2 ())
+CHECK_VALID (true, RawEnum&, re |= RawEnum ())
+CHECK_VALID (true, RawEnum&, re &= RawEnum ())
+CHECK_VALID (true, RawEnum&, re ^= RawEnum ())
/* operator OP= (enum_flags, raw_enum), rvalue ref on the lhs. */
-CHECK_VALID (false, void, EF () |= RE2 ())
-CHECK_VALID (false, void, EF () &= RE2 ())
-CHECK_VALID (false, void, EF () ^= RE2 ())
-CHECK_VALID (false, void, EF () |= RE ())
-CHECK_VALID (false, void, EF () &= RE ())
-CHECK_VALID (false, void, EF () ^= RE ())
+CHECK_VALID (false, void, EnumFlag () |= RawEnum2 ())
+CHECK_VALID (false, void, EnumFlag () &= RawEnum2 ())
+CHECK_VALID (false, void, EnumFlag () ^= RawEnum2 ())
+CHECK_VALID (false, void, EnumFlag () |= RawEnum ())
+CHECK_VALID (false, void, EnumFlag () &= RawEnum ())
+CHECK_VALID (false, void, EnumFlag () ^= RawEnum ())
/* operator OP= (enum_flags, raw_enum), lvalue ref on the lhs. */
-CHECK_VALID (false, void, ef |= RE2 ())
-CHECK_VALID (false, void, ef &= RE2 ())
-CHECK_VALID (false, void, ef ^= RE2 ())
-CHECK_VALID (true, EF&, ef |= EF ())
-CHECK_VALID (true, EF&, ef &= EF ())
-CHECK_VALID (true, EF&, ef ^= EF ())
+CHECK_VALID (false, void, ef |= RawEnum2 ())
+CHECK_VALID (false, void, ef &= RawEnum2 ())
+CHECK_VALID (false, void, ef ^= RawEnum2 ())
+CHECK_VALID (true, EnumFlag&, ef |= EnumFlag ())
+CHECK_VALID (true, EnumFlag&, ef &= EnumFlag ())
+CHECK_VALID (true, EnumFlag&, ef ^= EnumFlag ())
/* operator OP= (enum_flags, enum_flags), rvalue ref on the lhs. */
-CHECK_VALID (false, void, EF () |= EF2 ())
-CHECK_VALID (false, void, EF () &= EF2 ())
-CHECK_VALID (false, void, EF () ^= EF2 ())
-CHECK_VALID (false, void, EF () |= EF ())
-CHECK_VALID (false, void, EF () &= EF ())
-CHECK_VALID (false, void, EF () ^= EF ())
+CHECK_VALID (false, void, EnumFlag () |= EnumFlag2 ())
+CHECK_VALID (false, void, EnumFlag () &= EnumFlag2 ())
+CHECK_VALID (false, void, EnumFlag () ^= EnumFlag2 ())
+CHECK_VALID (false, void, EnumFlag () |= EnumFlag ())
+CHECK_VALID (false, void, EnumFlag () &= EnumFlag ())
+CHECK_VALID (false, void, EnumFlag () ^= EnumFlag ())
/* operator OP= (enum_flags, enum_flags), lvalue ref on the lhs. */
-CHECK_VALID (false, void, ef |= EF2 ())
-CHECK_VALID (false, void, ef &= EF2 ())
-CHECK_VALID (false, void, ef ^= EF2 ())
-CHECK_VALID (true, EF&, ef |= EF ())
-CHECK_VALID (true, EF&, ef &= EF ())
-CHECK_VALID (true, EF&, ef ^= EF ())
+CHECK_VALID (false, void, ef |= EnumFlag2 ())
+CHECK_VALID (false, void, ef &= EnumFlag2 ())
+CHECK_VALID (false, void, ef ^= EnumFlag2 ())
+CHECK_VALID (true, EnumFlag&, ef |= EnumFlag ())
+CHECK_VALID (true, EnumFlag&, ef &= EnumFlag ())
+CHECK_VALID (true, EnumFlag&, ef ^= EnumFlag ())
/* operator~ (raw_enum) */
-CHECK_VALID (false, void, ~RE ())
-CHECK_VALID (true, URE, ~URE ())
+CHECK_VALID (false, void, ~RawEnum ())
+CHECK_VALID (true, UnsignedRawEnum, ~UnsignedRawEnum ())
/* operator~ (enum_flags) */
-CHECK_VALID (false, void, ~EF ())
-CHECK_VALID (true, UEF, ~UEF ())
+CHECK_VALID (false, void, ~EnumFlag ())
+CHECK_VALID (true, UnsignedEnumFlag, ~UnsignedEnumFlag ())
/* Check ternary operator. This exercises implicit conversions. */
-CHECK_VALID (true, EF, true ? EF () : RE ())
-CHECK_VALID (true, EF, true ? RE () : EF ())
+CHECK_VALID (true, EnumFlag, true ? EnumFlag () : RawEnum ())
+CHECK_VALID (true, EnumFlag, true ? RawEnum () : EnumFlag ())
/* These are valid, but it's not a big deal since you won't be able to
assign the resulting integer to an enum or an enum_flags without a
@@ -246,19 +248,19 @@ CHECK_VALID (true, EF, true ? RE () : EF ())
They've been confirmed to compile/pass with gcc 5.3, gcc 7.1 and
clang 3.7. */
-CHECK_VALID (true, int, true ? EF () : EF2 ())
-CHECK_VALID (true, int, true ? EF2 () : EF ())
-CHECK_VALID (true, int, true ? EF () : RE2 ())
-CHECK_VALID (true, int, true ? RE2 () : EF ())
+CHECK_VALID (true, int, true ? EnumFlag () : EnumFlag2 ())
+CHECK_VALID (true, int, true ? EnumFlag2 () : EnumFlag ())
+CHECK_VALID (true, int, true ? EnumFlag () : RawEnum2 ())
+CHECK_VALID (true, int, true ? RawEnum2 () : EnumFlag ())
/* Same, but with an unsigned enum. */
-typedef unsigned int uns;
+using uns = unsigned int;
-CHECK_VALID (true, uns, true ? EF () : UEF ())
-CHECK_VALID (true, uns, true ? UEF () : EF ())
-CHECK_VALID (true, uns, true ? EF () : URE ())
-CHECK_VALID (true, uns, true ? URE () : EF ())
+CHECK_VALID (true, uns, true ? EnumFlag () : UnsignedEnumFlag ())
+CHECK_VALID (true, uns, true ? UnsignedEnumFlag () : EnumFlag ())
+CHECK_VALID (true, uns, true ? EnumFlag () : UnsignedRawEnum ())
+CHECK_VALID (true, uns, true ? UnsignedRawEnum () : EnumFlag ())
/* Unfortunately this can't work due to the way C++ computes the
return type of the ternary conditional operator. int isn't
@@ -270,39 +272,39 @@ CHECK_VALID (true, uns, true ? URE () : EF ())
error: operands to ?: have different types ‘enum_flags<RE>’ and ‘int’
Confirmed to work with gcc 4.9, 5.3 and clang 3.7.
*/
-CHECK_VALID (false, void, true ? EF () : 0)
-CHECK_VALID (false, void, true ? 0 : EF ())
+CHECK_VALID (false, void, true ? EnumFlag () : 0)
+CHECK_VALID (false, void, true ? 0 : EnumFlag ())
/* Check that the ++/--/<</>>/<<=/>>= operators are deleted. */
-CHECK_VALID (false, void, RE ()++)
-CHECK_VALID (false, void, ++RE ())
-CHECK_VALID (false, void, --RE ())
-CHECK_VALID (false, void, RE ()--)
+CHECK_VALID (false, void, RawEnum ()++)
+CHECK_VALID (false, void, ++RawEnum ())
+CHECK_VALID (false, void, --RawEnum ())
+CHECK_VALID (false, void, RawEnum ()--)
-CHECK_VALID (false, void, RE () << 1)
-CHECK_VALID (false, void, RE () >> 1)
-CHECK_VALID (false, void, EF () << 1)
-CHECK_VALID (false, void, EF () >> 1)
+CHECK_VALID (false, void, RawEnum () << 1)
+CHECK_VALID (false, void, RawEnum () >> 1)
+CHECK_VALID (false, void, EnumFlag () << 1)
+CHECK_VALID (false, void, EnumFlag () >> 1)
-CHECK_VALID (false, void, RE () <<= 1)
-CHECK_VALID (false, void, RE () >>= 1)
-CHECK_VALID (false, void, EF () <<= 1)
-CHECK_VALID (false, void, EF () >>= 1)
+CHECK_VALID (false, void, RawEnum () <<= 1)
+CHECK_VALID (false, void, RawEnum () >>= 1)
+CHECK_VALID (false, void, EnumFlag () <<= 1)
+CHECK_VALID (false, void, EnumFlag () >>= 1)
/* Test comparison operators. */
-CHECK_VALID (false, void, EF () == EF2 ())
-CHECK_VALID (false, void, EF () == RE2 ())
-CHECK_VALID (false, void, RE () == EF2 ())
+CHECK_VALID (false, void, EnumFlag () == EnumFlag2 ())
+CHECK_VALID (false, void, EnumFlag () == RawEnum2 ())
+CHECK_VALID (false, void, RawEnum () == EnumFlag2 ())
-CHECK_VALID (true, bool, EF (RE (1)) == EF (RE (1)))
-CHECK_VALID (true, bool, EF (RE (1)) == RE (1))
-CHECK_VALID (true, bool, RE (1) == EF (RE (1)))
+CHECK_VALID (true, bool, EnumFlag (RawEnum (1)) == EnumFlag (RawEnum (1)))
+CHECK_VALID (true, bool, EnumFlag (RawEnum (1)) == RawEnum (1))
+CHECK_VALID (true, bool, RawEnum (1) == EnumFlag (RawEnum (1)))
-CHECK_VALID (false, void, EF () != EF2 ())
-CHECK_VALID (false, void, EF () != RE2 ())
-CHECK_VALID (false, void, RE () != EF2 ())
+CHECK_VALID (false, void, EnumFlag () != EnumFlag2 ())
+CHECK_VALID (false, void, EnumFlag () != RawEnum2 ())
+CHECK_VALID (false, void, RawEnum () != EnumFlag2 ())
/* Disable -Wenum-compare due to:
@@ -323,23 +325,23 @@ CHECK_VALID (false, void, RE () != EF2 ())
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wenum-compare"
#endif
-CHECK_VALID (true, bool, RE () == RE2 ())
-CHECK_VALID (true, bool, RE () != RE2 ())
+CHECK_VALID (true, bool, RawEnum () == RawEnum2 ())
+CHECK_VALID (true, bool, RawEnum () != RawEnum2 ())
#if defined __GNUC__
# pragma GCC diagnostic pop
#endif
-CHECK_VALID (true, bool, EF (RE (1)) != EF (RE (2)))
-CHECK_VALID (true, bool, EF (RE (1)) != RE (2))
-CHECK_VALID (true, bool, RE (1) != EF (RE (2)))
+CHECK_VALID (true, bool, EnumFlag (RawEnum (1)) != EnumFlag (RawEnum (2)))
+CHECK_VALID (true, bool, EnumFlag (RawEnum (1)) != RawEnum (2))
+CHECK_VALID (true, bool, RawEnum (1) != EnumFlag (RawEnum (2)))
-CHECK_VALID (true, bool, EF () == 0)
+CHECK_VALID (true, bool, EnumFlag () == 0)
/* Check we didn't disable/delete comparison between non-flags enums
and unrelated types by mistake. */
-CHECK_VALID (true, bool, NF (1) == NF (1))
-CHECK_VALID (true, bool, NF (1) == int (1))
-CHECK_VALID (true, bool, NF (1) == char (1))
+CHECK_VALID (true, bool, NonFlagsEnum (1) == NonFlagsEnum (1))
+CHECK_VALID (true, bool, NonFlagsEnum (1) == int (1))
+CHECK_VALID (true, bool, NonFlagsEnum (1) == char (1))
/* -------------------------------------------------------------------- */
diff --git a/gdb/unittests/intrusive_list-selftests.c b/gdb/unittests/intrusive_list-selftests.c
index 28d0134..fbd89ed 100644
--- a/gdb/unittests/intrusive_list-selftests.c
+++ b/gdb/unittests/intrusive_list-selftests.c
@@ -18,9 +18,15 @@
#include "gdbsupport/intrusive_list.h"
+#include "gdbsupport/owning_intrusive_list.h"
#include "gdbsupport/selftest.h"
#include <unordered_set>
+/* Count of how many item_with_base or item_with_member objects are
+ currently alive. */
+
+static int items_alive = 0;
+
/* An item type using intrusive_list_node by inheriting from it and its
corresponding list type. Put another base before intrusive_list_node
so that a pointer to the node != a pointer to the item. */
@@ -35,7 +41,13 @@ struct item_with_base : public other_base,
{
explicit item_with_base (const char *name)
: name (name)
- {}
+ {
+ ++items_alive;
+ }
+
+ DISABLE_COPY_AND_ASSIGN (item_with_base);
+
+ ~item_with_base () { --items_alive; }
const char *const name;
};
@@ -50,64 +62,78 @@ struct item_with_member
{
explicit item_with_member (const char *name)
: name (name)
- {}
+ {
+ ++items_alive;
+ }
+
+ DISABLE_COPY_AND_ASSIGN (item_with_member);
+
+ ~item_with_member () { --items_alive; }
const char *const name;
intrusive_list_node<item_with_member> node;
};
-using item_with_member_node
- = intrusive_member_node<item_with_member, &item_with_member::node>;
-using item_with_member_list
- = intrusive_list<item_with_member, item_with_member_node>;
+/* Verify that LIST contains exactly the items in EXPECTED.
-/* To run all tests using both the base and member methods, all tests are
- declared in this templated class, which is instantiated once for each
- list type. */
+ Traverse the list forward and backwards to exercise all links. */
template <typename ListType>
-struct intrusive_list_test
+static void
+verify_items (const ListType &list,
+ gdb::array_view<const typename ListType::value_type *> expected)
{
using item_type = typename ListType::value_type;
- /* Verify that LIST contains exactly the items in EXPECTED.
+ int i = 0;
- Traverse the list forward and backwards to exercise all links. */
+ for (typename ListType::iterator it = list.begin (); it != list.end (); ++it)
+ {
+ const item_type &item = *it;
- static void
- verify_items (const ListType &list,
- gdb::array_view<const typename ListType::value_type *> expected)
- {
- int i = 0;
+ SELF_CHECK (i < expected.size ());
+ SELF_CHECK (&item == expected[i]);
- for (typename ListType::iterator it = list.begin ();
- it != list.end ();
- ++it)
- {
- const item_type &item = *it;
+ /* Access the item, to make sure the object is still alive. */
+ SELF_CHECK (strcmp (item.name, expected[i]->name) == 0);
- SELF_CHECK (i < expected.size ());
- SELF_CHECK (&item == expected[i]);
+ ++i;
+ }
- ++i;
- }
+ SELF_CHECK (i == expected.size ());
- SELF_CHECK (i == expected.size ());
+ for (typename ListType::reverse_iterator it = list.rbegin ();
+ it != list.rend (); ++it)
+ {
+ const item_type &item = *it;
- for (typename ListType::reverse_iterator it = list.rbegin ();
- it != list.rend ();
- ++it)
- {
- const item_type &item = *it;
+ --i;
- --i;
+ SELF_CHECK (i >= 0);
+ SELF_CHECK (&item == expected[i]);
- SELF_CHECK (i >= 0);
- SELF_CHECK (&item == expected[i]);
- }
+ /* Access the item, to make sure the object is still alive. */
+ SELF_CHECK (strcmp (item.name, expected[i]->name) == 0);
+ }
- SELF_CHECK (i == 0);
- }
+ SELF_CHECK (i == 0);
+}
+
+/* intrusive_list tests
+
+ To run all tests using both the base and member methods, all tests are
+ declared in this templated class, which is instantiated once for each
+ list type. */
+
+using item_with_member_node
+ = intrusive_member_node<item_with_member, &item_with_member::node>;
+using item_with_member_list
+ = intrusive_list<item_with_member, item_with_member_node>;
+
+template <typename ListType>
+struct intrusive_list_test
+{
+ using item_type = typename ListType::value_type;
static void
test_move_constructor ()
@@ -446,15 +472,18 @@ struct intrusive_list_test
ListType list;
- list.insert (list.begin (), a);
+ auto a_it = list.insert (list.begin (), a);
+ SELF_CHECK (&*a_it == &a);
expected = {&a};
verify_items (list, expected);
- list.insert (list.begin (), b);
+ auto b_it = list.insert (list.begin (), b);
+ SELF_CHECK (&*b_it == &b);
expected = {&b, &a};
verify_items (list, expected);
- list.insert (list.begin (), c);
+ auto c_it = list.insert (list.begin (), c);
+ SELF_CHECK (&*c_it == &c);
expected = {&c, &b, &a};
verify_items (list, expected);
}
@@ -465,15 +494,18 @@ struct intrusive_list_test
ListType list;
- list.insert (list.end (), a);
+ auto a_it = list.insert (list.end (), a);
+ SELF_CHECK (&*a_it == &a);
expected = {&a};
verify_items (list, expected);
- list.insert (list.end (), b);
+ auto b_it = list.insert (list.end (), b);
+ SELF_CHECK (&*b_it == &b);
expected = {&a, &b};
verify_items (list, expected);
- list.insert (list.end (), c);
+ auto c_it = list.insert (list.end (), c);
+ SELF_CHECK (&*c_it == &c);
expected = {&a, &b, &c};
verify_items (list, expected);
}
@@ -486,7 +518,8 @@ struct intrusive_list_test
list.push_back (a);
list.push_back (b);
- list.insert (list.iterator_to (b), c);
+ auto c_it = list.insert (list.iterator_to (b), c);
+ SELF_CHECK (&*c_it == &c);
expected = {&a, &c, &b};
verify_items (list, expected);
}
@@ -496,7 +529,8 @@ struct intrusive_list_test
item_type a ("a");
ListType list;
- list.insert (list.end (), a);
+ auto a_it = list.insert (list.end (), a);
+ SELF_CHECK (&*a_it == &a);
expected = {&a};
verify_items (list, expected);
}
@@ -570,7 +604,6 @@ struct intrusive_list_test
{
/* Both lists empty. */
- item_type a ("a"), b ("b"), c ("c");
ListType list1;
ListType list2;
std::vector<const item_type *> expected;
@@ -774,6 +807,811 @@ test_intrusive_list_1 ()
tests.test_begin_end ();
}
+/* owning_intrusive_list tests
+
+ To run all tests using both the base and member methods, all tests are
+ declared in this templated class, which is instantiated once for each
+ list type. */
+
+using item_with_base_owning_list = owning_intrusive_list<item_with_base>;
+using item_with_member_owning_list
+ = owning_intrusive_list<item_with_member, item_with_member_node>;
+
+template<typename ListType>
+struct owning_intrusive_list_test
+{
+ using item_type = typename ListType::value_type;
+
+ static void test_move_constructor ()
+ {
+ {
+ /* Other list is not empty. */
+ ListType list1;
+ std::vector<const item_type *> expected;
+
+ auto &a = list1.emplace_back ("a");
+ auto &b = list1.emplace_back ("b");
+ auto &c = list1.emplace_back ("c");
+
+ SELF_CHECK (items_alive == 3);
+ ListType list2 (std::move (list1));
+ SELF_CHECK (items_alive == 3);
+
+ expected = {};
+ verify_items (list1, expected);
+
+ expected = { &a, &b, &c };
+ verify_items (list2, expected);
+ }
+
+ {
+ /* Other list contains 1 element. */
+ ListType list1;
+ std::vector<const item_type *> expected;
+
+ auto &a = list1.emplace_back ("a");
+
+ SELF_CHECK (items_alive == 1);
+ ListType list2 (std::move (list1));
+ SELF_CHECK (items_alive == 1);
+
+ expected = {};
+ verify_items (list1, expected);
+
+ expected = { &a };
+ verify_items (list2, expected);
+ }
+
+ {
+ /* Other list is empty. */
+ ListType list1;
+ std::vector<const item_type *> expected;
+
+ SELF_CHECK (items_alive == 0);
+ ListType list2 (std::move (list1));
+ SELF_CHECK (items_alive == 0);
+
+ expected = {};
+ verify_items (list1, expected);
+
+ expected = {};
+ verify_items (list2, expected);
+ }
+ }
+
+ static void test_move_assignment ()
+ {
+ {
+ /* Both lists are not empty. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ auto &a = list1.emplace_back ("a");
+ auto &b = list1.emplace_back ("b");
+ auto &c = list1.emplace_back ("c");
+
+ list2.emplace_back ("d");
+ list2.emplace_back ("e");
+
+ SELF_CHECK (items_alive == 5);
+ list2 = std::move (list1);
+ SELF_CHECK (items_alive == 3);
+
+ expected = {};
+ verify_items (list1, expected);
+
+ expected = { &a, &b, &c };
+ verify_items (list2, expected);
+ }
+
+ {
+ /* rhs list is empty. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ list2.emplace_back ("a");
+ list2.emplace_back ("b");
+ list2.emplace_back ("c");
+
+ SELF_CHECK (items_alive == 3);
+ list2 = std::move (list1);
+ SELF_CHECK (items_alive == 0);
+
+ expected = {};
+ verify_items (list1, expected);
+
+ expected = {};
+ verify_items (list2, expected);
+ }
+
+ {
+ /* lhs list is empty. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ auto &a = list1.emplace_back ("a");
+ auto &b = list1.emplace_back ("b");
+ auto &c = list1.emplace_back ("c");
+
+ SELF_CHECK (items_alive == 3);
+ list2 = std::move (list1);
+ SELF_CHECK (items_alive == 3);
+
+ expected = {};
+ verify_items (list1, expected);
+
+ expected = { &a, &b, &c };
+ verify_items (list2, expected);
+ }
+
+ {
+ /* Both lists contain 1 item. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ auto &a = list1.emplace_back ("a");
+ list2.emplace_back ("b");
+
+ SELF_CHECK (items_alive == 2);
+ list2 = std::move (list1);
+ SELF_CHECK (items_alive == 1);
+
+ expected = {};
+ verify_items (list1, expected);
+
+ expected = { &a };
+ verify_items (list2, expected);
+ }
+
+ {
+ /* Both lists are empty. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ SELF_CHECK (items_alive == 0);
+ list2 = std::move (list1);
+ SELF_CHECK (items_alive == 0);
+
+ expected = {};
+ verify_items (list1, expected);
+
+ expected = {};
+ verify_items (list2, expected);
+ }
+ }
+
+ static void test_swap ()
+ {
+ {
+ /* Two non-empty lists. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ auto &a = list1.emplace_back ("a");
+ auto &b = list1.emplace_back ("b");
+ auto &c = list1.emplace_back ("c");
+
+ auto &d = list2.emplace_back ("d");
+ auto &e = list2.emplace_back ("e");
+
+ SELF_CHECK (items_alive == 5);
+ std::swap (list1, list2);
+ SELF_CHECK (items_alive == 5);
+
+ expected = { &d, &e };
+ verify_items (list1, expected);
+
+ expected = { &a, &b, &c };
+ verify_items (list2, expected);
+ }
+
+ {
+ /* Other is empty. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ auto &a = list1.emplace_back ("a");
+ auto &b = list1.emplace_back ("b");
+ auto &c = list1.emplace_back ("c");
+
+ SELF_CHECK (items_alive == 3);
+ std::swap (list1, list2);
+ SELF_CHECK (items_alive == 3);
+
+ expected = {};
+ verify_items (list1, expected);
+
+ expected = { &a, &b, &c };
+ verify_items (list2, expected);
+ }
+
+ {
+ /* *this is empty. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ auto &a = list2.emplace_back ("a");
+ auto &b = list2.emplace_back ("b");
+ auto &c = list2.emplace_back ("c");
+
+ SELF_CHECK (items_alive == 3);
+ std::swap (list1, list2);
+ SELF_CHECK (items_alive == 3);
+
+ expected = { &a, &b, &c };
+ verify_items (list1, expected);
+
+ expected = {};
+ verify_items (list2, expected);
+ }
+
+ {
+ /* Both lists empty. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ SELF_CHECK (items_alive == 0);
+ std::swap (list1, list2);
+ SELF_CHECK (items_alive == 0);
+
+ expected = {};
+ verify_items (list1, expected);
+
+ expected = {};
+ verify_items (list2, expected);
+ }
+
+ {
+ /* Swap one element twice. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ auto &a = list1.emplace_back ("a");
+
+ SELF_CHECK (items_alive == 1);
+ std::swap (list1, list2);
+ SELF_CHECK (items_alive == 1);
+
+ expected = {};
+ verify_items (list1, expected);
+
+ expected = { &a };
+ verify_items (list2, expected);
+
+ std::swap (list1, list2);
+ SELF_CHECK (items_alive == 1);
+
+ expected = { &a };
+ verify_items (list1, expected);
+
+ expected = {};
+ verify_items (list2, expected);
+ }
+ }
+
+ static void test_front_back ()
+ {
+ ListType list;
+ const ListType &clist = list;
+
+ auto &a = list.emplace_back ("a");
+ list.emplace_back ("b");
+ auto &c = list.emplace_back ("c");
+
+ SELF_CHECK (&list.front () == &a);
+ SELF_CHECK (&clist.front () == &a);
+ SELF_CHECK (&list.back () == &c);
+ SELF_CHECK (&clist.back () == &c);
+ }
+
+ static void test_push_front ()
+ {
+ ListType list;
+ std::vector<const item_type *> expected;
+
+ SELF_CHECK (items_alive == 0);
+ list.push_front (std::make_unique<item_type> ("a"));
+ auto &a = list.front ();
+ expected = { &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 1);
+
+ list.push_front (std::make_unique<item_type> ("b"));
+ auto &b = list.front ();
+ expected = { &b, &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 2);
+
+ list.push_front (std::make_unique<item_type> ("c"));
+ auto &c = list.front ();
+ expected = { &c, &b, &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 3);
+ }
+
+ static void test_push_back ()
+ {
+ ListType list;
+ std::vector<const item_type *> expected;
+
+ SELF_CHECK (items_alive == 0);
+ list.push_back (std::make_unique<item_type> ("a"));
+ auto &a = list.back ();
+ expected = { &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 1);
+
+ list.push_back (std::make_unique<item_type> ("b"));
+ auto &b = list.back ();
+ expected = { &a, &b };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 2);
+
+ list.push_back (std::make_unique<item_type> ("c"));
+ auto &c = list.back ();
+ expected = { &a, &b, &c };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 3);
+ }
+
+ static void test_insert ()
+ {
+ std::vector<const item_type *> expected;
+
+ {
+ /* Insert at beginning. */
+ ListType list;
+
+ auto &a = *list.insert (list.begin (), std::make_unique<item_type> ("a"));
+ expected = { &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 1);
+
+ auto &b = *list.insert (list.begin (), std::make_unique<item_type> ("b"));
+ expected = { &b, &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 2);
+
+ auto &c = *list.insert (list.begin (), std::make_unique<item_type> ("c"));
+ expected = { &c, &b, &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 3);
+ }
+
+ {
+ /* Insert at end. */
+ ListType list;
+
+ auto &a = *list.insert (list.end (), std::make_unique<item_type> ("a"));
+ expected = { &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 1);
+
+ auto &b = *list.insert (list.end (), std::make_unique<item_type> ("b"));
+ expected = { &a, &b };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 2);
+
+ auto &c = *list.insert (list.end (), std::make_unique<item_type> ("c"));
+ expected = { &a, &b, &c };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 3);
+ }
+
+ {
+ /* Insert in the middle. */
+ ListType list;
+
+ auto &a = list.emplace_back ("a");
+ auto &b = list.emplace_back ("b");
+
+ SELF_CHECK (items_alive == 2);
+ auto &c = *list.insert (list.iterator_to (b),
+ std::make_unique<item_type> ("c"));
+ expected = { &a, &c, &b };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 3);
+ }
+
+ {
+ /* Insert in empty list. */
+ ListType list;
+
+ SELF_CHECK (items_alive == 0);
+ auto &a = *list.insert (list.end (), std::make_unique<item_type> ("a"));
+ expected = { &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 1);
+ }
+ }
+
+ static void test_emplace_front ()
+ {
+ ListType list;
+ std::vector<const item_type *> expected;
+
+ SELF_CHECK (items_alive == 0);
+ auto &a = list.emplace_front ("a");
+ expected = { &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 1);
+
+ auto &b = list.emplace_front ("b");
+ expected = { &b, &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 2);
+
+ auto &c = list.emplace_front ("c");
+ expected = { &c, &b, &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 3);
+ }
+
+ static void test_emplace_back ()
+ {
+ ListType list;
+ std::vector<const item_type *> expected;
+
+ SELF_CHECK (items_alive == 0);
+ auto &a = list.emplace_back ("a");
+ expected = { &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 1);
+
+ auto &b = list.emplace_back ("b");
+ expected = { &a, &b };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 2);
+
+ auto &c = list.emplace_back ("c");
+ expected = { &a, &b, &c };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 3);
+ }
+
+ static void test_emplace ()
+ {
+ std::vector<const item_type *> expected;
+
+ {
+ /* Emplace at beginning. */
+ ListType list;
+
+ auto &a = list.emplace (list.begin (), "a");
+ expected = { &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 1);
+
+ auto &b = list.emplace (list.begin (), "b");
+ expected = { &b, &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 2);
+
+ auto &c = list.emplace (list.begin (), "c");
+ expected = { &c, &b, &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 3);
+ }
+
+ {
+ /* Emplace at end. */
+ ListType list;
+
+ auto &a = list.emplace (list.end (), "a");
+ expected = { &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 1);
+
+ auto &b = list.emplace (list.end (), "b");
+ expected = { &a, &b };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 2);
+
+ auto &c = list.emplace (list.end (), "c");
+ expected = { &a, &b, &c };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 3);
+ }
+
+ {
+ /* Emplace in the middle. */
+ ListType list;
+
+ auto &a = list.emplace_back ("a");
+ auto &b = list.emplace_back ("b");
+
+ SELF_CHECK (items_alive == 2);
+ auto &c = list.emplace (list.iterator_to (b), "c");
+ expected = { &a, &c, &b };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 3);
+ }
+
+ {
+ /* Emplace in empty list. */
+ ListType list;
+
+ SELF_CHECK (items_alive == 0);
+ auto &a = list.emplace (list.end (), "a");
+ expected = { &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 1);
+ }
+ }
+
+ static void test_splice ()
+ {
+ {
+ /* Two non-empty lists. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ auto &a = list1.emplace_back ("a");
+ auto &b = list1.emplace_back ("b");
+ auto &c = list1.emplace_back ("c");
+
+ auto &d = list2.emplace_back ("d");
+ auto &e = list2.emplace_back ("e");
+
+ SELF_CHECK (items_alive == 5);
+ list1.splice (std::move (list2));
+ SELF_CHECK (items_alive == 5);
+
+ expected = { &a, &b, &c, &d, &e };
+ verify_items (list1, expected);
+
+ expected = {};
+ verify_items (list2, expected);
+ }
+
+ {
+ /* Receiving list empty. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ auto &a = list2.emplace_back ("a");
+ auto &b = list2.emplace_back ("b");
+ auto &c = list2.emplace_back ("c");
+
+ SELF_CHECK (items_alive == 3);
+ list1.splice (std::move (list2));
+ SELF_CHECK (items_alive == 3);
+
+ expected = { &a, &b, &c };
+ verify_items (list1, expected);
+
+ expected = {};
+ verify_items (list2, expected);
+ }
+
+ {
+ /* Giving list empty. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ auto &a = list1.emplace_back ("a");
+ auto &b = list1.emplace_back ("b");
+ auto &c = list1.emplace_back ("c");
+
+ SELF_CHECK (items_alive == 3);
+ list1.splice (std::move (list2));
+ SELF_CHECK (items_alive == 3);
+
+ expected = { &a, &b, &c };
+ verify_items (list1, expected);
+
+ expected = {};
+ verify_items (list2, expected);
+ }
+
+ {
+ /* Both lists empty. */
+ ListType list1;
+ ListType list2;
+ std::vector<const item_type *> expected;
+
+ SELF_CHECK (items_alive == 0);
+ list1.splice (std::move (list2));
+ SELF_CHECK (items_alive == 0);
+
+ expected = {};
+ verify_items (list1, expected);
+
+ expected = {};
+ verify_items (list2, expected);
+ }
+ }
+
+ static void test_pop_front ()
+ {
+ ListType list;
+ std::vector<const item_type *> expected;
+
+ list.emplace_back ("a");
+ auto &b = list.emplace_back ("b");
+ auto &c = list.emplace_back ("c");
+
+ SELF_CHECK (items_alive == 3);
+ list.pop_front ();
+ expected = { &b, &c };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 2);
+
+ list.pop_front ();
+ expected = { &c };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 1);
+
+ list.pop_front ();
+ expected = {};
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 0);
+ }
+
+ static void test_pop_back ()
+ {
+ ListType list;
+ std::vector<const item_type *> expected;
+
+ auto &a = list.emplace_back ("a");
+ auto &b = list.emplace_back ("b");
+ list.emplace_back ("c");
+
+ SELF_CHECK (items_alive == 3);
+ list.pop_back ();
+ expected = { &a, &b };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 2);
+
+ list.pop_back ();
+ expected = { &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 1);
+
+ list.pop_back ();
+ expected = {};
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 0);
+ }
+
+ static void test_release ()
+ {
+ ListType list;
+ std::vector<const item_type *> expected;
+
+ auto &a = list.emplace_back ("a");
+ auto &b = list.emplace_back ("b");
+ auto &c = list.emplace_back ("c");
+
+ {
+ SELF_CHECK (items_alive == 3);
+ auto [next_it, released] = list.release (list.iterator_to (b));
+ SELF_CHECK (&*next_it == &c);
+ expected = { &a, &c };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 3);
+ released.reset ();
+ SELF_CHECK (items_alive == 2);
+ }
+
+ {
+ auto [next_it, released] = list.release (list.iterator_to (c));
+ SELF_CHECK (next_it == list.end ());
+ expected = { &a };
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 2);
+ released.reset ();
+ SELF_CHECK (items_alive == 1);
+ }
+
+ {
+ auto [next_it, released] = list.release (list.iterator_to (a));
+ SELF_CHECK (next_it == list.end ());
+ expected = {};
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 1);
+ released.reset ();
+ SELF_CHECK (items_alive == 0);
+ }
+ }
+
+ static void test_clear ()
+ {
+ ListType list;
+ std::vector<const item_type *> expected;
+
+ list.emplace_back ("a");
+ list.emplace_back ("b");
+ list.emplace_back ("c");
+
+ SELF_CHECK (items_alive == 3);
+ list.clear ();
+ expected = {};
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 0);
+
+ /* Verify idempotency. */
+ list.clear ();
+ expected = {};
+ verify_items (list, expected);
+ SELF_CHECK (items_alive == 0);
+ }
+
+ static void test_empty ()
+ {
+ ListType list;
+
+ SELF_CHECK (list.empty ());
+ auto &a = list.emplace_back ("a");
+ SELF_CHECK (!list.empty ());
+ list.erase (list.iterator_to (a));
+ SELF_CHECK (list.empty ());
+ }
+
+ static void test_begin_end ()
+ {
+ ListType list;
+ const ListType &clist = list;
+
+ auto &a = list.emplace_back ("a");
+ list.emplace_back ("b");
+ auto &c = list.emplace_back ("c");
+
+ SELF_CHECK (&*list.begin () == &a);
+ SELF_CHECK (&*list.cbegin () == &a);
+ SELF_CHECK (&*clist.begin () == &a);
+ SELF_CHECK (&*list.rbegin () == &c);
+ SELF_CHECK (&*list.crbegin () == &c);
+ SELF_CHECK (&*clist.rbegin () == &c);
+
+ /* At least check that they compile. */
+ list.end ();
+ list.cend ();
+ clist.end ();
+ list.rend ();
+ list.crend ();
+ clist.end ();
+ }
+};
+
+template<typename ListType>
+static void
+test_owning_intrusive_list_1 ()
+{
+ owning_intrusive_list_test<ListType> tests;
+
+ tests.test_move_constructor ();
+ tests.test_move_assignment ();
+ tests.test_swap ();
+ tests.test_front_back ();
+ tests.test_push_front ();
+ tests.test_push_back ();
+ tests.test_insert ();
+ tests.test_emplace_front ();
+ tests.test_emplace_back ();
+ tests.test_emplace ();
+ tests.test_splice ();
+ tests.test_pop_front ();
+ tests.test_pop_back ();
+ tests.test_release ();
+ tests.test_clear ();
+ tests.test_empty ();
+ tests.test_begin_end ();
+}
+
static void
test_node_is_linked ()
{
@@ -805,13 +1643,15 @@ test_intrusive_list ()
{
test_intrusive_list_1<item_with_base_list> ();
test_intrusive_list_1<item_with_member_list> ();
+ test_owning_intrusive_list_1<item_with_base_owning_list> ();
+ test_owning_intrusive_list_1<item_with_member_owning_list> ();
test_node_is_linked ();
}
void _initialize_intrusive_list_selftests ();
+
void
_initialize_intrusive_list_selftests ()
{
- selftests::register_test
- ("intrusive_list", test_intrusive_list);
+ selftests::register_test ("intrusive_list", test_intrusive_list);
}
diff --git a/gdb/unittests/scoped_mmap-selftests.c b/gdb/unittests/scoped_mmap-selftests.c
index 7b3a6f5..09a94ed 100644
--- a/gdb/unittests/scoped_mmap-selftests.c
+++ b/gdb/unittests/scoped_mmap-selftests.c
@@ -114,7 +114,7 @@ test_invalid_filename ()
try {
::scoped_mmap m = ::mmap_file ("/this/file/should/not/exist");
- } catch (gdb_exception &e) {
+ } catch (const gdb_exception &e) {
threw = true;
}
diff --git a/gdb/user-regs.c b/gdb/user-regs.c
index ac04f63..2ace46e 100644
--- a/gdb/user-regs.c
+++ b/gdb/user-regs.c
@@ -222,9 +222,19 @@ maintenance_print_user_registers (const char *args, int from_tty)
struct gdb_user_regs *regs = get_user_regs (gdbarch);
regnum = gdbarch_num_cooked_regs (gdbarch);
- gdb_printf (" %-11s %3s\n", "Name", "Nr");
+ ui_out_emit_table emitter (current_uiout, 2, -1, "UserRegs");
+
+ current_uiout->table_header (11, ui_left, "name", "Name");
+ current_uiout->table_header (3, ui_left, "regnum", "Nr");
+ current_uiout->table_body ();
+
for (reg = regs->first; reg != NULL; reg = reg->next, ++regnum)
- gdb_printf (" %-11s %3d\n", reg->name, regnum);
+ {
+ ui_out_emit_tuple tuple_emitter (current_uiout, nullptr);
+ current_uiout->field_string ("name", reg->name);
+ current_uiout->field_signed ("regnum", regnum);
+ current_uiout->text ("\n");
+ }
}
void _initialize_user_regs ();
diff --git a/gdb/utils.c b/gdb/utils.c
index 17498e0..a1bf9e4 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -80,6 +80,7 @@
#include "gdbsupport/buildargv.h"
#include "pager.h"
#include "run-on-main-thread.h"
+#include "gdbsupport/gdb_tilde_expand.h"
void (*deprecated_error_begin_hook) (void);
@@ -192,7 +193,7 @@ verror (const char *string, va_list args)
/* Emit a message and abort. */
-static void ATTRIBUTE_NORETURN
+[[noreturn]] static void
abort_with_message (const char *msg)
{
if (current_ui == NULL)
@@ -818,7 +819,9 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
}
/* Format the question outside of the loop, to avoid reusing args. */
- std::string question = string_vprintf (ctlstr, args);
+ string_file tem (gdb_stdout->can_emit_style_escape ());
+ gdb_vprintf (&tem, ctlstr, args);
+ std::string question = tem.release ();
std::string prompt
= string_printf (_("%s%s(%s or %s) %s"),
annotation_level > 1 ? "\n\032\032pre-query\n" : "",
@@ -1281,6 +1284,14 @@ set_screen_width_and_height (int width, int height)
set_width ();
}
+/* Import termcap variable UP (instead of readline private variable
+ _rl_term_up, which we're trying to avoid, see PR build/10723). The UP
+ variable doesn't seem be part of the regular termcap interface, but rather
+ curses-specific. But if it's missing in the termcap library, then readline
+ provides a fallback version. Let's assume the fallback is not part of the
+ private readline interface. */
+extern "C" char *UP;
+
/* Implement "maint info screen". */
static void
@@ -1339,6 +1350,46 @@ maintenance_info_screen (const char *args, int from_tty)
_("Number of lines environment thinks "
"are in a page is %s (LINES).\n"),
getenv ("LINES"));
+
+ bool have_up = UP != nullptr && *UP != '\0';
+
+ /* Fetch value of readline variable horizontal-scroll-mode. */
+ const char *horizontal_scroll_mode_value
+ = rl_variable_value ("horizontal-scroll-mode");
+ bool force_horizontal_scroll_mode
+ = (horizontal_scroll_mode_value != nullptr
+ && strcmp (horizontal_scroll_mode_value, "on") == 0);
+
+ const char *mode = nullptr;
+ const char *reason = nullptr;
+ if (batch_flag)
+ {
+ mode = "unsupported";
+ reason = "gdb batch mode";
+ }
+ else if (!have_up)
+ {
+ mode = "unsupported";
+ reason = "terminal is not Cursor Up capable";
+ }
+ else if (force_horizontal_scroll_mode)
+ {
+ mode = "disabled";
+ reason = "horizontal-scroll-mode";
+ }
+ else if (readline_hidden_cols)
+ {
+ mode = "readline";
+ reason = "terminal is not auto wrap capable, last column reserved";
+ }
+ else
+ {
+ mode = "terminal";
+ reason = "terminal is auto wrap capable";
+ }
+
+ gdb_printf (gdb_stdout, _("Readline wrapping mode: %s (%s).\n"), mode,
+ reason);
}
void
@@ -3667,6 +3718,23 @@ copy_bitwise (gdb_byte *dest, ULONGEST dest_offset,
}
}
+/* See utils.h. */
+
+std::string
+extract_single_filename_arg (const char *args)
+{
+ if (args == nullptr)
+ return {};
+
+ std::string filename = extract_string_maybe_quoted (&args);
+ args = skip_spaces (args);
+ if (*args != '\0')
+ error (_("Junk after filename \"%s\": %s"), filename.c_str (), args);
+ if (!filename.empty ())
+ filename = gdb_tilde_expand (filename.c_str ());
+ return filename;
+}
+
#if GDB_SELF_TEST
static void
test_assign_set_return_if_changed ()
diff --git a/gdb/utils.h b/gdb/utils.h
index 90c8012..d69c81c 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -371,6 +371,20 @@ assign_return_if_changed (T &lval, const T &val)
return true;
}
+/* ARG is an argument string as passed to a GDB command which is expected
+ to contain a single, possibly quoted, filename argument. Extract the
+ filename and return it as a string. If the filename is quoted then the
+ quotes will have been removed. If the filename is not quoted then any
+ escaping within the filename will have been removed.
+
+ If there is any content in ARG after the filename then an error will be
+ thrown complaining about the extra content.
+
+ If there is no filename in ARG, or if ARG is nullptr, then an empty
+ string will be returned. */
+
+extern std::string extract_single_filename_arg (const char *arg);
+
/* A class that can be used to intercept warnings. A class is used
here, rather than a gdb::function_view because it proved difficult
to use a function view in conjunction with ATTRIBUTE_PRINTF in a
diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c
index 531fdb4..de1cc6c 100644
--- a/gdb/v850-tdep.c
+++ b/gdb/v850-tdep.c
@@ -201,7 +201,7 @@ enum
E_R149_REGNUM,
E_NUM_OF_V850E2_REGS,
- /* v850e3v5 system registers, selID 1 thru 7. */
+ /* v850e3v5 system registers, selID 1 through 7. */
E_SELID_1_R0_REGNUM = E_NUM_OF_V850E2_REGS,
E_SELID_1_R31_REGNUM = E_SELID_1_R0_REGNUM + 31,
@@ -1047,7 +1047,7 @@ v850_push_dummy_call (struct gdbarch *gdbarch,
/* Now load as many as possible of the first arguments into
registers, and push the rest onto the stack. There are 16 bytes
- in four registers available. Loop thru args from first to last. */
+ in four registers available. Loop through args from first to last. */
for (argnum = 0; argnum < nargs; argnum++)
{
int len;
diff --git a/gdb/valops.c b/gdb/valops.c
index a0e945c..88a42d3 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -40,7 +40,6 @@
#include "observable.h"
#include "objfiles.h"
#include "extension.h"
-#include "gdbtypes.h"
#include "gdbsupport/byte-vector.h"
#include "typeprint.h"
@@ -129,8 +128,8 @@ find_function_in_inferior (const char *name, struct objfile **objf_p)
}
else
{
- struct bound_minimal_symbol msymbol =
- lookup_bound_minimal_symbol (name);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space, name);
if (msymbol.minsym != NULL)
{
@@ -1487,7 +1486,7 @@ value_coerce_to_target (struct value *val)
nonzero lower bound.
FIXME: A previous comment here indicated that this routine should
- be substracting the array's lower bound. It's not clear to me that
+ be subtracting the array's lower bound. It's not clear to me that
this is correct. Given an array subscripting operation, it would
certainly work to do the adjustment here, essentially computing:
diff --git a/gdb/value.c b/gdb/value.c
index e71f38b..d9b3c6e 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -61,7 +61,7 @@ struct internal_function
char *name;
/* The handler. */
- internal_function_fn handler;
+ internal_function_fn_noside handler;
/* User data for the handler. */
void *cookie;
@@ -1700,25 +1700,7 @@ value::record_latest ()
the value was taken, and fast watchpoints should be able to assume that
a value on the value history never changes. */
if (lazy ())
- {
- /* We know that this is a _huge_ array, any attempt to fetch this
- is going to cause GDB to throw an error. However, to allow
- the array to still be displayed we fetch its contents up to
- `max_value_size' and mark anything beyond "unavailable" in
- the history. */
- if (m_type->code () == TYPE_CODE_ARRAY
- && m_type->length () > max_value_size
- && array_length_limiting_element_count.has_value ()
- && m_enclosing_type == m_type
- && calculate_limited_array_length (m_type) <= max_value_size)
- m_limited_length = max_value_size;
-
- fetch_lazy ();
- }
-
- ULONGEST limit = m_limited_length;
- if (limit != 0)
- mark_bytes_unavailable (limit, m_enclosing_type->length () - limit);
+ fetch_lazy ();
/* Mark the value as recorded in the history for the availability check. */
m_in_history = true;
@@ -2336,9 +2318,9 @@ internalvar_name (const struct internalvar *var)
static struct internal_function *
create_internal_function (const char *name,
- internal_function_fn handler, void *cookie)
+ internal_function_fn_noside handler, void *cookie)
{
- struct internal_function *ifn = XNEW (struct internal_function);
+ struct internal_function *ifn = new (struct internal_function);
ifn->name = xstrdup (name);
ifn->handler = handler;
@@ -2362,7 +2344,8 @@ value_internal_function_name (struct value *val)
struct value *
call_internal_function (struct gdbarch *gdbarch,
const struct language_defn *language,
- struct value *func, int argc, struct value **argv)
+ struct value *func, int argc, struct value **argv,
+ enum noside noside)
{
struct internal_function *ifn;
int result;
@@ -2371,7 +2354,7 @@ call_internal_function (struct gdbarch *gdbarch,
result = get_internalvar_function (VALUE_INTERNALVAR (func), &ifn);
gdb_assert (result);
- return (*ifn->handler) (gdbarch, language, ifn->cookie, argc, argv);
+ return ifn->handler (gdbarch, language, ifn->cookie, argc, argv, noside);
}
/* The 'function' command. This does nothing -- it is just a
@@ -2388,7 +2371,7 @@ function_command (const char *command, int from_tty)
static struct cmd_list_element *
do_add_internal_function (const char *name, const char *doc,
- internal_function_fn handler, void *cookie)
+ internal_function_fn_noside handler, void *cookie)
{
struct internal_function *ifn;
struct internalvar *var = lookup_internalvar (name);
@@ -2403,17 +2386,50 @@ do_add_internal_function (const char *name, const char *doc,
void
add_internal_function (const char *name, const char *doc,
- internal_function_fn handler, void *cookie)
+ internal_function_fn_noside handler, void *cookie)
{
do_add_internal_function (name, doc, handler, cookie);
}
+/* By default, internal functions are assumed to return int. Return a value
+ with that type to reflect this. If this is not correct for a specific
+ internal function, it should use an internal_function_fn_noside handler to
+ bypass this default. */
+
+static struct value *
+internal_function_default_return_type (struct gdbarch *gdbarch)
+{
+ return value::zero (builtin_type (gdbarch)->builtin_int, not_lval);
+}
+
+/* See value.h. */
+
+void
+add_internal_function (const char *name, const char *doc,
+ internal_function_fn handler, void *cookie)
+{
+ internal_function_fn_noside fn
+ = [=] (struct gdbarch *gdbarch,
+ const struct language_defn *language,
+ void *_cookie,
+ int argc,
+ struct value **argv,
+ enum noside noside)
+ {
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return internal_function_default_return_type (gdbarch);
+ return handler (gdbarch, language, _cookie, argc, argv);
+ };
+
+ do_add_internal_function (name, doc, fn, cookie);
+}
+
/* See value.h. */
void
add_internal_function (gdb::unique_xmalloc_ptr<char> &&name,
gdb::unique_xmalloc_ptr<char> &&doc,
- internal_function_fn handler, void *cookie)
+ internal_function_fn_noside handler, void *cookie)
{
struct cmd_list_element *cmd
= do_add_internal_function (name.get (), doc.get (), handler, cookie);
@@ -2426,6 +2442,31 @@ add_internal_function (gdb::unique_xmalloc_ptr<char> &&name,
cmd->name_allocated = 1;
}
+/* See value.h. */
+
+void
+add_internal_function (gdb::unique_xmalloc_ptr<char> &&name,
+ gdb::unique_xmalloc_ptr<char> &&doc,
+ internal_function_fn handler, void *cookie)
+{
+ internal_function_fn_noside fn
+ = [=] (struct gdbarch *gdbarch,
+ const struct language_defn *language,
+ void *_cookie,
+ int argc,
+ struct value **argv,
+ enum noside noside)
+ {
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return internal_function_default_return_type (gdbarch);
+ return handler (gdbarch, language, _cookie, argc, argv);
+ };
+
+ add_internal_function (std::forward<gdb::unique_xmalloc_ptr<char>>(name),
+ std::forward<gdb::unique_xmalloc_ptr<char>>(doc),
+ fn, cookie);
+}
+
void
value::preserve (struct objfile *objfile, htab_t copied_types)
{
@@ -2933,8 +2974,8 @@ value_static_field (struct type *type, int fieldno)
{
/* With some compilers, e.g. HP aCC, static data members are
reported as non-debuggable symbols. */
- struct bound_minimal_symbol msym
- = lookup_minimal_symbol (phys_name, NULL, NULL);
+ bound_minimal_symbol msym
+ = lookup_minimal_symbol (current_program_space, phys_name);
struct type *field_type = type->field (fieldno).type ();
if (!msym.minsym)
@@ -3116,13 +3157,13 @@ value_fn_field (struct value **arg1p, struct fn_field *f,
struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
const char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
struct symbol *sym;
- struct bound_minimal_symbol msym;
+ bound_minimal_symbol msym;
sym = lookup_symbol (physname, nullptr, SEARCH_FUNCTION_DOMAIN,
nullptr).symbol;
if (sym == nullptr)
{
- msym = lookup_bound_minimal_symbol (physname);
+ msym = lookup_minimal_symbol (current_program_space, physname);
if (msym.minsym == NULL)
return NULL;
}
@@ -3931,6 +3972,11 @@ value::fetch_lazy_memory ()
if (len > 0)
read_value_memory (this, 0, stack (), addr,
contents_all_raw ().data (), len);
+
+ /* If only part of an array was loaded, mark the rest as unavailable. */
+ if (m_limited_length > 0)
+ mark_bytes_unavailable (m_limited_length,
+ m_enclosing_type->length () - m_limited_length);
}
/* See value.h. */
@@ -4236,7 +4282,8 @@ isvoid_internal_fn (struct gdbarch *gdbarch,
static struct value *
creal_internal_fn (struct gdbarch *gdbarch,
const struct language_defn *language,
- void *cookie, int argc, struct value **argv)
+ void *cookie, int argc, struct value **argv,
+ enum noside noside)
{
if (argc != 1)
error (_("You must provide one argument for $_creal."));
@@ -4245,6 +4292,8 @@ creal_internal_fn (struct gdbarch *gdbarch,
type *ctype = check_typedef (cval->type ());
if (ctype->code () != TYPE_CODE_COMPLEX)
error (_("expected a complex number"));
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value::zero (ctype->target_type (), not_lval);
return value_real_part (cval);
}
@@ -4255,7 +4304,7 @@ static struct value *
cimag_internal_fn (struct gdbarch *gdbarch,
const struct language_defn *language,
void *cookie, int argc,
- struct value **argv)
+ struct value **argv, enum noside noside)
{
if (argc != 1)
error (_("You must provide one argument for $_cimag."));
@@ -4264,6 +4313,8 @@ cimag_internal_fn (struct gdbarch *gdbarch,
type *ctype = check_typedef (cval->type ());
if (ctype->code () != TYPE_CODE_COMPLEX)
error (_("expected a complex number"));
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value::zero (ctype->target_type (), not_lval);
return value_imaginary_part (cval);
}
diff --git a/gdb/value.h b/gdb/value.h
index 9d7e88d..13cfb00 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -1598,13 +1598,24 @@ extern struct value *find_function_in_inferior (const char *,
extern struct value *value_allocate_space_in_inferior (int);
-/* User function handler. */
-
-typedef struct value *(*internal_function_fn) (struct gdbarch *gdbarch,
- const struct language_defn *language,
- void *cookie,
- int argc,
- struct value **argv);
+/* User function handler. The internal_function_fn variant assumes return
+ type int. The internal_function_fn_noside returns some value with the
+ return type when passed noside == EVAL_AVOID_SIDE_EFFECTS. */
+
+using internal_function_fn
+ = std::function<struct value *(struct gdbarch *gdbarch,
+ const struct language_defn *language,
+ void *cookie,
+ int argc,
+ struct value **argv)>;
+
+using internal_function_fn_noside
+ = std::function<struct value *(struct gdbarch *gdbarch,
+ const struct language_defn *language,
+ void *cookie,
+ int argc,
+ struct value **argv,
+ enum noside noside)>;
/* Add a new internal function. NAME is the name of the function; DOC
is a documentation string describing the function. HANDLER is
@@ -1615,6 +1626,9 @@ typedef struct value *(*internal_function_fn) (struct gdbarch *gdbarch,
extern void add_internal_function (const char *name, const char *doc,
internal_function_fn handler,
void *cookie);
+extern void add_internal_function (const char *name, const char *doc,
+ internal_function_fn_noside handler,
+ void *cookie);
/* This overload takes an allocated documentation string. */
@@ -1622,11 +1636,16 @@ extern void add_internal_function (gdb::unique_xmalloc_ptr<char> &&name,
gdb::unique_xmalloc_ptr<char> &&doc,
internal_function_fn handler,
void *cookie);
+extern void add_internal_function (gdb::unique_xmalloc_ptr<char> &&name,
+ gdb::unique_xmalloc_ptr<char> &&doc,
+ internal_function_fn_noside handler,
+ void *cookie);
struct value *call_internal_function (struct gdbarch *gdbarch,
const struct language_defn *language,
struct value *function,
- int argc, struct value **argv);
+ int argc, struct value **argv,
+ enum noside noside);
const char *value_internal_function_name (struct value *);
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 0cd0bd0..04f1fc8 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -323,10 +323,7 @@ varobj_create (const char *objname,
}
/* Don't allow variables to be created for types. */
- enum exp_opcode opcode = var->root->exp->first_opcode ();
- if (opcode == OP_TYPE
- || opcode == OP_TYPEOF
- || opcode == OP_DECLTYPE)
+ if (var->root->exp->type_p ())
{
gdb_printf (gdb_stderr, "Attempt to use a type name"
" as an expression.\n");
diff --git a/gdb/x86-tdep.c b/gdb/x86-tdep.c
index 5d7aa95..e50b5fb 100644
--- a/gdb/x86-tdep.c
+++ b/gdb/x86-tdep.c
@@ -42,7 +42,7 @@ bool
x86_in_indirect_branch_thunk (CORE_ADDR pc, const char * const *register_names,
int lo, int hi)
{
- struct bound_minimal_symbol bmfun = lookup_minimal_symbol_by_pc (pc);
+ bound_minimal_symbol bmfun = lookup_minimal_symbol_by_pc (pc);
if (bmfun.minsym == nullptr)
return false;
diff --git a/gdb/xml-support.c b/gdb/xml-support.c
index b60b2c5..33c8e41 100644
--- a/gdb/xml-support.c
+++ b/gdb/xml-support.c
@@ -93,8 +93,8 @@ struct gdb_xml_parser
ATTRIBUTE_PRINTF (2, 0);
/* Issue an error message, and stop parsing. */
- void verror (const char *format, va_list ap)
- ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 0);
+ [[noreturn]] void verror (const char *format, va_list ap)
+ ATTRIBUTE_PRINTF (2, 0);
void body_text (const XML_Char *text, int length);
void start_element (const XML_Char *name, const XML_Char **attrs);
diff --git a/gdb/xml-support.h b/gdb/xml-support.h
index b9bac7a..2ff0e3c 100644
--- a/gdb/xml-support.h
+++ b/gdb/xml-support.h
@@ -191,8 +191,9 @@ void gdb_xml_debug (struct gdb_xml_parser *parser, const char *format, ...)
/* Issue an error message from one of PARSER's handlers, and stop
parsing. */
-void gdb_xml_error (struct gdb_xml_parser *parser, const char *format, ...)
- ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 3);
+[[noreturn]] void gdb_xml_error (struct gdb_xml_parser *parser,
+ const char *format, ...)
+ ATTRIBUTE_PRINTF (2, 3);
/* Find the attribute named NAME in the set of parsed attributes
ATTRIBUTES. Returns NULL if not found. */
diff --git a/gdb/yy-remap.h b/gdb/yy-remap.h
index e32ce39..b3fcbc6 100644
--- a/gdb/yy-remap.h
+++ b/gdb/yy-remap.h
@@ -19,7 +19,7 @@
#define YY_REMAP_H
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror,
- etc), as well as gratuitiously global symbol names, so we can have
+ etc), as well as gratuitously global symbol names, so we can have
multiple yacc generated parsers in gdb. Note that these are only
the variables produced by yacc. If other parser generators (bison,
byacc, etc) produce additional global names that conflict at link
diff --git a/gdb/z80-tdep.c b/gdb/z80-tdep.c
index 23cdb68..c442b60 100644
--- a/gdb/z80-tdep.c
+++ b/gdb/z80-tdep.c
@@ -356,8 +356,8 @@ z80_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR pc_beg, CORE_ADDR pc_end,
/* stage2: check for FP saving scheme */
if (prologue[pos] == 0xcd) /* call nn */
{
- struct bound_minimal_symbol msymbol;
- msymbol = lookup_minimal_symbol ("__sdcc_enter_ix", NULL, NULL);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space, "__sdcc_enter_ix");
if (msymbol.minsym)
{
value = msymbol.value_address ();
@@ -621,8 +621,8 @@ z80_frame_unwind_cache (const frame_info_ptr &this_frame,
break; /* found */
for (i = sizeof(names)/sizeof(*names)-1; i >= 0; --i)
{
- struct bound_minimal_symbol msymbol;
- msymbol = lookup_minimal_symbol (names[i], NULL, NULL);
+ bound_minimal_symbol msymbol
+ = lookup_minimal_symbol (current_program_space, names[i]);
if (!msymbol.minsym)
continue;
if (addr == msymbol.value_address ())
@@ -719,8 +719,8 @@ z80_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
static int addr = -1;
if (addr == -1)
{
- struct bound_minimal_symbol bh;
- bh = lookup_minimal_symbol ("_break_handler", NULL, NULL);
+ bound_minimal_symbol bh
+ = lookup_minimal_symbol (current_program_space, "_break_handler");
if (bh.minsym)
addr = bh.value_address ();
else
@@ -894,14 +894,13 @@ read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr,
static int
z80_read_overlay_region_table ()
{
- struct bound_minimal_symbol novly_regions_msym;
- struct bound_minimal_symbol ovly_region_table_msym;
struct gdbarch *gdbarch;
int word_size;
enum bfd_endian byte_order;
z80_free_overlay_region_table ();
- novly_regions_msym = lookup_minimal_symbol ("_novly_regions", NULL, NULL);
+ bound_minimal_symbol novly_regions_msym
+ = lookup_minimal_symbol (current_program_space, "_novly_regions");
if (! novly_regions_msym.minsym)
{
error (_("Error reading inferior's overlay table: "
@@ -910,7 +909,8 @@ z80_read_overlay_region_table ()
return 0;
}
- ovly_region_table_msym = lookup_bound_minimal_symbol ("_ovly_region_table");
+ bound_minimal_symbol ovly_region_table_msym
+ = lookup_minimal_symbol (current_program_space, "_ovly_region_table");
if (! ovly_region_table_msym.minsym)
{
error (_("Error reading inferior's overlay table: couldn't find "